颜色混合

2019-05-08  本文已影响0人  Wi1ls努力努力再努力

设计给了一个需求,需要在图片的点击态下增加 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;

上一篇下一篇

猜你喜欢

热点阅读