掩蔽(裁剪)帧中的图像

Posted

技术标签:

【中文标题】掩蔽(裁剪)帧中的图像【英文标题】:Masking(crop) image in frame 【发布时间】:2012-09-18 20:02:52 【问题描述】:

有一个丰富的 UI 应用程序,我想在其中显示像这样复杂形状的图像

现在我想要的是按照蒙版图像裁剪我的图像,实际上 图像是动态的,可以从相机或图库(方形或矩形形状)导入,我希望该图像适合在我上面的布局框架中

所以只是想知道我是如何实现这一目标的?任何想法/提示欢迎

背景框面具

点赞this

【问题讨论】:

【参考方案1】:

在更改蒙版图像并使用XfermodeBitmap时终于得到了解决方案

面具

 ImageView mImageView= (ImageView)findViewById(R.id.imageview_id);
 Bitmap original = BitmapFactory.decodeResource(getResources(),R.drawable.content_image);
 Bitmap mask = BitmapFactory.decodeResource(getResources(),R.drawable.mask);
 Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Config.ARGB_8888);
 Canvas mCanvas = new Canvas(result);
 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
 mCanvas.drawBitmap(original, 0, 0, null);
 mCanvas.drawBitmap(mask, 0, 0, paint);
 paint.setXfermode(null);
 mImageView.setImageBitmap(result);
 mImageView.setScaleType(ScaleType.CENTER);
 mImageView.setBackgroundResource(R.drawable.background_frame);

查看输出

来源可以找到here

【讨论】:

你好@hotveryspicy,感谢示例代码,它帮助很大。我面临一些问题,一些小提示对我来说会有很长的路要走。我想以绘制的一些多边形形状切割位图。我的位图切割成多边形,但裁剪位图的内容取自左上角,即原始位图的 0,0。我想要绘制多边形的下面的内容。 @Nidhi 你可以创建相同的缩放位图。 @hotveryspicy 谢谢你的回复。实际上我想做这里给出的同样的事情。 ***.com/questions/15969028/…。我的问题是裁剪位图是从左上角裁剪,即 0,0。不形成我指定的路径。我也放了代码。请指导我哪里出错了。 感谢@hotveryspicy,对于任何需要它的人,我做了一个简单的叉子,可以帮助将图像缩放到面具的大小:github.com/worker8/MaskImage/tree/master 要缩放蒙版以适应图像,我使用这一行:Bitmap resized = Bitmap.createScaledBitmap(mask, original.getWidth(), original.getHeight(), true);并使用 mCanvas.drawBitmap(original, 0, 0, null); mCanvas.drawBitmap(resized, 0, 0, paint);【参考方案2】:

使用 Picasso 库和自定义转换更容易:

MaskTransformation.java:

 * ORIGINAL:
 * Copyright (C) 2015 Wasabeef
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package me.monori.example.utilities;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;

import com.squareup.picasso.Transformation;

public class MaskTransformation implements Transformation 

    private static Paint mMaskingPaint = new Paint();
    private Context mContext;
    private int mMaskId;

    static 
        mMaskingPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    

    /**
     * @param maskId If you change the mask file, please also rename the mask file, or Glide will get
     * the cache with the old mask. Because getId() return the same values if using the
     * same make file name. If you have a good idea please tell us, thanks.
     */
    public MaskTransformation(Context context, int maskId) 
        mContext = context.getApplicationContext();
        mMaskId = maskId;
    

    @Override public Bitmap transform(Bitmap source) 
        int width = source.getWidth();
        int height = source.getHeight();

        Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

        Drawable mask = getMaskDrawable(mContext, mMaskId);

        Canvas canvas = new Canvas(result);
        mask.setBounds(0, 0, width, height);
        mask.draw(canvas);
        canvas.drawBitmap(source, 0, 0, mMaskingPaint);

        source.recycle();

        return result;
    

    @Override public String key() 
        return "MaskTransformation(maskId=" + mContext.getResources().getResourceEntryName(mMaskId)
                + ")";
    

    public Drawable getMaskDrawable(Context context, int maskId) 
        Drawable drawable = ContextCompat.getDrawable(context, maskId);

        if (drawable == null) 
            throw new IllegalArgumentException("maskId is invalid");
        

        return drawable;
    

然后简单地在一行中定义它:

Picasso.with(context)
                    .load(imageUrl)
                    .transform(new MaskTransformation(context, _maskDrawableId))
                    .placeholder(R.drawable.drawableId)
                    .into(imageView);

【讨论】:

【参考方案3】:
     final ImageView mImageView = (ImageView) findViewById(R.id.image);
     mImageView.setBackgroundResource(R.drawable.user_outer_circle_icon);


     mImageView.setOnClickListener(new OnClickListener() 

        @Override
        public void onClick(View v) 


            if(b)
                 mImageView.setBackgroundResource(R.drawable.profil_circle);

                 Bitmap original = BitmapFactory.decodeResource(getResources(),R.drawable.doge);

                 Bitmap mask = BitmapFactory.decodeResource(getResources(),R.drawable.mask_white);

                 Bitmap mask1 = BitmapFactory.decodeResource(getResources(),R.drawable.pencil_bg);

                 original = Bitmap.createScaledBitmap(original, mask.getWidth(),mask.getHeight(), true);

                 Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(),Config.ARGB_8888);
                 Canvas mCanvas = new Canvas(result);
                 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
                 mCanvas.drawBitmap(original, 0, 0, null);
                 mCanvas.drawBitmap(mask, 0, 0, paint);
                 mCanvas.drawBitmap(mask1, 0, 0, null);
                 Bitmap mask2 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_pencil);
                 mCanvas.drawBitmap(mask2, 0, 0, null);
                 mImageView.setImageBitmap(result);
                 mImageView.setScaleType(ScaleType.FIT_XY);

                 b=false;
             else
                 ImageView mImageView = (ImageView) findViewById(R.id.image);
                 Bitmap original = BitmapFactory.decodeResource(getResources(),
                 R.drawable.doge);

                 Bitmap mask = BitmapFactory.decodeResource(getResources(),
                 R.drawable.mask_white);

                 original = Bitmap.createScaledBitmap(original, mask.getWidth(),
                 mask.getHeight(), true);

                 Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(),
                 Config.ARGB_8888);
                 Canvas mCanvas = new Canvas(result);
                 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
                 mCanvas.drawBitmap(original, 0, 0, null);
                 mCanvas.drawBitmap(mask, 0, 0, paint);
                 paint.setXfermode(null);
                 mImageView.setImageBitmap(result);
                 mImageView.setScaleType(ScaleType.FIT_XY);
                // mImageView.setBackgroundResource(R.drawable.user_outer_circle_icon);
                 b= true;


             


        
    );

【讨论】:

【参考方案4】:

这个例子用掩码“animation_mask”屏蔽了他的子元素(Imageview)

<com.christophesmet.android.views.maskableframelayout.MaskableFrameLayout
android:id="@+id/frm_mask_animated"
android:layout_
app:porterduffxfermode="DST_IN"
app:mask="@drawable/animation_mask"
android:layout_>

<ImageView android:layout_
           android:layout_
           android:scaleType="centerCrop"
           android:src="@drawable/unicorn"/>

check this git link

【讨论】:

以上是关于掩蔽(裁剪)帧中的图像的主要内容,如果未能解决你的问题,请参考以下文章

从 iPhone 中的视频帧中获取图像

TFS 掩蔽或取消掩蔽工作区中的文件夹

在掩蔽语言建模期间掩蔽每个输入句子中的特定标记

如何将视频文件作为输入传递给 NodeJS 中的子进程并接收帧/图像作为输出?

如何使用默认裁剪意图裁剪 android marshmallow 中的图像?

R中的裁剪图像