Posted By

GunnarHKarlsson on 09/28/11


Tagged

image Flex mxml android reorientation


Versions (?)

Exif image reorientation in android


 / Published in: ActionScript 3
 

URL: http://blog.flexnroses.com/?p=95

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
  3. xmlns:s="library://ns.adobe.com/flex/spark" title="Get That Image" creationComplete="creationCompleteHandler(event)">
  4.  
  5. <fx:Script>
  6. <![CDATA[
  7. import com.flexnroses.mobile.utils.hardware.ExifUtils;
  8.  
  9. import jp.shichiseki.exif.ExifInfo;
  10. import jp.shichiseki.exif.ExifLoader;
  11.  
  12. import mx.events.FlexEvent;
  13. private var loader:Loader;
  14. private var cameraRoll:CameraRoll;
  15. private var exifLoader:ExifLoader;
  16. private var mediaPromise:MediaPromise;
  17.  
  18. protected function btnLoad_clickHandler(event:MouseEvent):void
  19. {
  20. cameraRoll.browseForImage();
  21. }
  22.  
  23. //1. instantiate CameraRoll and get its event handlers ready
  24. protected function creationCompleteHandler(event:FlexEvent):void
  25. {
  26. if( CameraRoll.supportsBrowseForImage )
  27. {
  28. loader = new Loader();
  29. loader.contentLoaderInfo.addEventListener( Event.COMPLETE, this.contentLoadedHandler );
  30.  
  31. cameraRoll = new CameraRoll();
  32. cameraRoll.addEventListener( MediaEvent.SELECT, this.mediaSelectHandler );
  33. cameraRoll.addEventListener( Event.CANCEL, errorHandler );
  34. }
  35. else
  36. {
  37. lbl.text = "Unable to access Camera Roll";
  38. }
  39. }
  40.  
  41.  
  42. //2. once CameraRoll is browsed and an image selected, find its Exif data
  43. private function mediaSelectHandler( event:MediaEvent ):void
  44. {
  45. mediaPromise = event.data;
  46. lbl.text = mediaPromise.file.url;
  47.  
  48. this.exifLoader = new ExifLoader();
  49. this.exifLoader.addEventListener(Event.COMPLETE, completeHandler );
  50. this.exifLoader.load( new URLRequest( mediaPromise.file.url ) );
  51. }
  52.  
  53. private function errorHandler( event:Event ):void
  54. {
  55.  
  56. }
  57.  
  58. //3. once Exif data is available, use loader to obviously load mediaPromised found in step 2
  59. private function completeHandler( event:Event ):void
  60. {
  61. loader.unload();
  62. loader.loadFilePromise( mediaPromise );
  63. }
  64.  
  65. //4. use exif data and access ExifUtils to get the image found appear eye oriented.
  66. private function contentLoadedHandler( event:Event ):void
  67. {
  68. var exif:ExifInfo = this.exifLoader.exif;
  69.  
  70. var rotation:int = ExifUtils.getEyeOrientedAngle( exif.ifds );
  71.  
  72. //i created a new bitmap, but otherwise, you could also make use of the line above and
  73. //distor the image in your own way.
  74. var bitmap:Bitmap = ExifUtils.getEyeOrientedBitmap( Bitmap( event.currentTarget.content ), exif.ifds );
  75. this.image.source = bitmap;
  76. }
  77. ]]>
  78. </fx:Script>
  79.  
  80. <fx:Declarations>
  81. <!-- Place non-visual elements (e.g., services, value objects) here -->
  82. </fx:Declarations>
  83.  
  84. <s:layout>
  85. <s:VerticalLayout gap="10" paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"/>
  86. </s:layout>
  87.  
  88. <s:Label id="lbl" text="select an image" />
  89.  
  90. <s:Image id="image" width="100%" height="100%" />
  91. <s:HGroup id="ftr" width="100%">
  92. <s:Button id="btnLoad" label="Load" width="100%" click="btnLoad_clickHandler(event)" />
  93. </s:HGroup>
  94. </s:View>
  95.  
  96. /////
  97.  
  98. package com.flexnroses.mobile.utils.hardware
  99. {
  100. import flash.display.Bitmap;
  101. import flash.display.BitmapData;
  102. import flash.geom.Matrix;
  103.  
  104. import jp.shichiseki.exif.IFDSet;
  105.  
  106. public class ExifUtils
  107. {
  108. public static const PORTRAIT:int = 6;
  109. public static const PORTRAIT_REVERSE:int = 8;
  110.  
  111. public static const LANDSCAPE:int = 1;
  112. public static const LANDSCAPE_REVERSE:int = 3;
  113.  
  114. /**
  115.   * function figures out the rotation needed so the image
  116.   * appears in the right view for the user
  117.   *
  118.   *
  119.   * @param ifd attribute in exif belonging to image
  120.   * @return the angle to rotate an image based on ifd information
  121.   * @see http://bit.ly/j70E7T
  122.   */
  123. public static function getEyeOrientedAngle( set:IFDSet ):int
  124. {
  125. var angle:int = 0;
  126.  
  127. if( set.primary[ "Orientation" ] )
  128. {
  129. switch( set.primary[ "Orientation" ] )
  130. {
  131. case LANDSCAPE: angle = 0; break;
  132. case LANDSCAPE_REVERSE: angle = 180; break;
  133. case PORTRAIT: angle = 90; break;
  134. case PORTRAIT_REVERSE: angle = -90; break;
  135. }
  136. }
  137.  
  138. return angle;
  139. }
  140.  
  141.  
  142. /**
  143.   * creates a bitmap appealing to the eye, so that based on provided original bitmap and its IFDSet
  144.   * it's possible to track the orientation and create a transformed bitmap copied from the original.
  145.   *
  146.   * @see <a href="http://www.psyked.co.uk/actionscript/rotating-bitmapdata.htm">rotating-bitmapdata.htm</a>
  147.   * @see <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/geom/Matrix.html">matrix documentation</a>
  148.   *
  149.   * @param bitmap retrieved after selecting an image from CameraRoll
  150.   * @param set retrieved after loading the Exif data from selected image
  151.   * @return a new bitmap in the right angle and same dimensions as the original.
  152.   *
  153.   */
  154. public static function getEyeOrientedBitmap( bitmap:Bitmap, set:IFDSet ):Bitmap
  155. {
  156. var m:Matrix = new Matrix();
  157. var orientation:int= set.primary[ "Orientation" ];
  158. var bitmapData:BitmapData;
  159.  
  160. if( orientation == LANDSCAPE || orientation == LANDSCAPE_REVERSE )
  161. {
  162. bitmapData = new BitmapData( bitmap.width, bitmap.height, true );
  163. }
  164. else
  165. {
  166. bitmapData = new BitmapData( bitmap.height, bitmap.width, true );
  167. }
  168.  
  169. m.rotate( getEyeOrientedAngle( set ) * ( Math.PI / 180 ) );
  170.  
  171. if( orientation == PORTRAIT_REVERSE )
  172. {
  173. m.translate( 0, bitmap.width );
  174. }
  175. else
  176. if( orientation == PORTRAIT )
  177. {
  178. m.translate( bitmap.height, 0 );
  179. }
  180. else
  181. if( orientation == LANDSCAPE_REVERSE )
  182. {
  183. m.translate( bitmap.width, bitmap.height );
  184. }
  185.  
  186. bitmapData.draw( bitmap, m );
  187.  
  188. return new Bitmap( bitmapData );
  189. }
  190. }
  191. }

Report this snippet  

You need to login to post a comment.