I have been playing around with some image processing tools in java and was wondering how to create my own image format (with its own file extension and header).
Say I am trying to store 2 jpeg images into a new file with extension .abcde
How would I approach this and modify the file header?
I did some research and found this, but it didnt have any sort of example.
https://gamedevelopment.tutsplus.com/tutorials/create-custom-binary-file-formats-for-your-games-data--gamedev-206
Any advice/references/examples would be great, thanks.
Okay. Here you should ask yourself a question — what is binary file? It is some type of "box" that contains 8-bit values (0-255 range). And what actually images are? The same. But data in images is stored specifically. If you look at bitmaps (*.BMP files) for example, you'll see that it contains RGB values (it actually depends on the color depth, but we are talking about 24-bit colors now). So, what does it mean? It means that each pixel is stored with 3 bytes (24 bits) for Red Green and Blue values.
EG: 0x00 0x00 0x00 — This is black pixel in hex representation
0xFF 0xFF 0xFF — White.
But storing image data in such way is quite inefficient. For example, 1024x1024 image would be 1024*1024*3=3145728 bytes!! Or 3 MEGABYTES. And that is not including alpha channel, which also stored with one byte.
So, here the data compression comes in, it can be lossy or lossless. If you open for example a PNG file in the hex editor, you'll see a DEFLATE compressed data (LZ77+Huffman coding). It is lossless.
GIF files are compressed with LZW, which is quite inefficient nowadays. There lots of really nice image formats such as FLIF or BPG, which compress images better than PNG and JPEG.
So, if you want to create your own file format, you can create just a raw pixel container file (like BMP or PCX), or compressed pixel file (here you should write a custom data compression algorithm, C or C++ suits the best for this purpose).
Related
I've checked many sources about LZW compression but it didn't work with image file.
Here are the resources what I have checked so far:
https://www.codemiles.com/java/lzw-data-compression-decompression-algorithm-java-code-t99.html
This one the compress file is bigger than original file
https://codereview.stackexchange.com/questions/122080/simplifying-lzw-compression-decompression
Could you please give any resource that work with image compression?
Thanks!!!
Compressing an already compressed image is not a good idea, because the first compression removes any statistical hints the second compressor can use. That's at least true for contemporary compression algorithms, like they are used in the JPEG, PNG, GIF, TIFF, and WebP image formats. Typically, a compressed file, viewed in a hex editor, looks quite like a stream of random bytes, and random data (or non-random data with statistical properties similar to random data) cannot be compressed. Usually the result is even bigger than the original, due to some overhead in the storage format. Clever compressors detect this condition and revert to simply storing the original data, rather than compressing it.
So if you think that your image might be compressed further, you'll have to decompress it first. Then you can try a different compressor that might yield better results. However, I doubt that any LZW variant will give you any significant gain over JPEG. While it's a really clever enhancement of the Lempel-Ziv family of compression algorithms, LZW is a purely lossless technique, and hence has some innate limitation of the attainable compression ratio, rooted in the statistical distribution of the image data. JPEG and other lossy image formats trade image quality for size, and thus can easily outperform lossless techniques.
Note that the GIF format is a special case. While it uses lossless LZW compression, it requires a color palette of up to 256 entries. To encode a colorful image like a photograph as GIF, you'll have to quantize the color space first to get a 256-color palette. This is once again a lossy technique, albeit quite different from the algorithms used by JPEG and WebP lossy. Quantized GIF images of photos compress excellently due to the reduction of RGB information in the image, but expose noticeable deteriorations of color gradients, like they are found in human faces, flower leaves, and a cloudy heaven.
As an aside: If GIF would allow larger color palettes (say, 1024), it might become a real killer format for photographic images. Maybe it's time for a GIF17a format update?!
I am creating a post script file and text and lines work good. I need to put jpeg and gif images on it. How do I read in the jpeg or gif file and convert it to post script data so that the image appears correctly?
I found this on the internet but when I read in my jpeg and simply convert the file to hex bytes it doesn't appear correctly.
100 200 translate
26 34 scale
26 34 8 [26 0 0 -34 0 34]
{<
ffffffffffffffffffffffffffffffffffffffffffffffffffff
ff000000000000000000000000000000000000ffffffffffffff
ff00efefefefefefefefefefefefefefefef0000ffffffffffff
...
ff00efefefefefefefefefefefefefefefefefefefefefef00ff
ff000000000000000000000000000000000000000000000000ff
ffffffffffffffffffffffffffffffffffffffffffffffffffff
>}
image
That second to last line is greater than symbol followed by curly braces.
Thank you
The example you have found declares the image data using a procedural data source and no compression. Fortunately for you, a JPEG (specifically JFIF) image can be placed into a PostScript program, and the DCTDecode filter applied in order to decode it.
So you need to use a file data source, with currentfile as the input, and apply a DCTDecode filter to the file. Then put the image data after the image operator. Note that since this is a file rather than string data source you either put the image data in as binary, or you will need to apply multiple filters to the image source, eg ASCII85Dcode.
Obviously you will also need to know the width, height and colour depth of the image data and you should use the dictionary form of the image operator instead of the multiple argument form in your example code.
I would like to read an image and then change its format but without saving it.
For example I can read the image like this
BufferedImage img=ImageIO.read(new File(fileName));
Then I want to change the format of img, for example from jpeg to png.
The only way I found is to use ImageIO.read to write and then read the new image, but it does seem to be an efficient way to do it.
When you "read" the image via
BufferedImage img=ImageIO.read(new File('myimage.png'));
you are not only reading but also decoding it, i.e., transforming the raw bytes in the (say) PNG format to some "RAW" format that your aplication or API can manipulate (or display) - in this case, a BufferedImage. Once this is done, the fact that this image came from a PNG file is forgotten. To read it as PNG and save it as JPEG you need to decode it (as PNG) and then code it (as JPG).
I would like to read an image and then change its format but without saving it.
The "format" of the image (in the PNG/JPEG sense) gives you a way of packing an image in a sequence of bits. So, your desire makes little sense. At most, you could store those bits in memory (what for?), but that would be the same as "saving it" (to memory instead of disk).
I had a question concerning jpg image creation ImageIO.write(imgStega, "jpeg", file) :
I am doing some steganography, and I have to hide data in least significant bit of each pixel. I do this with getRGBA()[pos], which provide me Red, Blue, Green, Alpha components. Then I change each value with a +1 or -1 depending on a %2.
The problem is, every time I use ImageIO.write, it changes all my image at random (it is compressing). So, how can I save my image as it is ? I don't see any solution to do steganography on a real image.
Whether I use png or jpg is the same, the weight changes. Do you know a way to save my image the way it is ?
Thanks in advance !
JPEG is lossy by definition, so the data modifications that you see are expected and there is not much you can do about it in your context.
On the other hand, PNG is also compressed but in a lossless manner. The size of the png file changes because the png compression is similar to regular file compression (called LZ): very grossly explained, it detects repeated byte patterns and encodes them in fewer bytes. Changing the bytes of your image changes these patterns, and this may change the efficiency of the compression. You could as well see an increase in size. But when an application opens your modified image, it should see exactly the bytes that you have stored.
Is the change of size a concern because this might allow someone to detect your modifications? In that case, I don't see any other solution than using only uncompressed formats.
The BufferedImage class in Java contains a getType() method which returns an integer correlating with a BufferedImage constant type variable describing some information about how the image is encoded (you can look at the BufferedImage source to determine what number corresponds to what constant type variable). For instance, if it returns the integer corresponding with BufferedImage.TYPE_3BYTE_BGR, then that means that the BufferedImage is an 8-bit RGB image with no alpha and with blue, green, and yellow each being represented by 3 bits.
Some of these image types seem to correlate with certain properties of a particular format. For instance, TYPE_BYTE_INDEXED says that it is created from "a 256-color 6/6/6 color cube palette". This sounds a lot like GIF images, which are created from 256 colors.
Curious, I scanned several hundred photos on my hard drive and converted each of them to a BufferedImage, using ImageIO.read(File file), then called BufferedImage.getType() on them. I determined that there were only a few BufferedImage types that were generated from certain image types. The results were as follows:
JPG: TYPE_3BYTE_BGR, TYPE_BYTE_GRAY
PNG: TYPE_3BYTE_BGR, TYPE_BYTE_GRAY, TYPE_4BYTE_BGRA
GIF: TYPE_BYTE_INDEXED
While it looks like both JPGs and PNGs shared some similar BufferedImage constant types, only a PNG in my test resulted in a TYPE_4BYTE_BGRA and every GIF resulted in a TYPE_BYTE_INDEXED.
I'm not too familiar with image formats and it's true that my sample size isn't all that large. So I figured I'd ask: assuming that an image is properly formatted, do certain image types always result in BufferedImages with certain constant types? To provide a specific example, would a properly formatted GIF image always correspond to TYPE_BYTE_INDEXED? Or is it possible for all properly formatted images to correspond with all of the BufferedImage constant types?
[Do] certain image types always result in BufferedImage with certain constant types?
As in in your other question; No, there is no direct relationship between the BufferedImage types and file formats.
Or is it possible for all properly formatted images to correspond with all of the BufferedImage constant types?
Basically, yes. Of course, a color image would lose information if converted to gray,
a 16 bit per sample image would lose precision if converted to 8 bits per sample, etc.
However, different file formats have different ways of storing pixels and colors, and usually a certain BufferedImage type more closely represent the "layout" used in the file format.
Let's use your GIF example:
The storage "layout" of a GIF (before applying LZW compression) is normally closest to that of TYPE_BYTE_INDEXED, so that is usually the "cheapest" conversion to do in Java. For GIFs with up to 16 colors, TYPE_BYTE_BINARY would work just as well. And it's always possible for a GIF to be decoded into TYPE_4BYTE_ABGR or TYPE_INT_ARGB (or even TYPE_3BYTE_BGR or TYPE_INT_RGB if no transparent color).
In other words, the type of image depends on the decoder, and in some cases (like for the ImageIO API) the user.
To summarize, what you have found, is that the GIF plugin for ImageIO (GIFImageReader) by default will decode a GIF with more than 16 colors to TYPE_BYTE_INDEXED. Using a different decoder/framework may yield different results.
A little bit of history that might enlighten the curious reader:
The types of BufferedImages where not modeled to correspond to image formats. They were modeled to correspond to display hardware. An image having the same pixel layout as the display hardware is always going to be faster to display. Other layouts would first need to go through some kind of conversion. Now with modern display hardware being very fast, this is of course less of a concern, but in "ancient" times this was important.
Incidentally, many "ancient" image formats were created ad hoc, or for specific applications running on specific display hardware. Because of this, the pixel layout of the display hardware were often used in the file format. Again, because no conversion was needed, and it was the fastest/simplest thing to implement.
So, yes, there is a relationship. It's just not a direct "given A => B" relationship, it's a "given A and C => B".