Almost got a PCX parse working, but the colors aren't read properly

I almost have a parse for reading a PCX file working, but right now when it applies the texture it is just a jumbled mess of pixels of seemingly random colors. As far as I know it is reading the bytes of the image properly, as I am able to get accurate data on the max x and y for the image. It’s just so far every method I have tried to accurate create the image has been frustrated. The pcx is 8 bits per pixel, with a plane count of 1 and a 256 color with palette. My understanding from what I read is each byte after 127 is an R, G and then B color code for the image. My other thought was maybe each byte itself is a single full color code, since it never goes higher than 255 and this is a 256 color palette. If so, is there a way to convert a single byte value to a full RGB color? I have tried doing some << offsetting but so far no luck.

I am not necessarily asking for the the full answer, but rather some direction on where to take this, especially if I am not thinking about it the correct way.

Here is my code at present.

    string pcxPath = Application.dataPath + "texture.pcx";
    byte[] reader = File.ReadAllBytes(pcxPath);

    bitsInFrame = reader[3];
    minX = reader[4];
    minY = reader[6];
    maxX = reader[8];
    maxY = reader[10];
    horzDPI = reader[12];
    vertDPI = reader[14];
    numColorPlanes = reader[65];
    horzSourceScreen = reader[70];
    vertSourceScreen = reader[72];
    startingPoint = 128;

    Color[] colorArray = new Color[reader.Length / 3];

    Texture2D imgTexture = new Texture2D(maxX / 3, maxY / 3);

    string byteString = "";
    for (int i = startingPoint; i < reader.Length - 2; i += 3)
        byteString += reader *+ " ";*

Color newColor = new Color(reader / 255f, reader[i + 1] / 255f, reader[i +2] / 255f);
colorArray[(i - startingPoint) / 3] = newColor;
mat.materials[0].mainTexture = imgTexture;

Not sure why you think that you almost got it working :slight_smile: Most of your code doesn’t make too much sense.

First and foremost I highly recommend you take a look at this page which is the full spec of the PCX format. You did not read most of the header values properly. A lot of the values are “words” (16 bit integers). As you can read at the beginning, PCX uses little endian number format. So the first byte is the low order byte while the second byte is the high order byte.

It’s way easier to use the BinaryReader class to parse binary formats, especially when they are little endian. You said “your image” is 8 bit per plane and 1 plane. The question is, do you want to write a PCX loader or do you just want to load that one image? If you want to write a PCX loader you would need to implement all the different formats a PCX image could represent. When you read the section about the palette you may realize that there are many special cases because PCX is a really ancient format and the VGA palette was a quite late extension. If a VGA palette is present it would be at the end of the image. The actual image data is a simple run-length encoded format. The page I’ve linked does have some reference code for the loader. The image data represents indices into the color palette. It’s not that complicated but requires quite a bit more work than what you’ve done so far. Just for reference, here’s my BMP loader. It’s still not bullet proof and therefore still WIP, but does work with most BMP files.

If you’re not really interested in writing a complete PCX loader, why don’t you simply convert your PCX image into a proper modern format like png? The resulting image would probably be smaller anyways as run length encoding is not that efficient unless the image has large areas / lines of the same color. PNG uses deflate to compress the image which should be smaller in most cases. Unity can load PNG files out of the box.