When I rotate a bitmap it rotates but it keeps moving all over the screen and rotating simultaneously. I want it to rotate in the center ? My code is given below.
try {
c = holder.lockCanvas();
// clear the canvas
c.drawColor(Color.BLACK);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
if (c != null) {
int width=c.getWidth();
int height=c.getHeight();
c.drawBitmap(backgroundImage, 0, 0, null);
Matrix transform = new Matrix();
Matrix transform1=new Matrix();
transform.setRotate(degree, width/2,height/2);
c.drawBitmap(image1, transform, null);
//canvas.rotate(-90);
degree+=5;
c.restore();
}
}
Try this code..
c = holder.lockCanvas();
c.drawColor(Color.BLACK);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
if (c != null)
{
int width=c.getWidth();
int height=c.getHeight();
c.drawBitmap(backgroundImage, 0, 0, null);
Matrix matrix = new Matrix();
float px = width/2;
float py = height/2;
matrix.postTranslate(-image1.getWidth()/2, -image1.getHeight()/2);
matrix.postRotate(degree);
matrix.postTranslate(px, py);
c.drawBitmap(image1, matrix, paint);
degree+=5;
c.restore();
}
Related
I'm trying to draw a bunch of bitmaps vertically one below the other like this :
Original Bitmap :
Result expected :
Code :
int repeater = 4;
Bitmap bitmapTextSticker = ImageUtils.drawable2Bitmap(ResourceUtils.getDrawable(R.drawable.icon));
Bitmap background = Bitmap.createBitmap(bitmapTextSticker.getWidth(), bitmapTextSticker.getHeight() * repeater, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(background);
int top = 0;
for (int i = 0; i < repeater; i++) {
top = (i == 0 ? 0 : top + bitmapTextSticker.getHeight());
canvas.drawBitmap(bitmapTextSticker, 0f, top, null);
}
The above code is working, but the output is cropped.
I'm not sure if I'm missing something in your question, but all you have to do is change the top coordinate for each bitmap when calling drawBitmap(). In your specific code, just add:
top += height;
inside the for loop
Edit: from your updated question, it sounds like a Bitmap scaling issue, not a problem with position. Even your 1st bitmap is cropped. So, you should probably use a different canvas.drawbitmap() method:
public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)
You can specify the dimensions of the destination Rect, which should let it scale properly. So, your code should be:
for(...){
...
RectF dest = new RectF(new Rect(0, top, bitmapTextSticker.getWidth(), bitmapTextSticker.getHeight()));
canvas.drawBitmap(bitmapTextSticker, null, dest, null);
}
The issue was I didn't set the density for the bitmap and the canvas :
ArrayList<Bitmap> bitmaps = new ArrayList<>();
for (int i = 0; i < repeater; i++) bitmaps.add(bmp);
int height = 0;
for (Bitmap map : bitmaps) height += map.getHeight();
Bitmap bitmap = Bitmap.createBitmap(bmp.getWidth(), height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.setDensity(DisplayMetrics.DENSITY_MEDIUM);
bitmap.setDensity(DisplayMetrics.DENSITY_MEDIUM);
int drawHeight = 0;
for (Bitmap map : bitmaps) {
if (map != null) {
canvas.drawBitmap(map, 0, drawHeight, null);
drawHeight += map.getHeight();
}
}
return bitmap;
I'm trying to draw some text on bitmap with a fixed position (Bottom left corner) no matter how bitmap size different.
Code below works but, the Text is drawn on the center of the bitmap
public Bitmap drawTextToBitmap(Context gContext,
Bitmap bitmap,
String gText) {
Resources resources = gContext.getResources();
float scale = resources.getDisplayMetrics().density;
android.graphics.Bitmap.Config bitmapConfig =
bitmap.getConfig();
if (bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(getResources().getColor(R.color.fujiColor));
paint.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/DS-DIGI.TTF"));
paint.setTextSize((int) (14 * scale));
paint.setShadowLayer(1f, 0f, 1f, getResources().getColor(R.color.fujiShadowColor));
Rect bounds = new Rect();
paint.getTextBounds(gText, 0, gText.length(), bounds);
int x = (bitmap.getWidth() - bounds.width()) / 2;
int y = (bitmap.getHeight() + bounds.height()) / 2;
canvas.drawText(gText, x, y, paint);
return bitmap;
}
What I need is something similar to this :
Thank you.
As mentioned in the official docs, the text is drawn taking the (x,y) values as origin. Change the x,y values. Something along the following lines should work.
int horizontalSpacing = 24;
int verticalSpacing = 36;
int x = horizontalSpacing;//(bitmap.getWidth() - bounds.width()) / 2;
int y = bitmap.getHeight()-verticalSpacing;//(bitmap.getHeight() + bounds.height()) / 2;
below image and code see, if's give different output in different device.
bitmaptemplate= BitmapFactory.decodeResource(getResources(),R.drawable.fb_template);
android.graphics.Bitmap.Config bitmapConfig = bitmaptemplate.getConfig();
// set default bitmap config if none
if(bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmaptemplate = bitmaptemplate.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmaptemplate);
Bitmap bitmaplogo=BitmapFactory.decodeResource(getResources(),R.drawable.temp);
android.graphics.Bitmap.Config bitmapConfi = bitmaplogo.getConfig();
if(bitmapConfi == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmaplogo = bitmaplogo.copy(bitmapConfig, true);
Canvas canlogo=new Canvas(bitmaplogo);
canlogo.drawColor(Color.BLACK);
Rect dstRectForRender=new Rect(10,250,700,700);
canvas.drawBitmap (bitmaplogo , null, dstRectForRender, null );
Paint paint = new Paint();
paint.setColor(Color.BLACK);
int spSize = 45;
float scaledSizeInPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spSize, getResources().getDisplayMetrics());
paint.setTextSize(scaledSizeInPixels);
paint.setFakeBoldText(true);
paint.setColor(Color.BLACK);
canvas.drawText("PRATIK N SANYAJA", 20, 900+100, paint);
I have a motion JPEG stream that is put on a canvas in Android. My problem is that at the bottom right of the canvas there is a little, gray, pixelated bar. It kinda of disappears and re-appears. I don't have this issue on other platforms that use the same stream, so i'm guessing its an Android problem. Here is my code:
Canvas canvas = null;
try
{
Bitmap bmp = BitmapFactory.decodeByteArray(notifi.imgData, 0, notifi.imgData.length);
if (bmp == null)
System.out.println("Skipping invalid MJpeg frame");
else
{
canvas = holder.lockCanvas(null);
if (canvas == null)
{
System.out.println("Cannot lock canvas, skipping MJpeg frame");
return;
}
canvas.drawColor(Color.BLACK);
Rect dst = null;
int viewWidth = mPreview.getWidth();
int viewHeight = mPreview.getHeight();
float ratio = bmp.getWidth() / (float)bmp.getHeight();
int desiredHeight = (int)(viewWidth / ratio);
if (desiredHeight > viewHeight)
{ // Letterbox
int maxWidth = (int)(viewHeight * ratio);
int pad = (viewWidth - maxWidth) / 2;
dst = new Rect(pad, 0, maxWidth + pad, viewHeight);
}
else
{
int pad = (viewHeight - desiredHeight) / 2;
dst = new Rect(0, pad, viewWidth, desiredHeight + pad);
}
canvas.drawBitmap(bmp, null, dst, null);
}
} finally {
if (canvas != null)
holder.unlockCanvasAndPost(canvas);
}
}
});
canvas = holder.lockCanvas(null); looks suspect.
Try canvas = holder.lockCanvas(); instead.
I notice that you are adding a "Pad" to the destination rectangle to change it's height.
If you do that, I wonder if the destination rectangle size will match the size of the image you are drawing and thus "over draw" some gray bar as you are seeing. Just a guess - maybe if you remove the height pad it will go away? Just a guess.
dst = new Rect(0, pad, viewWidth, desiredHeight + pad);
canvas.drawBitmap(bmp, null, dst, null);
How to set all white the 10 rows on the left side of a Bitmap?
I'v got a Bitmap that has to be padded on the left side. I thought i can create a new image iterate on the old one getpixel for each position and setpixel on the new one (white or colored) than return the new bitmap...is this wrong?
Any suggestion? thanks a lot!
You can instead create a new Bitmap with the extra padding number of pixels.
Set this as the canvas bitmap and Color the entire image with the required color and then copy your bitmap.
public Bitmap pad(Bitmap Src, int padding_x, int padding_y) {
Bitmap outputimage = Bitmap.createBitmap(Src.getWidth() + padding_x,Src.getHeight() + padding_y, Bitmap.Config.ARGB_8888);
Canvas can = new Canvas(outputimage);
can.drawARGB(FF,FF,FF,FF); //This represents White color
can.drawBitmap(Src, padding_x, padding_y, null);
return outputimage;
}
public Bitmap addPaddingTopForBitmap(Bitmap bitmap, int paddingTop) {
Bitmap outputBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight() + paddingTop, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(outputBitmap);
canvas.drawColor(Color.RED);
canvas.drawBitmap(bitmap, 0, paddingTop, null);
return outputBitmap;
}
public Bitmap addPaddingBottomForBitmap(Bitmap bitmap, int paddingBottom) {
Bitmap outputBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight() + paddingBottom, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(outputBitmap);
canvas.drawColor(Color.RED);
canvas.drawBitmap(bitmap, 0, 0, null);
return outputBitmap;
}
public Bitmap addPaddingRightForBitmap(Bitmap bitmap, int paddingRight) {
Bitmap outputBitmap = Bitmap.createBitmap(bitmap.getWidth() + paddingRight, bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(outputBitmap);
canvas.drawColor(Color.RED);
canvas.drawBitmap(bitmap, 0, 0, null);
return outputBitmap;
}
public Bitmap addPaddingLeftForBitmap(Bitmap bitmap, int paddingLeft) {
Bitmap outputBitmap = Bitmap.createBitmap(bitmap.getWidth() + paddingLeft, bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(outputBitmap);
canvas.drawColor(Color.RED);
canvas.drawBitmap(bitmap, paddingLeft, 0, null);
return outputBitmap;
}
Here's a kotlin extension function with RxJava to get it done. I haven't tested completely but based combined the previous answers to get something
fun Bitmap.pad(top: Float = 0F, bottom: Float = 0F, left: Float = 0F, right: Float = 0F): Single<Bitmap> {
return Single.create<Bitmap> { emitter ->
val output = Bitmap.createBitmap(
(width + left + right).toInt(),
(height + top + bottom).toInt(),
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(output)
canvas.drawBitmap(this, left, top, null)
emitter.onSuccess(output)
}.subscribeOn(Schedulers.computation())
}
I think the coroutine version would simply be
suspend fun Bitmap.pad(top: Float = 0F, bottom: Float = 0F, left: Float = 0F, right: Float = 0F): Bitmap {
val output = Bitmap.createBitmap(
(width + left + right).toInt(),
(height + top + bottom).toInt(),
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(output)
canvas.drawBitmap(this, left, top, null)
return output
}
I just did this to give padding from all side. Hope it will help someone.
Combination of https://stackoverflow.com/a/44060669/6480433 & https://stackoverflow.com/a/6957333/6480433 these answer.
Bitmap outputimage = Bitmap.createBitmap(Src.getWidth() + padding_x,Src.getHeight() + padding_y, Bitmap.Config.ARGB_8888);
Canvas can = new Canvas(outputimage);
can.drawBitmap(Src, padding_x, padding_y, null);
Bitmap output = Bitmap.createBitmap(outputimage.getWidth()+padding_x, outputimage.getHeight() + padding_y, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
canvas.drawBitmap(outputimage, 0, 0, null);
return output;
You might want to look here:
http://download.oracle.com/javase/1.4.2/docs/api/java/awt/image/BufferedImage.html
methods you might want to use are: getHeight() then you know how many pixels to set and iterate over 10 columns
and setRGB (int x, int y, int RGB) to set the pixel