2013-10-13 6 views
2

Android 액티비티를 제공하는 앱이 있습니다. 내 활동 "ScanVinFromBarcodeActivity"에서 카메라를 사용하여 (zxing liberary)를 사용하여 바코드를 스캔합니다.Android 이미지/비디오가 시계 반대 방향으로 90도 회전 잘못되었습니다.

제가 직면 한 문제는 미리보기 (SurfaceView)의 카메라 출력이 시계 반대 방향으로 90도 회전 한 것입니다 (세로 방향 & 가로 방향). 당신이 90도 ??? 시계 방향으로 대응 사람과 컴퓨터가 회전 볼 수 있듯이

는 (내 화면의 스냅 샷을 참조하십시오.

방법 내 장치가 갤럭시 S3입니다함으로써

enter image description here

나는

관련 조각 서피스 뷰 SurfaceView를 확장 내 PreviewCamera 클래스에 다음 코드를 사용하고 있습니다 :

surfaceChanged(SurfaceHolder holder, int format, int w, int h) method 
{ 
. 
. 
. 
/*rotate the image by 90 degrees clockwise , in order to correctly displayed the image , images seem to be -90 degrees (counter clockwise) rotated 
* I even tried setting it to p.setRotation(0); , but still no effect. 

*/p.setRotation(90); 
mCamera.setParameters(p); 
. 
. 
. 
} 

그러나 효과가 없으며 이미지는 정확한 0 도가 아닌 시계 반대 방향으로 90도 회전합니다. 용도가 & 카메라가 보는 것을보고 미리 볼 수 있도록

CameraPreview.java 는 화면에 카메라에서 오는 현재의 이미지를 스트리밍하기 위해 서피스 뷰 SurfaceView를 제공합니다.

package com.ty.ownerspoc.barcode; 

import java.io.IOException; 
import java.util.List; 

import android.content.Context; 
import android.hardware.Camera; 
import android.hardware.Camera.Size; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.ViewGroup; 
import android.hardware.Camera.CameraInfo; 

/** A basic Camera preview class */ 
public class CameraPreview extends SurfaceView implements 
     SurfaceHolder.Callback { 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 
    private Context context; 

    public CameraPreview(Context context, Camera camera) { 
     super(context); 
     mCamera = camera; 
     this.context = context; 

     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed. 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     // deprecated setting, but required on Android versions prior to 3.0 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     // The Surface has been created, now tell the camera where to draw the 
     // preview. 
     try { 
      mCamera.setPreviewDisplay(holder); 
      mCamera.startPreview(); 
     } catch (IOException e) { 

     } 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     // empty. Take care of releasing the Camera preview in your activity. 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
     // If your preview can change or rotate, take care of those events here. 
     // Make sure to stop the preview before resizing or reformatting it. 

     if (mHolder.getSurface() == null) { 
      // preview surface does not exist 
      return; 
     } 

     // stop preview before making changes 
     try { 
      mCamera.stopPreview(); 
     } catch (Exception e) { 
      // ignore: tried to stop a non-existent preview 
     } 
       Camera.Parameters p = mCamera.getParameters(); 

     // get width & height of the SurfaceView 
     int SurfaceViewWidth = this.getWidth(); 
     int SurfaceViewHeight = this.getHeight(); 

     List<Size> sizes = p.getSupportedPreviewSizes(); 
     Size optimalSize = getOptimalPreviewSize(sizes, SurfaceViewWidth, SurfaceViewHeight); 


     // set parameters 
     p.setPreviewSize(optimalSize.width, optimalSize.height); 

     /*rotate the image by 90 degrees clockwise , in order to correctly displayed the image , images seem to be -90 degrees (counter clockwise) rotated 
     * I even tried setting it to p.setRotation(0); , but still no effect. 
     */ 
     p.setRotation(90); 

     mCamera.setParameters(p); 

     // start preview with new settings 
     try { 
      mCamera.setPreviewDisplay(mHolder); 
      mCamera.startPreview(); 

     } catch (Exception e) { 
      Log.d("CameraPreview , surfaceCreated() , orientation: ", 
        String.valueOf(e.getMessage())); 
     } 
    }// end surfaceChanged() 
    static Size getOptimalPreviewSize(List <Camera.Size>sizes, int w, int h) { 
      final double ASPECT_TOLERANCE = 0.1; 
      final double MAX_DOWNSIZE = 1.5; 

      double targetRatio = (double) w/h; 
      if (sizes == null) return null; 

      Size optimalSize = null; 
      double minDiff = Double.MAX_VALUE; 

      int targetHeight = h; 

      // Try to find an size match aspect ratio and size 
      for (Camera.Size size : sizes) { 
       double ratio = (double) size.width/size.height; 
       double downsize = (double) size.width/w; 
       if (downsize > MAX_DOWNSIZE) { 
       //if the preview is a lot larger than our display surface ignore it 
       //reason - on some phones there is not enough heap available to show the larger preview sizes 
       continue; 
       } 
       if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; 
       if (Math.abs(size.height - targetHeight) < minDiff) { 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
       } 
      } 
      // Cannot find the one match the aspect ratio, ignore the requirement 
      //keep the max_downsize requirement 
      if (optimalSize == null) { 
       minDiff = Double.MAX_VALUE; 
       for (Size size : sizes) { 
       double downsize = (double) size.width/w; 
       if (downsize > MAX_DOWNSIZE) { 
        continue; 
       } 
       if (Math.abs(size.height - targetHeight) < minDiff) { 
        optimalSize = size; 
        minDiff = Math.abs(size.height - targetHeight); 
       } 
       } 
      } 
      //everything else failed, just take the closest match 
      if (optimalSize == null) { 
       minDiff = Double.MAX_VALUE; 
       for (Size size : sizes) { 
       if (Math.abs(size.height - targetHeight) < minDiff) { 
        optimalSize = size; 
        minDiff = Math.abs(size.height - targetHeight); 
       } 
       } 
      } 
      return optimalSize; 
      } 

}//end class CameraPreview 

안드로이드 활동 (ScanVinFromBarcodeActivity) : 카메라를 & 레이아웃을 시작하기위한

담당합니다. 활동 "ScanVinFromBarcodeActivity"에 대한

package com.ty.ownerspoc.barcode; 

import java.io.IOException; 

import com.google.zxing.BinaryBitmap; 
import com.google.zxing.ChecksumException; 
import com.google.zxing.FormatException; 
import com.google.zxing.MultiFormatReader; //found via import at compile time, however was found at run time 
import com.google.zxing.NotFoundException; 
import com.google.zxing.RGBLuminanceSource;//found via import at compile time, however was found at run time 
import com.google.zxing.Reader; 
import com.google.zxing.Result; 
import com.google.zxing.common.HybridBinarizer; 
import android.annotation.SuppressLint; 
import android.app.Activity; 
import android.content.pm.PackageManager; 
import android.content.res.Configuration; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Point; 
import android.hardware.Camera; 
import android.hardware.Camera.CameraInfo; 
import android.hardware.Camera.PictureCallback; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.Display; 
import android.view.SurfaceView; 
import android.view.View; 
import android.widget.FrameLayout; 
import android.widget.TextView; 
import android.widget.Toast; 
import com.ty.ownerspoc.R; 

public class ScanVinFromBarcodeActivity extends Activity { 

    private Camera globalCamera; 
    private int cameraId = 0; 
    private TextView VINtext = null; 
    private View scanButton = null; 
    // bitmap from camera 
    private Bitmap bmpOfTheImageFromCamera = null; 
    // global flag whether a camera has been detected 
    private boolean isThereACamera = false; 
    // surfaceView for preview object 
    private FrameLayout frameLayoutBarcodeScanner = null; 
    private CameraPreview newCameraPreview = null; 
    private SurfaceView surfaceViewBarcodeScanner = null; 

    /* 
    * This method , finds FEATURE_CAMERA, opens the camera, set parameters , 
    * add CameraPreview to layout, set camera surface holder, start preview 
    */ 
    private void initializeGlobalCamera() { 
     try { 
      if (!getPackageManager().hasSystemFeature(
        PackageManager.FEATURE_CAMERA)) { 
       Toast.makeText(this, "No camera on this device", 
         Toast.LENGTH_LONG).show(); 
      } else { // check for front camera ,and get the ID 
       cameraId = findFrontFacingCamera(); 
       if (cameraId < 0) { 

        Toast.makeText(this, "No front facing camera found.", 
          Toast.LENGTH_LONG).show(); 
       } else { 
        Log.d("ClassScanViewBarcodeActivity", 
          "camera was found , ID: " + cameraId); 
        // camera was found , set global camera flag to true 
        isThereACamera = true; 
        // OPEN 
        globalCamera = Camera.open(cameraId); 

        // pass surfaceView to CameraPreview 
        newCameraPreview = new CameraPreview(this, globalCamera); 
        // pass CameraPreview to Layout 
        frameLayoutBarcodeScanner.addView(newCameraPreview); 
        try { 
         globalCamera 
           .setPreviewDisplay(surfaceViewBarcodeScanner 
             .getHolder()); 
        } catch (IOException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
        // PREVIEW 
        globalCamera.startPreview(); 

        Log.d("ClassScanViewBarcodeActivity", 
          "camera opened & previewing"); 
       } 
      }// end else ,check for front camera 
     }// end try 
     catch (Exception exc) { 

      // in case of exception release resources & cleanup 
      if (globalCamera != null) { 
       globalCamera.stopPreview(); 
       globalCamera.setPreviewCallback(null); 
       globalCamera.release(); 
       globalCamera = null; 

      } 
      Log.d("ClassScanViewBarcodeActivity initializeGlobalCamera() exception:", 
        exc.getMessage()); 
     }// end catch 
    } 

    // onCreate, instantiates layouts & surfaceView used for video preview 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_barcode_vin_scanner); 
     Log.d("ClassScanViewBarcodeActivity", "onCreate "); 

     // create surfaceView for previewing of camera image 
     frameLayoutBarcodeScanner = (FrameLayout) findViewById(R.id.FrameLayoutForPreview); 
     surfaceViewBarcodeScanner = (SurfaceView) findViewById(R.id.surfaceViewBarcodeScanner); 

     initializeGlobalCamera(); 

     // create text area & scan button 
     VINtext = (TextView) findViewById(R.id.mytext); 
     scanButton = findViewById(R.id.webbutton); 
     // on click listener, onClick take a picture 
     scanButton.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View v) { 
       try { 

        // if true take a picture 
        if (isThereACamera) { 
         Log.d("ClassScanViewBarcodeActivity", 
           "setOnClickListener() isThereACamera: " 
             + isThereACamera); 

         globalCamera.takePicture(null, null, jpegCallback); 
         globalCamera.stopPreview(); 
         // wait 2 secs , than start preview again 
         Thread.sleep(2000); 
         globalCamera.startPreview(); 
        } 

       }// end try 
       catch (Exception exc) { 

        // in case of exception release resources & cleanup 
        if (globalCamera != null) { 
         globalCamera.stopPreview(); 
         globalCamera.setPreviewCallback(null); 
         globalCamera.release(); 
         globalCamera = null; 

        } 
        Log.d("ClassScanViewBarcodeActivity setOnClickListener() exceprtion:", 
          exc.getMessage()); 
       }// end catch 

      }// end on Click 
     });// end OnClickListener() implementation 

    }// end onCreate 

    @Override 
    protected void onResume() { 

     Log.d("ClassScanViewBarcodeActivity, onResume() globalCamera:", 
       String.valueOf(globalCamera)); 

     if (globalCamera != null) { 
      // START PREVIEW 
      globalCamera.startPreview(); 
     } else { 
      initializeGlobalCamera(); 
     } 

     super.onResume(); 
    } 

    @Override 
    protected void onStop() { 

     if (globalCamera != null) { 
      globalCamera.stopPreview(); 
      globalCamera.setPreviewCallback(null); 
      globalCamera.release(); 
      globalCamera = null; 
     } 
     super.onStop(); 
    } 

    PictureCallback jpegCallback = new PictureCallback() { 

     public void onPictureTaken(byte[] imgData, Camera camera) { 
      try { 

       // get the bitmap from camera imageData 
       bmpOfTheImageFromCamera = BitmapFactory.decodeByteArray(
         imgData, 0, imgData.length); 
       BinaryBitmap bitmap = null; 
       if (bmpOfTheImageFromCamera != null) { 
        // convert bitmap to binary bitmap 
        bitmap = cameraBytesToBinaryBitmap(bmpOfTheImageFromCamera); 

        if (bitmap != null) { 
         // decode the VIN 
         String VIN = decodeBitmapToString(bitmap); 
         Log.d("***ClassScanViewBarcodeActivity ,onPictureTaken(): VIN ", 
           VIN); 
         VINtext.setText(VIN); 
        } else { 
         Log.d("ClassScanViewBarcodeActivity ,onPictureTaken(): bitmap=", 
           String.valueOf(bitmap)); 
        } 
       } else { 
        Log.d("ClassScanViewBarcodeActivity , onPictureTaken(): bmpOfTheImageFromCamera = ", 
          String.valueOf(bmpOfTheImageFromCamera)); 
       } 
      }// end try 

      catch (Exception exc) { 
       exc.getMessage(); 

       Log.d("ClassScanViewBarcodeActivity , scanButton.setOnClickListener(): exception = ", 
         exc.getMessage()); 
      } 
     }// end onPictureTaken() 
    };// jpegCallback implementation 

    private int findFrontFacingCamera() { 
     int cameraId = -1; 
     // Search for the front facing camera 
     int numberOfCameras = Camera.getNumberOfCameras(); 
     for (int i = 0; i < numberOfCameras; i++) { 
      CameraInfo info = new CameraInfo(); 
      Camera.getCameraInfo(i, info); 
      if (info.facing == CameraInfo.CAMERA_FACING_BACK) { 
       Log.d("ClassScanViewBarcodeActivity , findFrontFacingCamera(): ", 
         "Camera found"); 
       cameraId = i; 
       break; 
      } 
     } 
     return cameraId; 
    }// end findFrontFacingCamera() 

    @Override 
    protected void onPause() { 
     if (globalCamera != null) { 
      globalCamera.stopPreview(); 
      globalCamera.setPreviewCallback(null); 
      globalCamera.release(); 
      globalCamera = null; 
     } 
     super.onPause(); 
    }// end onPause() 

    public String decodeBitmapToString(BinaryBitmap bitmap) { 
     Reader reader = null; 
     Result result = null; 
     String textResult = null; 
     try { 

      reader = new MultiFormatReader(); 
      if (bitmap != null) { 
       result = reader.decode(bitmap); 
       if (result != null) { 
        textResult = result.getText(); 
       } else { 
        Log.d("ClassScanViewBarcodeActivity , String decodeBitmapToString (BinaryBitmap bitmap): result = ", 
          String.valueOf(result)); 
       } 
      } else { 
       Log.d("ClassScanViewBarcodeActivity , String decodeBitmapToString (BinaryBitmap bitmap): bitmap = ", 
         String.valueOf(bitmap)); 
      } 
      /* 
      * byte[] rawBytes = result.getRawBytes(); BarcodeFormat format = 
      * result.getBarcodeFormat(); ResultPoint[] points = 
      * result.getResultPoints(); 
      */ 

     } catch (NotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (ChecksumException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (FormatException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 

     } 

     return textResult; 
    }// end decodeBitmapToString (BinaryBitmap bitmap) 

    public BinaryBitmap cameraBytesToBinaryBitmap(Bitmap bitmap) { 
     BinaryBitmap binaryBitmap = null; 
     if (bitmap != null) { 

      int[] pixels = new int[bitmap.getHeight() * bitmap.getWidth()]; 
      bitmap.getPixels(pixels, 0, 0, bitmap.getWidth() - 1, 
        bitmap.getHeight() - 1, bitmap.getWidth(), 
        bitmap.getHeight()); 

      RGBLuminanceSource source = new RGBLuminanceSource(
        bitmap.getWidth(), bitmap.getHeight(), pixels); 

      HybridBinarizer bh = new HybridBinarizer(source); 
      binaryBitmap = new BinaryBitmap(bh); 
     } else { 
      Log.d("ClassScanViewBarcodeActivity , cameraBytesToBinaryBitmap (Bitmap bitmap): bitmap = ", 
        String.valueOf(bitmap)); 
     } 

     return binaryBitmap; 
    } 

    @SuppressLint("NewApi") 
    @SuppressWarnings("deprecation") 
    /* 
    * The method getScreenOrientation() return screen orientation either 
    * landscape or portrait. IF width < height , than orientation = portrait, 
    * ELSE landscape For backwards compatibility we use to methods to detect 
    * the orientation. The first method is for API versions prior to 13 or 
    * HONEYCOMB. 
    */ 
    public int getScreenOrientation() { 

     int currentapiVersion = android.os.Build.VERSION.SDK_INT; 
     // if API version less than 13 
     Display getOrient = getWindowManager().getDefaultDisplay(); 
     int orientation = Configuration.ORIENTATION_UNDEFINED; 

     if (currentapiVersion < android.os.Build.VERSION_CODES.HONEYCOMB) { 
      // Do something for API version less than HONEYCOMB 

      if (getOrient.getWidth() == getOrient.getHeight()) { 
       orientation = Configuration.ORIENTATION_SQUARE; 
      } else { 
       if (getOrient.getWidth() < getOrient.getHeight()) { 
        orientation = Configuration.ORIENTATION_PORTRAIT; 
       } else { 
        orientation = Configuration.ORIENTATION_LANDSCAPE; 
       } 
      } 
     } else { 
      // Do something for API version greater or equal to HONEYCOMB 

      Point size = new Point(); 
      this.getWindowManager().getDefaultDisplay().getSize(size); 
      int width = size.x; 
      int height = size.y; 

      if (width < height) { 
       orientation = Configuration.ORIENTATION_PORTRAIT; 
      } else { 
       orientation = Configuration.ORIENTATION_LANDSCAPE; 
      } 
     } 

     return orientation; 

    }// end getScreenOrientation() 
}// end class activity 

레이아웃, activity_barcode_vin_scanner.xml : 어떤 도움을 이해할 수있을 것이다

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" 
    android:padding="20dip" > 

    <TextView 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:gravity="center_horizontal" 
     android:padding="20dip" 
     android:text="@string/decode_label" 
     android:textColor="@color/mbackground1" /> 

    <TextView 
     android:id="@+id/mytext" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:background="@color/mbackground2" 
     android:gravity="center_horizontal" 
     android:padding="20dip" 
     android:textColor="@color/mytextcolor" /> 

    <TextView 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:gravity="center_horizontal" 
     android:padding="20dip" 
     android:text="@string/continue_label" 
     android:textColor="@color/mytextcolor" /> 

    <Button 
     android:id="@+id/webbutton" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="@string/web_button" 
     android:textColor="@color/mytextcolor" /> 

    <FrameLayout 
    android:id="@+id/FrameLayoutForPreview" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:layout_weight="1"> 

     <SurfaceView 
      android:id="@+id/surfaceViewBarcodeScanner" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" /> 

    </FrameLayout> 
</LinearLayout> 

.

감사

+0

어떤 기기에서이 문제가 발생합니까? – Darthtong

+0

갤럭시 S3. 그래서 해결책은 무엇입니까, 어떻게 제대로 작동하도록 해킹 할 수 있습니까? 갤럭시 S의 특정 로직을 넣을 수 있습니까? 그 것 같습니다 p.setRotation (90); , 효과가 없습니다. – cyber101

+0

이 기기 만 사용 하시겠습니까? 비디오를 확인해 봤어? – hichris123

답변

5

당신이 당신의 surfaceCreated 방법이이 서피스 뷰 SurfaceView 방향을하지만, 이미지 회전은 여전히 ​​잘못된 것을 수정해야에 setPreviewDisplay를 호출하기 전에 당신이 mCamera.setDisplayOrientation (90)를 호출합니다.

현재 Nexus 7 및 Galaxy S3에서 작업 중이며 Nexus (전면 카메라 만)로 카메라 매개 변수에서 setRotation (270)을 호출하면 이미지 회전이 고정됩니다. 이 세터는 S3에 영향을 미치지 않는 것 같습니다.

Matrix matrix = new Matrix(); 
matrix.postRotate(90); 
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bmpWidth, bmpHeight, matrix, true); 

: 나는 회전이 반 시계 방향 (-90) 할 필요가있는 전면 카메라를 들어, onPictureTaken 처리기에서 이미지 자체를 90도 회전하는 순간에 뭘하는지

이것은 위에서 언급 한 두 장치에서 작동하지만 다른 장치에서이 장치가 어떻게 작동하는지에 대해 우려하고 있습니다.

+0

@ RocketRonz, 미리보기가 올바르게 표시됩니다. 감사합니다. 나는 행렬 연산을 시도하지 않았지만, 그것을 시도하고 파일 작가를 사용하여 저장된 이미지가 올바른 방향인지 확인한다. 감사 – cyber101

관련 문제