Bitmap loses transparency when it's saved - android

i have a problem when i'm trying to save a bitmap to the external picture directory. When i use the Bitmap.compress function to save it, the bitmap loses its transparency and makes the background black. But when i pass the bitmap to a imageview and show it in the activity it looks fine and has transparency. Only when i try to save it, then transparency turns black.
I have to say, that im using two bitmaps and porterduff mode the draw a path on a bitmap and show only the picture in the drawn path, and all other pixels should be cut off or transparent.
So here's the function for creating a path bitmap:
private void createPathBitmap(RectF rect, Bitmap bitmap, Path path) {
RectF tmpRect = new RectF(rect);
Bitmap src = Bitmap.createBitmap(bitmap, (int) tmpRect.left, (int) tmpRect.top, (int) tmpRect.width(), (int) tmpRect.height());
Bitmap dst = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(dst);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(mDisplayDensity * SnippetLayer.PATH_DIAMETER);
path.offset(-rect.left, -rect.top);
canvas.drawPath(path, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
RectF srcRect = new RectF(0, 0, rect.width(), rect.height());
canvas.drawBitmap(src, null, srcRect, paint);
BitmapManager.sBitmapSnippet = dst;
}
And here's the method for saving that bitmap to external storage:
SimpleDateFormat dateFormat = new SimpleDateFormat("HH_mm_ss_dd_MM_yyyy");
File snippetFile = new File(picDir, fileName+"_"+dateFormat.format(new Date())+".png");
try {
FileOutputStream fileOutputStream = new FileOutputStream(snippetFile);
BitmapManager.sBitmapSnippet.setHasAlpha(true);
BitmapManager.sBitmapSnippet.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The picture is shown only in the path, and the rest of the bounding box is black and not transparent.
I appreciate any help.

I'm using compress() method to write bitmap into output stream:
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
It is important to use PNG format. JPEG transforms my transparent background into black color.

I don't know why exactly does it lose transparency, but I had the same problem. All you have to do is to change
BitmapManager.sBitmapSnippet.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
to
BitmapManager.sBitmapSnippet.compress(Bitmap.CompressFormat.PNG, 0, fileOutputStream);.
This will compress the bitmap with full quality, but containing transparent regions.

Don't loose transparency by this small snippet
Here Problem is you save image in .JPEG so JPEG take black background as transparent so we will save in .PNG so definitely get transparent Image
private void saveImage(Bitmap data, View view) {
File createFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Magic PhotoShoot");
if (!createFolder.exists())
createFolder.mkdir();
Calendar c = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strDate = sdf.format(c.getTime());
File saveImage = new File(createFolder, "Photoshoot_" + strDate + ".png");
try {
OutputStream outputStream = new FileOutputStream(saveImage);
data.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.flush();
outputStream.close();
Snackbar.make(view, "Saved to PhotoShoot successfully", Snackbar.LENGTH_SHORT).show();
isSave = true;
Glob.savedImage = saveImage.getAbsolutePath();
MediaStore.Images.Media.insertImage(getContentResolver(), saveImage.getAbsolutePath(), saveImage.getName(), saveImage.getName());
} catch (FileNotFoundException e) {
Snackbar.make(view, "File not found", Snackbar.LENGTH_SHORT).show();
e.printStackTrace();
} catch (IOException e) {
Snackbar.make(view, "Error while saving image", Snackbar.LENGTH_SHORT).show();
e.printStackTrace();
}
}

JPEG does not support transparency. JPEG's lossy compression also suffers from generation loss, where repeatedly decoding and re-encoding an image to save it
Use PNG extension file format for storing images in storage
In Kotlin:
Here is bitmap which is used for compression and saving into storage using file path
val file=File(outputImagePath)
var fout: OutputStream? = null
fout = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fout)
fout.flush()
fout.close()`
In Java:
Here is bitmap which is used for compression and saving into storage using file path
File imageFile = new File(outputImagePath);
OutputStream fout = null;
fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fout);
fout.flush();
fout.close();

You should use Bitmap.CompressFormat.PNG or Bitmap.CompressFormat.WEBP. If you want to get less size image. you should use Bitmap.CompressFormat.WEBP like me.

Related

want to add some text over a newly captured image in android

This is my problem:
Capture an image from the camera
Write some text on it
save it into an app folder
the first point I have covered.
help me out for the remaining two points
Thanks in advance
try this
1 - code to write text to bitmap
Bitmap bitmap = ... // your bitmap here
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(10);
canvas.drawText("Some Text here", x, y, paint);
2 - code to save bitmap to storage
// Assume block needs to be inside a Try/Catch block.
String path = Environment.getExternalStorageDirectory().toString();
OutputStream fOut = null;
File file = new File(path, "File.jpg");
fOut = new FileOutputStream(file);
pictureBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fOut); // saving the Bitmap to a file compressed as a JPEG with 85% compression rate
fOut.flush(); // Not really required
fOut.close(); // do not forget to close the stream
MediaStore.Images.Media.insertImage(getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());
source : Save bitmap to location
How to write text on an image

Android Creating an image from an API response [duplicate]

I need to create .jpeg/.png file on my Android application programmatically. I have simple image (black background), and it need to write some text on it programmatically. How can I do it? Is it possible?
It's definately possible.
To write text on an image you have to load the image in to a Bitmap object. Then draw on that bitmap with the Canvas and Paint functions. When you're done drawing you simply output the Bitmap to a file.
If you're just using a black background, it's probably better for you to simply create a blank bitmap on a canvas, fill it black, draw text and then dump to a Bitmap.
I used this tutorial to learn the basics of the canvas and paint.
This is the code that you'll be looking for to turn the canvas in to an image file:
OutputStream os = null;
try {
File file = new File(dir, "image" + System.currentTimeMillis() + ".png");
os = new FileOutputStream(file);
finalBMP.compress(CompressFormat.PNG, 100, os);
finalBMP.recycle(); // this is very important. make sure you always recycle your bitmap when you're done with it.
screenGrabFilePath = file.getPath();
} catch(IOException e) {
finalBMP.recycle(); // this is very important. make sure you always recycle your bitmap when you're done with it.
Log.e("combineImages", "problem combining images", e);
}
Yes, see here
Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
You can also use awt's Graphics2D with this compatibility project
Using Graphics2d you can create a PNG image as well:
public class Imagetest {
public static void main(String[] args) throws IOException {
File path = new File("image/base/path");
BufferedImage img = new BufferedImage(100, 100,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.YELLOW);
g2d.drawLine(0, 0, 50, 50);
g2d.setColor(Color.BLACK);
g2d.drawLine(50, 50, 0, 100);
g2d.setColor(Color.RED);
g2d.drawLine(50, 50, 100, 0);
g2d.setColor(Color.GREEN);
g2d.drawLine(50, 50, 100, 100);
ImageIO.write(img, "PNG", new File(path, "1.png"));
}
}

Can we save canvas as an Image to sd card in Android?

I am working with Canvas in Android Studio, have .png image on canvas and want to save it to sd card. Is it possible?
if yes then how?
thanks and regards.
This code may help you (Saving canvas to bitmap on Android)
Bitmap toDisk = null;
try {
// TODO: Get the size of the canvas, replace the 640, 480
toDisk = Bitmap.createBitmap(640,480,Bitmap.Config.ARGB_8888);
canvas.setBitmap(toDisk);
toDisk.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File("arun.jpg")));
} catch (Exception ex) {
}
You should have created Canvas with new Canvas(myBitmap);. So when you draw on the Canvas, it draws to your bitmap.
String fileName = Environment.getExternalStorageDirectory() + "/test.png";
OutputStream stream = new FileOutputStream(fileName);
/* Write bitmap to file using JPEG or PNG and 80% quality hint for JPEG. */
myBitmap.compress(CompressFormat.PNG, 80, stream);
stream.close();

open and save same image again on android

I am trying to open a saved image in the gallery, and after writing some text on this opened image, trying to close it. But so far, it doesn't work. Could you tell me what I am doing wrong please?
**I checked the path, it is correct. Here is the my code :
String path = android.os.Environment.getExternalStorageDirectory().toString() + "/DCIM/100LGDSC/";
String pathiki = path+filename;
Log.d("pathiki:",pathiki);
try {
Bitmap bm = BitmapFactory.decodeFile(pathiki);
Typeface tf = Typeface.create("Helvetica", Typeface.BOLD);
Paint paint = new Paint();
paint.setStyle(Style.FILL);
paint.setColor(Color.WHITE);
paint.setTypeface(tf);
paint.setTextAlign(Align.CENTER);
paint.setTextSize(14);
Canvas canvas = new Canvas(bm);
canvas.drawText("bla bla bla", 100, 100, paint);
OutputStream fOut = new FileOutputStream(new File(pathiki));
bm.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
// TODO: handle exception
e.toString();
}
BitmapFactory.decodeFile always returns an immutable bitmap. Use Bitmap.copy to make a copy of bitmap which is mutable. Now perform modifications on the copied bitmap.
Bitmap bm = BitmapFactory.decodeFile(pathiki).copy(Bitmap.Config.ARGB_8888, true);
Update the exception handler code. Either log e.getMessage() to logcat or use e.printStackTrace().

Android Paint PorterDuff.Mode.CLEAR

I'm working on application which is drawing on Canvas similar to Finger Paint demo from Android SDK. My problem is when I'm using PorterDuff.Mode.CLEAR. When drawing and Canvas and if I try to erase something, it's working fine. But if I try to save my image as PNG file the strokes of eraser are coloured black, and I'm not sure why is this happening. Here is an example what I'm doing :
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
Eraser :
case ERASE_MENU_ID:
mPaint.setXfermode(new PorterDuffXfermode(
PorterDuff.Mode.CLEAR));
return true;
And how I'm saving the image :
Calendar currentDate = Calendar.getInstance();
SimpleDateFormat formatter= new SimpleDateFormat("yyyyMMMddHmmss");
String dateNow = formatter.format(currentDate.getTime());
File dir = new File(mImagePath);
if(!dir.exists())
dir.mkdirs();
File file = new File(mImagePath + "/" + dateNow +".png");
FileOutputStream fos;
try {
fos = new FileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
Toast.makeText(getApplicationContext(), "File saved at \n"+mImagePath + "/" + dateNow +".png", Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
Log.e("Panel", "FileNotFoundException", e);
}
catch (IOException e) {
Log.e("Panel", "IOEception", e);
}
return true;
And here is an example of images :
here is what my canvas looks like before saving :
and here is the image after saving it on sd card :
The problem with the fingerpaint code is that what you see is not the same that is compressed into the png. Look at onDraw(). First you draw the screen white. Then you add the Bitmap. Because you used Porter Duff Clear the erased part of the bitmap contains actually transparent black pixels (value 0x00000000). But because you have the white background these black pixels show as white.
To fix this either change your save code to do the same thing as the draw code
try {
fos = new FileOutputStream(file);
Bitmap saveBitmap = Bitmap.createBitmap(mBitmap);
Canvas c = new Canvas(saveBitmap);
c.drawColor(0xFFFFFFFF);
c.drawBitmap(mBitmap,0,0,null);
saveBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
saveBitmap.recycle();
...
or don't use PortDuff.Clear:
case ERASE_MENU_ID:
mPaint.setColor(Color.WHITE);

Categories

Resources