2013-02-20 66 views
0

我在Flash Builder中構建了一個包含actionscript 3.0的應用程序。這是this question的後續問題,它可以工作,但是當我拍攝照片時,圖像旋轉到左側。我如何檢查用戶拿着手機的方式?然後用什麼代碼將圖像旋轉到相應的位置?如何從ActionScript 3.0中的cameraUI for iOS旋轉圖像

感謝先進!

編輯: 我使用這個代碼,以旋轉圖像,但它似乎只旋轉所顯示的圖像文件的圖像,任何想法?

var mat:Matrix = new Matrix(); 
mat.translate(-W/2, -H/2); 
mat.rotate(Math.PI/2); 
mat.translate(+W/2, +H/2); 
mat.concat(myObj.transform.matrix); 
myObj.transform.matrix = mat; 

〜MYY

回答

1

您可以使用Stage.deviceOrientationStage.orientation *,以確定哪種方式輪手機。

*如果這個iOS上

的工作原理是它的BitmapData結果本身要旋轉(即創建一個旋轉的圖像,一個新的BitmapData),或者只是顯示列表上的位圖旋轉不知道?

編輯:

好的,繼承人一些代碼旋轉BitmapData對象:

function rotateBitmapData(angle:int, source:BitmapData):BitmapData 
{ 
    var newWidth:int = source.rect.width; 
    var newHeight:int = source.rect.height; 
    if (angle==90 || angle==270) 
    { 
     newWidth = source.rect.height; 
     newHeight = source.rect.width; 
    } 
    var newBmd:BitmapData = new BitmapData(newWidth, newHeight, source.transparent); 
    var tx:Number = 0; 
    var ty:Number = 0; 
    if (angle==90 || angle==180) 
    { 
     tx = newWidth; 
} 
    if (angle==180 || angle==270) 
    { 
     ty = newHeight; 
    } 
    var matrix:Matrix = new Matrix(); 
    matrix.createBox(1, 1, Math.PI*angle/180, tx, ty); 
    newBmd.draw(source, matrix); 
    return newBmd; 
} 

角度應0,90,180或270將返回由指定的角度旋轉的新的BitmapData對象。

+0

的數據,我想旋轉的數據,我編輯的代碼,旋轉圖像和它的作品,但只有在顯示,我真的需要它旋轉文件(數據) – Myy 2013-02-20 18:28:08

+0

好的。添加了一些代碼來旋轉BitmapData – 2013-02-20 18:59:04

+0

hey Lee,非常感謝這些信息,我發佈了其餘的代碼,將其更改爲byteArray,但是從bitmapData到byteArray的轉換需要一點點時間。你知道更快更有效的方法來實現嗎? – Myy 2013-02-21 17:13:06

0

您可以使用StageOrientationEvent.ORIENTATION_CHANGING事件:

stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, OrientationChangeHandler); 

private function OrientationChangeHandler(e:StageOrientationEvent):void 
     { 
      switch (e.afterOrientation) 
      { 


       case StageOrientation.DEFAULT : 

       break; 
      case StageOrientation.ROTATED_RIGHT : 

       break; 
      case StageOrientation.ROTATED_LEFT : 

       break; 
      case StageOrientation.UPSIDE_DOWN : 

       break; 
      } 
     } 

這可以幫助你。

+0

嗨Vipul,謝謝你的回答,但我似乎無法進入switch語句。我試圖用我在問題的編輯部分發布的代碼來旋轉它,但它似乎只適用於顯示中的圖像,而不是文件(這正是我真正想要的) – Myy 2013-02-20 08:11:08

1

當cameraUI視圖處於活動狀態時,您無法獲得stage.orientation數據,所以我在這裏解釋了同樣的問題,請注意,此控制器具有許多可重用功能,我首先從媒體承諾中獲取原始圖像數據原始數據具有EXIF數據,我將讀取以從相機獲取圖像方向)然後,將此byteArray轉換爲BitmapData,然後根據需要調整大小和縮放比例。有一點需要注意的是,如果將原始圖像數據轉換爲位圖數據,您將失去EXIF數據,因此請在修改圖像之前先閱讀它,希望這有助於我將它發佈到此處,但我知道但在網絡中沒有其他解決方案,也許有人會需要這個時間。乾杯

SnapshotController.as

package controllers 
{ 

    import flash.display.BitmapData; 
    import flash.display.JPEGEncoderOptions; 
    import flash.display.Loader; 
    import flash.display.LoaderInfo; 
    import flash.display.Sprite; 
    import flash.events.Event; 
    import flash.events.IEventDispatcher; 
    import flash.events.MediaEvent; 
    import flash.filesystem.File; 
    import flash.filesystem.FileMode; 
    import flash.filesystem.FileStream; 
    import flash.geom.Matrix; 
    import flash.geom.Rectangle; 
    import flash.media.CameraUI; 
    import flash.media.MediaPromise; 
    import flash.media.MediaType; 
    import flash.utils.ByteArray; 
    import flash.utils.IDataInput; 

    import mx.utils.Base64Encoder; 

    import classes.APIupload; 


    public class SnapshotController 
    { 
     private var cameraUI:CameraUI = new CameraUI(); 
     private var dataSource:IDataInput; 
     private var tempDir:File = new File(); 
     private var imageOrientation:int = 0 ; 


     public function SnapshotController() 
     { 

     } 

     public function LaunchCameraUI():void 
     { 

      if(CameraUI.isSupported) { 
       trace("Initializing camera..."); 
       cameraUI.addEventListener(MediaEvent.COMPLETE, imageSelected); 
       cameraUI.launch(MediaType.IMAGE); 
      } else { 
       trace("CameraUI is not supported."); 
      } 
     } 

     private function imageSelected(event:MediaEvent):void { 
      trace("Media selected..."); 
      var imagePromise:MediaPromise = event.data; 


      dataSource = imagePromise.open(); 
      if(imagePromise.isAsync) { 
       trace("Asynchronous media promise."); 
       var eventSource:IEventDispatcher = dataSource as IEventDispatcher; 
       eventSource.addEventListener(Event.COMPLETE, onMediaLoaded); 
      } else { 
       trace("Synchronous media promise."); 
       readMediaData(); 
      } 
     } 
     private function onMediaLoaded(event:Event):void { 
      trace("Media load complete"); 
      readMediaData(); 
     } 

     private function readMediaData():void { 
      var imageBytes:ByteArray = new ByteArray(); 
      dataSource.readBytes(imageBytes); 

      imageOrientation = getOrientation(imageBytes); 

      //saveImageFile(imageBytes); 
      //Saving this byteArray will save a big file with the EXIF in it. 

      var loader:Loader = new Loader(); 
      loader.contentLoaderInfo.addEventListener(Event.INIT, onMediaPromiseLoaded); 
      loader.loadBytes(imageBytes); 

     } 


     private function onMediaPromiseLoaded(e:Event):void 
     { 
      trace("Media file loaded"); 
      var base64Enc:Base64Encoder = new Base64Encoder(); 
      var mpLoaderInfo:LoaderInfo = e.target as LoaderInfo; 
      mpLoaderInfo.removeEventListener(Event.COMPLETE, onMediaPromiseLoaded); 

      var scale:Number = 0.25; 
      var matrix:Matrix = new Matrix(); 
      matrix.scale(scale, scale); 


      var jpgQuality:int = 80; 


      var bmd:BitmapData = new BitmapData(mpLoaderInfo.width*scale, mpLoaderInfo.height*scale); 
      bmd.draw(mpLoaderInfo.content,matrix,null,null,null,true); 

      var rotatedBMD:BitmapData = rotateBitmapData(bmd, imageOrientation); 
      var bytes:ByteArray = rotatedBMD.encode(new Rectangle(0,0, rotatedBMD.width , rotatedBMD.height), new JPEGEncoderOptions(jpgQuality), bytes); 




      saveImageFile(bytes); //this is the smaller file saved. it does not have EXIF data but you can write your own using AS3 eXIF class. 

     } 

     private function rotateBitmapData(bitmapData:BitmapData, degree:int = 0) :BitmapData 
     { 
      var newBitmap:BitmapData; 
      var matrix:Matrix = new Matrix(); 
      matrix.rotate(degree * (Math.PI/180) ); 

      if (degree == 90) { 
       newBitmap = new BitmapData(bitmapData.height, bitmapData.width, true); 
       matrix.translate(bitmapData.height, 0); 
      } else if (degree == -90 || degree == 270) { 
       newBitmap = new BitmapData(bitmapData.height, bitmapData.width, true); 
       matrix.translate(0, bitmapData.width); 
      } else if (degree == 180) { 
       newBitmap = new BitmapData(bitmapData.width, bitmapData.height, true); 
       matrix.translate(bitmapData.width, bitmapData.height); 
      }else if(degree == 0){ 
       newBitmap = new BitmapData(bitmapData.width, bitmapData.height, true); 
       //matrix.translate(bitmapData.width, bitmapData.height); 
      } 

      newBitmap.draw(bitmapData, matrix, null, null, null, true) 
      return newBitmap; 
     } 

     private function saveImageFile(ba:ByteArray):void{ 
      var now:Date = new Date(); 
      var filename:String = "IMG" + now.fullYear + now.month + now.day + now.hours + now.minutes + now.seconds + ".jpg"; 
      var temp:File = File.documentsDirectory.resolvePath(filename); 
      var stream:FileStream = new FileStream(); 
      stream.open(temp, FileMode.WRITE); 
      stream.writeBytes(ba); 
      stream.close(); 
     } 



     private function getOrientation(jpeg:ByteArray):int{ 
      if (jpeg == null) { 
       return 0; 
      } 
      var offset:int = 0; 
      var length:int = 0; 


      while (offset + 3 < jpeg.length && (jpeg[offset++] & 0xFF) == 0xFF) { 
       var marker:int = jpeg[offset] & 0xFF; 

       // Check if the marker is a padding. 
       if (marker == 0xFF) { 
        continue; 
       } 
       offset++; 

       // Check if the marker is SOI or TEM. 
       if (marker == 0xD8 || marker == 0x01) { 
        continue; 
       } 
       // Check if the marker is EOI or SOS. 
       if (marker == 0xD9 || marker == 0xDA) { 
        break; 
       } 

       // Get the length and check if it is reasonable. 
       length = pack(jpeg, offset, 2, false); 
       if (length < 2 || offset + length > jpeg.length) { 
        trace("Invalid length"); 
        return 0; 
       } 

       // Break if the marker is EXIF in APP1. 
       if (marker == 0xE1 && length >= 8 && 
        pack(jpeg, offset + 2, 4, false) == 0x45786966 && 
        pack(jpeg, offset + 6, 2, false) == 0) { 
        offset += 8; 
        length -= 8; 
        break; 
       } 

       // Skip other markers. 
       offset += length; 
       length = 0; 
      } 

      if (length > 8) { 
       // Identify the byte order. 
       var tag:int = pack(jpeg, offset, 4, false); 
       if (tag != 0x49492A00 && tag != 0x4D4D002A) { 
        trace("Invalid byte order"); 
        return 0; 
       } 
       var littleEndian:Boolean = (tag == 0x49492A00); 

       // Get the offset and check if it is reasonable. 
       var count:int = pack(jpeg, offset + 4, 4, littleEndian) + 2; 
       if (count < 10 || count > length) { 
        trace("Invalid offset"); 
        return 0; 
       } 
       offset += count; 
       length -= count; 

       // Get the count and go through all the elements. 
       count = pack(jpeg, offset - 2, 2, littleEndian); 
       while (count-- > 0 && length >= 12) { 
        // Get the tag and check if it is orientation. 
        tag = pack(jpeg, offset, 2, littleEndian); 
        if (tag == 0x0112) { 
         // We do not really care about type and count, do we? 
         var orientation:int = pack(jpeg, offset + 8, 2, littleEndian); 
         switch (orientation) { 
          case 1: 
           return 0; 
          case 3: 
           return 180; 
          case 6: 
           return 90; 
          case 8: 
           return 270; 
         } 
         trace("Unsupported orientation"); 
         return 0; 
        } 
        offset += 12; 
        length -= 12; 
       } 
      } 

      trace("Orientation not found"); 
      return 0; 

     } 

     private function pack(bytes:ByteArray,offset:int,length:int, 
           littleEndian:Boolean):int { 
      var step:int = 1; 
      if (littleEndian) { 
       offset += length - 1; 
       step = -1; 
      } 

      var value:int = 0; 
      while (length-- > 0) { 
       value = (value << 8) | (bytes[offset] & 0xFF); 
       offset += step; 
      } 
      return value; 
     } 

    } 
}