2014-02-20 6 views
-1

사용자가 카메라에서 이벤트로 이미지를 업로드 할 수있는 앱을 개발하고 있는데, 일반적인 방법으로 수행했지만 Exif 인터페이스에 따라 회전하는 부분에 도달했습니다. 때로는 실망 스럽지만 OOM 오류가 발생하기도했는데, 잘 작동하는 것처럼 보였던 JniBitmapOperations library 을 사용하기로 마음 먹었습니다.하지만 이미지를 회전 시키려고하면 엉망이되어 버렸습니다./heres 사진JniBitmapOperations 회전으로 인해 이미지가 손상됩니다.

enter image description here

enter image description here

 Options options = new Options(); 
      options.inJustDecodeBounds = true; 
      options.inPreferredConfig = Config.ARGB_8888; 
      Bitmap srcBitmap = BitmapFactory.decodeFile(tempImageFilePath, options); 

      options.inSampleSize = calculateInSampleSize(options); 

      options.inJustDecodeBounds = false; 
      srcBitmap = BitmapFactory.decodeFile(tempImageFilePath, options); 

      ImageLoader.getInstance().clearMemoryCache(); 
      ImageLoader.getInstance().clearDiscCache(); 
      final JniBitmapHolder bitmapHolder = new JniBitmapHolder(srcBitmap); 
     //if we comment this part out, the image comes out fine but not rotated correctly 
      switch (angleFix) { 
      case 90: 
       bitmapHolder.rotateBitmapCw90(); 
       break; 
      case 180: 
       bitmapHolder.rotateBitmapCw90(); 
       bitmapHolder.rotateBitmapCw90(); 
       break; 
      case 270: 
       bitmapHolder.rotateBitmapCcw90(); 
       break; 
      } 

      srcBitmap = bitmapHolder.getBitmapAndFree(); 
//this is the old way which caused OOM errors occasionally 
      // Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), m, true); 

      try { 
       FileOutputStream out = new FileOutputStream(tempImageFilePath); 
       srcBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); 
       out.close(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      if (srcBitmap != null) { 
       GetImageUploadUrl getUrl = new GetImageUploadUrl(); 
       getUrl.execute(); 
      } 
     } 
    } 

내가 감사하겠습니다 :위의 올바른 위치로 회전 된 사진을 볼 수 있지만 아래의 하나가 여기에 원래

모든 손상 입니다 수있는 관련 코드의 일부입니다 어떤 도움이라도!

+0

같다 :

여기에 코드입니다. 이상하게도 나는 그것을 알아 채지 못했고 자원으로도 잘 작동했다. 이제 생각해 보면, 과거에 이미 수정 한 오래된 버그처럼 보입니다. 어쩌면 내가 커밋하는 걸 잊었을거야. 코드는 현재 width == height 인 경우에만 작동합니다. 곧 고칠 것이고 그것에 대해 말해 줄 것입니다. –

+0

정말 고마워요! :) –

+0

죄송합니다. 정말 여러 번 테스트 해 봤기 때문에 당신이 탓할 것이라고 확신했습니다. 나는 정말로 내가 가지고 있던 버그를 "다시 잡아"짧은 시간에 고칠 수 있기를 바란다. –

답변

1

확인, 회전 기능에 잘못된 너비와 높이를 설정했을 때 버그가있었습니다.

이제 코드를 업데이트했습니다. 이제는 효과가있다.

이 버그에 대해 매우 유감스럽게 생각합니다. 나는 그것을 전에 고쳤다 고 확신했다. 이제 180도 회전하는 기능을 추가 했으므로 두 번 회전하지 않아도됩니다 (좀 더 효율적입니다).

샘플 코드가 아무 것도 아니라고 가정하면 여기 샘플 코드가 좋습니다.

모든 카메라 이미지를 검토하고 3 가지 방법 중 하나로 회전하고 결과 파일을 Android/data/PACKAGE_NAME에 넣습니다. 내가 버그를 가지고있는 것처럼

public class MainActivity extends Activity 
    { 
    @Override 
    protected void onCreate(final Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    final File picFolder=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); 
    final int screenWidth=getResources().getDisplayMetrics().widthPixels; 
    final int screenHeight=getResources().getDisplayMetrics().heightPixels; 
    final File outputDir=getExternalFilesDir(null); 
    final ProgressDialog progressDialog=ProgressDialog.show(this,"please wait","processing"); 
    new AsyncTask<Void,Void,Void>() 
     { 
     @Override 
     protected Void doInBackground(final Void... params) 
      { 
      final File[] listFiles=outputDir.listFiles((FileFilter)null); 
      for(final File file : listFiles) 
      file.delete(); 
      final List<String> imageFilesPaths=new ArrayList<String>(); 
      getPicturesPaths(picFolder.getAbsolutePath(),imageFilesPaths); 
      final JniBitmapHolder bitmapHolder=new JniBitmapHolder(); 
      int i=0; 
      final Options options=new Options(); 
      for(final String filePath : imageFilesPaths) 
      { 
      options.inJustDecodeBounds=true; 
      options.inPreferredConfig=Config.ARGB_8888; 
      prepareForDownsampling(options,screenWidth,screenHeight); 
      Bitmap b=BitmapFactory.decodeFile(filePath,options); 
      bitmapHolder.storeBitmap(b); 
      b.recycle(); 
      switch(i++%3) 
       { 
       case 0: 
       bitmapHolder.rotateBitmapCw90(); 
       break; 
       case 1: 
       bitmapHolder.rotateBitmap180(); 
       break; 
       case 2: 
       bitmapHolder.rotateBitmapCcw90(); 
       break; 
       } 
      b=bitmapHolder.getBitmapAndFree(); 
      final File imageFile=new File(outputDir.getAbsoluteFile()+File.separator+System.currentTimeMillis()+".jpg"); 
      imageFile.getParentFile().mkdirs(); 
      FileOutputStream stream=null; 
      try 
       { 
       stream=new FileOutputStream(imageFile); 
       b.compress(CompressFormat.JPEG,80,stream); 
       stream.flush(); 
       stream.close(); 
       } 
      catch(final Exception e) 
       { 
       e.printStackTrace(); 
       } 
      finally 
       { 
       if(stream!=null) 
       try 
        { 
        stream.close(); 
        } 
       catch(final IOException e) 
        { 
        e.printStackTrace(); 
        } 
       } 
      } 
      return null; 
      } 

     @Override 
     protected void onPostExecute(final Void result) 
      { 
      super.onPostExecute(result); 
      progressDialog.dismiss(); 
      finish(); 
      } 
     }.execute(); 
    } 

    private static void prepareForDownsampling(final Options bitmapOptions,final int reqWidth,final int reqHeight) 
    { 
    final int inSampleSize=calculateInSampleSize(bitmapOptions,reqWidth,reqHeight); 
    // as much as possible, use google's way to downsample: 
    bitmapOptions.inSampleSize=1; 
    bitmapOptions.inDensity=1; 
    bitmapOptions.inTargetDensity=1; 
    bitmapOptions.inJustDecodeBounds=false; 
    while(bitmapOptions.inSampleSize*2<=inSampleSize) 
     bitmapOptions.inSampleSize*=2; 
    // if google's way to downsample isn't enough, do some more : 
    if(bitmapOptions.inSampleSize!=inSampleSize) 
     { 
     // downsample by bitmapOptions.inSampleSize/originalSampleSize . 
     bitmapOptions.inTargetDensity=bitmapOptions.inSampleSize; 
     bitmapOptions.inDensity=inSampleSize; 
     } 
    } 

    public static int calculateInSampleSize(final BitmapFactory.Options options,final int reqWidth,final int reqHeight) 
    { 
    final int height=options.outHeight; 
    final int width=options.outWidth; 
    int inSampleSize=1; 
    if(height>reqHeight||width>reqWidth) 
     { 
     final int heightRatio=Math.round((float)height/(float)reqHeight); 
     final int widthRatio=Math.round((float)width/(float)reqWidth); 
     inSampleSize=heightRatio<widthRatio ? heightRatio : widthRatio; 
     } 
    return Math.max(inSampleSize,1); 
    } 

    private static void getPicturesPaths(final String path,final List<String> filesPaths) 
    { 
    final Options options=new Options(); 
    options.inJustDecodeBounds=true; 
    File f=new File(path); 
    if(f.isFile()) 
     { 
     BitmapFactory.decodeFile(path,options); 
     if(options.outHeight>=0&&options.outWidth>=0) 
     filesPaths.add(path); 
     return; 
     } 
    if(!f.isDirectory()) 
     return; 
    final String[] childrenPaths=f.list(); 
    for(final String fileName : childrenPaths) 
     { 
     if(fileName.startsWith(".")) 
     continue; 
     f=new File(path+File.separator+fileName); 
     final String fullFilePath=f.getAbsolutePath(); 
     if(f.isFile()) 
     { 
     BitmapFactory.decodeFile(fullFilePath,options); 
     if(options.outHeight>=0&&options.outWidth>=0) 
      filesPaths.add(fullFilePath); 
     continue; 
     } 
     getPicturesPaths(fullFilePath,filesPaths); 
     } 
    } 
    } 
+0

끝내 주셔서 감사합니다. –

+1

고맙습니다. 이제 라이브러리를 업데이트하여 이미지의 크기를 조정하는 추가 방법을 얻었으며 색상을 처리하는 데 도움이되는 몇 가지 도우미 기능이 있음을 알 수 있으므로 이미지 필터를 직접 만들 수 있습니다. –

+0

다시 한 번 고맙습니다. :) –

관련 문제