Обрезать/отрегулировать изображение в форме сердца/раме

Я пытаюсь обрезать или отрегулировать изображение в соответствии с формой сердца. Пользователь может отрегулировать изображение в соответствии с формой сердца и задать изображение в форме сердца.

В настоящее время я использую Github Project для обрезки изображения как квадрата и установки формы сердца. Но все изображения вырезаются с верхней стороны, где сердце изогнуто. Итак, я хочу разрешить пользователю обрезать изображение в соответствии с границей сердца, а затем установить способ, которым пользователь хочет. Но нет никакой библиотеки, которую я могу настроить или использовать.

Вот текущий код, который я использую из проекта github.

  • Чтобы открыть камеру и галерею:

    CropImage.activity(). setGuidelines (CropImageView.Guidelines.ON).start(this);

  • Получение изображения и настройки изображения в ImageHeart View.

    CropImage.ActivityResult result = CropImage.getActivityResult(данные),
                  picUri = result.getUri();
                  bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), picUri);
         imvHeartRed.setImageBitmap(растровый);

Вот изображение, в котором я обрезаю стекло, используя квадратную обрезку, но при установке полного стекла изображение не наступит. Но если пользователь обрезает его с помощью формы сердца, будет показано полное стекло, потому что пользователь узнает, какая часть изображения будет обрезана.

введите описание изображения здесь

Любая помощь, ссылка будет действительно оценена.

Я не хочу напрямую устанавливать изображение в сердце, но пользователь может настроить изображение в сердце, коснувшись/движущегося

Ответ 1

Обновлен, чтобы иметь прозрачность, установленную только в форме сердца.

Если вам просто нужно вырезать изображение на основе созданной вами формы, вы можете использовать библиотеку, такую ​​как mafs-image-shape, но вам нужно будет предоставить способ манипулировать расположением фигур, прежде чем вырезать изображение.

Я предполагаю, что вы полагаетесь на структуру Android-Image-Cropper, поэтому к этой библиотеке применяются следующие изменения. Показанный код основан на выбранном коде Android-Image-Cropper, который лицензируется под Apache Лицензия 2.0.

Вот как выглядит пример приложения после внесения следующих изменений. В следующем обсуждении объясняется, как изменить базовый код для размещения формы сердца.

введите описание изображения здесь

Форма сердца должна быть определена как опция в дополнение к прямоугольнику и овалу. Чтобы сделать фигуру сердца опцией, измените enum 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>

Я использовал два изображения для формы сердца. Первое изображение представляет собой изображение кадрирования, которое используется для размещения кадра на базовом изображении. Изображение обрезки совпадает с изображением кадрирования, но является сплошным (альфа == 1), где изображение должно сохраняться во время операции обрезки. Прозрачные области должны иметь значение альфа, равное нулю. Вот изображения, которые я использовал, но вы захотите использовать свои собственные.

введите описание изображения здесь введите описание изображения здесь

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

Ответ 2

Вы должны использовать что-то вроде 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);

Ответ 3

Для преобразования определенного изображения в любую фигуру вам необходимо применить маскирование на этом изображении или растровое изображение с определенной формой (в вашем случае изображение маски будет иметь форму сердца). См. Данную ссылку. Это может помочь вам.

Ссылка: fooobar.com/info/72519/...