Question regarding jpeg and png file structure and header information - java

I need to be able to modify the contents of a jpeg or png files and am able to successfully break the image down into bytes and vice versa. The only problem is that i do not know how many bytes make up a jpeg file header or a png file header. The information on most websites is pretty vague and/or way too informative for a beginner like me.
Id really appreciate if someone can provide a simple answer telling me how many bytes i need to skip to get past the header and how to identify if the image is a jpeg image or a png image as well as any other important information that i may not have mentioned.
Ive added the code below which im using to extract the bytes from an image and to convert the image into bytes.
Note: This code works on android OS
Code used to convert image to bytes:
public byte[] imgtobytes(File f)
{
FileInputStream fis=null;
try
{
fis = new FileInputStream(f);
}
catch(Exception e) {}
Bitmap bm = BitmapFactory.decodeStream(fis);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100 , baos);
byte[] b = baos.toByteArray();
return b;
}
Code used to convert bytes to image and display it on an imageview:
public void bytestoimg(byte[] bytearray, ImageView imgv)
{
Bitmap bmp = BitmapFactory.decodeByteArray(bytearray, 0, bytearray.length);
imgv.setImageBitmap(Bitmap.createScaledBitmap(bmp, imgv.getWidth(),
imgv.getHeight(), false));
}

I've done some similar work in python a while ago playing with encryption. I believe that what you are looking for can be found in this wikipedia article under "Examples" section.
Also you can check out this answer

Related

How convert Bitmap to byte array and back without quality reduction?

When I convert a picture into bytes and back, the quality deteriorates a lot. How to do it without reducing quality?
I need to save the photo in the database or send it to the server. I can consider other options to do this.
public static byte[] fromBitmap(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
public static Bitmap toBitmap(byte[] bytes) {
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
How to do it without reducing quality?
Use a lossless image format, such as PNG.
It's not a good way to save the picture in the database directly. The best way is to upload pictures to the server in a directory and save the picture path in the database. Here you can find out a complete tutorial to upload the picture on the server and save its path in the MYSQL database.

Android - Save Bitmap Image on Mobile Storage without Compressing

The typical way (based on research) for saving bitmap images from a remote url is:
Bitmap bmImage = null;
InputStream in = new java.net.URL(imageUrl).openStream();
bmImage = BitmapFactory.decodeStream(in);
File file = new File(myPath);
FileOutputStream outputStream;
outputStream = new FileOutputStream(file);
bmImage.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
I cannot save bitmap unless it is compressed (Bitmap is always uncompressed).
The remote image size is 32KB, after compression it gets 110KB.
I know I have to lower compression parameter to get smaller size, but the remote image is optimize and much more efficient.
Is there a way I can save the remote image on mobile storage without compressing it?
===== ANSWER TO MY PROBLEM =====
First I apologize for misleading content; all I wanted is to save images that could be png|jpeg|gif|etc.. Probably I mislead you guys that the image I am trying to save is in BMP format, but it is not.
Nevertheless, for those who want to save images WITHOUT compressing, have a look to this answer
Use AndroidBmpUtil as shown in the code below:
new AndroidBmpUtil().save(bmImage, file);

Inserting 1 MB image in neo4j returns a different size (536 KB) when retrieved

I am trying to insert a 1 MB image inside neo4j using the following code:
File fnew = new File("C:\\Users\\myimage.jpg");
BufferedImage originalImage = ImageIO.read(fnew);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.flus();
ImageIO.write(originalImage, "jpg", baos);
return baos.toByteArray();
Then I insert this byte array using:
user.setProperty("photo", photo);
This all goes fine. When I try to select the photo, using the following method, it writes it on my hard drive disk as 536KB instead of the 1 MB original size.
byte[] imageInByte = (byte[]) user.getProperty("photo");
InputStream in = new ByteArrayInputStream(imageInByte);
BufferedImage bImageFromConvert = ImageIO.read(in);
ImageIO.write(bImageFromConvert, "jpg", new File("C:\\newimage.jpg"));
Now the weird part: I can see the image, open it, same resolution, I don't see any difference in terms of quality though. Looks like it is compressed.
Why is this happening?
Saving a jpg image through ImageIO results in lossy compression of the jpg (I believe the quality defaults to 70%). You can a) Change the the quality of the image when you write to file (see Setting jpg compression level with ImageIO in Java ) or b) if you don't actually need the BufferedImage, just read/write the bytes from file to database.

How to read Bytes of an Image in Java?

I am currently working with Image processing in Java. Initially I used ImageIO class to write images
ImageIO.write(image,"jpg",os);
the problem with this method is am lossing the actual image size and quality. Then I preferred ByteStream
Files.readAllBytes(fi.toPath());
to read and
fos.write(fileContent);
to write Images. This works perfectly. The issue I am facing here is I can read only files but not Images(ie, BuffreredImage image). Is it possible to read a Image rather than files here or should I move to someother IO?
Code Snippet is here,
try {
File fnew=new File("d:\\3\\IMG1.jpg");
java.io.FileOutputStream fos = new java.io.FileOutputStream(new File("d:\\3\\Test1\\4.jpg"));
File fi = new File("d:\\3\\7.jpg");
byte[] fileContent = Files.readAllBytes(fi.toPath());
fos.write(fileContent);
} catch (Exception e) {
System.out.println("Exception");
}
Any Kind of suggestions or help will be appreciated. Thanks in Advance.
the problem with this method is am lossing the actual image size and quality. Then I preferred ByteStream
When you read a JPEG with with ImageIO, it is converting the JPEG to a Bitmap automatically. Then when you write it, it is encoding to a JPEG again (which loses quality).
Just replace ImageIO.write(image,"jpg",os) with ImageIO.write(image,"png",os) and you are done. A lossless format such as PNG will not lose any data when you write the image.
BufferedImage getRGB() will get you all the actual pixel data for the image. There will be no compression or anything like JPEG. It will be the raw image.
Edited to add an example based on my comments...
BufferedImage image = ImageIO.read(new File("google.jpg"));
ImageWriter w = ImageIO.getImageWritersBySuffix("jpg").next();
ImageOutputStream out = ImageIO.createImageOutputStream(new File("output.jpg"));
w.setOutput(out);
ImageWriteParam param = new JPEGImageWriteParam(Locale.getDefault());
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(1);
w.write(null, new IIOImage(image, null, null), param);
out.close();

Proper way of transporting files in the source code

I need to transport several files inside the source code. Horrible, I know, but I don't have any other option. So far I'm only storing images, so I do this:
Encoding the image:
Bitmap bm = BitmapFactory.decodeFile(imagePath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String encodedimage = Base64.encodeToString(b, Base64.DEFAULT);
Decoding the image:
public static Bitmap decodeBitmap(imageString) {
return BitmapFactory.decodeStream(new ByteArrayInputStream(Base64.decode(imageString, Base64.DEFAULT)));
}
I use base64 so that putting a new image in the program is easier because it's just a simple string.
Now I'm trying to expand the functionality to any file format so I seek guidance as to find out if there is less bad way of storing files inside code.
for images you should be using the resources folder. It's built into the system for that.
For general final you should use the asset folder and access just like shown on this stackoverflow question: How to get URI from an asset File?
If you want to keep some data files, you can keep them in Assets folders and you can use AssetManager to get the files.

Categories