is it possible to shear image in Android? Seems I can't find any tutorial of it.
Perhaps you've found the solution, but just in case, I think this is what you needed:
Bitmap src = BitmapFactory.decodeResource(this.getResources(), drawable.sample);
int width = src.getWidth();
int height = src.getHeight();
float skewX = 5.0;
float skewY = 6.0;
Matrix matrix = new Matrix();
matrix.setSkew(skewX, skewY);
Bitmap img = Bitmap.createBitmap(src, 0, 0, width, height, matrix, true);
This May Help you
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
R.drawable.flower_blue);
Bitmap croppedBmp = Bitmap.createBitmap(bitmapOrg, 0, 0,
bitmapOrg.getWidth() / 2, bitmapOrg.getHeight());
int h = bitmapOrg.getHeight();
canvas.drawBitmap(bitmapOrg, 10, 10, paint);
canvas.drawBitmap(croppedBmp, 10, 10 + h + 10, paint);
Related
working on generate reflection for thumbnail in recent app menu
the code works very well with CM10 but since update to CM11 (kitkat) they moved to use Drawable instead of Bitmap for reduce memory usage
https://github.com/CyanogenMod/android_frameworks_base/commit/9926272f32868c858b24b45e048210cf3515741e
here should add the changes:
https://github.com/CyanogenMod/android_frameworks_base/blob/1e3c4a9e687b19cd7837fed51eb25e92a4f691c1/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java#L509
here my code:
final int reflectionGap = 4;
int width = thumbnail.getWidth();
int height = thumbnail.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
Bitmap reflectionImage = Bitmap.createBitmap(thumbnail, 0, height * 2 / 3, width, height/3, matrix, false);
Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height/3), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmapWithReflection);
canvas.drawBitmap(thumbnail, 0, 0, null);
Paint defaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, thumbnail.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,
TileMode.CLAMP);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, height, width,
bitmapWithReflection.getHeight() + reflectionGap, paint);
h.thumbnailViewImage.setImageBitmap(bitmapWithReflection);
my question is :
how i can make this code works with Drawable instead of Bitmap
thanks
try this:
Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher);
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, w, h);
Bitmap b = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas c = new Canvas(b);
c.translate(0, h);
c.scale(1, -1);
drawable.draw(c);
// test it
ImageView iv = new ImageView(this);
iv.setImageBitmap(b);
setContentView(iv);
I take a picture with camera through intent. After I receive the image, my app has a rotate button. say the image came back width = 900 and height=1200. After I rotate the image, I still want width = 900 and height=1200 as opposed to width = 1200 and height=900. Does anyone know how I might to that?
Here is the code that hasn't worked.
Bitmap bmp = readBitmap(context.getContentResolver(), imageUri, sampleScale, options);
float widthScale = 0.9f * deviceDimension[1] / bmp.getWidth();
float heightScale = 0.8f * deviceDimension[0] / bmp.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(widthScale, heightScale);
matrix.preRotate(angle);//90x
return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
So basically, I want the image to still fit a present dimension on the screen no matter how I orient the image. The present area is, say, 900 by 1200
Use
return Bitmap.createBitmap(bmp, 0, 0, bmp.getHeight(), bmp.getWidth(), matrix, true);
instead of
return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
see if this works??
public static Bitmap ScaleBitmap(Bitmap bm, float scalingFactor) {
int scaleHeight = (int) (bm.getHeight() * scalingFactor);
int scaleWidth = (int) (bm.getWidth() * scalingFactor);
return Bitmap.createScaledBitmap(bm, scaleWidth, scaleHeight, true);
}
private float getBitmapScalingFactor(Bitmap bm) {
// Get display width from device
int displayWidth = getWindowManager().getDefaultDisplay().getWidth();
// Get margin to use it for calculating to max width of the ImageView
LinearLayout.LayoutParams layoutParams =
(LinearLayout.LayoutParams)this.imageView.getLayoutParams();
int leftMargin = layoutParams.leftMargin;
int rightMargin = layoutParams.rightMargin;
// Calculate the max width of the imageView
int imageViewWidth = displayWidth - (leftMargin + rightMargin);
// Calculate scaling factor and return it
return ( (float) imageViewWidth / (float) bm.getWidth() );
}
I have got images which I want to slice into 10 pieces vertically of equal height so on hdpi slice dimensions are 800*48 (landscape application). I have got following code which is not working
public void convertBitmapinSlices(){
Bitmap tempBitmap;
try{
Paint paint = new Paint();
paint.setFilterBitmap(true);
tempBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img1);
int targetWidth = (int) Methods.dpToPx(tempBitmap.getWidth(), this);
Log.v("TARGET_WIDTH", Integer.toString(targetWidth));
int targetHeight = (int) (Methods.dpToPx(tempBitmap.getHeight(), this)/10);
Log.v("TARGET_HEIGHT", Integer.toString(targetHeight));
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight,Bitmap.Config.ARGB_8888);
RectF rectf = new RectF(0, 0, targetWidth, targetHeight);
Canvas canvas = new Canvas(targetBitmap);
Path path = new Path();
path.addRect(rectf, Path.Direction.CW);
canvas.clipPath(path);
int starty=0;
lLforGardenImages.removeAllViews();
for(int i=1; i<=10;i++){
Log.v("SRC-Height", Integer.toString(targetHeight*i));
Log.v("START-Y", Integer.toString(starty));
canvas.drawBitmap(tempBitmap, new Rect(0, starty, tempBitmap.getWidth(), (tempBitmap.getHeight()/10)+starty),
new Rect(0, 0, targetWidth,targetHeight), paint);
// Matrix matrix = new Matrix();
// matrix.postScale(1f, 1f);
Bitmap resizedBitmap = Bitmap.createBitmap(targetBitmap, 0, 0, targetWidth, targetHeight, null, true);
Log.v("Width after Resizing ", resizedBitmap.getWidth()+"");
Log.v("Height after Resizing ", resizedBitmap.getHeight()+"");
BitmapDrawable bd = new BitmapDrawable(resizedBitmap);
ImageView iv = new ImageView(this);
iv.setAdjustViewBounds(true);
iv.setBackgroundDrawable(bd);
lLforGardenImages.addView(iv, llayoutParams);
if((i % 2) == 0){
iv.startAnimation(sliderAnimation(-1.0f,0.0f,0.0f,0.0f,1000));
}else{
iv.startAnimation(sliderAnimation(1.0f,0.0f,0.0f,0.0f,1000));
}
starty= starty+targetHeight;
}
}
catch(Exception e){
System.out.println("Error1 : " + e.getMessage() + e.toString());
}
}
Any idea what I am doing wrong?
Output is that slice is not correct and have contents which seems to have smaller height but height of slice is correct i.e 48 and width is correct too. So only issue with above code is that contents height seems to be incorrect even though slice height is correct.
I have read those posts on this issue but my case is abit different as I am NOT DISPLAYING the bitmap but just post-processing the image from raw data.
First, I call ImageProcessing.rgbToBitmap(data,width, height); which will return a Bitmap object. Then I perform these 3 functions SEPARATELY.
Rotate Bitmap
Add a watermark overlay to Bitmap
Add date at lower right hand corner of Bitmap
All 3 methods called will create an return a Bitmap object which probably causes the crash as I am trying to save an image every 1000ms! Sometimes the images saved are distorted probably due to the memory error.
I am posting my codes below and any advices are greatly appreciated. I do not want to compromise on the quality on the image taken though. (Need to preserve the resolution)
public static Bitmap addWatermark(Resources res, Bitmap source) {
int w, h;
Canvas c;
Paint paint;
Bitmap bmp, watermark;
Matrix matrix;
float scale;
RectF r;
w = source.getWidth();
h = source.getHeight();
// Create the new bitmap
bmp = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG
| Paint.FILTER_BITMAP_FLAG);
// Copy the original bitmap into the new one
c = new Canvas(bmp);
c.drawBitmap(source, 0, 0, paint);
// Load the watermark
watermark = BitmapFactory.decodeResource(res, R.drawable.watermark);
// Scale the watermark to be approximately 10% of the source image
// height
scale = (float) (((float) h * 0.80) / (float) watermark.getHeight());
// Create the matrix
matrix = new Matrix();
matrix.postScale(scale, scale);
// Determine the post-scaled size of the watermark
r = new RectF(0, 0, watermark.getWidth(), watermark.getHeight());
matrix.mapRect(r);
// Center watermark
matrix.postTranslate((w - r.width()) / 2, (h - r.height()) / 2);
// Draw the watermark
c.drawBitmap(watermark, matrix, paint);
// Free up the bitmap memory
watermark.recycle();
return bmp;
}
public static Bitmap addDate(Bitmap src, String date) {
int w = src.getWidth();
int h = src.getHeight();
//Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Bitmap result = src;
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
paint.setColor(Color.rgb(255, 185, 15));
paint.setTextSize(20);
paint.setAntiAlias(true);
canvas.drawText(date, w - 200, h - 20, paint);
return result;
}
public static Bitmap rotate(Bitmap src, int rotation) {
int width = src.getWidth();
int height = src.getHeight();
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// rotate the Bitmap
matrix.postRotate(rotation);
// recreate the new Bitmap, swap width and height and apply
// transform
Bitmap rotatedBitmap = Bitmap.createBitmap(src, 0, 0, width, height,
matrix, true);
return rotatedBitmap;
}
Try this first:
Change
// Copy the original bitmap into the new one
c = new Canvas(bmp);
c.drawBitmap(source, 0, 0, paint);
with
// Copy the original bitmap into the new one
c = new Canvas(bmp);
bmp.recycle(); //here or below
c.drawBitmap(source, 0, 0, paint);
//below bmp.recycle();
and here:
canvas.drawText(date, w - 200, h - 20, paint);
return result;
with
canvas.drawText(date, w - 200, h - 20, paint);
result.recycle();
return result;
and here
Bitmap rotatedBitmap = Bitmap.createBitmap(src, 0, 0, width, height,
matrix, true);
return rotatedBitmap;
with
Bitmap rotatedBitmap = Bitmap.createBitmap(src, 0, 0, width, height,
matrix, true);
return rotatedBitmap;
rotatedBitmap.recycle();
Add all this (recycle();) maybe this is already enough and also try the code with smaller bitmaps, en see if it still crashes (like 50px by 50px).
And no, their is no way to increase the VM of your phone.
I have bitmaps which are squares or rectangles. I take the shortest side and do something like this:
int value = 0;
if (bitmap.getHeight() <= bitmap.getWidth()) {
value = bitmap.getHeight();
} else {
value = bitmap.getWidth();
}
Bitmap finalBitmap = null;
finalBitmap = Bitmap.createBitmap(bitmap, 0, 0, value, value);
Then I scale it to a 144 x 144 Bitmap using this:
Bitmap lastBitmap = null;
lastBitmap = Bitmap.createScaledBitmap(finalBitmap, 144, 144, true);
Problem is that it crops the top left corner of the original bitmap, Anyone has the code to crop the center of the bitmap?
This can be achieved with: Bitmap.createBitmap(source, x, y, width, height)
if (srcBmp.getWidth() >= srcBmp.getHeight()){
dstBmp = Bitmap.createBitmap(
srcBmp,
srcBmp.getWidth()/2 - srcBmp.getHeight()/2,
0,
srcBmp.getHeight(),
srcBmp.getHeight()
);
}else{
dstBmp = Bitmap.createBitmap(
srcBmp,
0,
srcBmp.getHeight()/2 - srcBmp.getWidth()/2,
srcBmp.getWidth(),
srcBmp.getWidth()
);
}
While most of the above answers provide a way to do this, there is already a built-in way to accomplish this and it's 1 line of code (ThumbnailUtils.extractThumbnail())
int dimension = getSquareCropDimensionForBitmap(bitmap);
bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension);
...
//I added this method because people keep asking how
//to calculate the dimensions of the bitmap...see comments below
public int getSquareCropDimensionForBitmap(Bitmap bitmap)
{
//use the smallest dimension of the image to crop to
return Math.min(bitmap.getWidth(), bitmap.getHeight());
}
If you want the bitmap object to be recycled, you can pass options that make it so:
bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
From: ThumbnailUtils Documentation
public static Bitmap extractThumbnail (Bitmap source, int width, int
height)
Added in API level 8 Creates a centered bitmap of the desired size.
Parameters source original bitmap source width targeted width
height targeted height
I was getting out of memory errors sometimes when using the accepted answer, and using ThumbnailUtils resolved those issues for me. Plus, this is much cleaner and more reusable.
Have you considered doing this from the layout.xml ? You could set for your ImageView the ScaleType to android:scaleType="centerCrop" and set the dimensions of the image in the ImageView inside the layout.xml.
You can used following code that can solve your problem.
Matrix matrix = new Matrix();
matrix.postScale(0.5f, 0.5f);
Bitmap croppedBitmap = Bitmap.createBitmap(bitmapOriginal, 100, 100,100, 100, matrix, true);
Above method do postScalling of image before cropping, so you can get best result with cropped image without getting OOM error.
For more detail you can refer this blog
Here a more complete snippet that crops out the center of an [bitmap] of arbitrary dimensions and scales the result to your desired [IMAGE_SIZE]. So you will always get a [croppedBitmap] scaled square of the image center with a fixed size. ideal for thumbnailing and such.
Its a more complete combination of the other solutions.
final int IMAGE_SIZE = 255;
boolean landscape = bitmap.getWidth() > bitmap.getHeight();
float scale_factor;
if (landscape) scale_factor = (float)IMAGE_SIZE / bitmap.getHeight();
else scale_factor = (float)IMAGE_SIZE / bitmap.getWidth();
Matrix matrix = new Matrix();
matrix.postScale(scale_factor, scale_factor);
Bitmap croppedBitmap;
if (landscape){
int start = (tempBitmap.getWidth() - tempBitmap.getHeight()) / 2;
croppedBitmap = Bitmap.createBitmap(tempBitmap, start, 0, tempBitmap.getHeight(), tempBitmap.getHeight(), matrix, true);
} else {
int start = (tempBitmap.getHeight() - tempBitmap.getWidth()) / 2;
croppedBitmap = Bitmap.createBitmap(tempBitmap, 0, start, tempBitmap.getWidth(), tempBitmap.getWidth(), matrix, true);
}
Probably the easiest solution so far:
public static Bitmap cropCenter(Bitmap bmp) {
int dimension = Math.min(bmp.getWidth(), bmp.getHeight());
return ThumbnailUtils.extractThumbnail(bmp, dimension, dimension);
}
imports:
import android.media.ThumbnailUtils;
import java.lang.Math;
import android.graphics.Bitmap;
To correct #willsteel solution:
if (landscape){
int start = (tempBitmap.getWidth() - tempBitmap.getHeight()) / 2;
croppedBitmap = Bitmap.createBitmap(tempBitmap, start, 0, tempBitmap.getHeight(), tempBitmap.getHeight(), matrix, true);
} else {
int start = (tempBitmap.getHeight() - tempBitmap.getWidth()) / 2;
croppedBitmap = Bitmap.createBitmap(tempBitmap, 0, start, tempBitmap.getWidth(), tempBitmap.getWidth(), matrix, true);
}
public Bitmap getResizedBitmap(Bitmap bm) {
int width = bm.getWidth();
int height = bm.getHeight();
int narrowSize = Math.min(width, height);
int differ = (int)Math.abs((bm.getHeight() - bm.getWidth())/2.0f);
width = (width == narrowSize) ? 0 : differ;
height = (width == 0) ? differ : 0;
Bitmap resizedBitmap = Bitmap.createBitmap(bm, width, height, narrowSize, narrowSize);
bm.recycle();
return resizedBitmap;
}
public static Bitmap resizeAndCropCenter(Bitmap bitmap, int size, boolean recycle) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
if (w == size && h == size) return bitmap;
// scale the image so that the shorter side equals to the target;
// the longer side will be center-cropped.
float scale = (float) size / Math.min(w, h);
Bitmap target = Bitmap.createBitmap(size, size, getConfig(bitmap));
int width = Math.round(scale * bitmap.getWidth());
int height = Math.round(scale * bitmap.getHeight());
Canvas canvas = new Canvas(target);
canvas.translate((size - width) / 2f, (size - height) / 2f);
canvas.scale(scale, scale);
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
canvas.drawBitmap(bitmap, 0, 0, paint);
if (recycle) bitmap.recycle();
return target;
}
private static Bitmap.Config getConfig(Bitmap bitmap) {
Bitmap.Config config = bitmap.getConfig();
if (config == null) {
config = Bitmap.Config.ARGB_8888;
}
return config;
}
val sourceWidth = source.width
val sourceHeight = source.height
val xScale = newWidth.toFloat() / sourceWidth
val yScale = newHeight.toFloat() / sourceHeight
val scale = xScale.coerceAtLeast(yScale)
val scaledWidth = scale * sourceWidth
val scaledHeight = scale * sourceHeight
val left = (newWidth - scaledWidth) / 2
val top = (newHeight - scaledHeight) / 2
val targetRect = RectF(
left, top, left + scaledWidth, top
+ scaledHeight
)
val dest = Bitmap.createBitmap(
newWidth, newHeight,
source.config
)
val mutableDest = dest.copy(source.config, true)
val canvas = Canvas(mutableDest)
canvas.drawBitmap(source, null, targetRect, null)
binding.imgView.setImageBitmap(mutableDest)