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);
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 would like to rotate and save the rotated image and move it elsewhere within my android device.
I am able to rotate my image and set it to image view.
I can copy an UN-ROTATED image to a destination of my choice.
The only thing I am unable to do is get the saved rotated image FILE (rotated.jpg)
My code below to rotate: (this does not save rotated file to storage?)
Bitmap bmp = BitmapFactory.decodeFile(filePathLocal);
Matrix matrix = new Matrix();
matrix.postRotate(getImageOrientation(filePathLocal));
rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
//Set Image
ImageButton ibProfile = (ImageButton) findViewById(R.id.ibProfile);
ibProfile.setImageBitmap(rotatedBitmap);
Now the above only rotates temporarily until the activity is ended, now I would like to save this rotated image from above code and move it somehwere before uploading it to server, I already know how to copy/move files and upload so no need to post those codes - all I need is the code for SAVING ROTATED IMAGE, so that I have something like /sdcard/saved_rotated_image.jpg
Bitmap bmp = BitmapFactory.decodeFile(filePathLocal);
Matrix matrix = new Matrix();
matrix.postRotate(getImageOrientation(filePathLocal));
rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, false);
//Set Image
ImageButton ibProfile = (ImageButton) findViewById(R.id.ibProfile);
ibProfile.setImageBitmap(rotatedBitmap);
Put false in the createbitmap's last argument
Refere my code:
#Override
protected Uri doInBackground(String... params) {
String filepath = params[0];
String filename = params[1];
String filetype = params[2];
Bitmap bitmap = takeScreenShot(root);
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(Datas.rotationvalue);
Log.e("rotationvalue", Datas.rotationvalue+"...");
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), rotateMatrix, false);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 100, bytes);
try {
File f = new File(filepath);
if (!f.exists()) {
f.mkdir();
}
String folderpath = f.toString();
File file = new File(folderpath, filename + "." + filetype);
file.createNewFile();
FileOutputStream fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.close();
Uri uri = Uri.fromFile(file);
Log.e("Edited img uri", uri.toString());
return uri;
} catch (Exception e) {
Log.e("Exception...occured", e.toString());
e.printStackTrace();
return null;
}
}
This code is working fine.At my own side, try at your side.
According to doc: last argument is filter boolean: true if the source
should be filtered. Only applies if the matrix contains more than just
translation.
Link for more info: Last argument more info
Save the image function is as follows:
private void saveBitmap(Bitmap bitmap, String fileName) {
File file = new File(Environment.getExternalStorageDirectory(), fileName);
FileOutputStream fileOS = null;
try {
fileOS = new FileOutputStream(file);
// quality: Hint to the compressor, 0-100. 0 meaning compress for small size, 100 meaning compress for max quality.
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOS);
fileOS.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOS != null) {
try {
fileOS.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Use the sample:
Bitmap bmp = BitmapFactory.decodeFile(filePathLocal);
Matrix matrix = new Matrix();
matrix.postRotate(getImageOrientation(filePathLocal));
rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
saveBitmap(rotatedBitmap, "saved_rotated_image.jpg");
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 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;
}