Пример #1
0
  /*
   * TODO This should use the decode/crop/encode single step API so that the whole (possibly large) Bitmap doesn't need to be read
   * into memory
   */
  private void onSaveClicked() {
    if (cropView == null || isSaving) {
      return;
    }
    isSaving = true;

    Bitmap croppedImage = null;
    Rect r = cropView.getScaledCropRect(sampleSize);
    int width = r.width();
    int height = r.height();

    int outWidth = width, outHeight = height;
    if (maxX > 0 && maxY > 0 && (width > maxX || height > maxY)) {
      float ratio = (float) width / (float) height;
      if ((float) maxX / (float) maxY > ratio) {
        outHeight = maxY;
        outWidth = (int) ((float) maxY * ratio + .5f);
      } else {
        outWidth = maxX;
        outHeight = (int) ((float) maxX / ratio + .5f);
      }
    }

    if (IN_MEMORY_CROP && rotateBitmap != null) {
      croppedImage =
          inMemoryCrop(rotateBitmap, croppedImage, r, width, height, outWidth, outHeight);
      if (croppedImage != null) {
        imageView.setImageBitmapResetBase(croppedImage, true);
        imageView.center(true, true);
        imageView.highlightViews.clear();
      }
    } else {
      try {
        croppedImage = decodeRegionCrop(croppedImage, r);
        if (isCircleCrop) {
          croppedImage = cropCircleView(croppedImage);
        }
      } catch (IllegalArgumentException e) {
        setResultException(e);
        finish();
        return;
      }

      if (croppedImage != null) {
        imageView.setImageRotateBitmapResetBase(new RotateBitmap(croppedImage, exifRotation), true);
        imageView.center(true, true);
        imageView.highlightViews.clear();
      }
    }
    saveImage(croppedImage);
  }
  private void onSaveClicked() {
    // TODO this code needs to change to use the decode/crop/encode single
    // step api so that we don't require that the whole (possibly large)
    // bitmap doesn't have to be read into memory
    if (mCrop == null) {
      return;
    }

    if (mSaving) return;
    mSaving = true;

    Bitmap croppedImage;

    // If the output is required to a specific size, create an new image
    // with the cropped image in the center and the extra space filled.
    if (mOutputX != 0 && mOutputY != 0 && !mScale) {
      // Don't scale the image but instead fill it so it's the
      // required dimension
      croppedImage = Bitmap.createBitmap(mOutputX, mOutputY, Bitmap.Config.RGB_565);
      Canvas canvas = new Canvas(croppedImage);

      Rect srcRect = mCrop.getCropRect();
      Rect dstRect = new Rect(0, 0, mOutputX, mOutputY);

      int dx = (srcRect.width() - dstRect.width()) / 2;
      int dy = (srcRect.height() - dstRect.height()) / 2;

      // If the srcRect is too big, use the center part of it.
      srcRect.inset(Math.max(0, dx), Math.max(0, dy));

      // If the dstRect is too big, use the center part of it.
      dstRect.inset(Math.max(0, -dx), Math.max(0, -dy));

      // Draw the cropped bitmap in the center
      canvas.drawBitmap(mBitmap, srcRect, dstRect, null);

      // Release bitmap memory as soon as possible
      mImageView.clear();
      mBitmap.recycle();
    } else {
      Rect r = mCrop.getCropRect();

      int width = r.width();
      int height = r.height();

      // If we are circle cropping, we want alpha channel, which is the
      // third param here.
      croppedImage =
          Bitmap.createBitmap(
              width, height, mCircleCrop ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);

      Canvas canvas = new Canvas(croppedImage);
      Rect dstRect = new Rect(0, 0, width, height);
      canvas.drawBitmap(mBitmap, r, dstRect, null);

      // Release bitmap memory as soon as possible
      mImageView.clear();
      mBitmap.recycle();

      if (mCircleCrop) {
        // OK, so what's all this about?
        // Bitmaps are inherently rectangular but we want to return
        // something that's basically a circle.  So we fill in the
        // area around the circle with alpha.  Note the all important
        // PortDuff.Mode.CLEAR.
        Canvas c = new Canvas(croppedImage);
        Path p = new Path();
        p.addCircle(width / 2F, height / 2F, width / 2F, Path.Direction.CW);
        c.clipPath(p, Region.Op.DIFFERENCE);
        c.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
      }

      // If the required dimension is specified, scale the image.
      if (mOutputX != 0 && mOutputY != 0 && mScale) {
        croppedImage =
            Util.transform(
                new Matrix(), croppedImage, mOutputX, mOutputY, mScaleUp, Util.RECYCLE_INPUT);
      }
    }

    mImageView.setImageBitmapResetBase(croppedImage, true);
    mImageView.center(true, true);
    mImageView.mHighlightViews.clear();

    // Return the cropped image directly or save it to the specified URI.
    Bundle myExtras = getIntent().getExtras();
    if (myExtras != null
        && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) {
      Bundle extras = new Bundle();
      extras.putParcelable("data", croppedImage);
      setResult(RESULT_OK, (new Intent()).setAction("inline-data").putExtras(extras));
      finish();
    } else {
      final Bitmap b = croppedImage;
      final int msdId = mSetWallpaper ? R.string.wallpaper : R.string.savingImage;
      Util.startBackgroundJob(
          this,
          this,
          null,
          getResources().getString(msdId),
          new Runnable() {
            public void run() {
              saveOutput(b);
            }
          },
          mHandler);
    }
  }
  private void onSaveClicked() {
    if (!mNeedCrop) {
      Bitmap nocropBitmap = createNoCropBitmap();
      mImageView.clear();
      if (nocropBitmap != mBitmap) {
        mBitmap.recycle();
        mBitmap = null;
      }
      if (null != nocropBitmap) {
        // Return the cropped image directly or save it to the specified
        // URI.
        Bundle myExtras = getIntent().getExtras();
        if (myExtras != null
            && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) {
          Bundle extras = new Bundle();
          extras.putParcelable("data", nocropBitmap);
          setResult(
              RESULT_OK,
              (new Intent()).setAction(ICustomAction.ACTION_INLINE_DATA).putExtras(extras));
          finish();
        } else {
          final Bitmap b = nocropBitmap;
          final int msdId = mSetWallpaper ? R.string.wallpaper : R.string.savingImage;
          Util.startBackgroundJob(
              this,
              null,
              getResources().getString(msdId),
              new Runnable() {
                @Override
                public void run() {
                  saveOutput(b);
                }
              },
              mHandler);
        }
      } else {
        setResult(RESULT_CANCELED);
        finish();
      }
      return;
    }
    // TODO this code needs to change to use the decode/crop/encode single
    // step api so that we don't require that the whole (possibly large)
    // bitmap doesn't have to be read into memory
    if (mCrop == null) {
      return;
    }

    if (mSaving) {
      return;
    }
    mSaving = true;

    Bitmap croppedImage = null;
    Bitmap.Config bmpConfig = mHasApha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.ARGB_8888;

    // If the output is required to a specific size, create an new image
    // with the cropped image in the center and the extra space filled.
    if (mOutputX != 0 && mOutputY != 0 && !mScale) {
      // Don't scale the image but instead fill it so it's the
      // required dimension
      try {
        croppedImage = Bitmap.createBitmap(mOutputX, mOutputY, bmpConfig);
      } catch (OutOfMemoryError e) {
        // 创建失败
        e.printStackTrace();
        OutOfMemoryHandler.handle();
        Toast.makeText(this, getString(R.string.err_out_of_memory), Toast.LENGTH_SHORT);
        // Release bitmap memory as soon as possible
        mImageView.clear();
        mBitmap.recycle();
        mBitmap = null;

        setResult(RESULT_CANCELED);
        finish();
        return;
      }

      Canvas canvas = new Canvas(croppedImage);
      Rect srcRect = mCrop.getCropRect();
      Rect dstRect = new Rect(0, 0, mOutputX, mOutputY);

      int dx = (srcRect.width() - dstRect.width()) / 2;
      int dy = (srcRect.height() - dstRect.height()) / 2;

      // If the srcRect is too big, use the center part of it.
      srcRect.inset(Math.max(0, dx), Math.max(0, dy));

      // If the dstRect is too big, use the center part of it.
      dstRect.inset(Math.max(0, -dx), Math.max(0, -dy));

      // Draw the cropped bitmap in the center
      canvas.drawBitmap(mBitmap, srcRect, dstRect, null);

      // Release bitmap memory as soon as possible
      mImageView.clear();
      mBitmap.recycle();
    } else {
      Rect r = mCrop.getCropRect();

      // int width = r.width();
      // int height = r.height();

      // If we are circle cropping, we want alpha channel, which is the
      // third param here.
      try {
        croppedImage = Bitmap.createBitmap(mOutputX, mOutputY, bmpConfig);
      } catch (OutOfMemoryError e) {
        e.printStackTrace();
        OutOfMemoryHandler.handle();
        // 创建失败
        // Toast.makeText(this, getString(R.string.err_out_of_memory),
        // Toast.LENGTH_SHORT).show();
        // Release bitmap memory as soon as possible
        mImageView.clear();
        mBitmap.recycle();

        setResult(RESULT_CANCELED);
        finish();
        return;
      }

      Canvas canvas = new Canvas(croppedImage);
      canvas.setDrawFilter(
          new PaintFlagsDrawFilter(
              0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); // 在有缩放的情况下需要提高绘图质量
      Rect dstRect = new Rect(0, 0, mOutputX, mOutputY);
      canvas.drawBitmap(mBitmap, r, dstRect, null);

      // Release bitmap memory as soon as possible
      mImageView.clear();
      mBitmap.recycle();

      // if (mCircleCrop) {
      // // OK, so what's all this about?
      // // Bitmaps are inherently rectangular but we want to return
      // // something that's basically a circle. So we fill in the
      // // area around the circle with alpha. Note the all important
      // // PortDuff.Mode.CLEAR.
      // Canvas c = new Canvas(croppedImage);
      // Path p = new Path();
      // p.addCircle(width / 2F, height / 2F, width / 2F,
      // Path.Direction.CW);
      // c.clipPath(p, Region.Op.DIFFERENCE);
      // c.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
      // }

      // If the required dimension is specified, scale the image.
      // if (mOutputX != 0 && mOutputY != 0 && mScale) {
      // croppedImage = Util.transform(new Matrix(), croppedImage,
      // mOutputX, mOutputY, mScaleUp, Util.RECYCLE_INPUT);
      // }
    }

    mImageView.setImageBitmapResetBase(croppedImage, true);
    mImageView.center(true, true);
    mImageView.mHighlightViews.clear();

    // Return the cropped image directly or save it to the specified URI.
    Bundle myExtras = getIntent().getExtras();
    if (myExtras != null
        && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) {
      Bundle extras = new Bundle();
      extras.putParcelable("data", croppedImage);
      setResult(
          RESULT_OK, (new Intent()).setAction(ICustomAction.ACTION_INLINE_DATA).putExtras(extras));
      finish();
    } else {
      final Bitmap b = croppedImage;
      final int msdId = mSetWallpaper ? R.string.wallpaper : R.string.savingImage;
      Util.startBackgroundJob(
          this,
          null,
          getResources().getString(msdId),
          new Runnable() {
            @Override
            public void run() {
              saveOutput(b);
            }
          },
          mHandler);
    }
  }