美文网首页
颜色混合

颜色混合

作者: Wi1ls努力努力再努力 | 来源:发表于2019-05-08 11:21 被阅读0次

    设计给了一个需求,需要在图片的点击态下增加 10%的黑色遮罩。并且只在有 alpha 通道的像素增加。于是需要进行颜色的混合。iOS 的同学已经做完了,于是要了算法

    - (UIColor *)bmbw_addColor:(UIColor *)addColor {
      NSArray *baseColorArr = [self bmbw_getRGBA];
      NSArray *addColorArr = [addColor bmbw_getRGBA];
    
      CGFloat alpha1 = [baseColorArr[3] doubleValue];
      CGFloat alpha2 = [addColorArr[3] doubleValue];
      CGFloat alpha = alpha1 + alpha2 - alpha1 * alpha2;
    
      CGFloat red1 = [baseColorArr[0] doubleValue];
      CGFloat red2 = [addColorArr[0] doubleValue];
      CGFloat red = (red1 * alpha1 * (1.0 - alpha2) + red2 * alpha2) / alpha;
    
      CGFloat green1 = [baseColorArr[1] doubleValue];
      CGFloat green2 = [addColorArr[1] doubleValue];
      CGFloat green = (green1 * alpha1 * (1.0 - alpha2) + green2 * alpha2) / alpha;
    
      CGFloat blue1 = [baseColorArr[2] doubleValue];
      CGFloat blue2 = [addColorArr[2] doubleValue];
      CGFloat blue = (blue1 * alpha1 * (1.0 - alpha2) + blue2 * alpha2) / alpha;
    
      return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
    }
    
    - (NSArray *)bmbw_getRGBA {
      CGFloat red = 0.0;
      CGFloat green = 0.0;
      CGFloat blue = 0.0;
      CGFloat alpha = 0.0;
      [self getRed:&red green:&green blue:&blue alpha:&alpha];
      return @[@(red), @(green), @(blue), @(alpha)];
    }
    

    发现 iOS 的算法对于通道的取值是从 0-1 的,而 Android 是0x00 到0xff,于是要修改一下算法

    private Bitmap mixBitmap(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
    
        // 保存所有的像素的数组,图片宽×高
        int[] pixels = new int[width * height];
        int[] newPixels = new int[width * height];
    
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    
        int addAlpha = 0x1A;
        int addRed = 0x00;
        int addGreen = 0x00;
        int addBlue = 0x00;
    
    
        for (int i = 0; i < pixels.length; i++) {
          int clr = pixels[i];
          int alpha = (clr & 0xff000000) >>> 24;
          if (alpha == 0x00) {
            pixels[i] = 0x00ffffff;
            continue;
          }
          int red = (clr & 0x00ff0000) >>> 16;
          int green = (clr & 0x0000ff00) >>> 8;
          int blue = clr & 0x000000ff;
          //
          int mixAlpha = alpha + addAlpha - alpha * addAlpha / 0xff;
          int mixRed = mixColor(red, alpha, addRed, addAlpha, mixAlpha);
          int mixGreen = mixColor(green, alpha, addGreen, addAlpha, mixAlpha);
          int mixBlue = mixColor(blue, alpha, addBlue, addAlpha, mixAlpha);
          newPixels[i] = Color.argb(mixAlpha, mixRed, mixGreen, mixBlue);
        }
        return Bitmap.createBitmap(newPixels, width, height, Bitmap.Config.ARGB_8888);
      }
    
      private int mixColor(int or, int oa, int ar, int aa, int ma) {
        return ((or * oa * (0xff - aa) + ar * aa * 0xff) / ma) /0xff;
      }
    

    算法中采取>>>而不是>>,是因为当 在进行移位的时候需要用0 补齐,不然 aplha 是0xff 的时候,通过>>会得到-1;
    有些地方用/0xff 而不是>>>8,是为了进位。如果用>>>8实际的时候发现有时候 mixAplha 是 256,而/0xff 则是255;

    相关文章

      网友评论

          本文标题:颜色混合

          本文链接:https://www.haomeiwen.com/subject/daqmoqtx.html