I'm recording the photos taken by my application in the sqlite database, I know it's not very recommended anymore I need to transfer these photos to a central database that unifies all data from all applications.
The way I'm reducing and writing to sqlite bank is this way:
Android.Graphics.Drawables.BitmapDrawable bd = (Android.Graphics.Drawables.BitmapDrawable)imageView.Drawable;
Bitmap bitmap = bd.Bitmap;
MemoryStream stream = new MemoryStream();
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, stream);
byte[] ba = stream.ToArray();
string bal = Base64.EncodeToString(ba, Base64.Default);
Personally, I am editing my question because the problem is not in the select as I had thought it could be, but at the time of writing to the database. The code above works great when searching for a photo or image on the device. The problem is when it takes the photo for the application, then I get this error that is below.
I think I need to compress App.bitmap, which gets the shot taken right away. I just do not know how to do it yet. As I said the above code works great with the pictures taken by the device, but when I shoot through my application I get this error.
I'm going to post my OnActivityResult method so that you can help me figure out what this error is.
Error:
Java.Lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
Searching on the internet this error is returning because of the size of the cursor that have a maximum of 2MB.
OnActivityResult Method:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
// Make it available in the gallery
try
{
Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
Uri contentUri = Uri.FromFile(App._file);
mediaScanIntent.SetData(contentUri);
SendBroadcast(mediaScanIntent);
// Display in ImageView. We will resize the bitmap to fit the display.
// Loading the full sized image will consume to much memory
// and cause the application to crash.
int height = Resources.DisplayMetrics.HeightPixels;
int width = imageView.Height;
App.bitmap = App._file.Path.LoadAndResizeBitmap(width, height);
if (App.bitmap != null)
{
imageView.SetImageBitmap(App.bitmap);
// App.bitmap = null;
}
// Dispose of the Java side bitmap.
GC.Collect();
}
catch
{
}
try
{
if (resultCode == Result.Ok)
{
var imageView =
FindViewById<ImageView>(Resource.Id.imageView1);
imageView.SetImageURI(data.Data);
}
}
catch
{
}
}
Without fetching the photo, the select does not return the error quoted above. I'm counting on your help.
Use EncoderParameter to specify the level of compression for an image.
see https://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoderparameter(v=vs.110).aspx
and https://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoder.quality(v=vs.110).aspx
Related
I have a program that allows the user to pick images from the gallery, saves it in a database and shows it on screen. This works for most images , but for certain images, the app crashes. There is no error message in the Logcat. But when i restart the app, i get a error message that says:
Couldn't read row 0, col 1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
(Tested on ANDROID SDK 24)
new AlertDialog.Builder(this).setTitle("Take or Pick?").setMessage("Choose to click a new picture or choose from existing").
setNegativeButton("CHOOSE PHOTO", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent i = new Intent(
Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, REQUEST_IMAGE_PICKER);
}
}).create().show();
onActivityResult code goes like this:
if (requestCode == REQUEST_IMAGE_PICKER && resultCode == RESULT_OK && null != data) {
Uri selectedImage = data.getData();
Bitmap bmp= null;
try { //GET BITMAP FROM URI , TRY CATCH USED TO TACKLE
bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage)); // IO STREAM FILE NOT FOUND ERROR
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(cameraTeamStatus==1) {
img1.setImageBitmap(bmp); //SET IMAGE
image1_to_save = convertToBlob(bmp); //CONVERT TO BLOB
}
This crash is due to large size of picture taken by camera and cursor not able to handle it ,cursor initialize fails.
In order to fix this I would suggest considering one of the following methods to reduce image size before upload Link:1 , Link:2 ,Link:3
or you can check this link Whatsapp like Image Compression.
Hope it Helps!
I've found a lot of answers for questions like mine but they doesn't make sense for me. Let me explain.
I have a ImageButton that let the user take a picture and display it on interface. When i try to get image URI, it returns null:
Uri uri = data.getData();
I've made some searches on internet and found solutions like:
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
try {
if (resultCode == Activity.RESULT_OK) {
updateProfilePicure = Boolean.TRUE;
switch(requestCode){
case 0:
Bundle extras = data.getExtras();
Object xx = data.getData();
Bitmap imageBitmap = (Bitmap) extras.get("data");
Uri tempUri = getImageUri(imageBitmap);
imageView.setImageBitmap(imageBitmap);
break;
default: break;
}
}
} catch(Exception e){
e.printStackTrace();
}
}
public Uri getImageUri(Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(
ApplicationContext.getInstance().getContext().getContentResolver(), inImage,
"Title", null);
return Uri.parse(path);
}
For me, it doesn't make sense because when the call goes to method onActivityResult(), the picture is already saved on DCIM folder and don't have any reason to save it again. So why should i use it?
Is possible to find another way to retrieve the URI from captured image?
Thank's in advance.
the picture is already saved on DCIM folder and don't have any reason to save it again.
Not necessarily. Quoting the documentation for ACTION_IMAGE_CAPTURE:
The caller may pass an extra EXTRA_OUTPUT to control where this image will be written. If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap object in the extra field.
(the "extra field" here is an extra keyed as data)
The code snippet that you pasted is retrieving the data extra, and so the image is not stored anywhere.
Is possible to find another way to retrieve the URI from captured image?
You already have the code for this, in your first code snippet -- if you are specifying the Uri as EXTRA_OUTPUT in your ACTION_IMAGE_CAPTURE request, you will get a Uri back to the image that was taken in the Intent handed to onActivityResult().
Using Android's gallery app to select a photo to upload with httppost later. The photo gets uploaded but it's very low quality and size. I have been reading about setting the Bitmap.CompressFormat.PNG will make it lossless but it's taking the photo from 2000x1500 to 250x187.
Is it possible that I'm getting the thumbnail and not the actual image? I'm using Photos from Google.
Code
#Override
public void onActivityResult( int requestCode, int resultCode, Intent data ) {
super.onActivityResult( requestCode, resultCode, data );
if ( resultCode == getActivity().RESULT_OK ) {
selectedImage = Uri.parse( data.getDataString() );
try {
final Bitmap v = DecodeUriImage.Decode( selectedImage, getActivity() );
ByteArrayOutputStream bao = new ByteArrayOutputStream();
v.compress( Bitmap.CompressFormat.PNG, 100, bao );
byte[] byte_arr = bao.toByteArray();
// Add image to array
images.set( selectedImageIndex, Base64.encodeToString( byte_arr, Base64.DEFAULT ) );
} catch ( FileNotFoundException e ) {
e.printStackTrace();
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
}
Result
The Bitmap.CompressFormat.PNG will compress the image but It depends on what kink of format you have used on the non-compressed image. You should use a vectorial image to get the best results because on the "compressing transfer" the immage loses the quality both in getting the image bigger on not.
There is no reason to put the selected image in a Bitmap for later use. Moreover you did not show what all is happening in DecodeUriImage.Decode( selectedImage, getActivity() );. Maybe it's quality is changed there. Instead realise you have a media path in selectedImage which you can convert to a real path to the filesystem. Save that path for later use.
If you use it later than just load the file in a byte array and encode base64. Do not use Bitmapfactory.
UPDATE!!
So Lokesh put me on the right path, and showed me that the problem was the size of the file being too large to show in the imageview. I was able to fix the imageview preview problem with the following code under my onActivityResult:
try {
Bitmap picture = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getPath()+"/td01.png");
int nh = (int) ( picture.getHeight() * (512.0 / picture.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(picture, 512, nh, true);
Log.v("Path", Environment.getExternalStorageDirectory().getPath()+"/td01.png");
pic1.setImageBitmap(scaled);
} catch (Exception e) {
Log.e("Error reading file", e.toString());
}
Thanks Lokesh!
----------------- ORIGINAL ISSUE BELOW THIS LINE -------------------
So I'm trying to both save an image to the SD card for use later, AND display the saved image in an imageview which also serves as the button which takes the photo. Here's the code:
pic1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent camera_intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File image1 = new File(Environment.getExternalStorageDirectory(),"td01.png");
camera_intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image1));
startActivityForResult(camera_intent, CAMERA_PIC_REQUEST1);
}
});
followed by:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode){
case 1:
if(resultCode==RESULT_OK){
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
pic1.setImageBitmap(thumbnail);
}
}
Now, if I remove the following code from the onclick, it shows the thumbnail as I expect it to:
File image1 = new File(Environment.getExternalStorageDirectory(),"td01.png");
camera_intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image1));
...but without that code, it doesn't save the file to my sd card.
The problem is, if I don't remove that code, it saves the image to my SD Card but immediately crashes before returning to the activity after tapping SAVE in the camera activity, unless I remove the following code from my onActivityResult:
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
pic1.setImageBitmap(thumbnail);
I've also tried many variations of the following code in my onActivityResult, hoping to display it from the actual file in a different way, but it never works and only shows a blank imageview, but at least in that case the crash doesn't occur, because I removed the get extras get data code:
Bitmap photo1 = BitmapFactory.decodeFile("/sdcard/td01.png");
pic1.setImageBitmap(photo1);
I've been struggling with this for days and am at a loss here. Hope someone can show me what stupid thing I'm doing wrong and explain why this isn't working.
Thanks!
Try this:
try {
Bitmap picture = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getPath()+"/DCIM/MyPhoto.jpg");
Log.v("Path", Environment.getExternalStorageDirectory().getPath()+"/DCIM/MyPhoto.jpg");
mImageView.setImageBitmap(picture);
} catch (Exception e) {
Log.e("Error reading file", e.toString());
}
do NOT access the SD card directly, try accessing it trough Environment Like this
String imageDir = Environment.getExternalStorageDirectory()+"/apple.jpg";
and then you can call BitmapFactory:
Bitmap myBitmap = BitmapFactory.decodeFile(imageDir);
here is the problem: i have searched for an answer for this and so far i made it work for the custom camera app that comes with htc phones.
i have the folowing
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode == REQUEST_FROM_CAMERA && resultCode == RESULT_OK) {
InputStream is=null;
File file=mInterface.getTempFile();
try {
is=new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(is==null){
try {
u = data.getData();
is=getContentResolver().openInputStream(u);
mInterface.saveStringPreferences(GlobalInterface.URI_SAVENAME, u.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
//Now "is" stream contains the required photo, you can process it
setImage(is);
}
//and this is the code to the function that calls the intent:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(mInterface.getTempFile()));
startActivityForResult(intent, REQUEST_FROM_CAMERA);
the remaining functions getTempFile() is to create a temp file on /sdcard/blabla.tmp
and a function to set the captured image in an image view.
so the problem is that i tested this code on the custom camera on a lg phone and it crashes. the question is: is there a way to get an uri for the image location (i dont need a specific save location it could be the default set from the camera) and there were also some issues i came across which i dont need to solve like getting a smaller resolution image. i just need one image and to be able to set it in an imageView and the method to work for every camera app that is there, custom or native regardless.
is this possible or i need to create a new camera class for this? in my opinion the camera apps that come with the phone are more adjusted to the phone model so i would prefer using them against building a custom one.
tnx.
Try this:
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
Source