package v2.simpleUi.util; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.util.TypedValue; import android.view.View; public class ImageTransform { /** * @param bitmap * the source * @param factor * should be between 2f (very visible round corners) and 20f * (nearly no round corners) * @return the result */ public static Bitmap createBitmapWithRoundCorners(Bitmap bitmap, float factor) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); Canvas canvas = new Canvas(result); Rect rect = new Rect(0, 0, width, height); RectF roundCornerFrameRect = new RectF(rect); float cornerRadius = width / factor; Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); canvas.drawRoundRect(roundCornerFrameRect, cornerRadius, cornerRadius, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return result; } public static Bitmap createDummyBitmap() { int size = 128; Bitmap b = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_4444); Canvas c = new Canvas(b); Paint p = new Paint(); p.setStyle(Paint.Style.STROKE); p.setStrokeWidth(20); int alpha = 255; p.setColor(Color.rgb(50, 0, 0)); p.setAlpha(alpha); c.drawLine(0, 0, size, size, p); p.setColor(Color.BLUE); p.setAlpha(alpha); c.drawLine(0, size, size, 0, p); p.setColor(Color.RED); p.setAlpha(alpha); c.drawLine(0, size / 2, size, size / 2, p); p.setColor(Color.YELLOW); p.setAlpha(alpha); c.drawLine(size / 2, 0, size / 2, size, p); float[] filterKernel = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; // improveSaturation(b, b, filterKernel, 1, 1, 1, 255, // 255); return b; } public static Bitmap createDummyBitmap2(View v) { int size = 128; Bitmap b = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_4444); Canvas c = new Canvas(b); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setColor(Color.BLUE); p.setStyle(Paint.Style.FILL); p.setStrokeWidth(10); drawCircle(v, c, size / 2, size / 2, size / 2, p); return b; } /** * use {@link ImageTransform#dipToPixels(Resources, Integer)} instead * * @param sizeInDip * @return size in pixels */ @Deprecated public static float dipToPixels(View v, float sizeInDip) { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, sizeInDip, v.getResources().getDisplayMetrics()); } /** * Converts the dip into its equivalent pixel size * * @param resources * get the ressources object e.g. via context.getRessources or * view.getRessources * @param sizeInDip * @return */ public static float dipToPixels(Resources resources, Integer sizeInDip) { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, sizeInDip, resources.getDisplayMetrics()); } /** * The Eclipse UI editor cant preview ressources loaded from the assets * folder so a dummy bitmap is used instead * * @param context * @param id * @return */ public static Bitmap loadBitmapFromIdInCustomView(View v, int id) { if (v.isInEditMode() || id == 0) { return createDummyBitmap(); } else { return IO.loadBitmapFromId(v.getContext(), id); } } /** * Use this method instead of * {@link Canvas#drawCircle(float, float, float, Paint)} or the Eclipse UI * Editor preview will be incorrect * * @param canvas * @param cx * @param cy * @param radius * @param paint */ public static void drawCircle(View v, Canvas canvas, float cx, float cy, float radius, Paint paint) { if (v.isInEditMode()) { RectF arcRect = new RectF(cx - radius, cy - radius, cx + radius, cy + radius); // Draw the Minutes-Arc into that rectangle canvas.drawArc(arcRect, -90, 360, false, paint); } else { canvas.drawCircle(cx, cy, radius, paint); } } /** * TODO compare to createBitmapWithRoundCorners(..) and combine to one * method * * @param bitmap * @param pixels * @return */ @Deprecated public static Bitmap createRoundedCornerBitmap(Bitmap bitmap, int pixels) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig()); Canvas canvas = new Canvas(output); final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(0xff424242); canvas.drawRoundRect(new RectF(rect), pixels, pixels, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; } /** * This will scale the image first to add soft corners * * @param bitmap * @param angle * @param smoothingFactor * try 1.5f; (1 would be no smoothing at all) * @return */ public static Bitmap rotateBitmap(Bitmap bitmap, int angle, float smoothingFactor) { Bitmap result = ImageTransform.resizeBitmap(bitmap, bitmap.getHeight() * smoothingFactor, bitmap.getWidth() * smoothingFactor); result = rotateBitmap(result, angle); result = ImageTransform.resizeBitmap(result, result.getHeight() / smoothingFactor, result.getWidth() / smoothingFactor); return result; } public static Bitmap rotateBitmap(Bitmap bitmap, int angle) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); Bitmap result = Bitmap.createBitmap(width, height, bitmap.getConfig()); Canvas canvas = new Canvas(result); Matrix matrix = new Matrix(); matrix.setRotate(angle, width / 2, height / 2); Paint p = new Paint(); p.setAntiAlias(true); canvas.drawBitmap(bitmap, matrix, p); return result; } public static Bitmap makeSquare(Bitmap bitmap) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); if (width == height) return bitmap; int size = width > height ? width : height; Bitmap newB = Bitmap.createBitmap(size, size, bitmap.getConfig()); Canvas c = new Canvas(newB); int left = 0; int top = 0; if (width < height) left = Math.abs((width - height) / 2); else top = Math.abs((width - height) / 2); c.drawBitmap(bitmap, left, top, new Paint()); return newB; } public static Bitmap addMargin(Bitmap bitmap, int marginSize) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); Bitmap newB = Bitmap.createBitmap(width + 2 * marginSize, height + 2 * marginSize, bitmap.getConfig()); Canvas c = new Canvas(newB); c.drawBitmap(bitmap, marginSize, marginSize, new Paint()); return newB; } public static Bitmap resizeBitmap(Bitmap bitmap, float newHeight, float newWidth) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true); } /** * From * http://android-developers.blogspot.com/2012/01/levels-in-renderscript * .html * * TODO add description for parameters * * @param sourceBitmap * @param resultBitmap * @param filterKernel * has to be a 3x3 matrix so float[9]. The kernal which will keep * all color values like they are is filterKernel={1,0,0, 0,1,0, * 0,0,1}. * @param mOverInWMinInB * from 0 to 1 * @param gammaValue * from 0 to 1 * @param mOutWMinOutB * from 0 to 1 * @param mInBlack * from 0 to 255 * @param mOutBlack * from 0 to 255 */ public static void improveSaturation(Bitmap sourceBitmap, Bitmap resultBitmap, float[] filterKernel, float mOverInWMinInB, float gammaValue, float mOutWMinOutB, float mInBlack, float mOutBlack) { int[] mInPixels = new int[sourceBitmap.getHeight() * sourceBitmap.getWidth()]; int[] mOutPixels = new int[resultBitmap.getHeight() * resultBitmap.getWidth()]; sourceBitmap.getPixels(mInPixels, 0, sourceBitmap.getWidth(), 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight()); for (int i = 0; i < mInPixels.length; i++) { float r = (float) (mInPixels[i] & 0xff); float g = (float) ((mInPixels[i] >> 8) & 0xff); float b = (float) ((mInPixels[i] >> 16) & 0xff); float tr = r * filterKernel[0] + g * filterKernel[3] + b * filterKernel[6]; float tg = r * filterKernel[1] + g * filterKernel[4] + b * filterKernel[7]; float tb = r * filterKernel[2] + g * filterKernel[5] + b * filterKernel[8]; r = tr; g = tg; b = tb; if (r < 0.f) r = 0.f; if (r > 255.f) r = 255.f; if (g < 0.f) g = 0.f; if (g > 255.f) g = 255.f; if (b < 0.f) b = 0.f; if (b > 255.f) b = 255.f; r = (r - mInBlack) * mOverInWMinInB; g = (g - mInBlack) * mOverInWMinInB; b = (b - mInBlack) * mOverInWMinInB; if (gammaValue != 1.0f) { r = (float) java.lang.Math.pow(r, gammaValue); g = (float) java.lang.Math.pow(g, gammaValue); b = (float) java.lang.Math.pow(b, gammaValue); } r = (r * mOutWMinOutB) + mOutBlack; g = (g * mOutWMinOutB) + mOutBlack; b = (b * mOutWMinOutB) + mOutBlack; if (r < 0.f) r = 0.f; if (r > 255.f) r = 255.f; if (g < 0.f) g = 0.f; if (g > 255.f) g = 255.f; if (b < 0.f) b = 0.f; if (b > 255.f) b = 255.f; mOutPixels[i] = ((int) r) + (((int) g) << 8) + (((int) b) << 16) + (mInPixels[i] & 0xff000000); } resultBitmap.setPixels(mOutPixels, 0, resultBitmap.getWidth(), 0, 0, resultBitmap.getWidth(), resultBitmap.getHeight()); } /** * @param targetBitmap * @param type * 1 is Green-Blue, 2 is Red-Blue, 3 is Red - Green */ public static void switchColors(Bitmap targetBitmap, int type) { int width = targetBitmap.getWidth(); int height = targetBitmap.getHeight(); int[] srcPixels = new int[width * height]; targetBitmap.getPixels(srcPixels, 0, width, 0, 0, width, height); int[] destPixels = new int[width * height]; switch (type) { case 1: swapGreenBlue(srcPixels, destPixels); break; case 2: swapRedBlue(srcPixels, destPixels); break; case 3: swapRedGreen(srcPixels, destPixels); break; } targetBitmap.setPixels(destPixels, 0, width, 0, 0, width, height); } private static void swapGreenBlue(int[] src, int[] dest) { for (int i = 0; i < src.length; i++) { dest[i] = (src[i] & 0xffff0000) | ((src[i] & 0x000000ff) << 8) | ((src[i] & 0x0000ff00) >> 8); } } private static void swapRedBlue(int[] src, int[] dest) { for (int i = 0; i < src.length; i++) { dest[i] = (src[i] & 0xff00ff00) | ((src[i] & 0x000000ff) << 16) | ((src[i] & 0x00ff0000) >> 16); } } private static void swapRedGreen(int[] src, int[] dest) { for (int i = 0; i < src.length; i++) { dest[i] = (src[i] & 0xff0000ff) | ((src[i] & 0x0000ff00) << 8) | ((src[i] & 0x00ff0000) >> 8); } } }