2014-02-20 104 views
-1

我正在开发一个应用程序,我可以从相机上传图像到一个事件,我以通常的方式做到了,但是当我根据Exif界面旋转它时我有时会得到OOM错误,这真是令人沮丧,我决定尝试使用JniBitmapOperations library 这似乎工作正常(我不会得到OOM错误),但当试图旋转图像时,它会变得腐败和混乱:/ 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

好像我有一个bug。奇怪的是,我没有注意到它,并且它在资源上运行良好。现在我想到了它,它看起来像我过去已经修复的一个旧bug。也许我忘了提交。该代码目前仅适用于宽度==高度。很快会解决它并告诉你。 –

+0

非常感谢你! :) –

+0

对不起。因为我已经测试过很多次了,所以我确信你应该责怪。我真的希望我能够重新“捕捉”我所拥有的错误,并在短时间内修复它。 –

回答

1

好的,错误是为旋转函数设置了错误的宽度和高度。

我已经更新了代码。现在它应该工作。

我对这个bug非常抱歉。我确信我之前已经修复过它。我现在增加了旋转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

再一次,非常感谢:) –