How to reverse that function

0

I've asked before about the opposite of Bitwise AND(&) and you told me its impossible to reverse.

Well,this is the situation: The server sends an image,which is encoded with the function I want to reverse,then it is encoded with zlib.

This is how I get the image from the server:

        UInt32[] image = new UInt32[200 * 64];
        int imgIndex = 0;
        byte[] imgdata = new byte[compressed];
        byte[] imgdataout = new byte[uncompressed];

        Array.Copy(data, 17, imgdata, 0, compressed);
        imgdataout = zlib.Decompress(imgdata);
        for (int h = 0; h < height; h++)
        {
            for (int w = 0; w < width; w++)
            {
                imgIndex = (int)((height - 1 - h) * width + w);
                image[imgIndex] = 0xFF000000;
                if (((1 << (Int32)(0xFF & (w & 0x80000007))) & imgdataout[((h * width + w) >> 3)]) > 0)
                {
                    image[imgIndex] = 0xFFFFFFFF;
                }
            }
        }

Width,Height,Image decompressed and Image compressed length are always the same.

When this function is done I put image(UInt32[] array) in a Bitmap and I've got it.

Now I want to be the server and send that image.I have to do two things:

Reverse that function and then compress it with zlib.

How do I reverse that function so I can encode the picture?

    for (int h = 0; h < height; h++)
    {
        for (int w = 0; w < width; w++)
        {
            imgIndex = (int)((height - 1 - h) * width + w);
            image[imgIndex] = 0xFF000000;
            if (((1 << (Int32)(0xFF & (w & 0x80000007))) & imgdataout[((h * width + w) >> 3)]) > 0)
            {
                image[imgIndex] = 0xFFFFFFFF;
            }
        }
    }

EDIT:The format is 32bppRGB

c#
asked on Stack Overflow Apr 26, 2009 by Ivan Prodanov • edited Apr 26, 2009 by Ivan Prodanov

1 Answer

6

The assumption that the & operator is always irreversible is incorrect.

Yes, in general if you have

c = a & b

and all you know is the value of c, then you cannot know what values a or b had before hand.

However it's very common for & to be used to extract certain bits from a longer value, where those bits were previously combined together with the | operator and where each 'bit field' is independent of every other. The fundamental difference with the generic & or | operators that makes this reversible is that the original bits were all zero beforehand, and the other bits in the word are left unchanged. i.e:

0xc0 | 0x03 = 0xc3   // combine two nybbles

0xc3 & 0xf0 = 0xc0   // extract the top nybble
0xc3 & 0x0f = 0x03   // extract the bottom nybble

In this case your current function appears to be extracting a 1 bit-per-pixel (monochrome image) and converting it to 32-bit RGBA.

You'll need something like:

int source_image[];
byte dest_image[];

for (int h = 0; h < height; ++h) {
    for (int w = 0; w < width; ++w) {
        int offset = (h * width) + w;
        if (source_image[offset] == 0xffffffff) {
            int mask = w % 8; // these two lines convert from one int-per-pixel
            offset /= 8;      // offset to one-bit-per-pixel
            dest_image[offset] |= (1 << mask); // only changes _one_ bit
        }
    }
}

NB: assumes the image is a multiple of 8 pixels wide, that the dest_image array was previously all zeroes. I've used % and / in that inner test because it's easier to understand and the compiler should convert to mask / shift itself. Normally I'd do the masking and shifting myself.

answered on Stack Overflow Apr 26, 2009 by Alnitak • edited Apr 26, 2009 by Alnitak

User contributions licensed under CC BY-SA 3.0