Since GIF uses LZW compression, your bit-twiddling is
damaging the data severely. It's not like a bitmap (BMP)
file where there is a one-to-one correlation between bits
in the file and bits on screen. In fact, a one-bit change
can ruin your entire GIF from that point on. JPEG, while
it employs a different compression system, is likely to
suffer the same sort of damage.
First, use PNG. It's better for your application because it
can express more colors, and unlike JPEG, the compression
does not destroy any data, so the image you get out is
exactly what you put in. JPEG will take some liberties with
your image in order to compress it, so the output may be
substantially different from the input.
So with that established, no matter what image you use,
you will have to decompress it first. You can use a library
like
Image::Magick to do this for you. When you have this
in a regular "bitmap" format, you can go to town on it,
perhaps using something like
vec to twiddle your bits,
or any other method you can think of. When you're finished,
you can pack it back up as a PNG and fire it off.
Of course, the tricky part is finding a "sneaky" way of modifying the
bitmap image.