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