#Converting .png to .8ci

18 messages · Page 1 of 1 (latest)

hushed jewel
#

So, I need to convert a .png file into a .8ci file because its the only accepted file format. It's not the intended way to do it, but I would like to try this way anyway. I managed to find a .png to .8ci converter, tried using Python to do it (but i dont think their libraries allow for direct conversion of such an old format as .8ci, I tried Pillow). I know this isn't a place for someone to just complete your work for you, but I would appreciate if someone would help me through understanding and reversing the process to convert a .png file to .8ci. (Learnt basics of Python but haven't learnt C++ yet)

earnest socketBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

hushed jewel
#
// compile with g++ -o 8ci-png 8ci-png.cpp -lpng
// add -I/usr/local/include if on mac and errors out with "png++/png.hpp: no such file or directory"
#include <iostream>
#include <fstream>
#include <vector>
#include <png++/png.hpp>

//-----------8ci palette---------------
std::vector<png::rgb_pixel> colors = {
    {255, 255, 255}, // white/none
    {0, 0, 255},     // BLUE
    {255, 0, 0},     // RED
    {0, 0, 0},       // BLACK
    {255, 0, 255},   // MAGENTA
    {0, 255, 0},     // GREEN
    {255, 160, 0},   // ORANGE
    {128, 32, 0},    // BROWN
    {0, 0, 128},     // NAVY
    {0, 144, 255},   // LTBLUE
    {255, 255, 0},   // YELLOW
    {255, 255, 255}, // WHITE
    {192, 192, 192}, // LTGRAY
    {128, 128, 128}, // MEDGRAY
    {96, 96, 96},    // GRAY
    {64, 64, 64}     // DARKGRAY
};

enum colors {
    COLOR_NONE,
    COLOR_BLUE,
    COLOR_RED,
    COLOR_BLACK,
    COLOR_MAGENTA,
    COLOR_GREEN,
    COLOR_ORANGE,
    COLOR_BROWN,
    COLOR_NAVY,
    COLOR_LTBLUE,
    COLOR_YELLOW,
    COLOR_WHITE,
    COLOR_LTGRAY,
    COLOR_MEDGRAY,
    COLOR_GRAY,
    COLOR_DARKGRAY
};
//-------------------------------------```
#
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <input.8ci> [output.png]\n";
        return 1;
    }
    std::string out = std::string(argv[1]) + ".png";
    if (argc > 2) out = std::string(argv[2]);
    std::ifstream in(argv[1]);
    if (!in.is_open()) {
        std::cerr << "Could not open " << argv[1] << ".\n";
        return 2;
    }
    in.seekg(74); // this may or may not always hold true
    png::image<png::rgb_pixel> img(266, 165); // same here
    int x = 0, y = 0;
    while (!in.eof() && y < 165) {
        char ch = in.get();
        img.set_pixel(x++, y, colors[(ch & 0xF0) >> 4]);
        img.set_pixel(x++, y, colors[ch & 0x0F]);
        if (x > 265) {x = 0; y++;}
    }
    img.write(out);
    std::cout << "Wrote image\n";
    return 0;
}```
gusty creek
#

The problem is that as far as I can tell, the 8ci image format is somewhat proprietary - the image data seems simple enough to implement, but there are likely problems with setting the header that is skipped in the program you linked - so we can't really reverse engineer it, and that this may or may not always hold true doesn't bode well either.

#

As for the pixel format, it's just a list of 165 rows of 254 4-bit color values, similar to a C-style 2D array. And the color values are in the vector, so you would have to create a reverse mapping, and possibly a color distance generator to get from the much larger png color space to the 4bit color space.

hushed jewel
#

So, i would need to go through all the pixels and find the closest colour that matches, then change it to fit that? Even after i do all that, how do i change it into .8ci?

Also, by 165 rows of 254 4-bit color values, do you mean the RGBA format? So i would need to go through all 254 4 bit color values, translate it into RGB format (with the specific colors), and do that for all 165 rows? Or is .8ci lower resolution in some way that for example 4 values would have to be blended together to achieve the right resolution?

gusty creek
# hushed jewel So, i would need to go through all the pixels and find the closest colour that m...

You wouldn't need to convert first, you can have a map of the possible colors and choose the closest one, and insert it right away, also there's no RGBA format, it's literally a key-value pair for 16 colors, though I should have written 165x266 (my brain's autocorrect swooped in there). Then you just need to combine the low and high nibble for each pixel value, since 8ci is using 4 bits, you have to coax the 8-bit minimum addressing of modern computers.

As for more, I can't really help, as the resources on the format are scarce online unfortunately. Though I can give a small diagram of the pixel portion of the image (note that | just denotes a pixel boundary, nothing more:

| 4bit color | 4 bit color | (262 more times) | 4bit color code | 4bit color code |
(163 more times)
| 4bit color | 4 bit color | (262 more times) | 4bit color code | 4bit color code |

As for reversing it code-wise:

uint8_t pixel_array[165][266/2];
for(int y = 0; y < 165; y++) {
  for(int x = 0; x < 266; x += 2) {
    pixel_array[y][x] = (find_closest_color(png[y][x]) << 4) | (find_closest_color(png[y][x + 1]) << 4);
  }
}

uint8_t find_closest_color(png::basic_rgb_pixel<int> &pixel) {
  // do some color stuffs to find the closest matching color to the list in std::vector<png::rgb_pixel> colors
  return color;
}
hushed jewel
#

Ah, i now realize that i had been confusing 4-bit with 4-byte. I believe that i should be able to get a png, use one of those online image resizers to get it to 165x266 pixels, then use the code to substitute all the values with the closest color. However, im still not sure as to how the final saving of the file as a .8ci would work.

gusty creek
earnest socketBOT
hushed jewel
#

Hmm, ill probably study up more on this later, im performing at a concert tmr and i have other projects due sooner. Thanks for the help though! Ill just leave this thread open for reference. cat_up

earnest socketBOT
#

@hushed jewel Has your question been resolved? If so, type !solved :)

hushed jewel
#

Uh

#

Does this close the thread?

#

Oh it doesnt seem to

#

!solved