I'm getting an image from a URL, I want to compress it and save it in the external memory device. I get this error
java.lang.IllegalStateException:
Can't compress a recycled bitmap
at android.graphics.Bitmap.checkRecycled(Bitmap.java:400)
at android.graphics.Bitmap.compress(Bitmap.java:1307)
at this line
mIcon11.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
String foto = UT_drive_dropbox.AM.getfoto();
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(foto).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
final Bitmap output = Bitmap.createBitmap(mIcon11.getWidth(),
mIcon11.getHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(output);
final int color = Color.RED;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, mIcon11.getWidth(), mIcon11.getHeight());
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawOval(rectF, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(mIcon11, rect, rect, paint);
mIcon11.recycle();
String fileName = "avatar.jpg";
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
mIcon11.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
File sd = new File(Environment.getExternalStorageDirectory(), getString(R.string.app_name) + File.separator + fileName);
FileOutputStream fileOutputStream = null;
try {
sd.createNewFile();
fileOutputStream = new FileOutputStream(sd);
fileOutputStream.write(bytes.toByteArray());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The error message is "Can't compress a recycled bitmap". If you look three lines before your mIcon11.compress(Bitmap.CompressFormat.JPEG, 40, bytes); line, you will see:
mIcon11.recycle();
So, either get rid of recycle() or move it to after you have done everything that you intend to do with the Bitmap pointed to by mIcon11.
Related
I want to generate bitmap for webview full page.
some codes
Below code for generating Bitmap from webview
Webview to Bitmap :
webview.measure(MeasureSpec.makeMeasureSpec(
MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
webview.layout(0, 0, webview.getMeasuredWidth(),
webview.getMeasuredHeight());
webview.setDrawingCacheEnabled(true);
webview.buildDrawingCache();
Bitmap bm=null;
try
{
Log.d("Measuredwidth", "MeasuredWidth"+webview.getMeasuredWidth());
Log.d("Measuredheight", "Measuredheight"+webview.getMeasuredHeight());
Log.d("Measuredheightandstate", "Measuredheight and state"+webview.getMeasuredHeightAndState());
bm = Bitmap.createBitmap(webview.getMeasuredWidth(),
webview.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
}
catch(OutOfMemoryError e)
{
e.printStackTrace();
return null;
}
Canvas bigcanvas = new Canvas(bm);
Paint paint = new Paint();
int iHeight = bm.getHeight();
bigcanvas.drawBitmap(bm, 0, iHeight, paint);
webview.draw(bigcanvas);
below code for to save the file in memory for that
To save as file :
if (bm != null) {
try {
String path = Environment.getExternalStorageDirectory()
.toString();
OutputStream fOut = null;
File file = new File(path, "/aaaa.png");
fOut = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 50, fOut);
fOut.flush();
fOut.close();
bm.recycle();
} catch (Exception e) {
e.printStackTrace();
}
}
Here my problem is webview loading completely but after saving as file bottom half not completely loading .
i tried to get solution for this but failed.
if any one have idea about this please help me.. Thanks in adavance
I am going to create a jpeg by drawing. The element is a text and a image. When it comes to the implementation, only image and background color is drawn but there is no text. I have no diea what happens actually even I have called canvas.drawText
The below is my code
String folderName = "droidCanvas";
String textString ="Hello , I am user 12345. \n Below is my signature.";
String fileNameString = "test.jpg";
File folder = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + folderName );
if(!folder.exists()){
folder.mkdir();
}
File bmpFile = new File(folder.getAbsolutePath() + File.separator + fileNameString );
if(!bmpFile.exists()){
try {
bmpFile.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//Draw something
Paint paint = new Paint();
paint.setColor(Color.RED);
Paint txtPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
txtPaint.setColor(Color.BLACK);
txtPaint.setTextSize(20);
bmpBase = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bmpBase);
canvas.drawColor(Color.WHITE);
canvas.drawCircle(w/2, h/2, 300, paint);
canvas.drawText(textString ,w/2, 0 , txtPaint);
//Export to jpeg
try
{
fos = new FileOutputStream(bmpFile);
bmpBase.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
fos = null;
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (fos != null)
{
try
{
fos.close();
fos = null;
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
Try canvas.drawText(textString ,w/2, h/2 , txtPaint); and you will be able to at least see the text. Then you can re-position it later. Right now it is being drawn but you can't see it because its at extreme top center and out of bounds.
If you want to place it on top left corner then do this:
canvas.drawText(textString ,0 , txtPaint.getFontSpacing(), txtPaint);
I'm developing an app that combines two bitmaps, where one bitmap is from drawable, and the other is taken from a camera snapshot. However the pictures always end up incomplete. Half the picture is fine, but the other half is gray. Is there a way to make sure that the file is completed before the app moves on with the code? Below is the code that works with writing and saving the file. Thanks
Combine.java
protected void createPostcard(byte[] data, File pictureFile, CameraActivity app, Button shareButton,
Button newButton) {
try {
Bitmap photo = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap splash = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(app.getResources(),
R.drawable.wishsplash), photo.getWidth(), photo.getHeight(), false);
Bitmap postcard = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), photo.getConfig());
Canvas canvas = new Canvas(postcard);
canvas.drawBitmap(photo, new Matrix(), null);
canvas.drawBitmap(splash, 0, 0, null);
savePostcard(postcard, pictureFile, app, shareButton, newButton);
} catch (Exception e) {
}//end catch
}//end createPostcard
/**
* Saves the postcard
*/
private void savePostcard(Bitmap postcard, File pictureFile, CameraActivity app, Button shareButton,
Button newButton) {
BitmapDrawable mBitmapDrawable = new BitmapDrawable(postcard);
Bitmap mNewSaving = mBitmapDrawable.getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
mNewSaving.compress(CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
save(byteArray, pictureFile, app);
shareButton.setBackgroundResource(R.drawable.sharebutton);
newButton.setBackgroundResource(R.drawable.newbutton);
shareButton.setEnabled(true);
newButton.setEnabled(true);
}//end savePostcard
/**
* Check if external is available. If not, postcard will be saved in internal.
* #retun
*/
private void save(byte[] data, File pictureFile, CameraActivity app) {
try {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
FileOutputStream fos = new FileOutputStream(pictureFile);
imageUri = Uri.fromFile(pictureFile);
fos.write(data);
imageFile = pictureFile;
fos.close();
app.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
} else {
File cache = app.getCacheDir();
File internalPic = new File(cache, pictureFile.getName());
FileOutputStream fos = new FileOutputStream(internalPic);
imageUri = Uri.fromFile(internalPic);
imageFile = internalPic;
fos.write(data);
fos.close();
}//end else
} catch (FileNotFoundException e) {
System.out.println("FILENOTFOUND");
} catch (IOException e) {
System.out.println("IOEXCEPTION");
}//end catch
}//end getStorage
try this code
public Bitmap PutoverBmp(Bitmap all, Bitmap scaledBorder) {
Paint paint = new Paint();
final int width = bmp.getWidth(); // bmp is your main Bitmap
final int height = bmp.getHeight();
patt = Bitmap.createScaledBitmap(bmp, width, height, true);
Bitmap mutableBitmap = patt.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(mutableBitmap);
scaledBorder = Bitmap.createScaledBitmap(border, width, height, true);
paint.setAlpha(100);
canvas.drawBitmap(scaledBorder, 0, 0, paint);
return mutableBitmap;
}
simply call this Bitmap combine = (bmp , yourOtherBitmap);
I have my SurfaceView up and running with a button to open the camera and take a picture which is used as the background and another button to add items that sit on top and can be moved around. This all works fine until I try to save the SurfaceView as a Bitmap when all I get is the background and none of the images on top.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(_mGotImage){
canvas.drawBitmap(_mImage, 0, 0, null);
}else{
canvas.drawColor(Color.BLACK);
}
//if the array is not empty
if(!_mJazzItems.isEmpty()){
//step through each item in the array
for(JazzItem item: _mJazzItems){
//get the bitmap it is using
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), item.getBitmap());
//and draw that bitmap at its X and Y coords
canvas.drawBitmap(bitmap, item.getX(), item.getY(), null);
}
}
}
This is the method called to try and save the Canvas.
public void screenGrab(){
Bitmap image = Bitmap.createBitmap(_mPanelWidth, _mPanelHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
this.onDraw(canvas);
String path=Environment.getExternalStorageDirectory() + "/test2.png";
File file = new File(path);
try{
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
image.compress(CompressFormat.PNG, 100, ostream);
ostream.flush();
ostream.close();
}catch (Exception e){
e.printStackTrace();
}
}
The onDraw works fine, I get my camera shot in the background and can add all my items over the top and move them around. Just when I try to get a screen shot, none of the items on top are present.
Thanks for any help!!
-- UPDATE --
I have modified the screen grab method to this:
public void screenGrab(){
Bitmap image = Bitmap.createBitmap(_mPanelWidth, _mPanelHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
canvas.drawBitmap(_mImage, 0, 0, null);
//if the array is not empty
if(!_mJazzItems.isEmpty()){
//step through each item in the array
for(JazzItem item: _mJazzItems){
//get the bitmap it is using
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), item.getBitmap());
//and draw that bitmap at its X and Y coords
canvas.drawBitmap(bitmap, item.getX(), item.getY(), null);
}
}
String path=Environment.getExternalStorageDirectory() + "/test2.png";
File file = new File(path);
try{
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
image.compress(CompressFormat.PNG, 100, ostream);
ostream.flush();
ostream.close();
}catch (Exception e){
e.printStackTrace();
}
}
I can't see why this is not drawing the other images over the top...
in my case i am using this:
public static Bitmap combineImages(Bitmap c, Bitmap overLayImage, Context con) {
Bitmap cs = null;
int width, height = 0;
width = c.getWidth();
height = c.getHeight();
cs = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas comboImage = new Canvas(cs);
comboImage.drawBitmap(c, 0, 0, null);
String left = yourleftPosition;
String top = yourtopPosition;
comboImage.drawBitmap(overLayImage, Float.parseFloat(left), Float.parseFloat(top),null);
/******
*
* Write file to SDCard
*
* ****/
String tmpImg = String.valueOf(System.currentTimeMillis()) + ".png";
OutputStream os = null;
try {
String pathis = Environment.getExternalStorageDirectory()
+ "/DCIM/Camera/" + tmpImg;
os = new FileOutputStream(pathis);
cs.compress(CompressFormat.PNG, 100, os);
}
catch (IOException e) {
Log.e("combineImages", "problem combining images", e);
}
return cs;
}
I was create image on the canvas using colorfilter
This my code
int color = mPaint.getColor();
f = new LightingColorFilter(color, 1);
mPaint.setColorFilter(f);
myBmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon10);
canvas.drawBitmap(myBmp, 20, 20, mPaint);
canvas.save();
canvas.restore();`
and then,I want to save it to sdcard
OutputStream outStream = null;
File file = new File(extStorageDirectory, "er.PNG");
try {
outStream = new FileOutputStream(file);
myBmp.compress(Bitmap.CompressFormat.PNG, 85, outStream);
outStream.flush();
outStream.close();
Toast.makeText(Draw.this, "Saved", Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(Draw.this, e.toString(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(Draw.this, e.toString(), Toast.LENGTH_LONG).show();
}
It's Work But have Problem,My picture on sd is old picture(not filter)
can I fix this problem??,Thank
You need draw into Bitmap. Try below:
int color = mPaint.getColor();
f = new LightingColorFilter(color, 1);
mPaint.setColorFilter(f);
Bitmap outBitmap = Bitmap.Create(myBmp.getWidth(),myBmp.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(outBitmap);
canvas.drawBitmap(myBmp,20,20,mPaint);
And than you can "save it"(outBitmap) to SD card.
If you're open Bitmap with BitmapFactory you'd get immutable bitmap, and can't draw on it.
That's why you need to create temp. Bitmap, connect Canvas for draw, Drawing and can saving.