Вращение JniBitmapOperations вызывает повреждение изображения

Я разрабатываю приложение i, которое пользователи могут загружать изображения с камеры на событие, я сделал это обычным способом, но когда я добрался до части вращения в соответствии с интерфейсом Exif, я бы иногда получал OOM ошибки, которые были действительно разочаровывающими, я решил попробовать JniBitmapOperations library который, казалось, работал нормально (я бы не получил ошибок OOM), но при попытке поворота изображения он становится коррумпированным и испорченным:/heres pictures

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

ok, ошибка заключалась в установке неправильной ширины и высоты для функций вращения.

Теперь я обновил код. теперь он должен работать.

Мне очень жаль эту ошибку. был уверен, что я исправил его раньше. теперь я добавил возможность поворота на 180 градусов, так что вам не нужно будет вращаться дважды (немного более эффективно).

и просто сказать, что образец кода был не зря, вот более хороший пример кода.

он будет просматривать все ваши изображения с камеры и поворачивать их любым из трех способов и помещать файлы результатов в 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 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 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);
      }
    }
  }