我正在尝试按照心形裁剪或调整图像。用户可以根据心形调整图像,并将图像设置为心形。
目前,我正在使用Github Project库将图像裁剪为方形并设置为心形。但是所有的图像都是从心脏弯曲的顶端切割出来的。所以,我希望允许用户按照心脏边界裁剪图像,然后设置用户想要的方式。但是没有任何我可以自定义或使用的库。
这是我从github项目上面使用的当前代码。
打开相机和图库:
CropImage.activity()。setGuidelines(CropImageView.Guidelines.ON).start(this);
获取裁剪图像并设置为ImageHeart视图。
CropImage.ActivityResult result = CropImage.getActivityResult(data);
picUri = result.getUri();
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),picUri);
imvHeartRed.setImageBitmap(位图);
这是我使用方形裁剪裁剪玻璃的图像,但设置全玻璃图像时不会出现。但是如果用户使用心形来裁剪它,那么将显示全玻璃,因为用户将知道图像的哪个部分将被裁剪。
任何帮助,参考将非常感谢。
我不想直接在心里设置图像,但用户可以通过触摸/移动来调整图像中的图像
答案 0 :(得分:10)
已更新,仅在心形状内设置透明度。
如果您只是需要根据自己创建的形状标记图像,可以使用mafs-image-shape等库,但在剪切图像之前需要提供一种操作形状放置的方法。
我假设您依赖Android-Image-Cropper
的结构,因此以下更改适用于该库。显示的代码基于Android-Image-Cropper中选定的代码,该代码在Apache License 2.0下获得许可。
以下是示例应用在进行以下更改后的外观。下面的讨论解释了如何更改基本代码以适应心形。
除了矩形和椭圆形之外,还需要将心形定义为选项。要将心形作为选项,请更改CropShape
中的CropImageView
枚举以将HEART
添加为裁剪形状,并将heart
添加为cropShape
选项attrs
:
<强> CropImageView.java 强>
public enum CropShape {
RECTANGLE,
OVAL,
HEART
}
<强> attrs.xml 强>
<attr name="cropShape">
<enum name="rectangle" value="0"/>
<enum name="oval" value="1"/>
<enum name="heart" value="2"/>
</attr>
我使用了两个图像作为心形。第一个图像是用于将帧定位在基础图像上的取景图像。裁剪图像与取景图像相同,但在裁剪操作期间应保留图像的任何位置都是实心的(alpha == 1)。透明区域应将alpha设置为零。以下是我使用过的图像,但您需要使用自己的图像。
CropOverlayView
是一个自定义视图,显示裁剪窗口和阴影背景。修改此类的drawBackground
和drawBorders
方法,如下所示,以适应心形。
<强> CropOverlayView.java 强>
/**
* Draw shadow background over the image not including the crop area.
*/
// Modifications made to accommodate heart cutouts
private void drawBackground(Canvas canvas) {
RectF rect = mCropWindowHandler.getRect();
float left = Math.max(BitmapUtils.getRectLeft(mBoundsPoints), 0);
float top = Math.max(BitmapUtils.getRectTop(mBoundsPoints), 0);
float right = Math.min(BitmapUtils.getRectRight(mBoundsPoints), getWidth());
float bottom = Math.min(BitmapUtils.getRectBottom(mBoundsPoints), getHeight());
if (mCropShape == CropImageView.CropShape.RECTANGLE) {
if (!isNonStraightAngleRotated() || Build.VERSION.SDK_INT <= 17) {
canvas.drawRect(left, top, right, rect.top, mBackgroundPaint);
canvas.drawRect(left, rect.bottom, right, bottom, mBackgroundPaint);
canvas.drawRect(left, rect.top, rect.left, rect.bottom, mBackgroundPaint);
canvas.drawRect(rect.right, rect.top, right, rect.bottom, mBackgroundPaint);
} else {
mPath.reset();
mPath.moveTo(mBoundsPoints[0], mBoundsPoints[1]);
mPath.lineTo(mBoundsPoints[2], mBoundsPoints[3]);
mPath.lineTo(mBoundsPoints[4], mBoundsPoints[5]);
mPath.lineTo(mBoundsPoints[6], mBoundsPoints[7]);
mPath.close();
canvas.save();
canvas.clipPath(mPath, Region.Op.INTERSECT);
canvas.clipRect(rect, Region.Op.XOR);
canvas.drawRect(left, top, right, bottom, mBackgroundPaint);
canvas.restore();
}
} else if (mCropShape == CropImageView.CropShape.HEART) {
Bitmap screen = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(screen);
// Draw the shadow background.
c.drawRect(0, 0, right, bottom, mBackgroundPaint);
// Punch out the heart shape.
Bitmap heart = BitmapFactory.decodeResource(getResources(), R.drawable.heart_image_solid);
heart = Bitmap.createScaledBitmap(heart, (int) rect.width(), (int) rect.height(), true);
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
c.drawBitmap(heart, rect.left, rect.top, paint);
// Now overdraw with the heart frame.
heart = BitmapFactory.decodeResource(getResources(), R.drawable.heart_image_frame);
heart = Bitmap.createScaledBitmap(heart, (int) rect.width(), (int) rect.height(), true);
c.drawBitmap(heart, rect.left, rect.top, null);
canvas.drawBitmap(screen, 0, 0, null);
} else {
mPath.reset();
if (Build.VERSION.SDK_INT <= 17 && mCropShape == CropImageView.CropShape.OVAL) {
mDrawRect.set(rect.left + 2, rect.top + 2, rect.right - 2, rect.bottom - 2);
} else {
mDrawRect.set(rect.left, rect.top, rect.right, rect.bottom);
}
mPath.addOval(mDrawRect, Path.Direction.CW);
canvas.save();
canvas.clipPath(mPath, Region.Op.XOR);
canvas.drawRect(left, top, right, bottom, mBackgroundPaint);
canvas.restore();
}
}
/**
* Draw borders of the crop area.
*/
private void drawBorders(Canvas canvas) {
if (mBorderPaint != null) {
float w = mBorderPaint.getStrokeWidth();
RectF rect = mCropWindowHandler.getRect();
rect.inset(w / 2, w / 2);
if (mCropShape == CropImageView.CropShape.RECTANGLE) {
// Draw rectangle crop window border.
canvas.drawRect(rect, mBorderPaint);
} else if (mCropShape == CropImageView.CropShape.OVAL) {
// Draw circular crop window border
canvas.drawOval(rect, mBorderPaint);
}
}
}
将以下方法添加到CropImage.java
。此方法将裁剪心脏图像并对其进行构图。
<强> CropImage 强>
/**
* Create a new bitmap that has all pixels beyond the heart shape transparent. Old bitmap is
* recycled.
*/
public static Bitmap toHeartBitmap(@NonNull Bitmap bitmap, @NonNull Context context) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
int color = 0xff424242;
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
RectF rect = new RectF(0, 0, width, height);
// Get solid heart to mask out the portion of the image we want to keep.
Bitmap heart = BitmapFactory.decodeResource(context.getResources(), R.drawable.heart_image_solid);
heart = Bitmap.createScaledBitmap(heart, width, height, true);
canvas.drawBitmap(heart, 0, 0, null);
// SRC_IN means to keep the portion of the bitmap that overlaps the solid heart. All pixels
// from the solid heart and outside the solid heart area of the bitmap are tossed.
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, 0, 0, paint);
// We now have an unframed heart shape. Get the heart frame and apply it.
heart = BitmapFactory.decodeResource(context.getResources(), R.drawable.heart_image_frame);
heart = Bitmap.createScaledBitmap(heart, width, height, true);
canvas.drawBitmap(heart, 0, 0, null);
bitmap.recycle();
return output;
}
以下是演示应用程序的主要活动,展示了如何使用心形调用裁剪库:
<强> MainActivity.java 强>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.retry).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
cropImage();
}
});
cropImage();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if (result == null) {
return;
}
Uri picUri = result.getUri();
if (picUri == null) {
return;
}
Bitmap bitmap;
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), picUri);
}
if (bitmap == null) {
return;
}
ImageView imageView = findViewById(R.id.imageView);
imageView.setImageBitmap(CropImage.toHeartBitmap(bitmap, this));
}
private void cropImage() {
CropImage.activity().setGuidelines(CropImageView.Guidelines.ON)
.setCropShape(CropImageView.CropShape.HEART)
.start(MainActivity.this);
}
}
答案 1 :(得分:0)
您必须使用类似Opencv的内容,并将心脏图像叠加到裁剪后的图像上。确保心脏在您想要覆盖图像的位置是透明的
Mat heartMat = new Mat (bmp.getWidth(), bmp.getHeight(), CvType.CV_8UC3); Utils.bitmapToMat(bmp, heartMat);
Mat imgMat = new Mat (bmp.getWidth(), bmp.getHeight(), CvType.CV_8UC3); Utils.bitmapToMat(bmp, imgMat);
heartMat.copyTo(imgMat);
答案 2 :(得分:0)
要将特定图像转换为任何形状,您需要对该图像应用蒙版或具有特定形状的位图(在您的情况下,蒙版图像将为心形)。参考给定的链接。它可能对你有帮助。