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;
}
Related
I am taking screenshot programmatically using the following code:
public static Bitmap takeScreenshot(View view)
{
try
{
// create bitmap screen capture
view.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return bitmap;
}
catch (Throwable e)
{
CustomLogHandler.printError(e);
}
return null;
}
private static void copyFile(Bitmap bitmap)
{
File dstFile = getShareResultFile();
//Delete old file if exist.
if(dstFile.exists()) {
dstFile.delete();
}
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(dstFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 0, fos);
fos.flush();
}
catch (Exception e) {
CustomLogHandler.printError(e);
}
finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ioe) {
CustomLogHandler.printError(ioe);
}
}
}
}
There are several problem like:
Back arrow, title and share menu background color is not correct. It looks messy.
Background color of toolbar is totally changed.
Image quality is too poor and list items rounded drawable has not smooth corners.
Background of layout is not taken that I set as background of my parent layout.
I am taking the screenshot from the root view.
bitmap.compress(Bitmap.CompressFormat.JPEG, 0, fos);
First, you are saving this as a JPEG. JPEG is designed for photos, and your screenshot is not a photo.
Second, you are saving this with a quality factor of 0. JPEG uses a lossy compression algorithm, and a quality factor of 0 says "please feel free to make this image be really poor, but compress it as far as you can".
I suggest switching to:
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
PNG is a better image format for a screenshot with the contents shown in your question. I don't think PNG uses the quality factor value; I put in 100 just to indicate that you want the best possible quality.
public static Bitmap takeScreenshot(View view)
{
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
This code can save view as bitmap.
But after you update your question with save code I see that you set 0 for quality, and what you expect?
#param quality Hint to the compressor, 0-100. 0 meaning compress for
* small size, 100 meaning compress for max quality. Some
* formats, like PNG which is lossless, will ignore the
* quality setting
just use your Ctrl button + click on method name to read doc about params
the answer is set second parameter 100 instead of 0!
Try using this:
public static Bitmap loadBitmapFromView(Context context, View v) {
DisplayMetrics dm = context.getResources().getDisplayMetrics();
v.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(dm.heightPixels, 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;
}
and
public void takeScreen() {
Bitmap bitmap = ImageUtils.loadBitmapFromView(this, view); //get Bitmap from the view
String mPath = Environment.getExternalStorageDirectory() + File.separator + "screen_" + System.currentTimeMillis() + ".jpeg";
File imageFile = new File(mPath);
OutputStream fout = null;
try {
fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
fout.close();
}
}
Images are saved in the external storage folder.
try this
private void captureScreen() {
View v = this.getWindow().getDecorView().findViewById(android.R.id.content);
v.setDrawingCacheEnabled(true);
Bitmap bitmap = v.getDrawingCache();
String extr = Environment.getExternalStorageDirectory().toString();
File file = new File(extr, getString(R.string.free_tiket) + ".jpg");
FileOutputStream f = null;
try {
f = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, f);
f.flush();
f.close();
MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Screen", "screen");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
I have long scrollview almost 50+ fields.
I'm converting that scrollview to pdf view. pdf also creating all done.
But pdf file showing data is blur (too blur).
With some merging, I provided some reference image (I mean output image).
output image
My code:
private void takeScreenShot() {
try {
//here getScroll is my scrollview id
View u = ((Activity) mContext).findViewById(R.id.getScroll);
ScrollView z = (ScrollView) ((Activity) mContext).findViewById(R.id.getScroll);
int totalHeight = z.getChildAt(0).getHeight();
int totalWidth = z.getChildAt(0).getWidth();
Bitmap bitmap = getBitmapFromView(u,totalHeight,totalWidth);
Image image;
//Save bitmap
String path = Environment.getExternalStorageDirectory()+"/Folder/";
String fileName = "report1.pdf";
File dir = new File(path);
if (!dir.exists())
dir.mkdirs();
Log.v("PDFCreator", "PDF Path: " + path);
File myPath = new File(path, fileName);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 10, stream);
image = Image.getInstance(stream.toByteArray());
image.setAbsolutePosition(0, 0);
Document document = new Document(image);
PdfWriter.getInstance(document, new FileOutputStream(myPath));
document.open();
document.add(image);
document.close();
} catch (Exception i1) {
i1.printStackTrace();
}
}
Any help?
Try this code:
View u = ((Activity) mContext).findViewById(R.id.getScroll);
u.setDrawingCacheEnabled(true);
u.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(u.getDrawingCache());
bitmap.setHasAlpha(true); //important for PNG
---------------DO SAVE WORK-----------------
v1.setDrawingCacheEnabled(false);
And at
bitmap.compress(Bitmap.CompressFormat.JPEG, 10, stream);
change 10 to 90 or 100. it is Image Quality.
Or just change in your code to higher quality.
Try another solution:
ScrollView v= (ScrollView)findViewById(R.id.getScroll);
int height = v.getChildAt(0).getHeight()
int width = v.getWidth()
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
v.draw(c);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
Take a screen shot using this code and
ScrollView iv = (ScrollView) findViewById(R.id.scrollView);
Bitmap bitmap = Bitmap.createBitmap(
iv.getChildAt(0).getWidth(),
iv.getChildAt(0).getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
c.drawColor(Color.WHITE);
iv.getChildAt(0).draw(c);
// Do whatever you want with your bitmap
saveBitmap(bitmap);
and save the bitmap as a image
public void saveBitmap(Bitmap bitmap) {
File imagePath = new File(Environment.getExternalStorageDirectory() + "/screenshot.png");
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}}
I might be late but anyway. Use png format instead, increase the quality to 100 and replace
View u = ((Activity) mContext).findViewById(R.id.getScroll);
with
View u = ((Activity) mContext).findViewById(R.id.yourfirstscrollviewchild);
Thatll do the trick.
I'm trying to capture all items in my ScrollView and save it as an image.
private void takeScreenShot()
{
ScrollView z = (ScrollView) findViewById(R.id.scroll_view);
int totalHeight = z.getChildAt(0).getHeight();
int totalWidth = z.getChildAt(0).getWidth();
Bitmap b = getBitmapFromView(u,totalHeight,totalWidth);
//Save bitmap
String extr = Environment.getExternalStorageDirectory()+"/Folder/";
String fileName = "report.jpg";
File myPath = new File(extr, fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myPath);
b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
MediaStore.Images.Media.insertImage(getContentResolver(), b, "Screen", "screen");
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Bitmap getBitmapFromView(View view, int totalHeight, int totalWidth) {
Bitmap returnedBitmap = Bitmap.createBitmap(totalWidth,totalHeight , Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
view.draw(canvas);
return returnedBitmap;
}
The resulting image is enter image description here
There should be some text in the black area but it isn't showing.
If someone has a solution that may work, I would greatly appreciate it.
public static Bitmap loadBitmapFromView(View v, int width, int height) {
Bitmap b = Bitmap.createBitmap(width , height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
v.draw(c);
return b;
}
Just pass ScrollView or it's immediate child view to above function.
Try this, and let me know. Hope it will help !
Sometimes it'll set background to black if it isn't set to anything and it'll show up as black text on black background when you create the bitmap.
You can solve this by adding a background color in the .XML file. Be sure to add a background color to the view you want to capture and each item within the views as well. Anything that doesn't have a set background will show up with a black background.
This question already has answers here:
Android saving file to external storage
(13 answers)
Closed 2 years ago.
I develop app that save images to sd Card and all the pictures are upside i want to rotate them and save them in the rotate position i choose .
i know how to rotate on my code but the image is not saved permanently.
here is my code :
//Rotate the picture
public static Bitmap rotate(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(),source.getHeight(), matrix, false);
}
//Resize image
public void resizeImage(String path , int Wdist,int Hdist){
try
{
int inWidth = 0;
int inHeight = 0;
InputStream in = new FileInputStream(path);
// decode image size (decode metadata only, not the whole image)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
in.close();
in = null;
// save width and height
inWidth = options.outWidth;
inHeight = options.outHeight;
// decode full image pre-resized
in = new FileInputStream(path);
options = new BitmapFactory.Options();
// calc rought re-size (this is no exact resize)
options.inSampleSize = Math.max(inWidth/Wdist, inHeight/Hdist);
// decode full image
Bitmap roughBitmap = BitmapFactory.decodeStream(in, null, options);
// calc exact destination size
Matrix m = new Matrix();
RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
RectF outRect = new RectF(0, 0, Wdist, Hdist);
m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
float[] values = new float[9];
m.getValues(values);
// resize bitmap
Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);
// save image
try
{
FileOutputStream out = new FileOutputStream(path);
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
}
catch (Exception e)
{
Log.e("Image", e.getMessage(), e);
}
}
catch (IOException e)
{
Log.e("Image", e.getMessage(), e);
}
}
thanks for the helpers :)
You'll need to save the Bitmap back.
try {
File dir = new File("path/to/directory");
if(!dir.exists())
dir.mkdirs();
File file = new File(dir, "original_img_name.png");
FileOutputStream out;
out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try{
out.close();
} catch(Throwable ignore) {}
}
Edit 1 :
Replace
bmp.compress(Bitmap.CompressFormat.PNG, 90, out); with
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out); and set correct values for the directory path and the image name. If you want to replace the previous images, use the original path and image name.
Also, make sure you include the following permission.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
You can also try this one
return Bitmap.createBitmap(source, 0, 0, source.getWidth(),source.getHeight(), matrix, true);
Go through this link
how to rotate a bitmap 90 degrees
The following code can help you compress and resize the bitmap.
Note:
Create a String type variable with name of photoPath and store the photo url in it.
public void compressImage(){
Log.i("compressPhoto", "Compress and resize photo started.");
// Getting Image
InputStream in = null;
try {
in = new FileInputStream(photoPath);
} catch (FileNotFoundException e) {
Log.e("TAG","originalFilePath is not valid", e);
}
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap = bitmap.createScaledBitmap(bitmap,(int)(bitmap.getWidth()*0.2), (int)(bitmap.getHeight()*0.2), true);
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);
byte[] byteArray = stream.toByteArray();
// Storing Back
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(photoPath);
outStream.write(byteArray);
outStream.close();
} catch (Exception e) {
Log.e("TAG","could not save", e);
}
}
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);