Modifying the color of an android drawable - android

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();
}
}
}

Related

How to use custom created drawable images for Android watch Face

Its been a week I was trying to create a watch Face for Android wear. As a kick start I followed Google official documentation and found these Android official watch face app tutorial with source code
So my current issue is , In Google documentation they use canvas to create analogue watch faces . The watch hands are generated using paint
Here is the sample of code for creating dial hand
public class AnalogWatchFaceService extends CanvasWatchFaceService {
private static final String TAG = "AnalogWatchFaceService";
/**
* Update rate in milliseconds for interactive mode. We update once a second to advance the
* second hand.
*/
private static final long INTERACTIVE_UPDATE_RATE_MS = TimeUnit.SECONDS.toMillis(1);
#Override
public Engine onCreateEngine() {
return new Engine();
}
private class Engine extends CanvasWatchFaceService.Engine {
static final int MSG_UPDATE_TIME = 0;
static final float TWO_PI = (float) Math.PI * 2f;
Paint mHourPaint;
Paint mMinutePaint;
Paint mSecondPaint;
Paint mTickPaint;
boolean mMute;
Calendar mCalendar;
/** Handler to update the time once a second in interactive mode. */
final Handler mUpdateTimeHandler = new Handler() {
#Override
public void handleMessage(Message message) {
switch (message.what) {
case MSG_UPDATE_TIME:
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "updating time");
}
invalidate();
if (shouldTimerBeRunning()) {
long timeMs = System.currentTimeMillis();
long delayMs = INTERACTIVE_UPDATE_RATE_MS
- (timeMs % INTERACTIVE_UPDATE_RATE_MS);
mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs);
}
break;
}
}
};
final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
mCalendar.setTimeZone(TimeZone.getDefault());
invalidate();
}
};
boolean mRegisteredTimeZoneReceiver = false;
/**
* Whether the display supports fewer bits for each color in ambient mode. When true, we
* disable anti-aliasing in ambient mode.
*/
boolean mLowBitAmbient;
Bitmap mBackgroundBitmap;
Bitmap mBackgroundScaledBitmap;
#Override
public void onCreate(SurfaceHolder holder) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onCreate");
}
super.onCreate(holder);
setWatchFaceStyle(new WatchFaceStyle.Builder(AnalogWatchFaceService.this)
.setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)
.setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
.setShowSystemUiTime(false)
.build());
Resources resources = AnalogWatchFaceService.this.getResources();
Drawable backgroundDrawable = resources.getDrawable(R.drawable.bg, null /* theme */);
mBackgroundBitmap = ((BitmapDrawable) backgroundDrawable).getBitmap();
mHourPaint = new Paint();
mHourPaint.setARGB(255, 200, 200, 200);
mHourPaint.setStrokeWidth(5.f);
mHourPaint.setAntiAlias(true);
mHourPaint.setStrokeCap(Paint.Cap.ROUND);
mMinutePaint = new Paint();
mMinutePaint.setARGB(255, 200, 200, 200);
mMinutePaint.setStrokeWidth(3.f);
mMinutePaint.setAntiAlias(true);
mMinutePaint.setStrokeCap(Paint.Cap.ROUND);
mSecondPaint = new Paint();
mSecondPaint.setARGB(255, 255, 0, 0);
mSecondPaint.setStrokeWidth(2.f);
mSecondPaint.setAntiAlias(true);
mSecondPaint.setStrokeCap(Paint.Cap.ROUND);
mTickPaint = new Paint();
mTickPaint.setARGB(100, 255, 255, 255);
mTickPaint.setStrokeWidth(2.f);
mTickPaint.setAntiAlias(true);
mCalendar = Calendar.getInstance();
}
#Override
public void onDestroy() {
mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME);
super.onDestroy();
}
#Override
public void onPropertiesChanged(Bundle properties) {
super.onPropertiesChanged(properties);
mLowBitAmbient = properties.getBoolean(PROPERTY_LOW_BIT_AMBIENT, false);
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onPropertiesChanged: low-bit ambient = " + mLowBitAmbient);
}
}
#Override
public void onTimeTick() {
super.onTimeTick();
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onTimeTick: ambient = " + isInAmbientMode());
}
invalidate();
}
#Override
public void onAmbientModeChanged(boolean inAmbientMode) {
super.onAmbientModeChanged(inAmbientMode);
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onAmbientModeChanged: " + inAmbientMode);
}
if (mLowBitAmbient) {
boolean antiAlias = !inAmbientMode;
mHourPaint.setAntiAlias(antiAlias);
mMinutePaint.setAntiAlias(antiAlias);
mSecondPaint.setAntiAlias(antiAlias);
mTickPaint.setAntiAlias(antiAlias);
}
invalidate();
// Whether the timer should be running depends on whether we're in ambient mode (as well
// as whether we're visible), so we may need to start or stop the timer.
updateTimer();
}
#Override
public void onInterruptionFilterChanged(int interruptionFilter) {
super.onInterruptionFilterChanged(interruptionFilter);
boolean inMuteMode = (interruptionFilter == WatchFaceService.INTERRUPTION_FILTER_NONE);
if (mMute != inMuteMode) {
mMute = inMuteMode;
mHourPaint.setAlpha(inMuteMode ? 100 : 255);
mMinutePaint.setAlpha(inMuteMode ? 100 : 255);
mSecondPaint.setAlpha(inMuteMode ? 80 : 255);
invalidate();
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mBackgroundScaledBitmap == null
|| mBackgroundScaledBitmap.getWidth() != width
|| mBackgroundScaledBitmap.getHeight() != height) {
mBackgroundScaledBitmap = Bitmap.createScaledBitmap(mBackgroundBitmap,
width, height, true /* filter */);
}
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onDraw(Canvas canvas, Rect bounds) {
mCalendar.setTimeInMillis(System.currentTimeMillis());
int width = bounds.width();
int height = bounds.height();
// Draw the background, scaled to fit.
canvas.drawBitmap(mBackgroundScaledBitmap, 0, 0, null);
// Find the center. Ignore the window insets so that, on round watches with a
// "chin", the watch face is centered on the entire screen, not just the usable
// portion.
float centerX = width / 2f;
float centerY = height / 2f;
// Draw the ticks.
float innerTickRadius = centerX - 10;
float outerTickRadius = centerX;
for (int tickIndex = 0; tickIndex < 12; tickIndex++) {
float tickRot = tickIndex * TWO_PI / 12;
float innerX = (float) Math.sin(tickRot) * innerTickRadius;
float innerY = (float) -Math.cos(tickRot) * innerTickRadius;
float outerX = (float) Math.sin(tickRot) * outerTickRadius;
float outerY = (float) -Math.cos(tickRot) * outerTickRadius;
canvas.drawLine(centerX + innerX, centerY + innerY,
centerX + outerX, centerY + outerY, mTickPaint);
}
float seconds =
mCalendar.get(Calendar.SECOND) + mCalendar.get(Calendar.MILLISECOND) / 1000f;
float secRot = seconds / 60f * TWO_PI;
float minutes = mCalendar.get(Calendar.MINUTE) + seconds / 60f;
float minRot = minutes / 60f * TWO_PI;
float hours = mCalendar.get(Calendar.HOUR) + minutes / 60f;
float hrRot = hours / 12f * TWO_PI;
float secLength = centerX - 20;
float minLength = centerX - 40;
float hrLength = centerX - 80;
if (!isInAmbientMode()) {
float secX = (float) Math.sin(secRot) * secLength;
float secY = (float) -Math.cos(secRot) * secLength;
canvas.drawLine(centerX, centerY, centerX + secX, centerY + secY, mSecondPaint);
}
float minX = (float) Math.sin(minRot) * minLength;
float minY = (float) -Math.cos(minRot) * minLength;
canvas.drawLine(centerX, centerY, centerX + minX, centerY + minY, mMinutePaint);
float hrX = (float) Math.sin(hrRot) * hrLength;
float hrY = (float) -Math.cos(hrRot) * hrLength;
canvas.drawLine(centerX, centerY, centerX + hrX, centerY + hrY, mHourPaint);
}
}
The entire code can be found inside the official sample app . Below you can find the screen shot of application which I made using Google official tutorial .
If anyone have any idea how to replace the clock hands with an drawable images ? . Any help would be appreciated .
Create a Bitmap of your drawable resource:
Bitmap hourHand = BitmapFactory.decodeResource(context.getResources(), R.drawable.hour_hand);
Do whatever transformations you need to your canvas and draw the bitmap:
canvas.save();
canvas.rotate(degrees, px, py);
canvas.translate(dx, dy);
canvas.drawBitmap(hourHand, centerX, centerY, null); // Or use a Paint if you need it
canvas.restore();
Use following method to rotate bitmap from canvas,
/**
* To rotate bitmap on canvas
*
* #param canvas : canvas on which you are drawing
* #param handBitmap : bitmap of hand
* #param centerPoint : center for rotation
* #param rotation : rotation angle in form of seconds
* #param offset : offset of bitmap from center point (If not needed then keep it 0)
*/
public void rotateBitmap(Canvas canvas, Bitmap handBitmap, PointF centerPoint, float rotation, float offset) {
canvas.save();
canvas.rotate(secondRotation - 90, centerPoint.x, centerPoint.y);
canvas.drawBitmap(handBitmap, centerPoint.x - offset, centerPoint.y - handBitmap.getHeight() / Constants.INTEGER_TWO, new Paint(Paint.FILTER_BITMAP_FLAG));
canvas.restore();
}
I am a little bit late with the answer, but maybe it can be helpful for others
canvas.save()
val antialias = Paint()
antialias.isAntiAlias = true
antialias.isFilterBitmap = true
antialias.isDither = true
canvas.rotate(secondsRotation - minutesRotation, centerX, centerY)
canvas.drawBitmap(
secondsHandBitmap,
centerX - 10,
centerY - 160,
antialias
)
canvas.restore()
Here is my public Git Repo you can check the source code

How to programmatically change contrast of a bitmap in android?

I want to programmatically change the contrast of bitmap. Till now I have tried this.
private Bitmap adjustedContrast(Bitmap src, double value)
{
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// get contrast value
double contrast = Math.pow((100 + value) / 100, 2);
// scan through all pixels
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
// apply filter contrast for every channel R, G, B
R = Color.red(pixel);
R = (int)(((((R / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(R < 0) { R = 0; }
else if(R > 255) { R = 255; }
G = Color.green(pixel);
G = (int)(((((G / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(G < 0) { G = 0; }
else if(G > 255) { G = 255; }
B = Color.blue(pixel);
B = (int)(((((B / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(B < 0) { B = 0; }
else if(B > 255) { B = 255; }
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
return bmOut;
}
But this does not work as expected. Please help me in this or provide any other solution to achieve this. Thanks in advance.
Here is complete method:
/**
*
* #param bmp input bitmap
* #param contrast 0..10 1 is default
* #param brightness -255..255 0 is default
* #return new bitmap
*/
public static Bitmap changeBitmapContrastBrightness(Bitmap bmp, float contrast, float brightness)
{
ColorMatrix cm = new ColorMatrix(new float[]
{
contrast, 0, 0, 0, brightness,
0, contrast, 0, 0, brightness,
0, 0, contrast, 0, brightness,
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;
}
Try this. Your code didn't work because you create only a mutable bitmap and didn't copy the image of source bitmap to the mutable one if i'm not mistaken.
Hope It helps :)
private Bitmap adjustedContrast(Bitmap src, double value)
{
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
// create a mutable empty bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// create a canvas so that we can draw the bmOut Bitmap from source bitmap
Canvas c = new Canvas();
c.setBitmap(bmOut);
// draw bitmap to bmOut from src bitmap so we can modify it
c.drawBitmap(src, 0, 0, new Paint(Color.BLACK));
// color information
int A, R, G, B;
int pixel;
// get contrast value
double contrast = Math.pow((100 + value) / 100, 2);
// scan through all pixels
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
// apply filter contrast for every channel R, G, B
R = Color.red(pixel);
R = (int)(((((R / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(R < 0) { R = 0; }
else if(R > 255) { R = 255; }
G = Color.green(pixel);
G = (int)(((((G / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(G < 0) { G = 0; }
else if(G > 255) { G = 255; }
B = Color.blue(pixel);
B = (int)(((((B / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(B < 0) { B = 0; }
else if(B > 255) { B = 255; }
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
return bmOut;
}
We can use seek bar to adjust contrast.
MainActivity.java:
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
ImageView imageView;
SeekBar seekbar;
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.image);
textView = (TextView) findViewById(R.id.label);
seekbar = (SeekBar) findViewById(R.id.seekbar);
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
imageView.setImageBitmap(changeBitmapContrastBrightness(BitmapFactory.decodeResource(getResources(), R.drawable.lhota), (float) progress / 100f, 1));
textView.setText("Contrast: "+(float) progress / 100f);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
seekbar.setMax(200);
seekbar.setProgress(100);
}
public static Bitmap changeBitmapContrastBrightness(Bitmap bmp, float contrast, float brightness) {
ColorMatrix cm = new ColorMatrix(new float[]
{
contrast, 0, 0, 0, brightness,
0, contrast, 0, 0, brightness,
0, 0, contrast, 0, brightness,
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;
}
}
activity_main.java:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:textAppearance="#android:style/TextAppearance.Holo.Medium" />
<SeekBar
android:id="#+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Here is a Renderscript implementation (from the Gradle Example Projects)
ip.rsh
#pragma version(1)
#pragma rs java_package_name(your.app.package)
contrast.rs
#include "ip.rsh"
static float brightM = 0.f;
static float brightC = 0.f;
void setBright(float v) {
brightM = pow(2.f, v / 100.f);
brightC = 127.f - brightM * 127.f;
}
void contrast(const uchar4 *in, uchar4 *out)
{
#if 0
out->r = rsClamp((int)(brightM * in->r + brightC), 0, 255);
out->g = rsClamp((int)(brightM * in->g + brightC), 0, 255);
out->b = rsClamp((int)(brightM * in->b + brightC), 0, 255);
#else
float3 v = convert_float3(in->rgb) * brightM + brightC;
out->rgb = convert_uchar3(clamp(v, 0.f, 255.f));
#endif
}
Java
private Bitmap changeBrightness(Bitmap original RenderScript rs) {
Allocation input = Allocation.createFromBitmap(rs, original);
final Allocation output = Allocation.createTyped(rs, input.getType());
ScriptC_contrast mScript = new ScriptC_contrast(rs);
mScript.invoke_setBright(50.f);
mScript.forEach_contrast(input, output);
output.copyTo(original);
return original;
}
Assumption - ImageView is used to display the bitmap
I did a more enhancement in the Ruslan's answer
Instead of replacing bitmap every time (which makes it slow if you are using seek bar) we can work on the Color Filter of the ImageView.
float contrast;
float brightness = 0;
ImageView imageView;
// SeekBar ranges from 0 to 90
// contrast ranges from 1 to 10
mSeekBarContrast.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
contrast = (float) (i + 10) / 10;
// Changing the contrast of the bitmap
imageView.setColorFilter(getContrastBrightnessFilter(contrast,brightness));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
ColorMatrixColorFilter getContrastBrightnessFilter(float contrast, float brightness) {
ColorMatrix cm = new ColorMatrix(new float[]
{
contrast, 0, 0, 0, brightness,
0, contrast, 0, 0, brightness,
0, 0, contrast, 0, brightness,
0, 0, 0, 1, 0
});
return new ColorMatrixColorFilter(cm);
}
P.S - Brightness can also be changed along with contrast using this method
I just had the same problem and ended up using the Color Matrix that Ruslan Yanchyshyn describes. I needed to automatically adjust brightness depending on the image, so I used BoofCV to create a histogram from a scaled version of the image - It took way to long to process the whole image. Then I analyzed the histogram - looked at what was the darkest and brightest colors and then created a color matrix which transforms the colors so the darkest colors are 0 and the brightest colors are 255. In this way the new image uses the whole spectrum from dark/black to light/white now.
Ended up writing a small post on how I did it on our company blog here if anyone are interested. http://appdictive.dk/blog/projects/2016/07/26/levels_with_color_matrix/
Maybe you can try this one:
http://xjaphx.wordpress.com/2011/06/21/image-processing-contrast-image-on-the-fly/
Hope that helps! :)
http://android.okhelp.cz/bitmap-set-contrast-and-brightness-android/
have a look at this ,this might solve your problem

using hue image effect with a seekbar

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.

How to have a Moving graph or chart in android?

I am new to android and I need to know how to make a graph or chart (eg. line chart) move i.e, from right to left.
Basically I am going to draw the graph in accordance with the RAM Memory Usage of the phone. I need to draw a graph similarly present in Task Manager of Windows.
Please help on this.
Take A Look This Class.
It's Simple and Useful.
Original Author is Arno den Hond, Google it.
I redesign this Class.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.view.View;
/**
* GraphView creates a scaled line or bar graph with x and y axis labels.
* #author Arno den Hond
* #redesign Reinhard & kimkmkm
*
*/
public class GraphView extends View {
public static boolean BAR = true;
public static boolean LINE = false;
private Paint paint;
private float[] values;
private String[] horlabels;
private String[] verlabels;
private String title;
private boolean type;
/**
* Generate Graph
* Variable Array for GraphView
* verlabel : Background Height Values
* horlabel : Background Width Values
* values : Max Values of Foreground Active Graph
*
* basic draw rule
* if Array is not null
* Draw Background width, height & active Graph all time
* or Array is null
* Draw Background width, height
* active Graph fixed 0
*
*/
public GraphView(Context context, float[] values, String title, String[] horlabels, String[] verlabels, boolean type) {
super(context);
if (values == null)
values = new float[0];
else
this.values = values;
if (title == null)
title = "";
else
this.title = title;
if (horlabels == null)
this.horlabels = new String[0];
else
this.horlabels = horlabels;
if (verlabels == null)
this.verlabels = new String[0];
else
this.verlabels = verlabels;
this.type = type;
paint = new Paint();
}
/**
* Graph for Background
* &
* Value for Background
*/
#Override
protected void onDraw(Canvas canvas) {
float border = 20;
float horstart = border * 2;
float height = getHeight();
float width = getWidth() - 1;
float max = 700;
float min = 0;
float diff = max - min;
float graphheight = height - (2 * border);
float graphwidth = width - (2 * border);
paint.setTextAlign(Align.LEFT);
/** vers : BackGround Height Values length*/
int vers = verlabels.length - 1;
for (int i = 0; i < verlabels.length; i++) {
paint.setColor(Color.LTGRAY);
// Width Line of background
float y = ((graphheight / vers) * i) + border;
// float y : ((getHeight / Height values length) * Height values length ) + 20
canvas.drawLine(horstart, y, width, y, paint);
// drawLine ( 40, y, getWidth()-1, y, paint)
paint.setColor(Color.WHITE);
// Left Height of background
canvas.drawText(verlabels[i], 0, y, paint);
}
/** hors : BackGround width Values length*/
int hors = horlabels.length - 1;
for (int i = 0; i < horlabels.length; i++) {
// Height Line of background
paint.setColor(Color.DKGRAY);
float x = ((graphwidth / hors) * i) + horstart;
canvas.drawLine(x, height - border, x, border, paint);
paint.setTextAlign(Align.CENTER);
if (i==horlabels.length-1)
paint.setTextAlign(Align.RIGHT);
if (i==0)
paint.setTextAlign(Align.LEFT);
// Value of Width
paint.setColor(Color.WHITE);
canvas.drawText(horlabels[i], x, height - 4, paint);
}
paint.setTextAlign(Align.CENTER);
canvas.drawText(title, (graphwidth / 2) + horstart, border - 4, paint);
/**
* Yellow Line Graph
* continue Repaint....
*
*/
if (max != min) {
paint.setColor(Color.YELLOW);
if (type == BAR) {
float datalength = values.length;
float colwidth = (width - (10 * border)) / datalength;
for (int i = 0; i < values.length; i++) {
float val = values[i] - min;
float rat = val / diff;
//diff : max - min
float h = graphheight * rat;
canvas.drawRect((i * colwidth) + horstart, (border - h) + graphheight, ((i * colwidth) + horstart) + (colwidth - 1), height - (border - 1), paint);
}
} else {
float datalength = values.length;
float colwidth = (width - (2 * border)) / datalength;
float halfcol = colwidth / 2;
float lasth = 0;
for (int i = 0; i < values.length; i++) {
float val = values[i] - min;
float rat = val / diff;
float h = graphheight * rat;
if (i > 0)
canvas.drawLine(((i - 1) * colwidth) + (horstart + 1) + halfcol, (border - lasth) + graphheight, (i * colwidth) + (horstart + 1) + halfcol, (border - h) + graphheight, paint);
lasth = h;
}
}
}
}
It's My Sample Code.
I did not test yet.
But I think This code works fine.
public class DrawGraph extends Activity{
/**
* Variable Array for GraphView
* verlabel : Background Height Values
* horlabel : Background Width Values
* values : Max Values of Foreground Active Graph
*/
private float[] values = new float[60];
private String[] verlabels = new String[] { "600","500","400","300","200","100","80","60","40","20","0", };
private String[] horlabels = new String[] { "0","10", "20", "30", "40", "50", "60"};
private GraphView graphView;
private LinearLayout graph;
private boolean runnable = false;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
graph = (LinearLayout)findViewById(R.id.graph);
graphView = new GraphView(DrawGraph.this, values, "TEST GRAPH", horlabels, verlabels, GraphView.LINE);
graph.addView(graphView);
runnable = true;
startDraw.start();
}
#Override
public void onDestroy(){
super.onDestroy();
runnable = false;
}
public void setGraph(int data){
for(int i=0; i<values.length-1; i++){
values[i] = values[i+1];
}
values[values.length-1] = (float)data;
graph.removeView(graphView);
graph.addView(graphView);
}
public Handler handler = new Handler(){
#Override
public void handleMessage(android.os.Message msg){
switch(msg.what){
case 0x01:
int testValue = (int)(Math.random() * 600)+1;
setGraph(testValue);
break;
}
}
}
public Thread startDraw = new Thread(){
#Override
public void run(){
while(runnable){
handler.sendEmptyMessage(0x01);
try{
Thread.sleep(1000);
} catch (Exception e){
e.printstacktrace();
}
}
}
}
Try AndroidPlot, it's a simple to use library!
See also achartengine.

Rotate a sprite in game android

I want implement move a sprite from position (x ,y ) to position action_down (x1 , y1) .But I can't rotate it .Please help me .Thanks
This is my code:
public Sprite(GameView gameView, Bitmap bmp) {
this.gameView = gameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;// create width, height
this.height = bmp.getHeight() / BMP_ROWS;
Random rnd = new Random(System.currentTimeMillis());
x = rnd.nextInt(gameView.getWidth() - bmp.getWidth());
y = rnd.nextInt(gameView.getHeight() - bmp.getHeight());
}
public void onDraw(Canvas canvas) {
Matrix matrix = new Matrix();
matrix.postTranslate(x, y);
float dx = x1-x;
float dy = y1-y;
float d = (float)Math.sqrt(dx*dx+dy*dy);
vx = (float) (dx*5/d)/3 ;
vy = (float) (dy*5/d)/3 ;
if(k==1){
x += vx ;
y += vy ;
}
currentFrame = ++currentFrame % BMP_COLUMNS;
int srcX = currentFrame * width;
int srcY = 0 * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
You should look at matrix.postRotate or canvas.rotate.
Here you go:
Note: you need to convert from Bitmap to Image.
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
/**
* Created by Chris on 3/28/2014.
*/
public class Sprite {
private Image i;
public Sprite(Image image) {
this.i = image;
}
private BufferedImage image = null;
private Graphics2D graphics = null;
public void onDraw(Canvas canvas) {
if(image == null || graphics == null) {
setup();
}
Graphics g = canvas.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, image.getWidth(), image.getHeight());
//Where to draw the Sprite on the canvas.
int x = 100;
int y = 100;
//Because graphics is an instance of Graphics2D
//Converts the degrees "45" to radians.
double rotationAngle = Math.toRadians(45);
double locX = image.getWidth() / 2;
double locY = image.getHeight() / 2;
AffineTransform tx = AffineTransform.getRotateInstance(rotationAngle, locX, locY);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
graphics.drawImage(op.filter(image, null), 0, 0, null);
g.drawImage(image, x, y, (int) (image.getWidth() / 2), (int) (image.getHeight() / 2), null);
}
/**
* Sets the Image up.
*/
private void setup() {
if(image != null) {
image.flush();
image = null;
}
if(graphics != null) {
graphics.dispose();
graphics = null;
}
image = new BufferedImage(i.getWidth(null) * 2, i.getHeight(null) * 2, BufferedImage.TYPE_INT_ARGB);
graphics = image.createGraphics();
}
}

Categories

Resources