【问题标题】:Android Mask bitmap on canvas gen a black space画布上的Android Mask位图生成黑色空间
【发布时间】:2014-05-31 04:05:53
【问题描述】:

我有一个蒙版位图,一半是红色,一个是透明的,像这样 https://www.dropbox.com/s/931ixef6myzusi0/s_2.png

我想用遮罩位图在画布上绘制内容,只在红色区域可见,代码如下:

Paint paint = new Paint();


public void draw(Canvas canvas) {
// draw content here
  ...

//and mask bitmap here
  paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_IN));
  canvas.drawBitmap(maskBitmap, 0, 0, paint);

}

结果如我所愿(内容仅在红色区域可见,但透明区域变为黑色是问题!)

此图像结果:https://www.dropbox.com/s/mqj48992wllfkiq/s_2%20copy.png 有人帮我吗???

【问题讨论】:

    标签: android bitmap mask


    【解决方案1】:

    这是一个帮助我实现屏蔽的解决方案:

    public void draw(Canvas canvas) {
            Bitmap original = BitmapFactory.decodeResource(getContext().getResources(),R.drawable.original_image);
            Bitmap mask = BitmapFactory.decodeResource(getContext().getResources(),R.drawable.mask_image);
    
            //You can change original image here and draw anything you want to be masked on it.
    
            Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Config.ARGB_8888);
            Canvas tempCanvas = new Canvas(result);
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
            tempCanvas.drawBitmap(original, 0, 0, null);
            tempCanvas.drawBitmap(mask, 0, 0, paint);
            paint.setXfermode(null);
    
            //Draw result after performing masking
            canvas.drawBitmap(result, 0, 0, new Paint());
    }
    

    蒙版应该是具有透明度的白色图像。
    它将像这样工作:
    + =

    【讨论】:

    • 这会很慢,因为屏幕外画布没有硬件加速
    • 我发现即使您使用 OpenGL,画布图形仍然非常必要,因为它可以动态生成图形,以后可以将其加载到 OpenGL 着色器中。也就是说,这仍然很有用。
    • 但是在 onDraw() 中创建位图可能会导致内存不足异常
    • 它不应该是白色的,就像你提到的那样。透明通道就足够了。检查developer.android.com/reference/android/graphics/…
    • 你传入draw参数的内容
    【解决方案2】:

    我在自定义视图中遇到了同样的问题,我没有从资源中解码位图,而是通过canvas.draw*() 方法从头开始创建了原始位图和掩码位图(因为原始位图和蒙版都是基本形状)。我得到的是blank opaque space,而不是transparent。我通过在我的视图中设置一个硬件层来修复它。

    View.setLayerType(LAYER_TYPE_HARDWARE, paint);
    

    更多关于为什么要这样做的信息:https://stackoverflow.com/a/33483016/4747587

    【讨论】:

      【解决方案3】:
      Bitmap finalMasking = stackMaskingProcess(imageBitmap, bitmapMasking);
      
      
      private Bitmap stackMaskingProcess(Bitmap _originalBitmap, Bitmap _maskingBitmap) {
              try {
                  if (_originalBitmap != null)
                  {
                      int intWidth = _originalBitmap.getWidth();
                      int intHeight = _originalBitmap.getHeight();
                      resultMaskBitmap = Bitmap.createBitmap(intWidth, intHeight, Bitmap.Config.ARGB_8888);
                      getMaskBitmap = Bitmap.createScaledBitmap(_maskingBitmap, intWidth, intHeight, true);
                      Canvas mCanvas = new Canvas(resultMaskBitmap);
                      Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                      paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
                      mCanvas.drawBitmap(_originalBitmap, 0, 0, null);
                      mCanvas.drawBitmap(getMaskBitmap, 0, 0, paint);
                      paint.setXfermode(null);
                      paint.setStyle(Paint.Style.STROKE);
                  }
              } catch (OutOfMemoryError o) {
                  o.printStackTrace();
              }
              return resultMaskBitmap;
          }
      

      【讨论】:

        【解决方案4】:

        我喜欢Er. Praful Parmar's 答案中的方法,但对我来说,它并没有达到预期的效果。我遇到了问题,因为一些扩展是在无意中进行的。
        我的位图的密度与我的设备不同,这搞砸了。

        另外我想减少对象的创建,所以我将Paint对象移动到一个常量中以便重复使用。

        这是我的 utils 方法:

          public static final//
          Bitmap createWithMask(final Bitmap img, final Bitmap mask) {
            final Bitmap result = Bitmap.createBitmap(img.getWidth(), img.getHeight(),
                Bitmap.Config.ARGB_8888);
            result.setDensity(originalBitmap.getDensity()); // to avoid scaling if density of 'img' is different form the default on your device
            final Canvas canvas = new Canvas(result);
            canvas.drawBitmap(img, 0, 0, null);
            canvas.drawBitmap(mask, 0, 0, PAINT_FOR_MASK);
            return result;
          }//end-method
        
          private static final Paint PAINT_FOR_MASK = createPaintForMask();
        
          private static final//
          Paint createPaintForMask() {
            final Paint paint = new Paint();
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            return paint;
          }//end-method
        

        【讨论】:

          【解决方案5】:

          与@Sergey Pekar 给出的答案相同,但我已在 Kotlin 中进行了更新。

          fun ImageView.getMaskBitmap(imageUrl: String? = null, mContent: Int, mMaskedImage : Int) {
              runOnBackground {
                  // if you have https image url then use below line
                  //val original: Bitmap = BitmapFactory.decodeStream(URL(imageUrl).openConnection().getInputStream())
          
                  // if you have png or jpg image then use below line
                  val original: Bitmap = BitmapFactory.decodeResource(resources, mContent)
          
                  val mask = BitmapFactory.decodeResource(resources, mMaskedImage) // mMaskedImage Your masking image
                  val result: Bitmap = Bitmap.createBitmap(mask.width, mask.height, Bitmap.Config.ARGB_8888, true)
                  val tempCanvas = Canvas(result)
                  val paint = Paint(Paint.ANTI_ALIAS_FLAG)
                  paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
                  tempCanvas.apply {
                      drawBitmap(original, 0f, 0f, null)
                      drawBitmap(mask, 0f, 0f, paint)
                  }
                  paint.xfermode = null
          
                  //Draw result after performing masking
                  runOnBackground(onMainThread = {
                      this.apply {
                          setImageBitmap(result)
                          scaleType = ImageView.ScaleType.FIT_CENTER
                      }
                  })
              }
          }
          

          Github Demo

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-11-25
            • 1970-01-01
            • 2014-01-22
            • 1970-01-01
            • 2015-02-16
            • 1970-01-01
            • 1970-01-01
            • 2023-03-11
            相关资源
            最近更新 更多