using hue image effect with a seekbar - android

I have a hue effect code and I want to use it with a seek bar, the effect can be applied using applyHueFilter( bitmap, level ) I want when i move the circle of the seekbar to the right the hue filter increases and when i move it to the left the hue filter decreases ( removes ) ..
public static Bitmap applyHueFilter(Bitmap source, int level) {
// get image size
int width = source.getWidth();
int height = source.getHeight();
int[] pixels = new int[width * height];
float[] HSV = new float[3];
// get pixel array from source
source.getPixels(pixels, 0, width, 0, 0, width, height);
int index = 0;
// iteration through pixels
for(int y = 0; y < height; ++y) {
for(int x = 0; x < width; ++x) {
// get current index in 2D-matrix
index = y * width + x;
// convert to HSV
Color.colorToHSV(pixels[index], HSV);
// increase Saturation level
HSV[1] *= level;
HSV[1] = (float) Math.max(0.0, Math.min(HSV[1], 1.0));
// take color back
pixels[index] |= Color.HSVToColor(HSV);
}
}
// output bitmap
myBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return myBitmap;
}
at the time Im using this applyHueFilter in the progressChanged ..
hueSB.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
applyHueFilter(myBitmap, 100);
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
what happens is when i move the seekbar to the right the hue applys but when i move it to the left it doesn't get removed ( decreased ) ..

Canvas canvas = new Canvas(yourbitmap);
Paint paint = new Paint();
paint.setColorFilter(ColorFilterGenerator.adjustHue(seekbarvalue));
canvas.drawBitmap(yourbitmap, 0, 0, paint);
return yourbitmap;
public class ColorFilterGenerator
{
public static ColorFilter adjustHue( float value )
{
ColorMatrix cm = new ColorMatrix();
adjustHue(cm, value);
return new ColorMatrixColorFilter(cm);
}
public static void adjustHue(ColorMatrix cm, float value)
{
value = (value % 360.0f) * (float) Math.PI / 180.0f;
if (value == 0)
{
return;
}
float cosVal = (float) Math.cos(value);
float sinVal = (float) Math.sin(value);
float lumR = 0.213f;
float lumG = 0.715f;
float lumB = 0.072f;
float[] mat = new float[]
{
lumR + cosVal * (1 - lumR) + sinVal * (-lumR), lumG + cosVal * (-lumG) + sinVal * (-lumG), lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0,
lumR + cosVal * (-lumR) + sinVal * (0.143f), lumG + cosVal * (1 - lumG) + sinVal * (0.140f), lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0,
lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)), lumG + cosVal * (-lumG) + sinVal * (lumG), lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0,
0f, 0f, 0f, 1f, 0f,
0f, 0f, 0f, 0f, 1f };
cm.postConcat(new ColorMatrix(mat));
}
}
this code is efficiently work for Hue effect using Color Filter.

Simple logic error. You have applyHueFilter(myBitmap, 100);... you are increasing it by 100 no matter what.
It should be:
applyHueFilter(myBitmap, progress);
Looking at the applyHueFilter method, you are also always doing HSV[0] *= level;, so no matter what, you are always increasing the hue, just by lesser or greater amounts.

Related

How do i use a parabola for throwing a ball on a particular angle?

I have used this method but its not working according to my requirement,please suggest me
public void applyTransformation(float interpolatedTime, Transformation t) {
float dx = 0, dy = 0;
if (mFromXValue != mToXValue) {
dx = (float) ((1.0 - interpolatedTime) * (1.0 - interpolatedTime)
* mFromXValue + 2.0 * interpolatedTime
* (1.0 - interpolatedTime) * mBezierXDelta + interpolatedTime
* interpolatedTime * mToXValue);
}
if (mFromYValue != mToYValue) {
dy = (float) ((1.0 - interpolatedTime) * (1.0 - interpolatedTime)
* mFromYValue + 2.0 * interpolatedTime
* (1.0 - interpolatedTime) * mBezierYDelta + interpolatedTime
* interpolatedTime * mToYValue);
}
t.getMatrix().setTranslate(dx, dy);
}
Use this method in sprite class it will help you...
public void paintFromCenter(float angle, Canvas c) {
Bitmap b = sprite;
Matrix matrix = new Matrix();
matrix.postRotate(angle, b.getWidth() / 2, b.getHeight());
matrix.postTranslate(getX(), getY());
Bitmap bmp2 = Bitmap.createBitmap(b, 0, 0, frameWidth, frameHeight,
matrix, true);
c.drawBitmap(b, matrix, null);
}

How to draw a pie chart using RectF which will be easy to support multiple screen size in android?

Hi I am using following code to draw a pie chart in android :-
public class Chart extends View
{
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private float[] value_degree;
private String[] Title_value;
RectF rectf = new RectF(50, 5, 200, 150);
Rect rect = new Rect(50, 5, 200, 150);
float temp = 0;
public Chart(Context context, float[] values, String[] heading)
{
super(context);
value_degree = new float[values.length];
Title_value = new String[heading.length];
for (int i = 0; i < values.length; i++)
{
value_degree[i] = values[i];
Log.i("abc", "" + values[i]);
Title_value[i] = heading[i];
}
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Random r;
int centerX = (rect.left + rect.right) / 2;
int centerY = (rect.top + rect.bottom) / 2;
int radius = (rect.right - rect.left) / 2;
int color;
radius *= 0.5; // 1 will put the text in the border, 0 will put the text
// in the center. Play with this to set the distance of
// your text.
for (int i = 0; i < value_degree.length; i++)
{
if (i == 0)
{
r = new Random();
color = Color.argb(100, r.nextInt(256), r.nextInt(256),
r.nextInt(256));
paint.setColor(color);
Log.i("Color", "" + color);
canvas.drawArc(rectf, temp, value_degree[i], true, paint);
paint.setColor(Color.BLACK); // set this to the text color.
paint.setTextSize(12);
/*
* paint.setTextAlign(Align.CENTER);
*/float medianAngle = (temp + (value_degree[i] / 2f))
* (float) Math.PI / 180f; // this angle will place the
// text in the center of the
// arc.
canvas.drawText(Title_value[i],
(float) (centerX + (radius * Math.cos(medianAngle))),
(float) (centerY + (radius * Math.sin(medianAngle))),
paint);
} else
{
temp += value_degree[i - 1];
r = new Random();
color = Color.argb(255, r.nextInt(256), r.nextInt(256),
r.nextInt(256));
paint.setColor(color);
Log.i("Else Color", "" + color);
canvas.drawArc(rectf, temp, value_degree[i], true, paint);
paint.setColor(Color.BLACK); // set this to the text color.
paint.setTextSize(12);
/*
* paint.setTextAlign(Align.CENTER);
*/float medianAngle = (temp + (value_degree[i] / 2f))
* (float) Math.PI / 180f; // this angle will place the
// text in the center of the
// arc.
canvas.drawText(Title_value[i],
(float) (centerX + (radius * Math.cos(medianAngle))),
(float) (centerY + (radius * Math.sin(medianAngle))),
paint);
}
}
}
}
It is showing chart in good quality in small screen sizes. But when I check it on big screen like S4 or other same screen size device it is shows a pie chart in very small size.
What should I do so it will draw perfectly on small as well as big screens?
Please help me, suggest something.
Also suggest how can I take color value to each slice in pie chart as it is assigned randomly.

Using 2 different colors on the same paint, for the same canvas cause flickering

This is the code i'm using, it is running the heavy part on the Background, and it draws a growing circle, and while it is growing, the text that is inside the circle fades out, the problem is that the text flickers between blue (the same color as the circle) and white (the color of the Text). I'm using double buffering (using a canvas, drawing everything i need and after that, publish the image that is beign used on the UI thread).
Any suggestions?
Canvas c = new Canvas(mBitmap);
c.drawColor(0, PorterDuff.Mode.SRC_OVER);
GrowingButtonData buttonInfo = (GrowingButtonData) params[0]
.get("buttonInfo");
int pickedCirclNumber = params[0].getInt("pickedCirclNumber");
int color = buttonInfo.getColor();
currentPaint.setColor(color);
Rect bounds = new Rect();
currentPaint.getTextBounds(buttonData.get(pickedCirclNumber)
.getText(), 0, buttonData.get(pickedCirclNumber)
.getText().length(), bounds);
String name = buttonData.get(pickedCirclNumber).getText();
float xText = offsetX * (pickedCirclNumber + 1)
+ (pickedCirclNumber * radius) + radius / 2.0f;
float yText = offsetY + radius / 2.0f + +bounds.height() / 2.0f;
float initalOffsetX = offsetX * (pickedCirclNumber + 1)
+ (pickedCirclNumber * radius);
while (lastRadius < getMeasuredWidth() * 1.5f) {
currentPaint.setAlpha(255);
currentPaint.setColor(Color.BLUE);
lastRadius += (System.currentTimeMillis() - lastTime);
lastTime = System.currentTimeMillis();
RectF rectF = new RectF();
rectF.set(
initalOffsetX
- ((lastRadius - (float) radius) / 2.0f),
(offsetY - ((lastRadius - (float) radius) / 2.0f)),
initalOffsetX + radius
+ ((lastRadius - (float) radius) / 2.0f),
(offsetY + radius + ((lastRadius - (float) radius) / 2.0f)));
c.drawArc(rectF, 0, 360, true, currentPaint);
int newAlpha = (int)(255.0f * (1.0f-lastRadius/(getMeasuredWidth()*2.0f)))-63;
if (newAlpha<0)
newAlpha =0;
currentPaint.setAlpha(newAlpha);
currentPaint.setColor(Color.GREEN);
c.drawText(name, xText, yText, currentPaint);
publishProgress(new JSONObject());
}
return params[0];
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
#Override
protected void onProgressUpdate(JSONObject... values) {
super.onProgressUpdate(values);
setImageBitmap(mBitmap);
}

Modifying the color of an android drawable

I would like to be able to use the same drawable to represent both:
and
as the same drawable, and re-color the drawable based on some programmatic values, so that the end user could re-theme the interface.
What is the best way to do this? I have tried (and reused the icons from) this previous S.O. question but I can't represent the change as a simple change of hue, since it also varies in saturation and value..
Is it best to store the icon as all white in the area I want changed? or transparent? or some other solid color?
Is there some method that allows you to figure out the matrix based on the difference between Color of red_icon and Color of blue_icon?
So after a lot of trial and error, reading different articles, and most importantly, going through the API Demos (ColorFilters.java -- found in com.example.android.apis.graphics) I found the solution.
For solid images, I have found it is best to use the color filter PorterDuff.Mode.SRC_ATOP because it will overlay the color on top of the source image, allowing you to change the color to the exact color you are looking for.
For images that are more complex, like the one above, I have found the best thing to do is to color the entire image WHITE (FFFFFF) so that when you do PorterDuff.Mode.MULTIPLY, you end up with the correct colors, and all of the black (000000) in your image will remain black.
The colorfilters.java shows you how it's done if your drawing on a canvas, but if all you need is to color a drawable then this will work:
COLOR2 = Color.parseColor("#FF"+getColor());
Mode mMode = Mode.SRC_ATOP;
Drawable d = mCtx.getResources().getDrawable(R.drawable.image);
d.setColorFilter(COLOR2,mMode)
I created a demo activity using some of the API Demo code to swap between every color filter mode to try them out for different situations and have found it to be invaluable, so I thought I would post it here.
public class ColorFilters extends GraphicsActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
private Activity mActivity;
private Drawable mDrawable;
private Drawable[] mDrawables;
private Paint mPaint;
private Paint mPaint2;
private float mPaintTextOffset;
private int[] mColors;
private PorterDuff.Mode[] mModes;
private int mModeIndex;
private Typeface futura_bold;
private AssetManager assets;
private static void addToTheRight(Drawable curr, Drawable prev) {
Rect r = prev.getBounds();
int x = r.right + 12;
int center = (r.top + r.bottom) >> 1;
int h = curr.getIntrinsicHeight();
int y = center - (h >> 1);
curr.setBounds(x, y, x + curr.getIntrinsicWidth(), y + h);
}
public SampleView(Activity activity) {
super(activity);
mActivity = activity;
Context context = activity;
setFocusable(true);
/**1. GET DRAWABLE, SET BOUNDS */
assets = context.getAssets();
mDrawable = context.getResources().getDrawable(R.drawable.roundrect_gray_button_bg_nine);
mDrawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
mDrawable.setDither(true);
int[] resIDs = new int[] {
R.drawable.roundrect_gray_button_bg,
R.drawable.order_button_white,
R.drawable.yellowbar
};
mDrawables = new Drawable[resIDs.length];
Drawable prev = mDrawable;
for (int i = 0; i < resIDs.length; i++) {
mDrawables[i] = context.getResources().getDrawable(resIDs[i]);
mDrawables[i].setDither(true);
addToTheRight(mDrawables[i], prev);
prev = mDrawables[i];
}
/**2. SET Paint for writing text on buttons */
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(16);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint2 = new Paint(mPaint);
/** Calculating size based on font */
futura_bold = Typeface.createFromAsset(assets,
"fonts/futurastd-bold.otf");
//Determine size and offset to write text in label based on font size.
mPaint.setTypeface(futura_bold);
Paint.FontMetrics fm = mPaint.getFontMetrics();
mPaintTextOffset = (fm.descent + fm.ascent) * 0.5f;
mColors = new int[] {
0,
0xFFA60017,//WE USE THESE
0xFFC6D405,
0xFF4B5B98,
0xFF656565,
0xFF8888FF,
0xFF4444FF,
};
mModes = new PorterDuff.Mode[] {
PorterDuff.Mode.DARKEN,
PorterDuff.Mode.DST,
PorterDuff.Mode.DST_ATOP,
PorterDuff.Mode.DST_IN,
PorterDuff.Mode.DST_OUT,
PorterDuff.Mode.DST_OVER,
PorterDuff.Mode.LIGHTEN,
PorterDuff.Mode.MULTIPLY,
PorterDuff.Mode.SCREEN,
PorterDuff.Mode.SRC,
PorterDuff.Mode.SRC_ATOP,
PorterDuff.Mode.SRC_IN,
PorterDuff.Mode.SRC_OUT,
PorterDuff.Mode.SRC_OVER,
PorterDuff.Mode.XOR
};
mModeIndex = 0;
updateTitle();
}
private void swapPaintColors() {
if (mPaint.getColor() == 0xFF000000) {
mPaint.setColor(0xFFFFFFFF);
mPaint2.setColor(0xFF000000);
} else {
mPaint.setColor(0xFF000000);
mPaint2.setColor(0xFFFFFFFF);
}
mPaint2.setAlpha(0);
}
private void updateTitle() {
mActivity.setTitle(mModes[mModeIndex].toString());
}
private void drawSample(Canvas canvas, ColorFilter filter) {
/** Create a rect around bounds, ensure size offset */
Rect r = mDrawable.getBounds();
float x = (r.left + r.right) * 0.5f;
float y = (r.top + r.bottom) * 0.5f - mPaintTextOffset;
/**Set color filter to selected color
* create canvas (filled with this color)
* Write text using paint (new color)
*/
mDrawable.setColorFilter(filter);
mDrawable.draw(canvas);
/** If the text doesn't fit in the button, make the text size smaller until it does*/
final float size = mPaint.measureText("Label");
if((int) size > (r.right-r.left)) {
float ts = mPaint.getTextSize();
Log.w("DEBUG","Text size was"+ts);
mPaint.setTextSize(ts-2);
}
canvas.drawText("Sausage Burrito", x, y, mPaint);
/** Write the text and draw it onto the drawable*/
for (Drawable dr : mDrawables) {
dr.setColorFilter(filter);
dr.draw(canvas);
}
}
#Override protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC);
canvas.translate(8, 12);
for (int color : mColors) {
ColorFilter filter;
if (color == 0) {
filter = null;
} else {
filter = new PorterDuffColorFilter(color,
mModes[mModeIndex]);
}
drawSample(canvas, filter);
canvas.translate(0, 55);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
// update mode every other time we change paint colors
if (mPaint.getColor() == 0xFFFFFFFF) {
mModeIndex = (mModeIndex + 1) % mModes.length;
updateTitle();
}
swapPaintColors();
invalidate();
break;
}
return true;
}
}
}
The two other dependencies, GraphicsActivity.java and PictureLayout.java, can be copied directly from the API Demos activity if you would like to test it out.
This is really easy to do on Lollipop. Make an xml drawable and reference your png and set the tint like this:
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/ic_back"
android:tint="#color/red_tint"/>
Your answer is very nice. Although, this solution is practice too if you're using a Textview and a embed drawable:
int colorARGB = R.color.your_color;
Drawable[] textviewDrawables = drawerItem.getCompoundDrawables();
// Left Drawable
textviewDrawables[0].setColorFilter(colorARGB, PorterDuff.Mode.SRC_ATOP);
This is what i did after looking into documentation
public PorterDuffColorFilter getDrawableFilter(){
return new PorterDuffColorFilter(ContextCompat.getColor(this, R.color.color_black), PorterDuff.Mode.SRC_ATOP);
}
and called it
yourdrawable.setColorFilter(getDrawableFilter());
In case if you want to apply color filter to your image in ImageView you can implement it even in easier way. Just use attribute android:tint in ImageView in xml.
Example:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/your_drawable"
android:tint="#color/your_color" />
Tested on Android 4.1.2 and 6.0.1
Here is something better, IMHO, than the accepted answer. It is derived from this StackOverflow thread: Understanding the Use of ColorMatrix and ColorMatrixColorFilter to Modify a Drawable's Hue
Example usage:
ImageView imageView = ...;
Drawable drawable = imageView.getDrawable();
ColorFilter colorFilter = ColorFilterGenerator.from(drawable).to(Color.RED);
imageView.setColorFilter(colorFilter);
Copy the class into your project:
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PictureDrawable;
import android.widget.ImageView;
/**
* Creates a {#link ColorMatrixColorFilter} to adjust the hue, saturation, brightness, or
* contrast of an {#link Bitmap}, {#link Drawable}, or {#link ImageView}.
* <p/>
* Example usage:
* <br/>
* {#code imageView.setColorFilter(ColorFilterGenerator.from(Color.BLUE).to(Color.RED));}
*
* #author Jared Rummler <jared.rummler#gmail.com>
*/
public class ColorFilterGenerator {
// Based off answer from StackOverflow
// See: https://stackoverflow.com/a/15119089/1048340
private ColorFilterGenerator() {
throw new AssertionError();
}
public static From from(Drawable drawable) {
return new From(drawableToBitmap(drawable));
}
public static From from(Bitmap bitmap) {
return new From(bitmap);
}
public static From from(int color) {
return new From(color);
}
// --------------------------------------------------------------------------------------------
private static final double DELTA_INDEX[] = {
0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11, 0.12, 0.14, 0.15, 0.16, 0.17, 0.18,
0.20, 0.21, 0.22, 0.24, 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42, 0.44,
0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89,
0.92, 0.95, 0.98, 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54, 1.60, 1.66, 1.72,
1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25, 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6,
3.8, 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0, 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4,
9.6, 9.8, 10.0
};
public static void adjustHue(ColorMatrix cm, float value) {
value = cleanValue(value, 180f) / 180f * (float) Math.PI;
if (value == 0) {
return;
}
float cosVal = (float) Math.cos(value);
float sinVal = (float) Math.sin(value);
float lumR = 0.213f;
float lumG = 0.715f;
float lumB = 0.072f;
float[] mat = new float[]{
lumR + cosVal * (1 - lumR) + sinVal * (-lumR),
lumG + cosVal * (-lumG) + sinVal * (-lumG),
lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0,
lumR + cosVal * (-lumR) + sinVal * (0.143f),
lumG + cosVal * (1 - lumG) + sinVal * (0.140f),
lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0,
lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)),
lumG + cosVal * (-lumG) + sinVal * (lumG),
lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f,
0f, 1f
};
cm.postConcat(new ColorMatrix(mat));
}
public static void adjustBrightness(ColorMatrix cm, float value) {
value = cleanValue(value, 100);
if (value == 0) {
return;
}
float[] mat = new float[]{
1, 0, 0, 0, value, 0, 1, 0, 0, value, 0, 0, 1, 0, value, 0, 0, 0, 1, 0, 0, 0, 0, 0,
1
};
cm.postConcat(new ColorMatrix(mat));
}
public static void adjustContrast(ColorMatrix cm, int value) {
value = (int) cleanValue(value, 100);
if (value == 0) {
return;
}
float x;
if (value < 0) {
x = 127 + value / 100 * 127;
} else {
x = value % 1;
if (x == 0) {
x = (float) DELTA_INDEX[value];
} else {
x = (float) DELTA_INDEX[(value << 0)] * (1 - x)
+ (float) DELTA_INDEX[(value << 0) + 1] * x;
}
x = x * 127 + 127;
}
float[] mat = new float[]{
x / 127, 0, 0, 0, 0.5f * (127 - x), 0, x / 127, 0, 0, 0.5f * (127 - x), 0, 0,
x / 127, 0, 0.5f * (127 - x), 0, 0, 0, 1, 0, 0, 0, 0, 0, 1
};
cm.postConcat(new ColorMatrix(mat));
}
public static void adjustSaturation(ColorMatrix cm, float value) {
value = cleanValue(value, 100);
if (value == 0) {
return;
}
float x = 1 + ((value > 0) ? 3 * value / 100 : value / 100);
float lumR = 0.3086f;
float lumG = 0.6094f;
float lumB = 0.0820f;
float[] mat = new float[]{
lumR * (1 - x) + x, lumG * (1 - x), lumB * (1 - x), 0, 0, lumR * (1 - x),
lumG * (1 - x) + x, lumB * (1 - x), 0, 0, lumR * (1 - x), lumG * (1 - x),
lumB * (1 - x) + x, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1
};
cm.postConcat(new ColorMatrix(mat));
}
// --------------------------------------------------------------------------------------------
private static float cleanValue(float p_val, float p_limit) {
return Math.min(p_limit, Math.max(-p_limit, p_val));
}
private static float[] getHsv(int color) {
float[] hsv = new float[3];
Color.RGBToHSV(Color.red(color), Color.green(color), Color.blue(color), hsv);
return hsv;
}
/**
* Converts a {#link Drawable} to a {#link Bitmap}
*
* #param drawable
* The {#link Drawable} to convert
* #return The converted {#link Bitmap}.
*/
private static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else if (drawable instanceof PictureDrawable) {
PictureDrawable pictureDrawable = (PictureDrawable) drawable;
Bitmap bitmap = Bitmap.createBitmap(pictureDrawable.getIntrinsicWidth(),
pictureDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawPicture(pictureDrawable.getPicture());
return bitmap;
}
int width = drawable.getIntrinsicWidth();
width = width > 0 ? width : 1;
int height = drawable.getIntrinsicHeight();
height = height > 0 ? height : 1;
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
/**
* Calculate the average red, green, blue color values of a bitmap
*
* #param bitmap
* a {#link Bitmap}
* #return
*/
private static int[] getAverageColorRGB(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int size = width * height;
int[] pixels = new int[size];
int r, g, b;
r = g = b = 0;
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
for (int i = 0; i < size; i++) {
int pixelColor = pixels[i];
if (pixelColor == Color.TRANSPARENT) {
size--;
continue;
}
r += Color.red(pixelColor);
g += Color.green(pixelColor);
b += Color.blue(pixelColor);
}
r /= size;
g /= size;
b /= size;
return new int[]{
r, g, b
};
}
/**
* Calculate the average color value of a bitmap
*
* #param bitmap
* a {#link Bitmap}
* #return
*/
private static int getAverageColor(Bitmap bitmap) {
int[] rgb = getAverageColorRGB(bitmap);
return Color.argb(255, rgb[0], rgb[1], rgb[2]);
}
// Builder
// --------------------------------------------------------------------------------------------
public static final class Builder {
int hue;
int contrast;
int brightness;
int saturation;
public Builder setHue(int hue) {
this.hue = hue;
return this;
}
public Builder setContrast(int contrast) {
this.contrast = contrast;
return this;
}
public Builder setBrightness(int brightness) {
this.brightness = brightness;
return this;
}
public Builder setSaturation(int saturation) {
this.saturation = saturation;
return this;
}
public ColorFilter build() {
ColorMatrix cm = new ColorMatrix();
adjustHue(cm, hue);
adjustContrast(cm, contrast);
adjustBrightness(cm, brightness);
adjustSaturation(cm, saturation);
return new ColorMatrixColorFilter(cm);
}
}
public static final class From {
final int oldColor;
private From(Bitmap bitmap) {
oldColor = getAverageColor(bitmap);
}
private From(int oldColor) {
this.oldColor = oldColor;
}
public ColorFilter to(int newColor) {
float[] hsv1 = getHsv(oldColor);
float[] hsv2 = getHsv(newColor);
int hue = (int) (hsv2[0] - hsv1[0]);
int saturation = (int) (hsv2[1] - hsv1[1]);
int brightness = (int) (hsv2[2] - hsv1[2]);
return new ColorFilterGenerator.Builder()
.setHue(hue)
.setSaturation(saturation)
.setBrightness(brightness)
.build();
}
}
}

Can you change image hue of bitmap on android ImageView?

Here is the situation, I have a SeekBar and I want, when I slide it, to change the hue of an image that is in an ImageView. All of the things I've seen about changing hue require the use of a ColorMatrix, but I don't know how to relate a bitmap to a color matrix. Suggestions?
public static void adjustHue(ColorMatrix cm, float value)
{
value = cleanValue(value, 180f) / 180f * (float) Math.PI;
if (value == 0)
{
return;
}
float cosVal = (float) Math.cos(value);
float sinVal = (float) Math.sin(value);
float lumR = 0.213f;
float lumG = 0.715f;
float lumB = 0.072f;
float[] mat = new float[]
{
lumR + cosVal * (1 - lumR) + sinVal * (-lumR), lumG + cosVal * (-lumG) + sinVal * (-lumG), lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0,
lumR + cosVal * (-lumR) + sinVal * (0.143f), lumG + cosVal * (1 - lumG) + sinVal * (0.140f), lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0,
lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)), lumG + cosVal * (-lumG) + sinVal * (lumG), lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0,
0f, 0f, 0f, 1f, 0f,
0f, 0f, 0f, 0f, 1f };
cm.postConcat(new ColorMatrix(mat));
}
private static float cleanValue(float p_val, float p_limit)
{
return Math.min(p_limit, Math.max(-p_limit, p_val));
}
-------
while drawing from canvas ... create an object of paint and ... set...
ColorMatrix mat = new ColorMatrix();`
adjustHue(mat, 110);
paint.setColorFilter(new ColorMatrixColorFilter(mat));
----
canvas.draw(bmp, 0,0,paint);
There's an example here that draws a bitmap in greyscale.
http://www.mail-archive.com/android-developers#googlegroups.com/msg38890.html
Just replace cm.setSaturation(0); with cm.setRotate(int axis, float degrees);.

Categories

Resources