web-dev-qa-db-fra.com

Rogner/ajuster l'image en forme de coeur/cadre

J'essaie de rogner ou d'ajuster l'image selon la forme du cœur. L'utilisateur peut ajuster l'image en fonction de la forme du cœur et définir l'image sur cette forme. 

Actuellement, j'utilise Github Project library pour rogner l'image sous forme de carré et la définir en forme de cœur. Mais toutes les images sont coupées du côté supérieur où le cœur est courbé. Donc, je veux permettre à l'utilisateur de rogner l'image selon la bordure du cœur, puis de définir la façon dont l'utilisateur le souhaite. Mais il n’existe aucune bibliothèque que je puisse personnaliser ou utiliser. 

Voici le code actuel que j'utilise depuis le projet github ci-dessus. 

  1. Pour ouvrir Appareil photo et Galerie: 

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

  2. Obtenir une image de rognage et la définir sur ImageHeart View. 

    CropImage.ActivityResult resultat = CropImage.getActivityResult (données);
    picUri = result.getUri ();
    bitmap = MediaStore.Images.Media.getBitmap (this.getContentResolver (), picUri);
    imvHeartRed.setImageBitmap (bitmap);

Voici une image dans laquelle je recadre le verre en utilisant un recadrage carré mais que je ne vis pas en plein écran. Mais si l'utilisateur le recadre en utilisant la forme de cœur, le verre sera plein, car il saura quelle partie de l'image sera recadrée. 

 enter image description here

Toute aide, référence sera vraiment appréciée. 

Je ne veux pas définir l'image dans le coeur directement, mais l'utilisateur peut ajuster l'image dans le coeur en touchant/se déplaçant

12
Sandip Armal Patil

Mise à jour pour que la transparence ne soit définie que dans la forme de cœur.

Si vous devez simplement supprimer une image à partir d’une forme que vous créez, vous pouvez utiliser une bibliothèque telle que mafs-image-shape , mais vous devrez fournir un moyen de manipuler l’emplacement de la forme avant de découper le image. 

Je suppose que vous vous appuyez sur la structure de Android-Image-Cropper, de sorte que les modifications suivantes s'appliquent à cette bibliothèque. Le code affiché est basé sur le code sélectionné dans Android-Image-Cropper qui est sous licence Apache License 2.0 .

Voici à quoi ressemble un exemple d'application après avoir apporté les modifications suivantes. La discussion qui suit explique comment changer le code de base pour s'adapter à la forme d'un cœur.

 enter image description here

La forme de coeur doit être définie comme une option en plus d'un rectangle et d'un ovale. Pour que le cœur soit une forme, changez la variable CropShape en CropImageView pour ajouter HEART en tant que forme de rognage et ajoutez heart en tant qu'option cropShape dans 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>

J'ai utilisé deux images pour la forme de coeur. La première image est l'image de cadrage utilisée pour positionner le cadre sur l'image sous-jacente. L'image de rognage est la même que l'image de cadrage, mais est pleine (alpha == 1) partout où l'image doit être conservée pendant l'opération de rognage. Les zones transparentes doivent avoir la valeur alpha définie sur zéro. Voici les images que j'ai utilisées, mais vous voudrez utiliser les vôtres.

 enter image description here  enter image description here

CropOverlayView est une vue personnalisée qui présente la fenêtre de recadrage et l’arrière-plan ombré. Modifiez les méthodes drawBackground et drawBorders de cette classe comme suit pour s'adapter à la forme d'un cœur.

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

Ajoutez la méthode suivante à CropImage.Java. Cette méthode permet de recadrer l'image du cœur et de l'encadrer.

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

Voici l'activité principale de l'application de démonstration montrant comment appeler la bibliothèque de recadrage à l'aide de la forme de cœur:

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

Pour convertir une image spécifique en toute forme, vous devez appliquer le Masquage à cette image ou à une image bitmap de forme spécifique (dans votre cas, l’image de masque sera en forme de cœur). Voir le lien donné. Cela peut vous aider.

Lien: https://stackoverflow.com/a/12637039/7461291

0
Hitesh Modhwadia

Vous devez utiliser quelque chose comme Opencv et simplement superposer l'image du cœur sur votre image recadrée. Assurez-vous que le cœur est transparent à l'endroit où vous souhaitez surcharger l'image 

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);
0
Niza Siwale