I got a problem with an Air Native Extension in Android.
The ANE receive a Bitmap from the Actionscript side, compress it in jpeg format and send it back to the Actionscript that will write it on the storage.
Everything is good but one last thing.
It seems that the channels order for Actionscript is different than in Android, so my compressed image have RED colors in place of BLUE.. here is the code:
Actionscript (I'm using a library called deng.fzip.FZipLibrary to get the bitmap from a zip package)
__image = __fl.getBitmapData(path);
__de = new DataExchange();
__ba = __de.bitmapEncode(__image) as ByteArray;
Android
...
try {
inputValue = (FREBitmapData)arg1[0];
inputValue.acquire();
int srcWidth = inputValue.getWidth();
int srcHeight = inputValue.getHeight();
Bitmap bm = Bitmap.createBitmap(srcWidth, srcHeight, Config.ARGB_8888);
bm.copyPixelsFromBuffer(inputValue.getBits());
ByteArrayOutputStream os = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 80, os);
compressed = os.toByteArray();
inputValue.release();
} catch (Exception e) {
e.printStackTrace();
}
try {
returnValue = FREByteArray.newByteArray();
returnValue.setProperty("length", FREObject.newObject(compressed.length));
returnValue.acquire();
ByteBuffer returnBytes = returnValue.getBytes();
returnBytes.put(compressed, 0, compressed.length);
returnValue.release();
}
...
Anyone have an idea on how to convert the red to blue in the android side before send the image back? Or it needs to be done in the actionscript side?
Thank you very much and regards,
Gianpiero
You can switch the colors like this:
(This code does not origin from me, unfortunately I forgot where I found it, so credit goes somewhere else)
private Bitmap m_encodingBitmap = null;
private Canvas m_canvas = null;
private Paint m_paint = null;
private final float[] m_bgrToRgbColorTransform =
{
0, 0, 1f, 0, 0,
0, 1f, 0, 0, 0,
1f, 0, 0, 0, 0,
0, 0, 0, 1f, 0
};
private final ColorMatrix m_colorMatrix = new ColorMatrix(m_bgrToRgbColorTransform);
private final ColorMatrixColorFilter m_colorFilter = new ColorMatrixColorFilter(m_colorMatrix);
...
try{
FREBitmapData as3Bitmap = (FREBitmapData)args[0];
as3Bitmap.acquire();
m_encodingBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
m_canvas = new Canvas(m_encodingBitmap);
m_paint = new Paint();
m_paint.setColorFilter(m_colorFilter);
m_encodingBitmap.copyPixelsFromBuffer(as3BitmapBytes);
as3Bitmap.release();
//
// Convert the bitmap from BGRA to RGBA.
//
m_canvas.drawBitmap(m_encodingBitmap, 0, 0, m_paint);
...
}
Hope that helps ... Timm
Related
I have a class that uses a color matrix to add image effects on an ImageView. I have several color matrices for contrast,exposure,temperature and saturation.
Ex:
public static Bitmap changeContrast(Bitmap bmp, float contrast)
{
ColorMatrix cm = new ColorMatrix(new float[]
{
contrast, 0, 0, 0, 0,
0, contrast, 0, 0, 0,
0, 0, contrast, 0, 0,
0, 0, 0, 1, 0
});
return getBitmapFromColorMatrix(cm, bmp);
}
Now my problem is, the sharpening of the image. There seems to be no color matrix for these. Please help.
I tried sharpening the image using the code from here but it takes too long to process and I do not know what valid values should be passed to the weight parameter of the sharpenImage(Bitmap src, double weight) method.
It may be too late but i'd just wanted to share a fast way to sharpen an image.
public static Bitmap doSharpen(Bitmap original, float[] radius) {
Bitmap bitmap = Bitmap.createBitmap(
original.getWidth(), original.getHeight(),
Bitmap.Config.ARGB_8888);
RenderScript rs = RenderScript.create(yourContext);
Allocation allocIn = Allocation.createFromBitmap(rs, original);
Allocation allocOut = Allocation.createFromBitmap(rs, bitmap);
ScriptIntrinsicConvolve3x3 convolution
= ScriptIntrinsicConvolve3x3.create(rs, Element.U8_4(rs));
convolution.setInput(allocIn);
convolution.setCoefficients(radius);
convolution.forEach(allocOut);
allocOut.copyTo(bitmap);
rs.destroy();
return bitmap;
}
And here are 3 different sharpen types that i created:
// low
private static void loadBitmapSharp() {
float[] sharp = { -0.60f, -0.60f, -0.60f, -0.60f, 5.81f, -0.60f,
-0.60f, -0.60f, -0.60f };
//you call the method above and just paste the bitmap you want to apply it and the float of above
yourbitmap = doSharpen(getbitmap, sharp));
}
// medium
private static void loadBitmapSharp1() {
float[] sharp = { 0.0f, -1.0f, 0.0f, -1.0f, 5.0f, -1.0f, 0.0f, -1.0f,
0.0f
};
//you call the method above and just paste the bitmap you want to apply it and the float of above
yourbitmap = doSharpen(getbitmap, sharp));
}
// high
private static void loadBitmapSharp2() {
float[] sharp = { -0.15f, -0.15f, -0.15f, -0.15f, 2.2f, -0.15f, -0.15f,
-0.15f, -0.15f
};
//you call the method above and just paste the bitmap you want to apply it and the float of above
yourbitmap = doSharpen(getbitmap, sharp));
}
You can also apply them direct to a bitmap without a void, its fast simple and there are good results!
Here are the values that i used for color temperature with a seekbar. (you asked them into a comment of one question that i asked)
public static Bitmap doTemperature(Bitmap bmp, float temp){
ColorMatrix cm = new ColorMatrix(new float[]
{
1, 0, 0, temp, 0,
0, 1, 0, temp/2, 0,
0, 0, 1, temp/4, 0,
0, 0, 0, 1, 0
});
Bitmap ret = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());
Canvas canvas = new Canvas(ret);
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(cm));
canvas.drawBitmap(bmp, 0, 0, paint);
return ret;
}
//you call it with this method
private void loadBitmapTemp() {
//private Seekbar temp_value;
temp_value = (SeekBar) findViewById(R.id.temp_value);
temp_value.setMax(100);
temp_value.setProgress(50);
int progressTemp = temp_value.getProgress();
progressTemp -= 50;
float temp = (float) progressTemp / 220;
progress_text.setVisibility(View.VISIBLE);
progress_text.setText(" " + progressTemp * 2);
yourBitmap = doTemperature(getbitmap, temp));
}
Improving the first answer here, adding a seekbar (slider) to change the sharpness of an image.
public Bitmap doSharpen(Bitmap original, float multiplier) {
float[] sharp = { 0, -multiplier, 0, -multiplier, 5f*multiplier, -multiplier, 0, -multiplier, 0};
Bitmap bitmap = Bitmap.createBitmap(
original.getWidth(), original.getHeight(),
Bitmap.Config.ARGB_8888);
RenderScript rs = RenderScript.create(MainActivity.this);
Allocation allocIn = Allocation.createFromBitmap(rs, original);
Allocation allocOut = Allocation.createFromBitmap(rs, bitmap);
ScriptIntrinsicConvolve3x3 convolution
= ScriptIntrinsicConvolve3x3.create(rs, Element.U8_4(rs));
convolution.setInput(allocIn);
convolution.setCoefficients(sharp);
convolution.forEach(allocOut);
allocOut.copyTo(bitmap);
rs.destroy();
return bitmap;
}
I had to modify it a little according to my project. Instead of taking the convolution matrix in method, i declared it inside the method. We are going to take the changed variable of seekbar instead.
sharpnessSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
Bitmap sharpenedBitmap = doSharpen(btmp,(float)i);
imageV.setImageBitmap(sharpenedBitmap);
}
Inside the setOnSeekBarChangeListener we get the changed value which is int i and pass it with doSharpen method so that it can be used in the convolution matrix which is defined inside doSharpen() Method.
I am trying to chain two Renderscripts : ScriptIntrinsicBlur and ScriptIntrinsicColorMatrix.
I want to blur and image and then apply a color filter to it.
Here is my current code (I tried many different implementations, including ScriptGroups, that I can't get to work :
final ScriptIntrinsicBlur scriptBlur = ScriptIntrinsicBlur.create(
mRenderScript,
Element.U8_4(mRenderScript));
final Allocation input = Allocation.createFromBitmap(mRenderScript,
bmp);
Bitmap blurOutBitmap = bmp.copy(bmp.getConfig(), true);
final Allocation output = Allocation.createFromBitmap(
mRenderScript, blurOutBitmap);
scriptBlur.setRadius(mBlur_Radius);
scriptBlur.setInput(input);
scriptBlur.forEach(output);
bmp.recycle();
output.copyTo(blurOutBitmap);
mRenderScript.finish();
final ScriptIntrinsicColorMatrix scriptColor = ScriptIntrinsicColorMatrix
.create(mRenderScript, Element.U8_4(mRenderScript));
/** for a first test, I am using a simple blue filter **/
Matrix3f mat = new Matrix3f(new float[] {
1, 0, 1,
0, 1, 1,
0, 0, 1
});
scriptColor.setColorMatrix(mat);
final Allocation colorInput = Allocation.createFromBitmap(mRenderScript,
blurOutBitmap);
Bitmap outBitmap = bmp.copy(blurOutBitmap.getConfig(), true);
final Allocation colorOutput = Allocation.createFromBitmap(
mRenderScript, outBitmap);
scriptColor.forEach(colorInput, colorOutput);
blurOutBitmap.recycle();
colorOutput.copyTo(outBitmap);
displayBitmap(outBitmap);
This code produces very ugly artifacts on the image (parallel red lines) and if I try to use a ScriptGroup instead it simply crashes.
Does anybody with Renderscript Experience can help me decipher why ? Since there are very few samples or documentation on that topic, I am stuck trying random modifications.
Here is the correct way to do this (or at least one that works, this case is a bit buggy) :
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.lenna);
ScriptIntrinsicBlur scriptBlur = ScriptIntrinsicBlur.create(mRenderScript, Element.U8_4(mRenderScript));
scriptBlur.setRadius(5f);
ScriptIntrinsicColorMatrix scriptColor = ScriptIntrinsicColorMatrix.create(mRenderScript, Element.U8_4(mRenderScript));
final Allocation input = Allocation.createFromBitmap(mRenderScript, bitmap,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT | Allocation.USAGE_SHARED);
scriptBlur.setInput(input);
Bitmap outBitmap = bitmap.copy(bitmap.getConfig(), true);
final Allocation output = Allocation.createTyped(mRenderScript, input.getType());
scriptColor.setColorMatrix(new Matrix4f(
new float[]{1, 0f, 0f, 0,
1, 1, 0f, 0,
1, 0f, 1, 0,
0, 0, 0, 1}
));
ScriptGroup.Builder b = new ScriptGroup.Builder(mRenderScript);
b.addKernel(scriptBlur.getKernelID());
b.addKernel(scriptColor.getKernelID());
b.addConnection(input.getType(), scriptBlur.getKernelID(), scriptColor.getKernelID());
ScriptGroup group = b.create();
// group.setInput(scriptBlur.getKernelID(),input);
group.setOutput(scriptColor.getKernelID(), output);
group.execute();
output.copyTo(outBitmap);
return outBitmap;
I have the following code for creating a bitmap:
public PixelMapper(Path inputPath){
RectF src = new RectF();
inputPath.computeBounds(src, true);
int width = (int)src.width()+1;
int height = (int)src.height()+1;
largeBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Paint canvasPaint = new Paint();
canvasPaint.setAntiAlias(false);
canvasPaint.setColor(Color.BLACK);
canvasPaint.setStyle(Style.STROKE);
canvasPaint.setStrokeWidth(5);
Canvas canvas = new Canvas(largeBitmap);
canvas.drawPath(inputPath, canvasPaint);
bitmap = Bitmap.createScaledBitmap(largeBitmap, SIDE_OF_BITMAP, SIDE_OF_BITMAP, true);
bitmap = Bitmap.createBitmap(bitmap);//so that a immutable bitmap is created
drawPixelMap();
}
public void drawPixelMap(){
for(int x=0; x<bitmap.getWidth(); x++){
String msg="";
for(int y=0; y<bitmap.getHeight(); y++){
msg = Integer.toHexString( bitmap.getPixel(x,y) );
Log.v("bitmap", msg);
}
}
}
int[] pixels = new int[64];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, SIDE_OF_BITMAP, SIDE_OF_BITMAP);
bitmap.setPixels(pixels, 0, 8, 0, 0, 8, 8);
for ( int pixel : pixels)
Log.v("bitmap", Integer.toHexString(pixel) );
The problem is that all the log messages are "0": both getPixel and getPixels return "0". What is worse is that if I remove the line bitmap.getPixels(...); and leave the bitmap.setPixels(...) line,the image is still drawn as before. It seems that the bitmap variable is just a reference and a bitmap doesn't exist, and for some reason, I am unable to get those pixels.
I know the bitmap is created as required as I am able to view it on a ImageView. It shows black and white pixels with a few grey ones too. Code:
Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, 128, 128, false);
imageView1.setImageBitmap(newBitmap);
The SIDE_OF_BITMAP = 8, all classes (Path, Bitmap, Canvas) are of android.
I tried saving the bitmap to file with the following code:
public String saveToStorage(String fileName){
if( !storageDir.exists() )
storageDir.mkdirs();
File file = new File(storageDir, fileName + ".png");
try{
OutputStream out = new FileOutputStream(file);
boolean result = bitmap.compress(CompressFormat.PNG, 100, out);
out.close();
return Boolean.toString(result);
}
catch (FileNotFoundException e){
Log.e("save", "cannot save file", e);
return "File not found exception";
}
catch (IOException e){
Log.e("save", "IO error", e);
return "IO Exception";
}
}
but it returns "false" i.e. the bitmap.compress method returns false. Please give me any help at all, not necessarily sample code.
I found my mistake. It lies in the line
largeBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
The Bitmap.Config.ALPHA_8 only creates a mask. It does not create actual pixels. That is why I was getting the erroneous results. However, when I was setting it to a ImageView I was getting the required result because its background (by default) is white.
I solved my problem by changing the Bitmap.Config.ALPHA_8 to Bitmap.Config.ARGB_8888
The line
bitmap = Bitmap.createBitmap(bitmap);
creates a immutable bitmap of the same dimension/color depth, etc as the source bitmap, but not converting the source bitmap from mutable to immutable. So your new bitmap is blank.
You can first create a immutable bitmap using newBitmap = Bitmap.createBitmap(int[], int, int, Bitmap.Config), then create a canvas for it by canvas = new Canvas(newBitmap). Your bitmap can now be copied to newBitmap by canvas.drawBitmap(bitmap, 0, 0, null).
byte[] GetImageFromText(string text, float fontSize)
{
//do make png image
//and returns byte array
}
I want to get a method like the one above.
thanks Lumis~
here is my final solution
float textSize = 30;
String text = "testing";
TextPaint tp = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
tp.setColor(Color.WHITE);
tp.setTextSize(textSize);
Rect bounds = new Rect();
tp.getTextBounds(text , 0, text.length(), bounds);
StaticLayout sl = new StaticLayout(text , tp, bounds.width()+5,
Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false);
Bitmap bmp = Bitmap.createBitmap(bounds.width()+5, bounds.height()+5,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
sl.draw(canvas);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(CompressFormat.PNG, 100, stream);
byte[] image = stream.toByteArray();
You can do this drawing a text view into bitmap first, then you would have to save it as PNG into private app memory or SD card and send it. Here is an exmple how to convert text into bitmap: How to draw a TextView into a Bitmap (without ever beeing drawn on the display)
I am developing an android application in which I set an image to imageview. Now programmatic I want to change the bitmap image color. Suppose my image have red color initially and now I need to change it to orange color. How can I do that? Please help.
Here is my code. I managed to change the opacity but I do not know how to change the color.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView iv = (ImageView) findViewById(R.id.img);
Drawable d = getResources().getDrawable(R.drawable.pic1);
Bitmap mNewBitmap = ((BitmapDrawable)d).getBitmap();
Bitmap nNewBitmap = adjustOpacity(mNewBitmap);
iv.setImageBitmap(nNewBitmap);
}
private Bitmap adjustOpacity( Bitmap bitmap ) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
int[] pixels = new int[width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
dest.setPixels(pixels, 0, width, 0, 0, width, height);
return dest;
}
I tried Josip's answer but wouldn't work for me, regardless of whether the offset parameter was 1 or 0 - the drawn bitmap just appeared in original colour.
However, this did work:
// You have to copy the bitmap as any bitmaps loaded as drawables are immutable
Bitmap bm = ImageLoader.getInstance().loadImageSync("drawable://" + drawableId, o)
.copy(Bitmap.Config.ARGB_8888, true);
Paint paint = new Paint();
ColorFilter filter = new PorterDuffColorFilter(ContextCompat.getColor(this, R.color.COLOR_1_DARK), PorterDuff.Mode.SRC_IN);
paint.setColorFilter(filter);
Canvas canvas = new Canvas(bm);
canvas.drawBitmap(bm, 0, 0, paint);
Update 1
Whilst the above works well and is useful in a lot of cases, if you just want to change the main colour of an ImageView drawable, which the op did, you can just use:
imgView.setColorFilter(ContextCompat.getColor(this, R.color.COLOR_1_DARK));
If you need more flexibility or this doesn't give the desired effect, there's an overload that allows you to change the PorterDuff Mode until you get what you're after:
imgView.setColorFilter(ContextCompat.getColor(this, R.color.COLOR_1_DARK), PorterDuff.Mode.SRC_ATOP);
Update 2
Another good use case I've had for this lately is customizing the appearance of a Google map v2 marker icon. In order to use 2 graphics to allow (for example) small/large icons on a marker, but also a range of colours on those 2 graphics by changing the colour of them dynamically. In my case I was doing this inside a ClusterRenderer as the markers were also clustered, but this can be used with a regular map marker the same way:
#Override
protected void onBeforeClusterItemRendered(MyClusterItem item, MarkerOptions markerOptions) {
try {
int markerColor = item.getColor();
Bitmap icon;
if (item.isFeatured()) {
// We must copy the bitmap or we get an exception "Immutable bitmap passed to Canvas constructor"
icon = BitmapFactory.decodeResource(context.getResources(),
R.drawable.icon_marker_large).copy(Bitmap.Config.ARGB_8888, true);
} else {
// We must copy the bitmap or we get an exception "Immutable bitmap passed to Canvas constructor"
icon = BitmapFactory.decodeResource(context.getResources(),
R.drawable.icon_marker_small).copy(Bitmap.Config.ARGB_8888, true);
}
Paint paint = new Paint();
ColorFilter filter = new PorterDuffColorFilter(ContextCompat.getColor(context, markerColor), PorterDuff.Mode.SRC_IN);
paint.setColorFilter(filter);
Canvas canvas = new Canvas(icon);
canvas.drawBitmap(icon, 0, 0, paint);
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
} catch (Exception ex) {
ex.printStackTrace();
}
}
I got kind of solution.
Bitmap sourceBitmap = BitmapFactory.decodeFile(imgPath);
float[] colorTransform = {
0, 1f, 0, 0, 0,
0, 0, 0f, 0, 0,
0, 0, 0, 0f, 0,
0, 0, 0, 1f, 0};
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(0f); //Remove Colour
colorMatrix.set(colorTransform); //Apply the Red
ColorMatrixColorFilter colorFilter = new ColorMatrixColorFilter(colorMatrix);
Paint paint = new Paint();
paint.setColorFilter(colorFilter);
Display display = getWindowManager().getDefaultDisplay();
Bitmap resultBitmap = Bitmap.createBitmap(sourceBitmap, 0, (int)(display.getHeight() * 0.15), display.getWidth(), (int)(display.getHeight() * 0.75));
image.setImageBitmap(resultBitmap);
Canvas canvas = new Canvas(resultBitmap);
canvas.drawBitmap(resultBitmap, 0, 0, paint);
private void changeColor(){
ImageView image = (ImageView) findViewById(R.id.imageView1);
Bitmap sourceBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
changeBitmapColor(sourceBitmap, image, Color.BLUE);
}
private void changeBitmapColor(Bitmap sourceBitmap, ImageView image, int color) {
Bitmap resultBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0,
sourceBitmap.getWidth() - 1, sourceBitmap.getHeight() - 1);
Paint p = new Paint();
ColorFilter filter = new LightingColorFilter(color, 1);
p.setColorFilter(filter);
image.setImageBitmap(resultBitmap);
Canvas canvas = new Canvas(resultBitmap);
canvas.drawBitmap(resultBitmap, 0, 0, p);
}
It's better obtain mutable bitmap by copy, without changing size:
public static Bitmap changeBitmapColor(Bitmap sourceBitmap, int color)
{
Bitmap resultBitmap = sourceBitmap.copy(sourceBitmap.getConfig(),true);
Paint paint = new Paint();
ColorFilter filter = new LightingColorFilter(color, 1);
paint.setColorFilter(filter);
Canvas canvas = new Canvas(resultBitmap);
canvas.drawBitmap(resultBitmap, 0, 0, paint);
return resultBitmap;
}
public Bitmap replaceColor(Bitmap src,int fromColor, int targetColor) {
if(src == null) {
return null;
}
// Source image size
int width = src.getWidth();
int height = src.getHeight();
int[] pixels = new int[width * height];
//get pixels
src.getPixels(pixels, 0, width, 0, 0, width, height);
for(int x = 0; x < pixels.length; ++x) {
pixels[x] = (pixels[x] == fromColor) ? targetColor : pixels[x];
}
// create result bitmap output
Bitmap result = Bitmap.createBitmap(width, height, src.getConfig());
//set pixels
result.setPixels(pixels, 0, width, 0, 0, width, height);
return result;
}
The simplest way to change the bitmaps color is with this method:
bitmap.eraseColor(ContextCompat.getColor(this, R.color.your_color));
If you want to overlay the ImageView with color use:
imageView.setColorFilter(ContextCompat.getColor(this, R.color.your_color));
A little off topic, but considering you only want to display in changed color here is my solution. Namely, the easiest and fast way is just applying a filter by using drawColor() method on Canvas, right after drawBitmap():
m_canvas.drawColor(Color.RED, PorterDuff.Mode.ADD);
Sources: https://developer.android.com/reference/android/graphics/PorterDuff.Mode.html
Even if bitmap is immutable, it will work.
Paint paint = new Paint();
ColorFilter filter = new PorterDuffColorFilter(ContextCompat.getColor(context, R.color.whatColorNeed), PorterDuff.Mode.SRC_IN);
paint.setColorFilter(filter);
canvas.drawBitmap(bitmapToModify, some_x, some_y, paint);
I have solved the problem by using the below code
public void changeColor(Bitmap srcImage) {
Bitmap bmpRedscale = Bitmap.createBitmap(srcImage.getWidth(),
srcImage.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmpRedscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setRGB2YUV();
paint.setColorFilter(new ColorMatrixColorFilter(cm));
canvas.drawBitmap(srcImage, 0, 0, paint);
mImgEdited.setImageBitmap(bmpRedscale);
}
In Kotlin :
private fun changeBitmapColor(oldBitmap: Bitmap, newColor: Int): Bitmap {
val paint = Paint()
val filter: ColorFilter = PorterDuffColorFilter(
newColor,
PorterDuff.Mode.SRC_IN
)
paint.colorFilter = filter
val canvas = Canvas(oldBitmap)
canvas.drawBitmap(oldBitmap, 0f, 0f, paint)
return oldBitmap
}
This function PorterDuff.Mode.SRC_IN can change due to the Bitmap file, look this link https://developer.android.com/reference/android/graphics/PorterDuff.Mode