Introduction to Android Image Processing-image storage and metadata

Source: Internet
Author: User
Android provides content providers for data sharing between applications. providers provide standard interfaces for storing and retrieving various types of data. The standard content provider for images, audios, and videos is mediastore.

1) retrieve the image URI

To obtain a standard image storage path, we need to obtain mediastore reference, which is implemented through content resolver (because content resolver can be used to obtain the content provider, mediastore is a content provider ).

Pass the specified URI to the content resolver to obtain the corresponding content provider. Because an image is added, the insert method is used and the corresponding URI is Android. provider. mediastore. images. the constant external_content_uri defined by the media class. This constant indicates that the image is stored in the primary external memory, usually the SD card. If you want to store the image in the device memory, use internal_content_uri. Of course, because the sizes of media files are generally large, external_content_uri is preferred.

The insert function of the content resolver class returns the URI type:

Uri imagefileuri = getcontentresolver (). insert (<br/> media. external_content_uri, new contentvalues (); <br/> // start the camera app <br/> intent it = new intent (Android. provider. mediastore. action_image_capture); <br/> it. putextra (Android. provider. mediastore. extra_output, imagefileuri); <br/> startactivityforresult (it, camera_result );

The contentvalues object in the code above is the metadata to be associated when the captured image is created. Of course, the metadata above is empty. We can use the put function to write metadata to contentvalues. contentvalues stores data in the form of key-value pairs, and the key name is defined in Android. provider. mediastore. images. constants in the media class:

// Save the name and description of an image in a contentvalues Map <br/> contentvalues = new contentvalues (3); <br/> contentvalues. put (media. display_name, "asce1885_title"); <br/> contentvalues. put (media. description, "asce1885_description"); <br/> contentvalues. put (media. mime_type, "image/JPEG"); </P> <p> // Add a new recode without the bitmap, but with some values set. <br/> // insert () returns the URI of the new record <br/> URI imagefileuri = getcontentresolver (). insert (media. external_content_uri, contentvalues );

The URI obtained above may be similar:

Content: // media/external/images/Media/16

It is noted that Uris starting with content are generally used by the content provider. For example, the URI above is used by mediastore.

In turn, based on Uri, we can use this URI to retrieve the image data in the corresponding path. The Code is as follows:

Bitmap BMP = bitmapfactory. decodestream (getcontentresolver (). openinputstream (imagefileuri), null, BMP factory); </P> <p>

After the captured image is stored in mediastore, you can use the contentresolver update function to add metadata information:

// Update the mediastore record with title and description <br/> contentvalues = new contentvalues (3); <br/> contentvalues. put (media. display_name, "wen1885_title"); <br/> contentvalues. put (media. description, "wen1885_description"); <br/> getcontentresolver (). update (imagefileuri, contentvalues, null, null );

The complete code example is as follows. First look at the layout/Main. xml file:

<? XML version = "1.0" encoding = "UTF-8"?> <Br/> <linearlayout xmlns: Android = "http://schemas.android.com/apk/res/android" <br/> Android: Orientation = "vertical" <br/> Android: layout_width = "fill_parent" <br/> Android: layout_height = "fill_parent" <br/> <imageview <br/> Android: id = "@ + ID/returnedimageview" <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content"/> <br/> <textview <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content" <br/> Android: text = "title:" <br/> Android: id = "@ + ID/titletextview"/> <br/> <edittext <br/> Android: layout_width = "fill_parent" <br/> Android: layout_height = "wrap_content" <br/> Android: Id = "@ + ID/titleedittext"/> <br/> <textview <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content" <br/> Android: text = "Description" <br/> Android: id = "@ + ID/descriptiontextview"/> <br/> <edittext <br/> Android: layout_width = "fill_parent" <br/> Android: layout_height = "wrap_content" <br/> Android: Id = "@ + ID/descriptionedittext"/> <br/> <button <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content" <br/> Android: Id = "@ + ID/takepicturebutton" <br/> Android: TEXT = "take picture"/> <br/> <button <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content" <br/> Android: Id = "@ + ID/savedatabutton" <br/> Android: TEXT = "save data"/> <br/> </linearlayout>

The complete Java code is as follows:

Package HUST. iprai. asce1885.promedia; </P> <p> Import Java. io. filenotfoundexception; </P> <p> Import android. app. activity; <br/> Import android. content. contentvalues; <br/> Import android. content. intent; <br/> Import android. graphics. bitmap; <br/> Import android. graphics. bitmapfactory; <br/> Import android.net. uri; <br/> Import android. OS. bundle; <br/> Import android. provider. mediastore. images. media; <br/> Import android. util. log; <br/> Import android. view. view; <br/> Import android. view. view. onclicklistener; <br/> Import android. widget. button; <br/> Import android. widget. edittext; <br/> Import android. widget. imageview; <br/> Import android. widget. textview; <br/> Import android. widget. toast; </P> <p> public class mediastorecameraactivity extends activity {<br/> final static int camera_result = 0; </P> <p> URI imagefileuri = NULL; </P> <p> // user interface elements, specified in RES/layout/main. XML <br/> imageview returnedimageview; <br/> button takepicturebutton; <br/> button savedatabutton; <br/> textview titletextview; <br/> textview descriptiontextview; <br/> edittext titleedittext; <br/> edittext descriptionedittext; </P> <p> @ override <br/> protected void oncreate (bundle savedinstancestate) {<br/> super. oncreate (savedinstancestate); </P> <p> // set the content view to be what is defined in the Res/layout/main. XML file <br/> setcontentview (R. layout. main); </P> <p> // get references to UI elements <br/> returnedimageview = (imageview) findviewbyid (R. id. returnedimageview); <br/> takepicturebutton = (button) findviewbyid (R. id. takepicturebutton); <br/> savedatabutton = (button) findviewbyid (R. id. savedatabutton); <br/> titletextview = (textview) findviewbyid (R. id. titletextview); <br/> descriptiontextview = (textview) findviewbyid (R. id. descriptiontextview); <br/> titleedittext = (edittext) findviewbyid (R. id. titleedittext); <br/> descriptionedittext = (edittext) findviewbyid (R. id. descriptionedittext); </P> <p> // set all parameters T takepicturebutton to not be visible initially <br/> // view. gone is invisible and doesn' t take up space in the layout <br/> returnedimageview. setvisibility (view. gone); <br/> savedatabutton. setvisibility (view. gone); <br/> titletextview. setvisibility (view. gone); <br/> descriptiontextview. setvisibility (view. gone); <br/> titleedittext. setvisibility (view. gone); <br/> descriptionedittext. setvisibility (view. gone); </P> <p> // when the take picture button is clicked <br/> takepicturebutton. setonclicklistener (New onclicklistener () {</P> <p> Public void onclick (view V) {<br/> // Add a new record without the bitmap <br/> // return the URI of the new record <br/> imagefileuri = getcontentresolver (). insert (<br/> media. external_content_uri, new contentvalues (); <br/> // start the camera app <br/> intent it = new intent (Android. provider. mediastore. action_image_capture); <br/> it. putextra (Android. provider. mediastore. extra_output, imagefileuri); <br/> startactivityforresult (it, camera_result); <br/>}</P> <p >}); </P> <p> savedatabutton. setonclicklistener (New onclicklistener () {</P> <p> Public void onclick (view V) {<br/> // update the mediastore record with title and description <br/> contentvalues = new contentvalues (3); <br/> contentvalues. put (media. display_name, titleedittext. gettext (). tostring (); <br/> contentvalues. put (media. description, descriptionedittext. gettext (). tostring (); <br/> getcontentresolver (). update (imagefileuri, contentvalues, null, null); </P> <p> // tell the user <br/> toast bread = toast. maketext (mediastorecameraactivity. this, "record updated", toast. length_long); <br/> bread. show (); </P> <p> // go back to the initial state, set take picture button visible <br/> // hide other UI elements <br/> takepicturebutton. setvisibility (view. visible); <br/> returnedimageview. setvisibility (view. gone); <br/> titletextview. setvisibility (view. gone); <br/> descriptiontextview. setvisibility (view. gone); <br/> titleedittext. setvisibility (view. gone); <br/> descriptionedittext. setvisibility (view. gone); <br/>}</P> <p> }); <br/>}</P> <p> @ override <br/> protected void onactivityresult (INT requestcode, int resultcode, intent data) {<br/> super. onactivityresult (requestcode, resultcode, data); </P> <p> If (result_ OK = resultcode) {<br/> // The Camera app has returned <br/> // hide the take picture button <br/> takepicturebutton. setvisibility (view. gone); </P> <p> // show the other UI elements <br/> savedatabutton. setvisibility (view. visible); <br/> returnedimageview. setvisibility (view. visible); <br/> titletextview. setvisibility (view. visible); <br/> descriptiontextview. setvisibility (view. visible); <br/> titleedittext. setvisibility (view. visible); <br/> descriptionedittext. setvisibility (view. visible); </P> <p> // scale the image <br/> int DW = 200; // make it at most 200 pixels wide <br/> int DH = 200; // make it at most 200 pixels tall </P> <p> bitmapfactory. options BMP factoryoptions = new bitmapfactory. options (); <br/> BMP factoryoptions. injustdecodebounds = true; <br/> bitmap BMP = NULL; <br/> try {<br/> BMP = bitmapfactory. decodestream (<br/> getcontentresolver (). openinputstream (imagefileuri), null, BMP factoryoptions); <br/>}catch (filenotfoundexception e) {<br/> E. printstacktrace (); <br/>}< br/> int heightratio = (INT) math. ceil (BMP factoryoptions. outheight/(float) DH); <br/> int widthratio = (INT) math. ceil (BMP factoryoptions. outwidth/(float) dw); </P> <p> log. V ("heightratio", "" + heightratio); <br/> log. V ("widthratio", "" + widthratio ); </P> <p> // if both of the ratios are greater than 1 <br/> // one of the sides of the image is greater than the screen <br/> if (heightratio> 1) & (widthratio> 1) {<br/> If (heightratio> widthratio) {<br/> // height ratio is larger, scale according to it <br/> BMP factoryoptions. insamplesize = heightratio; <br/>}else {<br/> // width ratio is larger, scale according to it <br/> BMP factoryoptions. insamplesize = widthratio; <br/>}</P> <p> // decode it for real <br/> BMP factoryoptions. injustdecodebounds = false; <br/> try {<br/> BMP = bitmapfactory. decodestream (<br/> getcontentresolver (). openinputstream (imagefileuri), null, BMP factoryoptions); <br/>}catch (filenotfoundexception e) {<br/> E. printstacktrace (); <br/> log. V ("error", E. tostring (); <br/>}</P> <p> // display it <br/> returnedimageview. setimagebitmap (BMP); <br/>}< br/>}

2) use mediastore to retrieve image data

Mediastore, like all content providers, uses database operations to retrieve data. Select a data record from the specified Uri, and then use the cursor object to iterate the result.

First, you must create a string array to indicate the type of the column to be returned. The standard column type of image data in mediastore. Images. media class is:

String [] Columns = <br/> {media. Data, media. _ id, media. Title, media. display_name };

Execute the actual query operation using the managedquery function of activity. The first parameter is Uri, the second parameter is a string array composed of column names, and the third parameter is the where statement, the following parameters are the where parameters, and the last parameter is the order by statement:

Long onehourago = system. currenttimemillis ()/1000-(60*60); <br/> string [] wherevalues = {"" + onehourago }; <br/> // specify the column of the returned result <br/> string [] Columns = {media. data, media. _ id, media. title, media. display_name, media. date_added }; <br/> // obtain the cursor <br/> cursor = managedquery (media. external_content_uri, columns, media. date_added + ">? ", Wherevalues, media. date_added + "ASC"); <br/> // returns the index of the specified column <br/> int displaycolumnindex = cursor. getcolumnindexorthrow (mediastore. images. media. data); <br/> // move to the beginning of the cursor <br/> If (cursor. movetofirst () {<br/> string displayname = cursor. getstring (displaycolumnindex); <br/>}

The complete example is as follows:

<? XML version = "1.0" encoding = "UTF-8"?> <Br/> <linearlayout xmlns: Android = "http://schemas.android.com/apk/res/android" <br/> Android: Orientation = "vertical" <br/> Android: layout_width = "fill_parent" <br/> Android: layout_height = "fill_parent" <br/> <imagebutton <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content" <br/> Android: id = "@ + ID/imagebutton"/> <br/> <textview <br/> Android: layout_width = "fill_parent" <br/> Android: layout_height = "wrap_content" <br/> Android: Id = "@ + ID/titletextview" <br/> Android: TEXT = "image title"/> <br/> </linearlayout>

The Java code is as follows:

Package HUST. iprai. asce1885.promedia; </P> <p> Import android. app. activity; <br/> Import android. database. cursor; <br/> Import android. graphics. bitmap; <br/> Import android. graphics. bitmapfactory; <br/> Import android. OS. bundle; <br/> Import android. provider. mediastore; <br/> Import android. provider. mediastore. images. media; <br/> Import android. util. log; <br/> Import android. view. view; <br/> Import android. view. view. onclicklistener; <br/> Import android. widget. imagebutton; <br/> Import android. widget. textview; </P> <p> public class mediastoregallery extends activity {</P> <p> Public final static int displaywidth = 200; <br/> Public final static int displayheight = 200; </P> <p> textview titletextview; <br/> imagebutton; </P> <p> cursor; <br/> bitmap BMP; <br/> string imagefilepath; <br/> int filecolumn; <br/> int titlecolumn; <br/> int displaycolumn; </P> <p> @ override <br/> protected void oncreate (bundle savedinstancestate) {<br/> super. oncreate (savedinstancestate); <br/> setcontentview (R. layout. main); </P> <p> titletextview = (textview) findviewbyid (R. id. titletextview); <br/> imagebutton = (imagebutton) findviewbyid (R. id. imagebutton); </P> <p> string [] Columns = {media. data, media. _ id, media. title, media. display_name }; <br/> cursor = managedquery (media. external_content_uri, columns, null); </P> <p> // Note: media. data is mediastore. images. media. data abbreviation <br/> filecolumn = cursor. getcolumnindexorthrow (mediastore. images. media. data); <br/> titlecolumn = cursor. getcolumnindexorthrow (mediastore. images. media. title); <br/> displaycolumn = cursor. getcolumnindexorthrow (mediastore. images. media. display_name); </P> <p> If (cursor. movetofirst () {<br/> titletextview. settext (cursor. getstring (titlecolumn); </P> <p> imagefilepath = cursor. getstring (filecolumn); <br/> BMP = getbitmap (imagefilepath); </P> <p> // display it <br/> imagebutton. setimagebitmap (BMP); <br/>}</P> <p> imagebutton. setonclicklistener (New onclicklistener () {</P> <p> Public void onclick (view v) {<br/> If (cursor. movetonext () {<br/> titletextview. settext (cursor. getstring (displaycolumn); </P> <p> imagefilepath = cursor. getstring (filecolumn); <br/> BMP = getbitmap (imagefilepath); <br/> imagebutton. setimagebitmap (BMP); <br/>}</P> <p> }); <br/>}</P> <p> private bitmap getbitmap (string imagefilepath) {<br/> // load up the image's dimensions not the image itself <br/> bitmapfactory. options BMP factoryoptions = new bitmapfactory. options (); <br/> BMP factoryoptions. injustdecodebounds = true; <br/> bitmap BMP = bitmapfactory. decodefile (imagefilepath, BMP factoryoptions); </P> <p> int heightratio = (INT) math. ceil (BMP factoryoptions. outheight/(float) displayheight); <br/> int widthratio = (INT) math. ceil (BMP factoryoptions. outwidth/(float) displaywidth); </P> <p> log. V ("heightratio", "" + heightratio); <br/> log. V ("widthratio", "" + widthratio); </P> <p> // if both of the ratios are greater than 1, one of the sides of <br/> // The image is greater than the screen <br/> If (heightratio> 1) & (widthratio> 1 )) {<br/> If (heightratio> widthratio) {<br/> BMP factoryoptions. insamplesize = heightratio; <br/>}else {<br/> BMP factoryoptions. insamplesize = widthratio; <br/>}</P> <p> // decode it for real <br/> BMP factoryoptions. injustdecodebounds = false; <br/> BMP = bitmapfactory. decodefile (imagefilepath, BMP factoryoptions); </P> <p> return BMP; <br/>}< br/>}

2) Internal metadata

EXIF, an exchangeable image file format, is a standard format for storing metadata in an image file. Its data storage is exactly the same as the JPEG format. It inserts the digital photo recording information in the JPEG format header.

EXIF data contains many technical parameters closely related to image shooting, such as the exposure time exposuretime and shutter speed shutterspeedvalue. Some parameters can be filled or modified later, for example:

Usercomment: User comment

Imagedescription: Image Description

Artist: the creator or photographer of the image.

Copyright: Copyright

Software: software used to create images

Android provides a convenient interface exifinterface to read and write EXIF data:

Exifinterface Ei = new exifinterface (imagefilepath); <br/> string imagedescription = ei. getattribute ("imagedescription"); <br/> If (null! = Imagedescription) {<br/> log. V ("EXIF", imagedescription); <br/>}

The code snippet used to save the EXIF data to the image file is as follows:

Exifinterface Ei = new exifinterface (imagefilepath); <br/> ei. setattribute ("imagedescription", "asce1885 ");

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.