Skip to content

Instantly share code, notes, and snippets.

@Den-Rimus
Created November 21, 2014 09:10
Show Gist options
  • Save Den-Rimus/a64615b197f04869a5a6 to your computer and use it in GitHub Desktop.
Save Den-Rimus/a64615b197f04869a5a6 to your computer and use it in GitHub Desktop.
Blender modes for android
package com.example.blendmodes;
import android.graphics.Bitmap;
import android.util.Log;
public class Blender {
private static final String TAG = Blender.class.getSimpleName();
public static Bitmap performBlending(Bitmap source, Bitmap destination, int mode) {
return performBlending(source, destination, mode, 1F);
}
public static Bitmap performBlending(Bitmap source, Bitmap destination, int mode, float alpha) {
int width = source.getWidth();
int height = source.getHeight();
int srcPixels[] = new int[width * height];;
int destPixels[] = new int[width * height];
int resultPixels[] = new int[width * height];
int aS = 0, rS = 0, gS = 0, bS = 0;
int rgbS = 0;
int aD = 0, rD = 0, gD = 0, bD = 0;
int rgbD = 0;
try
{
source.getPixels(srcPixels, 0, width, 0, 0, width, height);
destination.getPixels(destPixels, 0, width, 0, 0, width, height);
source.recycle();
destination.recycle();
}
catch(IllegalArgumentException e) {
}
catch(ArrayIndexOutOfBoundsException e) {
}
if (mode == Mode.SOFT_LIGHT || mode == Mode.OVERLAY) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
rgbS = srcPixels[y * width + x];
aS = (rgbS >> 24) & 0xff;
rS = (rgbS >> 16) & 0xff;
gS = (rgbS >> 8) & 0xff;
bS = (rgbS) & 0xff;
rgbD = destPixels[y * width + x];
aD = (rgbD >> 24) & 0xff;
rD = (rgbD >> 16) & 0xff;
gD = (rgbD >> 8) & 0xff;
bD = (rgbD) & 0xff;
rS = blendByte(rD, rS, mode);
gS = blendByte(gD, gS, mode);
bS = blendByte(bD, bS, mode);
aS = aS + aD - Math.round((aS * aD) / 255f);
resultPixels[y * width + x] = ((int) aS << 24) | ((int) rS << 16) | ((int) gS << 8) | (int) bS;
}
}
} else {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
rgbS = srcPixels[y * width + x];
aS = (rgbS >> 24) & 0xff;
rS = (rgbS >> 16) & 0xff;
gS = (rgbS >> 8) & 0xff;
bS = (rgbS) & 0xff;
Color S = new Color(aS, rS, gS, bS);
rgbD = destPixels[y * width + x];
aD = (rgbD >> 24) & 0xff;
rD = (rgbD >> 16) & 0xff;
gD = (rgbD >> 8) & 0xff;
bD = (rgbD) & 0xff;
Color D = new Color(aD, rD, gD, bD);
Color resultColor = setLum(D, lum(S));
rS = resultColor.r;
gS = resultColor.g;
bS = resultColor.b;
aS = aS + aD - Math.round((aS * aD) / 255f);
resultPixels[y * width + x] = ((int) aS << 24) | ((int) rS << 16) | ((int) gS << 8) | (int) bS;
}
}
}
return Bitmap.createBitmap(resultPixels, width, height, source.getConfig());
}
private static int blendByte(int colChannelDest, int colChannelSrc, int mode) {
int result = 0;
switch (mode) {
case Mode.SOFT_LIGHT:
result = softLightBlendByte(colChannelDest, colChannelSrc);
break;
case Mode.OVERLAY:
result = overlayBlendByte(colChannelDest, colChannelSrc);
}
return result;
}
/** http://stackoverflow.com/questions/5919663/how-does-photoshop-blend-two-images-together */
private static int softLightBlendByte(int A, int B) {
return ((int) ( (B < 128) ? (2*((A>>1)+64))*((float)B/255) : (255-(2*(255-((A>>1)+64))*(float)(255-B)/255))));
}
/** http://stackoverflow.com/questions/5919663/how-does-photoshop-blend-two-images-together */
private static int overlayBlendByte(int A, int B) {
return (((B < 128) ? (2 * A * B / 255) : (255 - 2 * (255 - A) * (255 - B) / 255)));
}
private static Color setLum(Color c, int l) {
int d = l - lum(c);
c.r += d;
c.g += d;
c.b += d;
return clipColor(c);
}
private static int lum(Color c) {
return (int) Math.round((0.3 * c.r) + (0.59 * c.g) + (0.11 * c.b));
}
private static Color clipColor(Color c) {
int l = lum(c);
int n = Math.min(Math.min(c.r, c.g), c.b);
int x = Math.max(Math.max(c.r, c.g), c.b);
Color resCol = new Color();
resCol.r = clipChannel(c.r, l, n, x);
resCol.g = clipChannel(c.g, l, n, x);
resCol.b = clipChannel(c.b, l, n, x);
return clamp(resCol, 0, 255);
}
private static int clipChannel(int ch, int l, int n, int x) {
ch = (n < 0) ? l + (((ch - l) * l) / (l - n)) : ch;
ch = (x > 255) ? l + (((ch - l) * (255 - l)) / (x - l)) : ch;
return ch;
}
public static Color clamp(Color c, int min, int max) {
c.r = clamp(c.r, min, max);
c.g = clamp(c.g, min, max);
c.b = clamp(c.b, min, max);
return c;
}
public static int clamp(int c, int min, int max) {
if (c < min) {
// Log.d(TAG, "Clamped: " + c + " > " + min);
return min;
}
else if(c > max) {
// Log.d(TAG, "Clamped: " + c + " > " + max);
return max;
}
else return c;
}
public static class Mode {
public static final int SOFT_LIGHT = 42;
public static final int OVERLAY = 43;
public static final int COLOR = 44;
}
private static class Color {
public int a;
public int r;
public int g;
public int b;
public Color() {
new Color(0, 0, 0, 0);
}
public Color(int a, int r, int g, int b) {
this.a = a;
this.r = r;
this.g = g;
this.b = b;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment