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.
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 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).
I have a base64 string that it contains an image which scanned by 300DPI and it size is around 500kb . I need to reduce file size to 300kb (+/- %20) without changing DPI in java. Resolution MUST be 300 DPI. I can't change it.
Hovewer, I don't care about dimensions (pixels). I could not figure out how can I do it. I hope, you can help me ?
Thanks:)
Since the size of the photographed object does not change (inches), and the resolution you mandate to be fixed at 300DPI (Dots/pixels per inch), the number of pixels in the image also cannot change.
The only thing you can do in order to reduce the file size is to compress it.
Depending on the image contents, you can, for example, use JPEG compression and set its quality level to a setting that will yield a 300Kb output. Other compression methods may be more applicable, depending on the contents on the image. For example CCITT G4 compression for scanned black & white text.
Regarding how to compress, Google is your friend:
https://www.google.com/search?q=compress+image+jpeg+java
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".
I'm trying to display a big image file in a J2ME application. But I found that when the image file is too big I can not even create the Image instance and get a OutOfMemory exception.
I suppose I can read the image file in small chunks and create a thumbnail to show to the user?
Is there a way to do this? Or is there any other method to display the image file in the application?
Thanks.
There are a number of things to try, depending on exactly what you are trying to do and what handset you want your application to run on.
If your image is packaged inside your MIDlet JAR file, You have less control over what the MIDP runtime does because the data needs to be unzipped before it can be loaded as an Image. In that case, I would suggest simply packaging a smaller image. Either reduce the number of pixels or the number of bytes used to encode each pixel.
If you can read the image bytes from a GCF-based InputStream (file, network...), You need to understand the image format (BMP is straightforward, JPEG less so...) so you can scale it down into a mutable Image object that would take less memory, one chunk at a time.
In that case, you also need to decide what your scaling algorithm should be. Turning 32 bits pixels in a file into 8 bits pixels in memory might not actually work as expected if the LCDUI implementation on your mobile phone was badly written.
Depending on the content of the image, simply removing half of the pixel columns and half of the pixel lines may be either exactly what you need or way too naive an approach. You may want to look at existing image scaling algorithms and write one into your application.
Remember that basic LCDUI may not be the only way to display an image on the screen. JSR-184, JSR-239, JSR-226 and eSWT could all allow you to do that in a way that may be totally independant from your handset LCDUI implementation.
Finally, let's face it, if your phone MIDP runtime doesn't allow you to create at least 2 images the size of your screen at full color depth at the same time, then it might be time to decide to not support that specific handset.