I use sockets to send jpg images from server (android) to client. I want to attach timestamps to these images which are of type long. Since these images are already processed by image filters I don't want to save them before transmission, so using ExifInterface seems impossible. I therefore tried to use IIOMetadata but never got it to work. I dont want to use external libs like senselan.
What is the easiest way to do it? If using IIOMetadata is the best way to do it, could you please provide me with a working example on how to attach this to my byte[] and extract it later?
You can send a jpg file and then add 8 bytes to encode the long timestamp, then
another jpg and 8 bytes of timestam, and so on.
You can detect the end of the jpeg, using what it is commented here
Detect Eof for JPG images
Okay, I did what Pablo suggested, but attached the timestamp to the front of the image.
Related
I am trying to implement attachments in my application and user is able to upload image files (png, jpg, jpeg). I have read OWASP recommendations for image uploads, and one of the tips was to - convert the input image to a bitmap (keeping only the bitmap data, and throwing away all the extra annotations), then convert the bitmap to your desired output format. One reasonable way to do this is to convert to PBM format, then convert to PNG.
Image is saved as byte array.
I am trying to rewrite uploaded image by using ImageTranscoder from ImageIO library. But i am not really sure what it is doing, and if all the possibly malicious code is removed from image, because it seems that only metadata is being rewritten.
Is there any suggestions, best practices, of how desired goal should be achieved to remove all possibly malicious code inside image file?
You do not need an intermediate file format like PBM, as BufferedImage (which is the standard way of representing an in-memory bitmap in Java) is just plain pixel data. You can just go from encoded "anything" to decoded bitmap to encoded PNG.
The simplest way you could possibly do what you describe is:
ImageIO.write(ImageIO.read(input), "PNG", output);
This is rather naive code, and will break for many real-world files, or possibly just silently not output anything. You probably want to handle at least the most normal error cases, so something like below:
BufferedImage image = ImageIO.read(input);
if (image == null) {
// TODO: Handle image not read (decoded)
}
else if (!ImageIO.write(image, "PNG", output)) {
// TODO: Handle image not written (could not be encoded as PNG)
}
Other things to consider: The above will remove malicious code in the meta data. However, there might be special images crafted for DoS (small files decoding to huge in-memory representations, TIFF IFD loops, and much more). These problems need to be addressed in the image decoders for the various input formats. But at least your output files should be safe from this.
In addition, malicious code could be stored in the ICC profile, which might be carried over to the output image. You can probably avoid this by force converting all images to the built-in sRGB color space, or writing the images without ICC profiles.
PS: The ImageTranscoder interface is intended for situations where you want to keep as much meta data as possible (that is why it has methods only for meta data), and allows transformation of meta data from one file format to another (one could argue the name should have been MetadataTranscoder).
I want to modify the metadata of some types of images (png, jpeg or gif) and I found a a code that works very well for PNG images on this topic, provided by haraldK. When I try to run it on a jpg image though, it throws this error :
javax.imageio.IIOException: JFIF APP0 must be first marker after SOI. The error is thrown when arriving on the line IIOImage image = reader.readAll(0, null);
What can I do to get this working ?
Thanks in advance for your answer.
The problem you face is the JPEG standard did not define a file format. Several file formats appeared. E.g. JFIF. EXIF. SPIFF. These formats represent metadata in different ways. Apparently the library you are trying to use only supports the JFIF file format. Apparently your library only supports the JFIF format while you have a file in a different format (likely EXIF).
So you need a library that supports your file format or you need to modify the library you have to work with whatever file format you have. That could be a fairly substantial change.
I'm trying to create a Java program that will OCR many formats of images. Images cannot be read directly from file, because their bytes are to be send through network.
I'm currently able to read raw bytes of image pixels using ImageIO. However I would like to support all the formats that are supported by ImageMagick, so read the image using JMagick and then give raw bytes to Tess4J. I'm not sure how I should approach this. I found this function can give me bytes:
PixelPacket[] MagickImage.getColormap();
But I would have to write special method for transforming obtained the PixelPacket objects to consecutive bytes. I can do that, but maybe there's better way to do this? For example maybe there's some extremely raw file format (even more than http://en.wikipedia.org/wiki/BMP_file_format#mediaviewer/File:BMPfileFormat.png) that I could use for example in this method:
byte[] imageToBlob(ImageInfo imageInfo) ?
The imageInfo object will have to point to this raw format and then I can cut out the pixels information from the bytes array.
Is this the proper way or I should use something simpler (faster/more robust)?
Edit
I found the format I had in mind is called PNM.
I think using the dispatchImage method is what you are looking for, if using JMagick. It will give you access to the raw pixels of the image directly. No file format required.
See my MagickUtil class for examples, or just use that class if you feel like.
I've also written pure Java ImageIO plugins for many of the same formats that JMagick supports, that might be of use. You'll find them in the my GitHub repository.
I have a curious question. When decode a JPG image in Bitmap, it take very high memory as JPG is a compressed format.So for 0.5 MB JPG image, bitmap is almost 4 MB.
My question is if I want to upload an image, I can just read it from file and send it to server i.e. I do NOT need to load it in Bitmap.
Have anybody ever tried this?
Does it makes sense?
Thanks for help.
Yes this is possible. You don't need to covert jpg to bitmap to upload it to server.
You can consider using a higher level API like http://loopj.com/android-async-http/. Please see the section "Uploading Files with RequestParams" for more details.
jpg is a format to store compressed images into files. It is practical because it takes less memory than the raw bitmap format, where the color values of all pixels in the image are explicitly present in the data.
You do need to decompress the jpg file in order to display it, however the best way to send it would be to use the compressed jpg file (no need to load the bitmap, just send the data in the file).
Note that JPEG compression is lossy, meaning that the reduction in size comes with a degradation in quality from the original source image. (see the thorough and well illustrated wikipedia entry: https://en.wikipedia.org/wiki/Jpg).
I have a situation where I would like to do some very light image file obfustication. My application ships with a bunch of .png files and I'd like it if they weren't so readily editable.
I'm not looking for a 'secure' solution (I don't believe one really exists), I'd just like Joe Public to be unable to edit the files.
I am currently using;
ImageIO.read(new File("/images/imagefile.png"));
I'd rather not have to use Serialisation, as the ImageIO system is pretty deeply ingrained in the code, each image needs also to remain as its own file on disk.
I was hoping I could just change the file extension eg;
ImageIO.read(new File("/images/imagefile.dat"));
But ImageIO seems to use it to identify the file. Can I tell ImageIO that it is a PNG despite its extension?
Encrypt all the files on disk.
Then in the program, decrypt a file, load it in memory and go rocking.
Java image I/O uses the Service Provider Interface to support new image formats1. I believe it might be possible to add a new decoder using a file extension. If that is the case, there is the route to providing an easily pluggable reader for a custom image format.
Note that you will probably need to change the file extension in the source. That might be the job for an advanced IDE, or a one-time search and replace using grep.
As to the format, one extremely simple way make media files unreadable in common readers is to write the bytes of the image in reverse order. Then flip them back after read, put them in a ByteArrayInputStream, and pass them to ImageIO.read(InputStream).
After you have written the service provider and Jar'd it properly (using a manifest with attributes to identify the file/content type it handles, and the corresponding encoder/decoder), add it to the run-time class-path of the app., and it should be able to read the custom image format.
...or keep all images in a single file and seek() to the start position of each image as you load. You can do this by pre-seeking against a FileInputStream, or conversely by creating a ByteArrayInputStream for ImageIO.read(InputStream).
You could try this:
Iterator rs = ImageIO.getImageReadersByFormatName("png");
ImageReader ir = (ImageReader) rs.next();
File srcFile = new File("/images/imagefile.dat");
ImageInputStream iis = ImageIO.createImageInputStream(srcFile);
ir.setInput(iis);