Bytes and characters aren't always interchangeable - single byte values can't always represent all characters (though
multiple bytes can), and you can't use characters to represent all bytes (
refer to the gaps in the ISO/IEC_8859-1 code page, for eg - notice how there aren't any glyphs before char 32?). If you were able to use something like good ol'
code page 437 this wouldn't be an issue, but there's actually no need to be bringing strings or characters into this in the first place. The content you're working with isn't
text, see, and those just aren't the right data types for the job.
So ditch the
BufferedWriter and pass a
FileOutputStream through a
BufferedOutputStream instead, while likewise ditching all the UTF-8-handling stuff on the Lua side. Then you can simply pass your numeric values around without any special handling, since most of 'em fit within the 0-255 range that single bytes can represent.
Though it may be that you'll need to split your image dimensions and co-ords over multiple bytes (if you want to allow for images larger than 255px). For eg:
output.write(image.getWidth() & 255); // Where "output" is a BufferedOutputStream
output.write((image.getWidth()>>8) & 255);
Hey presto, 16bit little-endian integer representation, good for values ranging from 0-65,535. Reading it back in Lua:
local width = input.read() + input.read() * 256 --# Where "input" is a binary-mode file handle
Hey presto, it's now… well, probably stored as something like a double-precision float somewhere, but in any case you've got some sort of representation of the original number back in memory.
As for the colours, you might do:
int clr = image.getRGB(x, y);
output.write((clr & 0x00ff0000) >> 16); // R
output.write((clr & 0x0000ff00) >> 8); // G
output.write(clr & 0x000000ff); // B
output.write((clr & 0xff000000) >>> 24); // A
Or you could pull the pixel to a Color and getRed/getBlue/etc, if you prefer that aesthetic:
Color clr = new Color(image.getRGB(x, y), true);
output.write(clr.getRed());
output.write(clr.getGreen());
output.write(clr.getBlue());
output.write(clr.getAlpha());
Bear in mind ComputerCraft's timers don't generate any events until the next server tick, at the earliest. Assuming it isn't overloaded, the server ticks every 0.05s - meaning that "sleep(0.001)" call is really pausing your script for a
twentieth of a second, not a thousandth. If you want to yield purely for the sake of yielding, then I suggest:
local function snooze()
local myEvent = tostring({})
os.queueEvent(myEvent)
os.pullEvent(myEvent)
end
Edit:
It occurs to me that your reason for attempting to use UTF-8 might be because you intend to transfer these converted images through the pre-CC1.8 http API (which only handles text, and poorly at that). If this is the case, then I strongly recommend you let
BBPack handle your uploads and downloads - it'll sort out the text encoding and decoding for you (using
base64, which is rather more appropriate for that sort of thing), ensuring that the data you put in is the data you get out.