diff --git a/gallery/src/main/java/cc/winboll/studio/gallery/CropActivity.java b/gallery/src/main/java/cc/winboll/studio/gallery/CropActivity.java index f1eef7c..187fa09 100644 --- a/gallery/src/main/java/cc/winboll/studio/gallery/CropActivity.java +++ b/gallery/src/main/java/cc/winboll/studio/gallery/CropActivity.java @@ -7,6 +7,7 @@ import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.view.View; +import android.widget.ImageView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import cc.winboll.studio.libappbase.LogUtils; @@ -55,6 +56,16 @@ public class CropActivity extends AppCompatActivity { } }); + final ImageView btnColorPick = findViewById(R.id.btn_color_pick); + btnColorPick.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean pickMode = !cropCanvasView.isColorPickMode(); + cropCanvasView.setColorPickMode(pickMode); + btnColorPick.setAlpha(pickMode ? 0.5f : 1.0f); + } + }); + findViewById(R.id.btn_done).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -107,36 +118,26 @@ public class CropActivity extends AppCompatActivity { } private void saveCroppedCover() { - if (originalBitmap == null) { + Bitmap canvasBitmap = cropCanvasView.getCanvasBitmap(); + if (canvasBitmap == null) { Toast.makeText(this, "Failed to get image", Toast.LENGTH_SHORT).show(); return; } try { RectF cropRect = cropCanvasView.getCropRect(); - RectF canvasBounds = cropCanvasView.getCanvasBounds(); - RectF imageBounds = cropCanvasView.getImageBounds(); - int imgW = originalBitmap.getWidth(); - int imgH = originalBitmap.getHeight(); + int cropX = (int) cropRect.left; + int cropY = (int) cropRect.top; + int cropW = (int) cropRect.width(); + int cropH = (int) cropRect.height(); - float scaleX = (float) imgW / canvasBounds.width(); - float scaleY = (float) imgH / canvasBounds.height(); + cropX = Math.max(0, Math.min(cropX, canvasBitmap.getWidth() - 1)); + cropY = Math.max(0, Math.min(cropY, canvasBitmap.getHeight() - 1)); + cropW = Math.max(1, Math.min(cropW, canvasBitmap.getWidth() - cropX)); + cropH = Math.max(1, Math.min(cropH, canvasBitmap.getHeight() - cropY)); - float canvasLeft = cropRect.left - canvasBounds.left; - float canvasTop = cropRect.top - canvasBounds.top; - - int cropX = (int) ((canvasLeft - imageBounds.left) * scaleX); - int cropY = (int) ((canvasTop - imageBounds.top) * scaleY); - int cropW = (int) (cropRect.width() * scaleX); - int cropH = (int) (cropRect.height() * scaleY); - - cropX = Math.max(0, Math.min(cropX, imgW - 1)); - cropY = Math.max(0, Math.min(cropY, imgH - 1)); - cropW = Math.max(1, Math.min(cropW, imgW - cropX)); - cropH = Math.max(1, Math.min(cropH, imgH - cropY)); - - Bitmap cropped = Bitmap.createBitmap(originalBitmap, cropX, cropY, cropW, cropH); + Bitmap cropped = Bitmap.createBitmap(canvasBitmap, cropX, cropY, cropW, cropH); File cacheDir = getCacheDir(); File coverFile = new File(cacheDir, "cover_" + System.currentTimeMillis() + ".png"); diff --git a/gallery/src/main/java/cc/winboll/studio/gallery/CropCanvasView.java b/gallery/src/main/java/cc/winboll/studio/gallery/CropCanvasView.java index 7cfb626..470ba3c 100644 --- a/gallery/src/main/java/cc/winboll/studio/gallery/CropCanvasView.java +++ b/gallery/src/main/java/cc/winboll/studio/gallery/CropCanvasView.java @@ -38,7 +38,11 @@ public class CropCanvasView extends View { private RectF imageBounds = new RectF(); private RectF canvasBounds = new RectF(); private Bitmap originalBitmap; + private Bitmap canvasBitmap; private float initialSpan; + private int backgroundColor = Color.GREEN; + private boolean colorPickMode = false; + private float pickX, pickY; public CropCanvasView(Context context) { super(context); @@ -98,10 +102,51 @@ public class CropCanvasView extends View { cropRect = new RectF(0, 0, canvasWidth, canvasHeight); + createCanvasBitmap(); + requestLayout(); invalidate(); } + private void createCanvasBitmap() { + if (canvasBitmap != null) { + canvasBitmap.recycle(); + } + canvasBitmap = Bitmap.createBitmap(canvasWidth, canvasHeight, Bitmap.Config.ARGB_8888); + android.graphics.Canvas canvas = new android.graphics.Canvas(canvasBitmap); + canvas.drawColor(backgroundColor); + if (originalBitmap != null && !originalBitmap.isRecycled()) { + canvas.drawBitmap(originalBitmap, imageBounds.left, imageBounds.top, imagePaint); + } + } + + public Bitmap getCanvasBitmap() { + return canvasBitmap; + } + + public void setBackgroundColor(int color) { + this.backgroundColor = color; + createCanvasBitmap(); + invalidate(); + } + + public int getBackgroundColor() { + return backgroundColor; + } + + public void setColorPickMode(boolean enable) { + this.colorPickMode = enable; + if (enable) { + pickX = -1; + pickY = -1; + } + invalidate(); + } + + public boolean isColorPickMode() { + return colorPickMode; + } + public void scaleToView(int viewWidth, int viewHeight) { if (viewWidth > 0 && viewHeight > 0 && canvasWidth > 0 && canvasHeight > 0) { float scale = Math.max((float) viewWidth / canvasWidth, (float) viewHeight / canvasHeight); @@ -141,14 +186,6 @@ public class CropCanvasView extends View { return canvasHeight; } - public int getExtendWidth() { - return extendWidth; - } - - public int getExtendHeight() { - return extendHeight; - } - public RectF getCanvasBounds() { return new RectF(canvasBounds); } @@ -157,10 +194,6 @@ public class CropCanvasView extends View { return new RectF(imageBounds); } - public float getCoverRatio() { - return coverRatio; - } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int w = canvasWidth > 0 ? canvasWidth : 0; @@ -172,10 +205,8 @@ public class CropCanvasView extends View { protected void onDraw(Canvas canvas) { super.onDraw(canvas); - canvas.drawColor(Color.GREEN); - - if (originalBitmap != null && !originalBitmap.isRecycled()) { - canvas.drawBitmap(originalBitmap, imageBounds.left, imageBounds.top, imagePaint); + if (canvasBitmap != null && !canvasBitmap.isRecycled()) { + canvas.drawBitmap(canvasBitmap, 0, 0, null); } if (cropRect != null) { @@ -210,7 +241,7 @@ public class CropCanvasView extends View { newHeight = newWidth / coverRatio; cropRect.set(centerX - newWidth / 2, centerY - newHeight / 2, - centerX + newWidth / 2, centerY + newHeight / 2); + centerX + newWidth / 2, centerY + newHeight / 2); initialSpan = span; invalidate(); @@ -222,6 +253,17 @@ public class CropCanvasView extends View { float x = event.getX(); float y = event.getY(); + if (colorPickMode) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + pickX = x; + pickY = y; + int color = getColorAt(x, y); + setBackgroundColor(color); + return true; + } + return true; + } + switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = x; @@ -313,19 +355,24 @@ public class CropCanvasView extends View { } private int getActiveCorner(float x, float y) { - if (Math.abs(x - cropRect.left) <= touchArea && Math.abs(y - cropRect.top) <= touchArea) { + float dx = Math.abs(x - cropRect.left); + float dy = Math.abs(y - cropRect.top); + float dx2 = Math.abs(x - cropRect.right); + float dy2 = Math.abs(y - cropRect.bottom); + + if (dx <= touchArea && dy <= touchArea) { return CORNER_TOP_LEFT; } - if (Math.abs(x - cropRect.right) <= touchArea && Math.abs(y - cropRect.top) <= touchArea) { + if (dx2 <= touchArea && dy <= touchArea) { return CORNER_TOP_RIGHT; } - if (Math.abs(x - cropRect.left) <= touchArea && Math.abs(y - cropRect.bottom) <= touchArea) { + if (dx <= touchArea && dy2 <= touchArea) { return CORNER_BOTTOM_LEFT; } - if (Math.abs(x - cropRect.right) <= touchArea && Math.abs(y - cropRect.bottom) <= touchArea) { + if (dx2 <= touchArea && dy2 <= touchArea) { return CORNER_BOTTOM_RIGHT; } - if (cropRect.contains(x, y)) { + if (x > cropRect.left && x < cropRect.right && y > cropRect.top && y < cropRect.bottom) { return CORNER_CENTER; } return -1; @@ -338,4 +385,16 @@ public class CropCanvasView extends View { float y1 = event.getY(1); return (float) Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); } + + public int getColorAt(float x, float y) { + if (canvasBitmap != null && !canvasBitmap.isRecycled()) { + int bitmapX = (int) x; + int bitmapY = (int) y; + if (bitmapX >= 0 && bitmapX < canvasBitmap.getWidth() && + bitmapY >= 0 && bitmapY < canvasBitmap.getHeight()) { + return canvasBitmap.getPixel(bitmapX, bitmapY); + } + } + return Color.TRANSPARENT; + } } \ No newline at end of file diff --git a/gallery/src/main/res/drawable/ic_color_pick.xml b/gallery/src/main/res/drawable/ic_color_pick.xml new file mode 100644 index 0000000..538fb37 --- /dev/null +++ b/gallery/src/main/res/drawable/ic_color_pick.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/gallery/src/main/res/layout/activity_crop.xml b/gallery/src/main/res/layout/activity_crop.xml index 45a5925..e90e7df 100644 --- a/gallery/src/main/res/layout/activity_crop.xml +++ b/gallery/src/main/res/layout/activity_crop.xml @@ -21,6 +21,14 @@ android:src="@drawable/ic_close" android:background="?attr/selectableItemBackgroundBorderless"/> + +