view.getDrawingCache() only works once - android

I have a RelativeLayout with a loaded bitmap image using the Touch V2 example from Pragmatic Bookshelf -- http://media.pragprog.com/titles/eband3/code/Touchv2/src/org/example/touch/Touch.java
I've added a separate button with onclicklistener that when clicked will load an image from the gallery. On the activity result the image is loaded as a bitmap into the RelativeLayout:
public void getPictureFromFile(Uri targetUri){
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = scale(getContentResolver()
.openInputStream(targetUri));
workinprogress = BitmapFactory.decodeStream(
getContentResolver().openInputStream(targetUri),
null, options);
view.setImageBitmap(workinprogress);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
One the next button click, I grab the image of the relativelayout using:
thepicture.buildDrawingCache(true);
Bitmap bm = Bitmap.createBitmap(thepicture.getDrawingCache());
The process works terrific -- for the first image. When I load another image again, the bitmap passed is still the same as the original. I've tried the thepicture.invalidate() and thepicture.resetDrawableState() before getDrawingCache() but neither seem to update the image to the newly loaded picture, although the frame layout displays the correct image.
Is there something I don't understand about refreshing drawingCache that I need to implement for the second image I load?

To make it work more than once you have to use view.setDrawingCacheEnabled(true) each time before and view.setDrawingCacheEnabled(false) each time after calling view.getDrawingCache(). See the example:
imageView.setDrawingCacheEnabled(true);
imageView.buildDrawingCache(true);
File imageFile = new File(Environment.getExternalStorageDirectory(),
"Pictures/image.jpg");
FileOutputStream fileOutputStream = new FileOutputStream(imageFile);
imageView.getDrawingCache(true).compress(CompressFormat.JPEG, 100,
fileOutputStream);
fileOutputStream.close();
imageView.setDrawingCacheEnabled(false);

Related

Saving View bitmap with getDrawingCache gives a black image

Everything I tried with setDrawingCacheEnabled and getDrawingCache was not working. The system was making an image but it just looked black.
Other people on SO seemed to be having a similar problem but the answers seemed either too complicated or irrelevant to my situation. Here are some of the ones I looked at:
Save view like bitmap, I only get black screen
Screenshot shows black
getDrawingCache always returns the same Bitmap
Convert view to bitmap on Android
bitmap is not saving properly only black image
Custom view converting to bitmap returning black image
And here is my code:
view.setDrawingCacheEnabled(true);
Bitmap bitmap = view.getDrawingCache();
try {
FileOutputStream stream = new FileOutputStream(getApplicationContext().getCacheDir() + "/image.jpg");
bitmap.compress(CompressFormat.JPEG, 80, stream);
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
view.setDrawingCacheEnabled(false);
I'm sharing my answer below in case anyone else makes the same mistake I did.
My problem was that my view was a TextView. The text on the TextView was black (naturally) and in the app the background looked white. However, I later recalled reading that a view's background is by default transparent so that whatever color is below shows through.
So I added android:background="#color/white" to the layout xml for the view and it worked. When I had been viewing the image before I had been looking at black text over a black background.
See the answer by #BraisGabin for an alternate way that does not require overdrawing the UI.
I just found a good option:
final boolean cachePreviousState = view.isDrawingCacheEnabled();
final int backgroundPreviousColor = view.getDrawingCacheBackgroundColor();
view.setDrawingCacheEnabled(true);
view.setDrawingCacheBackgroundColor(0xfffafafa);
final Bitmap bitmap = view.getDrawingCache();
view.setDrawingCacheBackgroundColor(backgroundPreviousColor);
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream);
view.setDrawingCacheEnabled(cachePreviousState);
Where 0xfffafafa is the desired background color.
Used below code to get bitmap image for view it work fine.
public Bitmap loadBitmapFromView(View v) {
DisplayMetrics dm = getResources().getDisplayMetrics();
v.measure(View.MeasureSpec.makeMeasureSpec(dm.widthPixels,
View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(dm.heightPixels,
View.MeasureSpec.EXACTLY));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap returnedBitmap =
Bitmap.createBitmap(v.getMeasuredWidth(),
v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(returnedBitmap);
v.draw(c);
return returnedBitmap;
}

Changing image of ImageButton

I have an ImageButton that is initially set to a drawable resource. During an Activity, I want to set the image to a bitmap of a user photo. The picture taking and saving work correctly, but the ImageButton's image does not change.
Here is my code:
Bitmap bitmap = BitmapFactory.decodeFile(PATH + "/image.jpg");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 20, stream);
Log.d(TAG, bitmap.toString()); //prints out android.graphics.Bitmap#41d772a8
rearEndImageButton.setImageBitmap(bitmap);
To do it form sd card you can try with..
Bitmap bmp = BitmapFactory.decodeFile("path_to_file");
ImageButton rearEndImageButton = (ImageButton)findViewById(R.id.rearEndImageButton);
rearEndImageButton.setImageBitmap(bmp);
In the activity onCreate method assign your button to a variable, and then set a resource or Bitmap which will be decoded from a file using the BitmapFactory class.
You can use File explorer to select an image from sd card and assign that image path to BitmapFactory.decodeFile().

How to capture everything currently on screen including Dialogs

I have looked at probably every SO article concering capturing the screen (screenshot, screendump) programmatically on Android, and they usually all end up with the same answer.
The problem with it is that it captures the View that you have specified, but it does NOT capture any Dialogs that may be "on top of" the "root view". This is the code I use, that fails to capture anything "on top":
Bitmap bitmap;
View v1 = findViewById(android.R.id.content);
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
File path = Environment.getExternalStorageDirectory();
File file = new File(path, "myDump.jpg");
FileOutputStream outputStream;
try
{
outputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 10, outputStream);
outputStream.flush();
outputStream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
The question is: how can I capture the entire screen, including Dialogs that are on top? I am only interested in capturing the app that I am writing, not the home screen or anything like that, just anything that is on top of my root view.
I did read something about rooting, but I really hope that taking a complete screendump of the app Im writing cannot be impossible.
use this library .... it works great for me.
https://github.com/jraska/Falcon
// Saving screenshot to file
Falcon.takeScreenshot(this, imageFile);
// Take bitmap and do whatever you want
Bitmap bitmap = Falcon.takeScreenshotBitmap(this);
It is possible, you need to draw all view roots to the bitmap. Try out this library: https://github.com/jraska/Falcon it can capture Dailogs to your screenshot.
This is working inside an opened DialogFragment.
View v1 = ((ViewGroup) (((MyActivity)getActivity()).findViewById(android.R.id.content)));
v1.setDrawingCacheEnabled(true);
Bitmap bitmapParent = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
// dialogView is the inflated view of the DialogFragment
dialogView.setDrawingCacheEnabled(true);
Bitmap bitmapDialog = Bitmap.createBitmap(dialogView.getDrawingCache());
dialogView.setDrawingCacheEnabled(false);
Canvas canvas = new Canvas(bitmapParent);
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(bitmapDialog, 0, 0, paint);
// Activity and dialog captured!!
bitmapParent.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(new File(directory, name)));

Android Bitmaps always saved with 72dpi

I'm making bitmap (that will be printed on paper, later) and using canvas to draw on it.
But after saving it always have 72 dpi resolution. I tried to use bitmap.setDensity(96);but it does not seems to work.
This is how I make bitmap and save it, nothing fancy
Bitmap outBitmap = Bitmap.createBitmap(378,559,Bitmap.Config.RGB_565);
OutputStream outStream = null;
File file = new File(Environment.getExternalStorageDirectory(),
"96dpiBitmap.png");
try {
outStream = new FileOutputStream(file);
outBitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
// doh
} catch (IOException e) {
// doh
}
So. How do I save bitmap with dpi > 72?
you have to create scaled bitmap from the original one for ex :
MyNewBitmap = Bitmap.createScaledBitmap(myOldOne,612,612,false);
where 612 width and 612 height the result will be image squared. i'm using this method to prevent instagram from scaling or cutting my image so its perfectly fit into instagram image cropping :).
anyway you have to find the proper way to scale your image to fit 72dpi. i guess 800x600 will do the trick. try to create new bitmap and scale the old one and then save the newBitmap.
good luck

Retrieve "Clean" Image Out Of ImageView

I've Image stored in ImageView and after several processes (flip, rotate, fix color, etc) it's saved back as new file. However, I just realize that when I just load into ImageView and soon after that directly save the result, I got different result. Take a look at attached image for reference.
image source
image result
Here's how I extract image from ImageView:
String filePath = Environment.getExternalStorageDirectory()
+ File.separator + bufferPath;
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
selectedImage.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(selectedImage.getDrawingCache());
selectedImage.setDrawingCacheEnabled(false);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
imageFile = new File( filePath );
//write the bytes in file
FileOutputStream fo = new FileOutputStream(imageFile);
fo.write(bytes.toByteArray());
Is there any workaround to make resulting image the same as source? different component, maybe?
Hold a backing Bitmap (originally the source) that you carry out your manipulations on.
Use the ImageView just to show this Bitmap - do not manipulate the post-scaled version that is held in the ImageView's drawing cache.

Categories

Resources