My program starts with a Base64 string which i turn into a byte array
byte[] bytes = Convert.FromBase64String(imageBase64);
then i turn the byte array into a Bitmap
Bitmap bitmap = BitmapFactory.DecodeByteArray(bytes, 0, bytes.Length);
then i try to use the Emgucv Image<> Bitmap constructor
image = new Image<Gray, byte>(bitmap);
but i get this error System.NullReferenceException: Object reference not set to an instance of an object.
I've debugged and can confirm that the bitmap is being created successfully and has a byte count, width, height but still gives me this error. Here's the full method I'm using to go from Base64 to Emgucv UMat.
private async void SetBase64Pattern()
{
detection.Clear();
foreach (Assets asset in lstAssets)
{
if (asset.Used == 1)
{
detection.Add(0);
UMat imagePattern = new UMat();
VectorOfKeyPoint keyPoint = new VectorOfKeyPoint();
Mat desc = new Mat();
Image<Gray, byte> image;
string imageBase64 = asset.AssetImage;
imageBase64 = imageBase64.Split(',')[1];
byte[] bytes = Convert.FromBase64String(imageBase64);
#if __IOS__
NSData data = NSData.FromArray(bytes);
UIImage uiImage = UIImage.LoadFromData(data);
image = new Image<Gray, byte>(uiImage);
#elif __ANDROID__
//IImageSourceHandler handler = new StreamImagesourceHandler();
//Bitmap bitmap = await handler.LoadImageAsync(ImageSource.FromStream(() => new MemoryStream(bytes)), Forms.Context);
//image = new Image<Gray, byte>(bitmap);
Bitmap bitmap = BitmapFactory.DecodeByteArray(bytes, 0, bytes.Length);
image = new Image<Gray, byte>(bitmap);
#endif
imagePattern = image.ToUMat();
featureDetector.DetectAndCompute(imagePattern, null, keyPoint, desc, false);
triggers.Add(imagePattern);
triggersKPS.Add(keyPoint);
triggersDescs.Add(desc);
}
}
}
Thanks for looking!
EDIT
Just wanted to mention that the iOS code in fact works and that's what makes this all the more confusing on why the Android code does not work.
Answer to my own question.
The images were gif images before being encoded to Base64. After changing the gif to a jpeg before being encoded the process now works.
Related
Guys I am facing this issue since 2 days straight. I want to pick an image from gallery and convert it to Base64 method. I have tried Picasso but my imageview is large. Can you please help me. I tried everything but out of memory is too much for me when converting it to bitmap and then to base64.
BitmapDrawable drawable = (BitmapDrawable) ProfilePic.getDrawable();
yourSelectedIBitmapDrawable drawable = (BitmapDrawable) ProfilePic.getDrawable();
yourSelectedImage = drawable.getBitmap();mage = drawable.getBitmap();
Code which is converting this bitmap to Base64. Is there any possibility of skipping the bitmap and directly converting to Base64
private String encodeToBase64(Bitmap image) {
Bitmap immagex = image;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
immagex.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
String imageEncoded = Base64.encodeToString(b,Base64.DEFAULT);
//Log.e("LOOK", imageEncoded);
return imageEncoded;
}
Profile Pic is name of Imageview.
EDIT: So guyz one of the ways is to use the large heap, but Google says you should not use that unless absolutely necessary. The other one that worked for me is the accepted answer. Now I came up with my own solution. In theory, I am using Picasso to load the image into image view. So what if I can extract the image from the ImageView. Not from URI or path, but from Imageview. This way you have an image which is already reduced by Picasso. Picasso provides Callback to for Success or failure. So on Success, you can access the cache memory of ImageView and extract the Bit map out of it.
I will post the code as an answer shortly. I tried it and even an image of 35Mb originally can be converted to bitmap without Out of memory exception.
So here is my ans: https://stackoverflow.com/a/52125006/6022584
You can try to read the bitmap data with a buffer. Something like that :
private String encodeToBase64(Bitmap image) {
// get an InputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(CompressFormat.PNG, 0, baos);
byte[] bitmapdata = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bitmapdata);
// prepare a buffer to read the inputStream
byte[] buffer = new byte[10 * ONE_KIO]; // ONE_KIO = 1024
int bytesRead;
// prepare the stream to encode in Base64
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Base64OutputStream base64OutputStream = new Base64OutputStream(outputStream, Base64.DEFAULT);
// read the inputStream
while ((bytesRead = bais.read(buffer)) != -1) {
base64OutputStream.write(buffer, 0, bytesRead);
}
base64OutputStream.close();
// get the encoded result string
return outputStream.toString();
}
This is my Code that worked. New Issue is the name of Activity for me
if (requestCode == PICK_IMAGE) {
if(resultCode == RESULT_OK){
//isImageFromGallery = true;
//isImageSelected = true;
ImagePath = data.getData();
Picasso.get()
.load(ImagePath)
.resize(1024,1024)
.onlyScaleDown()
.centerCrop()
.into(picture, new Callback(){
#Override
public void onSuccess() {
BitmapDrawable drawable = (BitmapDrawable) picture.getDrawable();
yourSelectedImage = drawable.getBitmap();
//isImageSelected = true;
Log.d("FileSize",Formatter.formatFileSize(NewIssue.this,
yourSelectedImage.getByteCount()));
}
#Override
public void onError(Exception e) {
Toast.makeText(NewIssue.this, "Could Not Load Image", Toast.LENGTH_SHORT).show();
}
});
}
}
My current method of converting the image's bitmap to a byte array to a string crashes the application. The code is below
sampleIV.BuildDrawingCache();
Bitmap bm = sampleIV.DrawingCache;
byte[] finalData;
using (var stream= new MemoryStream())
{
bm.Compress(Bitmap.CompressFormat.Png, 0, stream);
finalData = stream.ToArray();
}
addBook.image =finalData;
await booksTable.InsertAsync(addBook);
If the line is removed then it does work so this is the problem does anybody have a solution for uploading a photo to an azure table.
EDIT:
New code with now converting to base 64 string which does have a length less than 500,000 and a breakpoint in the catch is being reached.
sampleIV.BuildDrawingCache();
Bitmap bm = sampleIV.DrawingCache;
byte[] finalData;
using (var stream = new MemoryStream())
{
bm.Compress(Bitmap.CompressFormat.Png, 0, stream);
finalData = stream.ToArray();
}string s = Convert.ToBase64String(finalData);
addBook.image = s;
try
{
await booksTable.InsertAsync(addBook);
}
catch (Exception)
{
int x = 45;
}
Xamarin Android Application to Store Image in SQLite From Gallery(available images in the phone) .My Question is How to Image Storage in SQLite? And Retrieve Image From SQLite? Is possible only Image Compressing using bitmap function ?
The basic idea to store/fetch Image bitmaps in most of the DB is following,
Store: Convert the Image bitmap into a Base64String and store it to SQLite.
public static string Base64Encode(string plainText) {
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
Retrieve: Fetch the Base64String and convert that to Bitmap again.
public static string Base64Decode(string base64EncodedData) {
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
You can store your bitmap image as a byte[] to SQlite. For this operation you should convert bitmap to byte array. This piece of code, convert bitmap to byte[]
var memoryStream = new MemoryStream();
bitmap.Compress(Bitmap.CompressFormat.Png, 0, memoryStream);
imageByteArray = memoryStream.ToArray();
imageView.BuildDrawingCache (true);
Bitmap bitmap = imageView.GetDrawingCache (true);
BitmapDrawable drawable = (BitmapDrawable)imageView.GetDrawable();
Bitmap bitmap = drawable.GetBitmap();
Edit: Solved.
I'm trying to upload an image to parse that has been selected from the phone's gallery. However I cannot seem to locate the imageview as it returns null. I think this page: Saving images to Parse has a similar question to what I'm asking but there is no answer to it.
Fragment class:
public void onClick(View view) {
img = (ImageView) rootView.findViewById(R.id.imageView1);
// Locate the image (error is here)
Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), img);
// Convert it to byte
ByteArrayOutputStream stream = new ByteArrayOutputStream();
// Compress image to lower quality scale 1 - 100
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] image = stream.toByteArray();
//byte[] image = img.getContext().toString().getBytes();
//Bitmap bitmap = BitmapFactory.decodeFile(img);
ParseFile file = new ParseFile("image.jpg", image);
file.saveInBackground();
ParseObject familyTree = new ParseObject("FamilyTree");
familyTree.put("image", file);
familyTree.put("name", etName.getText().toString());
familyTree.put("relation", etRelation.getText().toString());
familyTree.saveInBackground();
Toast.makeText(FamilyTreeFragment2.this.getActivity(), "Saved.", Toast.LENGTH_SHORT).show();
// getFragmentManager().beginTransaction().replace(R.id.container, new FamilyTreeFragment2()).addToBackStack(null).commit();
}
Any help is appreciated. Thank you.
I've managed to find the solution.
Replaced
Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), img);
with
Bitmap bitmap = ((BitmapDrawable) img.getDrawable()).getBitmap();
I am trying to show a image saved as blob in my DB. I am using ORMLite and Android 1.6.
I created a textView who show a 'html.FromHtml'
Here is the code:
//Save the image in DB.
...
Bitmap myBitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().toString()+"/images/imagem.png");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
myBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
glossary.setImageBytes(byteArray);
'glossary' is an instance of Glossary. Who has the field 'imageBytes':
#DatabaseField(dataType = DataType.BYTE_ARRAY)
private byte[] imageBytes;
In my activity I pass this 'imageBytes' to string to use 'html.FromHtml':
//Activity
...
String htmlContent = "<h1> Title </h1>
<img src=\""+glossary.getImageBytes.toString()+"\" />"
Now in my Adapter I try to show the content of 'htmlContent':
//Adapter
...
holder.tvContent.setText(Html.fromHtml(htmlContent, new Html.ImageGetter() {
#Override
public Drawable getDrawable(String source) {
byte[] data;
data = source.getBytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//Log.i("bitmap", "bitmap height:" + String.valueOf(bitmap.getHeight) );
//THIS LOG RETURN NPE
Drawable d = null;
d = new BitmapDrawable(getResources(),bitmap);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
return d;
}
}, null));
...
I think the problem is when I change byte to string and string to byte. Because the bitmap created by 'BitmapFactory.decodeFile()' is returning a NPE.
But I don't know how fix that.
Any suggestions?
thx!
Well certainly your first problem is that you should not be doing:
glossary.getImageBytes().toString()
To turn a byte[] into a String you should do:
new String(glossary.getImageBytes())
If you do a byte[].toString() it will be set to something like:
[B#3487a5cc
Instead of a String made up of the bytes in the array.
That said, I'm not sure you can just put the bytes from a PNG file into a byte[] array to be printing out as a String. That sounds like you are going to be printing binary information in your HTML which I don't think will convert correctly. Also, it looks like you are putting the PNG bytes into the src="..." HTML section. That won't work either AFAIK.