image size reduced after editing - android

i created a new image by combining two images. but the size of the final is image is reduced to the size(resolution) of the screen. the code used is
Bitmap pic = BitmapFactory.decodeResource(getResources(), R.drawable.me);
Bitmap stat= BitmapFactory.decodeResource(getResources(), R.drawable.static);
Bitmap out1 = Bitmap.createBitmap(stat) ;
Canvas comboImage = new Canvas(out1);
comboImage.drawBitmap(map, 0, 0, null);
comboImage.drawBitmap(pic, 150f, 30f, null);
after this i am storing the image as
OutputStream os = null;
os = new FileOutputStream("/sdcard/DCIM/Camera/" + "myNewFileName5.png");
out1.compress(CompressFormat.PNG, 100, os);
os.flush();
os.close();
dimension of image is staic 640x480. but my final image is 320x240, which is my phones screen resolution. is it because i use Canvas? is there any way to do this without changing the image sizes?

Check your API version? There's an explanation at In the onDraw() method, why does the supplied Canvas already have scale? that for an API level lower than 4 the canvas has a default scaled compatibility mode as if it were targeting a G1 screen.

Related

Android: BitmapFactory changes dimensions of image when decoding from ByteArray

I am converting an android Image captured in my application to a bitmap. I am doing this by getting the image buffer from the pixel plane of the image and then using BitMapFactory to decode it into a Bitmap. However, doing so seems to change the resolution of the Image from 1920 x 1440 to 1800 x 1600, cropping out the top and bottom of the image in the process. The code for the method is shown here.
`protected void getImageFromBuffer(ImageReader reader){
Image image = null;
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
System.out.println("Getting Image Ready");
synchronized (this){
image_to_upload = new byte[buffer.capacity()];
buffer.get(image_to_upload);
Bitmap storedBitmap = BitmapFactory.decodeByteArray(image_to_upload, 0, image_to_upload.length, null);
Matrix mat = new Matrix();
mat.postRotate(jpegOrientation); // angle is the desired angle you wish to rotate
storedBitmap = Bitmap.createBitmap(storedBitmap, 0, 0, storedBitmap.getWidth(), storedBitmap.getHeight(), mat, true);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
storedBitmap.compress(Bitmap.CompressFormat.JPEG,70, byteArrayOutputStream);
image_to_upload = byteArrayOutputStream.toByteArray();
image_ready = true;
System.out.println("Image Ready");
}
}`
Debugging shows that the height and width of the Image are correct before the buffer is converted to a bitmap, but the bitmap dimensions are wrong immediately after decodeByteArray. Can anyone suggest why this may be? I have checked the dimensions before applying the matrix transformation.
EDIT: To add further details, I have tried using BitmapFactory.Options() to disable scaling or to set the target density and neither have any impact on the resulting Bitmap, it is always size 1800 x 1600.
You can change some options that affects the result resolution of your bitmap by using the Options param to the decodeByteArray:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDensity = DisplayMetrics.DENSITY_XXHIGH;//for example
BitmapFactory.decodeByteArray(image_to_upload, 0, image_to_upload.length, options);

Dynamically creating a compressed Bitmap

I'm writing a custom printing app in Android and I'm looking for ways to save on memory. I have three basic rectangles I need to print on a full page. Currently I'm creating a base Bitmap the size of the page:
_baseBitmap = Bitmap.createBitmap(width/_scale, height/_scale, Bitmap.Config.ARGB_8888);
The print process requests a Rect portion of that page. I cannot predetermine the dimensions of this Rect.
newBitmap = Bitmap.createBitmap(fullPageBitmap, rect.left/_scale, rect.top/_scale, rect.width()/_scale, rect.height()/_scale);
return Bitmap.createScaledBitmap(newBitmap, rect.width(), rect.height(), true);
Using bitmap config ARGB_8888 _baseBitmap is about 28MB (8.5"x11" # 300dpi = 2250*3300*4bytes). Even at 50% scaling (used above), my image is over 7MB. Scaling any smaller than this and image quality is too poor.
I've attempted to create _baseBitmap using Bitmap.Config.RGB_565, which does greatly reduce the full image size, but then when I overlay an image (jpegs) I get funny results. The image is compressed in width, duplicated next to itself, and all the color is green.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap myBitmap = BitmapFactory.decodeStream(input, null, options);
input.close();
return myBitmap;
....
private static Bitmap overlay(Bitmap bmp1, Bitmap bmp2, float left, float top) {
Canvas canvas = new Canvas(bmp1);
canvas.drawBitmap(bmp2, left, top, null);
return bmp1;
}
I know I can compress an image of these dimensions down to a reasonable size. I've looked into Bitmap.compress, but for some reason beyond my understanding I'm getting the same size image back:
ByteArrayOutputStream os = new ByteArrayOutputStream();
_baseBitmap.compress(Bitmap.CompressFormat.JPEG, 3, os);
byte[] array = os.toByteArray();
Bitmap newBitmap = BitmapFactory.decodeByteArray(array, 0, array.length);
_baseBitmap.getAllocationByteCount() == newBitmap.getAllocationByteCount()
It would be better to create it compressed than to create a large one and then compress it. Is there any way to create a compressed Bitmap? Any advice is greatly appreciated.
note: Not an Android expert. I'm not necessarily familiar with the platform specific terms you may use to respond. Please be gentle.
Try something like this, if you have a target size in mind.
private static final int MAX_BYTES_IMAGE = 4194304; // 4MB
//...
ByteArrayOutputStream out;
int quality = 90;
do
{
out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, out);
quality -= 10;
} while (out.size() > MAX_BYTES_IMAGE_FILESIZE);
out.close();

Android draw area from Bitmap or Imageview with canvas

i'm trying to draw a Bitmap but only with a selected area from the original Bitmap or Imageview. The requirement is that the final picture must show only 1/3 from the top of the original Bitmap. I attach a draft. I suppose that i should use canvas, but i do not know exactly how it works.
Thanks in advance!!
Bitmap getTheReducedBitmap(Bitmap fullLengthBitnap)
{
Bitmap backDrop=Bitmap.createBitmap(fullLengthBitnap.getWidth(), fullLengthBitnap.getHeight()/3, Bitmap.Config.RGB_565);
Canvas can = new Canvas(backDrop);
can.drawBitmap(fullLengthBitnap, 0, 0, null);
return backDrop;
}
This is the documentation for the method you should use.
private void draw(Canvas c, Bitmap bmp){
Rect r=new Rect(0,0,bmp.width,bmp.height/3);
Rect drawR=new Rect(0,0,c.width,c.height/3);
c.drawBitmap(bmp,r,drawR,null);
}
or as a one liner:
c.drawBitmap(bmp,new Rect(0,0,bmp.width,bmp.height/3),new Rect(0,0,c.width,c.height/3),null);
It allows you to specify where on the canvas you want to draw it too, and where you want the segment to be from.
#Eu.Dr. 's answer would not work if you wanted to draw anything else on the canvas below it.
val newBitmap=Bimtap
.createBitmap(your_view.width,your_view.height,Bitmap.Config.ALPHA_8)
//note: for tablet mode your_view.width,height will increase drastically so
//you might want
//to fix the size of drawing area for optimization
//ALPHA_8 each pixel requires 1 byte of memory.
//RGB_565 Each pixel is stored on 2 bytes
//ARGB_8888 Each pixel is stored on 4 bytes
//after this you can further apply the compress like
[Refer more from google][1]
val stream = ByteArrayOutputStream();
newBitmap.compress(Bitmap.CompressFormat.PNG, 80, stream);
val byteArray = stream.toByteArray(); // convert drawing photo to byte array
// save it in your internal storage.
val storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES
+"attendance_sheet.png");
try{
val fo = FileOutputStream(storageDir);
fo.write(byteArray);
fo.flush();
fo.close();
}catch(Exception ex){
}

Change PPI (pixel per inches) of PNG file in Android

I have app which is used to edit PNG file (like write text on them).
My process is create bitmap from that PNG, use Canvas to draw Text, then use bitmap.compress to save result into SD Card.
Everything work fine. But when i check my result, i see that PPI was changed. How to keep that PPI like the Original one.
Here is the example: my Original image has 1300x700 res and 250 ppi (i checked with PS) but after use my app to edit that image, my result image has 1300x700 res and 72 ppi. I want my result image still has 1300x700 res and 250 ppi
Please help me, thanks for your help.
here it is:
Bitmap bitmap = null;
try
{
BufferedInputStream buf = new BufferedInputStream(
PicksActivity.this.getAssets().open( file_name ) );
bitmap = BitmapFactory.decodeStream( buf );
}
catch ( Exception e )
{
// TODO: handle exception
}
Then create bitmap overlay:
Bitmap bmOverlay = Bitmap.createBitmap( bitmap.getWidth(), bitmap
.getHeight(), Config.ARGB_8888 );
and them compress it:
bmOverlay.compress( CompressFormat.PNG, 100, fos );
this problem not because of drawText, cause when im not draw text, just open and save, PPI still change.

Android - Rotated text on a large bitmap

I have a picture (bitmap) and I want to draw some shapes and rotated
text on it.
This works fine as long as the picture doesn't get too large. However,
when using a picture (2560 x 1920 pixels)taken with the build-in
camera of my android 2.1 phone, the result is distorted.
It looks like the rotation back, after drawing the rotated text, has
not been completed. Also, the distortion point is not always the same,
like it depends on the cpu usage.
You can see some resulting pictures here:
http://dl.dropbox.com/u/4751612/Result1.png
http://dl.dropbox.com/u/4751612/Result2.png
The code is executed inside a AsyncTask. The strange this is that this code works fine in one Activity, but not in another. In both activities the AsyncTask is executed when a button is clicked.
These are some excerpts of the code I'm using.
// Load the image from the MediaStore
c = MediaStore.Images.Media.query(context.getContentResolver(),
Uri.parse(drawing.fullImage), new String[] {MediaColumns.DATA});
if (c != null && c.moveToFirst()) {
imageFilePath = c.getString(0);
bitmap = ImageUtil.getBitmap(new File(imageFilePath), 10000);
}
c.close();
// Create a canvas to draw on
drawingBitmap = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
canvas = new Canvas(drawingBitmap);
// Draw image
canvas.drawBitmap(bitmap, 0, 0,
MeasureFactory.getMeasurePaint(context));
// calculate text width
rect = new Rect();
paint.getTextBounds(text, 0, text.length(), rect);
// Draw rotated text
canvas.save();
canvas.rotate(-angle, centerPoint.x, centerPoint.y);
canvas.drawText(text, centerPoint.x-Math.abs(rect.exactCenterX()),
Math.abs(centerPoint.y-rect.exactCenterY()), paint);
canvas.restore();
// Upload the bitmap to the Media Library
Uri uri =
getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);
OutputStream outStream = getContentResolver().openOutputStream(uri);
drawingBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outStream);
outStream.flush();
outStream.close();
Thanks in advance for any help.
Since it works as long as the resolution isn't too high, I would just rescale all images to something that works.
You can accomplish this using
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, 800 /* width */, 600 /* height */, true);
This turned out to be a memory problem although no OutOfMemoryException was visible in the log.
So, I "solved" it by scaling the image if the resolution is too high, as suggested by ingo. The problem is that I don't know how to determine the limits of a device. I suppose they are different for every device and depends on the current memory usage.

Categories

Resources