JniBitmapOperations旋转导致图像损坏

时间:2014-02-20 16:35:36

标签: android bitmap rotation image-rotation

我正在开发一个应用程序,用户可以将图像从相机上传到事件,我按照通常的方式进行,但是当我根据Exif界面进行旋转时,我有时会得到OOM错误,这真的令人沮丧,我决定尝试使用JniBitmapOperations library 这似乎工作正常(我不会得到OOM错误)但是当试图旋转图像时它会变得腐败并搞砸了:/ heres图片

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();
            }
        }
    }

我将不胜感激任何帮助!

1 个答案:

答案 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);
      }
    }
  }