How to attach EXIF metadata to a serialized Bitmap in Android? - android

In Android, when decoding a Bitmap from a photo on the phone, the EXIF data in the original gets lost. I am sending this Bitmap to my server via a socket and would like to re-attach the missing EXIF data to the data being sent.
I have some code that loads a Bitmap object from the MediaStore and compresses it to a byte array in preparation to send it over a socket:
Bitmap bitmap = ...
ByteArrayOutputStream stream = new ByteArrayOutputStream(bitmap);
bitmap.compress(CompressFormat.JPEG, 70, stream);
byte[] input = stream.toByteArray();
I want to use the ExifInterface to get at the EXIF metadata in the original jpeg on the SD card and somehow add that to the outgoing byte array in a way that I'd be able to extract a jpeg with all the correct EXIF on the server side (hopefully without doing this on the server). So far, I managed to use the ExifInterface to read all EXIF data:
String path = ... //bitmap file path
ExifInterface exif = new ExifInterface(path);
... = exif.getAttribute(...)
EDIT: Optimally, I'd like to find a solution that uses no libraries. If I could just get the indices of the byte array of the original jpeg that contain the EXIF and prepend/append these bytes to the byte array produced by bitmap.compress(...) that would be best.

Thanks to #Nick Campion and Sanselan.
Working code:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 100, bos); //Bitmap object is your image
byte[] data = bos.toByteArray();
TiffOutputSet outputSet = null;
IImageMetadata metadata = Sanselan.getMetadata(new File(filepath)); // filepath is the path to your image file stored in SD card (which contains exif info)
JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
if (null != jpegMetadata)
{
TiffImageMetadata exif = jpegMetadata.getExif();
if (null != exif)
{
outputSet = exif.getOutputSet();
}
}
if (null != outputSet)
{
bos.flush();
bos.close();
bos = new ByteArrayOutputStream();
ExifRewriter ER = new ExifRewriter();
ER.updateExifMetadataLossless(data, bos, outputSet);
data = bos.toByteArray(); //Update you Byte array, Now it contains exif information!
}

Related

Compare size of file and size of byte array of that file

When we convert the file (say - image)
To byteArray how can be approximately compared between them (image file and byteArray) ?
Is there also a way to first convert image file to byteArray and this byteArray has to be written in a text-file..
Again after this read these lines of byteArray from text-file and make byteArray and hence converted to image file...... I'm beginner and just for knowledge purpose i want to know....
You can convert your image to byte array like this.
BufferedImage bImage = ImageIO.read(new File("sample.jpg"));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(bImage, "jpg", bos );
byte [] data = bos.toByteArray();
Yes you can directly compare 2 byteArray.
Just do something like
if (bytearray1.length == bytearray2.length)
//its same
Try this to write the ByteArray in text file
public void writeToFile(byte[] array)
{
try
{
String path = "/data/data/YOURFILE.txt"; //provide your path here
File file = new File(path);
if (!file.exists()) { //just to check if file is actually present
file.createNewFile();
}
FileOutputStream stream = new FileOutputStream(path);
stream.write(array);
} catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
}

Why is my BitmapFactory.decodeByteArray returning null?

I am trying to convert an image stored in Database in Base64 format, to a Bitmap to be used in an Imageview.
So, I store it in SQLite this way:
Bitmap imageBitmap = (Bitmap) extras.get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap fotoGrande=(Bitmap) extras.get("data");
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
//I am adding some data to EXIF here, add to an static ArrayList<Bitmap> in other class and I store it this way:
int bytes=listaFotos.get(i).getFoto().getByteCount();
ByteBuffer buffer = ByteBuffer.allocate(bytes);
listaFotos.get(i).getFoto().copyPixelsToBuffer(buffer);
values.put("foto", Base64.encodeToString(buffer.array(), Base64.DEFAULT));
Later, i need to get that image to fit it in an ImageView:
String foto = csr2.getString(0);//csr2 is a cursor
byte[] arrayFoto = Base64.decode(foto, Base64.DEFAULT);//This is not null
Bitmap fotoBitmap = BitmapFactory.decodeByteArray(arrayFoto, 0, arrayFoto.length);//This is null
I know there are tons of questions about this. I searched, but no answer fix my problem.
Why is my BitmapFactory.decodeByteArray returning null? What I am doing wrong? Any help?
Thank you.
Turned out to be a database issue. SQLite gives you a cursor of 1MB MAX size. I was getting the bytes from database, with a 1MB cursor, the pic was not sent properly.
To fix it, I stored the path to the photo in database instead of the bytes.
firstly image is convert in Bitmap to String like this
ByteArrayOutputStream stream = new ByteArrayOutputStream();
camera.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte imageInByte[] = stream.toByteArray();
String encodedImage = Base64.encodeToString(imageInByte, Base64.DEFAULT);
where camera is a Bitmap.
and store the String encodedImage in database
And getImage string like this
byte[] b = Base64.decode(encodedImage , Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);

Storing Image in VCard and reading from it in android code manually

I am creating vCard files from my android app.
I am storing data manually(without using any libray)
I am able to write the data,read and parse it in my app.But when I save Image .I have gor two issues.
1)I am not able to save the image captured using camera..which throws an Out of memoery exception while writing the base 64 encoded string into vcard.
2)I am able to save the base 64 encoded string of some image which I took from gallery,but while reading it doesn't get me image.I am reding all the data from vCard line by line and base64 encoded string is not coming as a single line.(Please note that I stored each value to the file using \r\n)
Please let me know the proper way of doing this.
Code Snippets
Encoding
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
encodedProfileImage = Base64.encodeToString(byteArray, Base64.DEFAULT);
Writing
fw = new FileWriter(vcfFile);
...
fw.write("PHOTO;ENCODING=BASE64;TYPE=PNG:"+encodedProfileImage + "\r\n");
Reading and decoding
else if(strline[0].equals("PHOTO;ENCODING=BASE64;TYPE=PNG")){
String imagestr=strline[1];
byte[] byteArray = Base64.decode(imagestr, Base64.DEFAULT);
card.profileImage = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
}
When reading it in you can use BitmapFactory.Options
http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html
Use the decodeByteArray call that takes BitmapFactory.Options as the last argument.
if you set inSampleSize = 2
It will reduce the size of the incoming image to something managable.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2; //Scale it down
options.inPreferredConfig = Bitmap.Config.RBG_565; // Less memory

ImageView data to Byte Array Android

I am trying to use parse.com database to upload file and syntax needs me to use byte []. I will write syntax below:
byte[] data = "Working at Parse is great!".getBytes();
ParseFile file = new ParseFile("resume.png", data);
file.saveInBackground();
ParseObject jobApplication = new ParseObject("JobApplication");
jobApplication.put("applicantResumeFile", file);
jobApplication.saveInBackground();
I need to know how to use the first instruction to get ImageView Data in byte[] and upload it.
#wisejoy I have an implementation but I think its a little bit different... hope it can help you... cheers!!
myBitmap = (Bitmap) data.getExtras().get("data");//here I set an image taken by the camera
imageView.setImageBitmap(myBitmap);//I set it into an image view
imageView.buildDrawingCache();
ByteArrayOutputStream baos = new ByteArrayOutputStream();//and then I convert that image into a byteArray
myBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
encondedImage = android.util.Base64.encodeToString(b, Base64.DEFAULT);
Log.e(TAG, "" + txt);

Bitmap - compare contact picture with picture on sd card

I want to check, if the current user picture of a contact is the same as the one on the sd card...
I set the user picture like following:
byte[] photo = ImageFunctions.convertImageToByteArray(bitmap);
ContentValues values = new ContentValues();
....
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, photo);
...
And I read the image like following:
InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(
contentResolver,
ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, mId),
fullsize);
if (inputStream != null)
return BitmapFactory.decodeStream(inputStream);
And my convert function is following:
public static byte[] convertImageToByteArray(Bitmap bitmap)
{
ByteArrayOutputStream streamy = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 100, streamy);
return streamy.toByteArray();
}
And I use a md5 hash on the byte array of the bitmap to find changes... Actually, the images are not exactly the same.
What can I do, so that I compare the hash codes? It seems, like compression or whatever is not exactly the same, so the md5 hash check fails...

Categories

Resources