Main Menu

telepaint.lua

Started by RaiuTheEevee, Jul 11, 2023, 03:08 AM

Previous topic - Next topic

RaiuTheEevee



What is telepaint.lua?
This program is an art tool for making images with square pixels using the 32 teletext symbols. This program was designed to fit on any type of computer terminal (not including monitors).
 
The core functions of this program will work on a monitor, but of course right and middle click and scrolling won't work. The program also won't be able to launch if this monitor is too small. Minimum term size is 26x12.

To download, run: pastebin get V0gqrj2v telepaint.lua

This program also requires three APIs to work:
pastebin get Rac6Jxjg /API/LibAppend.lua
pastebin get t2TvSiSU /API/Class.lua
pastebin get KA2dK07y /API/Events.lua


Running the program works like the built-in paint program. Run 'telepaint <path>' to load a .bpi file for editing. The program will automatically load a file starting from the directory the shell is currently in. If you put "/" at the start of the path, it will load starting from the root directory. If the file does not exist, a new file and empty canvas will be created.

What is a .bpi file?
'.bpi' is a work in progress file format for images that contain text, as an alternative to ComputerCraft's '.nfp' files. .bpi files are saved in binary encoding. When reading a .bpi file, the format goes as follows per pixel:

  • X Length = 4 bits for the byte length of the X Coordinate.
  • Y Length = 4 bits for the byte length of the Y Coordinate.
  • X Coordinate = X Length bytes.
  • Y Coordinate = Y Length bytes.
  • Text Code = 1 byte for the text character code.
  • Text Color = 4 bits.
  • Background Color = 4 bits.

The pixels are not in any specific order. Empty spaces between pixels may be treated as transparent pixels.

Do a bitwise right shift by 4 bits on the first byte to get the length in bytes of the X Coordinate. Do a bitwise 'and' 15 to get the length in bytes of the Y Coordinate.

Do 'bitwise left shift' by 8 bits the number of times provided by X Length and Y Length to get the full value of a coordinate. Of course if the coordinate is only 1 byte you don't do any shifts.

Do bitwise right shift by 4 bits to get the text color, and do bitwise 'and' 15 to get the background color, then do 2 to the power of either value to get the actual color codes which can then be converted to blit codes with colors.toBlit.

Alternatively you can also turn the whole byte into a hexadecimal string to get the blit characters, then use string.sub to get the individual colors. My LibAppend.lua API has a function 'tobase(n, b)' which does that exact thing. If you use it you should do 'string.pad(tobase(n, 16), "0", 2)' - which is also provided by my API - to ensure the string is 2 characters. You may also want to use string.upper or string.lower to ensure the capitalization is consistent with your program. You could also use these functions to get the coordinate lengths.

How do I use this program?

The Canvas
The largest window on the left is your canvas. This is your source image used to paint like the built-in paint. Use left click to paint with the primary selected color, right click to erase, and middle click to pick a new primary color from the canvas.

The window in the top right is the output image that will be saved to the .bpi file. Every 2x3 pixels in the source image is a "pixel" in the output image.

Each "pixel" in the output image can only have two colors, the text and background color for that character. Any extra colors will be converted to the text or background color, based on the dithering mode, explained below.

The background color is based on the bottom right pixel in the 2x3 space, and the text color is based on the first color -  going from left to right, top to bottom - that doesn't match the background color, or it will be the background color if no other color is found.

If there are any transparent pixels in that 2x3 space, they will be automatically converted to the background color. If the pixel for the background color is transparent, it will be converted to the secondary selected color. Here are some examples of that in action.


If all pixels in the 2x3 space are transparent, then the output pixel will also be transparent.

Scrolling
Put your mouse cursor over the source canvas and use scroll wheel to scroll the image up or down. Hold shift while scrolling to scroll left or right. You can also hold shift while clicking and dragging to pan the image. Doing any of these actions with your mouse over the output image will scroll/pan faster. The current scroll position of the output image is printed on the horizontal border under the output image.

Selected Pixel
The bottom right window is the menu. The first line in the menu window starts off blank. If you left click any where in the output window, that pixel will be selected. The selected pixel will be shown by the blinking shell cursor. That pixel and its character code will be printed on the first line in the menu. If you right or middle click on the output, it will deselect the pixel.


Colors
The two pixels all the way on the right are your selected colors. Click any of the other colors with left click to select the primary color, and use right click to select the secondary color.

Dithering Mode
'Dither' is the dithering mode. This controls how pixels with more than two colors are converted to teletext. Click this or press 0 or 1 on your keyboard to toggle this option.

When the mode is 0, extra colors will be converted to the background color.


When the mode is 1, extra colors will be converted to the text color.

This does not affect transparent pixels.

Main Menu
You can use ctrl to access the save and exit menu. Use left or right arrow keys to select either button, then press enter to use them. You can also click on either button to use them. When saving, you will get a message saying if the task was successful, if the file would be too big to save, or if the file is unable to be saved for some other reason.

Additional Screenshots
In the image below, I've drawn the player sprite from Pokémon red. As you can see, it looks corrupted in the output image, and that's because there's more than 2 colors in the corrupted pixels. It can't be effectively converted without damaging the image.


In this image, I've redrawn the sprite in two different ways to adhere to the limitations of teletext. I've also swapped some of the colors to spice up the image.


In this image, I've redrawn the sprite with 2x2 pixels. This makes it so you actually can draw an image with pixel perfect color, but it has the unfortunate side effect of being twice as big. There's also some conflicts with the transparency, as you can see in the output image, which makes this type of image not the most effective way to use this technique. I may make another program in the future that utilizes this technique better.