On a rooted Android device, i want to take a screenshot and convert the raw format image to a Png image then save it locally. So far, i managed to access the framebuffer, take the screenshot and save the raw image. The problem is when i convert it to Png format, the image i get is all wrong.. a bunch of white and grey lines.
Here's what i did:
public void putRawImageInArray (byte [] array, File f ) throws IOException{
#SuppressWarnings("resource")
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(f)); //The framebuffer raw image is in the file
bufferedInputStream.read(array, 0, array.length);//read the file
}
public void convertToBitmap (byte [] rawarray) throws IOException{
byte [] Bits = new byte[rawarray.length*4];
int i;
for(i=0;i<rawarray.length;i++)
{
Bits[i*4] =
Bits[i*4+1] =
Bits[i*4+2] = (byte) ~rawarray[i];
Bits[i*4+3] = -1;//0xff, that's the alpha.
}
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
bm.copyPixelsFromBuffer(ByteBuffer.wrap(Bits));
File f = new File(Environment.getExternalStorageDirectory(), "/pictures/picture.png");
f.createNewFile();
if (f.exists() == true) {
f.delete();
}
try{
OutputStream fos=new FileOutputStream(f);
bm.compress(CompressFormat.PNG, 100, fos);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
What am i doing wrong?
Try removing all this
byte [] Bits = new byte[rawarray.length*4];
int i;
for(i=0;i<rawarray.length;i++)
{
Bits[i*4] =
Bits[i*4+1] =
Bits[i*4+2] = (byte) ~rawarray[i];
Bits[i*4+3] = -1;//0xff, that's the alpha.
}
and use rawarray directly
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
bm.copyPixelsFromBuffer(ByteBuffer.wrap(rawarray));
and make sure that the color model that you are using(Bitmap.Config.ARGB_8888) is same as the color model of the image data.
Related
My aim is to
Capture bytes from the camera onPictureTaken
Convert the byte[] to a Bitmap BitmapFactory.decodeByteArray
Save the Bitmap
I have a problem with step 2. This step for some reason makes the picture contain jagged edges and a loss of quality. If I do step 1 and save the bytes to a file directly (without step 2) then the image looks a lot better.
How do I convert bytes to a bitmap (step 2) without losing quality?
#Override
public void onPictureTaken(byte[] byteData, Camera camera) {
String filePath = "PATH_TO_IMAGE_FILE";
//Save bytes directly
{
File pictureFile = new File(filePath + ".fromBytes");
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(byteData);
fos.close();
} catch (Exception error) {
Log.d( "File not saved: " , error.getMessage());
}
}
//convert to bitmap -> convert to bytes -> then save
{
//I think this is where is loses quality ??
Bitmap decodedBitmap = BitmapFactory.decodeByteArray(byteData, 0, byteData.length);
//
ByteArrayOutputStream blob = new ByteArrayOutputStream();
decodedBitmap.compress(Bitmap.CompressFormat.PNG, 100, blob);
byte[] bitmapdata = blob.toByteArray();
File pictureFile = new File(filePath + ".fromBitmap");
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(bitmapdata);
fos.close();
} catch (Exception error) {
Log.d( "File not saved: " , error.getMessage());
}
}
}
Thanks
Trying to upload image as file using Retrofit, have uploaded files when path was of type file:// but now due to naugat , have changed the path Uri to Content:/ type, now when i convert this path to file and make retrofit Call, it gives FileNotFoundException
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"),photoFile);
this is the value of photoFile used above- file:/storage/emulated/0/Android/data/com.Bawa.Sketches/files/Pictures/JPEG_20161114_063716_-1561886067.jpg
USed setPic() method given in developer's site
private void setPic(ImageView sketchIv) {
InputStream input = null;
try {
input = getContentResolver().openInputStream(Uri.parse(mCurrentPhotoPath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// Get the dimensions of the View
int targetW = 300;
int targetH = 300;
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(input, null, bmOptions);
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW / targetW, photoH / targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
try {
input = getContentResolver().openInputStream(Uri.parse(mCurrentPhotoPath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap bitmap = BitmapFactory.decodeStream(input, null, bmOptions);
sketchIv.setImageBitmap(bitmap);
compressImage(bitmap);
//showAlertDialog(bitmap);
}
called CompressImage() method to reduce size of the image and got the photoFile value in the method
private void compressImage(Bitmap lbitmap) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
File f = new File(Uri.parse(mCurrentPhotoPath).toString());
try {
f.createNewFile();
Bitmap bitmap = lbitmap;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 20, bos);
byte[] bitmapdata = bos.toByteArray();
FileOutputStream fos = null;
fos = new FileOutputStream(f);
fos.write(bitmapdata);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
}
photoFile = f;
Log.i("response","FILE : "+ f);
}
P.S. have read Commonsware's answer most of the places - If you get a content:// Uri, please consume it using a ContentResolver and methods like openInputStream() and openOutputStream().
do not have any idea how to implement this.
called CompressImage() method to reduce size of the image and got the photoFile value in the method
We discussed this previously.
File f = new File(Uri.parse(mCurrentPhotoPath).toString());
Uri.parse(mCurrentPhotoPath).toString() will give you mCurrentPhotoPath back, as parse() and toString() undo each other. And mCurrentPhotoPath is a string representation of a Uri, not a filesystem path.
So, modify compressImage() to use the same InputStream approach that you used in setPic().
check this code,Create a typed file using your image path. I think it will work.
TypedFile typedFile = new TypedFile("image/jpeg", new File(photoFile ));
or
if you are using retrofit version above 2 then you can you use following code.
RequestBody file = RequestBody.create(MediaType.parse("image/*"), photoFile );
I'm having quite a problem here.
When I read image and then save it, I get the same picture. But when I open the pixel value, the value of each pixel is slightly different(larger or smaller around 10 units).
Why did that pixel change? I only read the image, then save it, I don't make changes to the pixel. I create it with format RGB and save as a PNG with ByteArrayOutputStream method.
private void onCaptureImageResult(Intent data) {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
File destination = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".jpg");
FileOutputStream fo;
try {
destination.createNewFile();
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
ivImage.setImageBitmap(thumbnail);
}
private void onSelectFromGalleryResult(Intent data) {
Bitmap bm=null;
if (data != null) {
try {
bm = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(), data.getData());
} catch (IOException e) {
e.printStackTrace();
}
}
bmp = bm;
}
public void save(View view){
operation= Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(),bmp.getConfig());
int size = bmp.getRowBytes() * bmp.getHeight();
bytearrayoutputstream = new ByteArrayOutputStream();
int[] gambarR = new int[size];
int[] gambarG = new int[size];
int[] gambarB = new int[size];
int[] gambarA = new int[size];
int k = 0;
for(int i=0; i<bmp.getWidth(); i++){
for(int j=0; j<bmp.getHeight(); j++){
int p = bmp.getPixel(i, j);
gambarR[k] = Color.red(p);
gambarG[k] = Color.green(p);
gambarB[k] = Color.blue(p);
gambarA[k] = Color.alpha(p);
k++;
}
}
int l = 0;
for(int i = 0; i<bmp.getWidth(); i++){
for(int j = 0; j<bmp.getHeight();j++){
operation.setPixel(i, j, Color.rgb(gambarR[l], gambarG[l], gambarB[l]));
l++;
}
}
String fileName = "_hasil.bmp";
Long tsLong = System.currentTimeMillis()/1000;
String ts = tsLong.toString();
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
File gambar = new File(baseDir + File.separator + ts + fileName);
try
{
gambar.createNewFile();
fileoutputstream = new FileOutputStream(gambar);
fileoutputstream.write(bytearrayoutputstream.toByteArray());
fileoutputstream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
ivImage.setImageBitmap(operation);
}
I will show you the difference between the image. I only read and save, and don't change the pixel. I need the pixel didn't change when I save it back.
As others have noticed, much of the code that you posted appears to do not much useful, indicating that you either haven't read the documentation, or haven't thought through the problem thoroughly.
However, the specific problem appears to be that you are saving your image in a lossy compression format (JPEG), in this case, at 90% quality. "Lossy" means that by definition you will never get back exactly the bitmap that you had before compression. Even setting JPEG quality to 100% is unlikely to get you exactly the same bitmap as before compression.
If you want exactly the same values back when reading the file, you'll need to write a lossless format, such as PNG or BMP.
I want to capture edit text content in image. But text can be scrollable.
How to capture with scrollable content from edit text?
without scrollable i am using the following link to do..
Create Bitmap Image from EditText & its content
Please help me to solve the issue
Here is the sample code
please try your best...
Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(),
R.drawable.edittextimage);// get the image same as your EditText
bitmap = convertToMutable(bitmap);// converting the bitmap to mutable
Canvas cs = new Canvas(bitmap);
int h = bitmap.getHeight();
int w = bitmap.getWidth();
Paint pt = new Paint();
pt.setColor(Color.GREEN);
String iam = "your text that get from the Edit Text";
cs.drawText(iam, 0, iam.length(), (h / 2) + 10, (w / 2) / 2, pt);
pt.setColor(Color.RED);
cs.drawText("this is praki", 0, 13, h / 2, w / 3, pt);
Save_to_SD(bitmap , path)//save the bitmap in to sdcard
convertToMutable(bitmap) Methode ....
public static Bitmap convertToMutable(Bitmap imgIn) {
try {
// this is the file going to use temporally to save the bytes.
// This file will not be a image, it will store the raw image data.
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + "temp.tmp");
// Open an RandomAccessFile
// Make sure you have added uses-permission
// android:name="android.permission.WRITE_EXTERNAL_STORAGE"
// into AndroidManifest.xml file
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
// get the width and height of the source bitmap.
int width = imgIn.getWidth();
int height = imgIn.getHeight();
Bitmap.Config type = imgIn.getConfig();
// Copy the byte to the file
// Assume source bitmap loaded using options.inPreferredConfig =
// Config.ARGB_8888;
FileChannel channel = randomAccessFile.getChannel();
MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE,
0, imgIn.getRowBytes() * height);
imgIn.copyPixelsToBuffer(map);
// recycle the source bitmap, this will be no longer used.
imgIn.recycle();
System.gc();// try to force the bytes from the imgIn to be released
// Create a new bitmap to load the bitmap again. Probably the memory
// will be available.
imgIn = Bitmap.createBitmap(width, height, type);
map.position(0);
// load it back from temporary
imgIn.copyPixelsFromBuffer(map);
// close the temporary file and channel , then delete that also
channel.close();
randomAccessFile.close();
// delete the temp file
file.delete();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return imgIn;
}
Save_to_SD(bitmap , path) methode....
public static void Save_to_SD(Bitmap bm, String image_name) {
// String extStorageDirectory =
// Environment.getExternalStorageDirectory()
// .toString();
// String meteoDirectory_path = extStorageDirectory +
// "/Weather_Belgium";
OutputStream outStream = null;
File file = new File(image_name);
try {
outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
Log.i("Hub", "OK, Image Saved to SD");
Log.i("Hub",
"height = " + bm.getHeight() + ", width = " + bm.getWidth());
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.i("Hub", "FileNotFoundException: " + e.toString());
} catch (IOException e) {
e.printStackTrace();
Log.i("Hub", "IOException: " + e.toString());
}
}
this question is easy,we can :
public static void writePhotoJpg(Bitmap data, String pathName) {
File file = new File(pathName);
try {
file.createNewFile();
// BufferedOutputStream os = new BufferedOutputStream(
// new FileOutputStream(file));
FileOutputStream os = new FileOutputStream(file);
data.compress(Bitmap.CompressFormat.JPEG, 100, os);
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
but this method not all successful:because "Note: not all Formats support all bitmap configs directly, so it is possible that the returned bitmap from BitmapFactory could be in a different bitdepth, and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque pixels)." in the google document. without luck i have this problem: in the Camera preview i used :
private Bitmap printScreen() {
View view = this.getWindow().getDecorView();
// if (view.isDrawingCacheEnabled()) {
view.setDrawingCacheEnabled(true);
Calendar c = Calendar.getInstance();
String date = c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH) + " " + c.get(Calendar.HOUR_OF_DAY) + "-" + c.get(Calendar.MINUTE) + "-" + c.get(Calendar.SECOND);
// }
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
return bmp ;
}
so when i used setImageBitmap(bmp) ,looks very well,but when i open the save jpeg file it is a black jpeg.so i think the save method is not well,can you tell me another save method?
you can try this:
public static final int BUFFER_SIZE = 1024 * 8;
static void writeExternalToCache(Bitmap bitmap, File file) {
try {
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
final BufferedOutputStream bos = new BufferedOutputStream(fos, BUFFER_SIZE);
bitmap.compress(CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
}
}
it works in my code, so if it's not work, try to find error:
1.the bitmap display right ?
2.where is the bitmap save file? the file has some limit? like size or ...
if the error is your post reason, you can try decode the bitmap again using Bitmap.Config.RGB_565.
Use .getRootView() method of view OR the layout contains this view, use it (e.g.) mainLayout contain one image view at index 1 then mainlayou.getChildAt(1) to get the view.
E.g.
View v1 = mainLayout.getChildAt(1); //OR View v1 = mainLayout.getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
return bitmap;
Hope helpful to you...