I have been able to export my code into an application and use the Tess-Two file from this tutorial
to integrate the tesseract into it. But now I'm facing problems; when the picture is sent to the tesseract it just returns the same random characters each time: 'f' wig, W fin. A. " 5' ' ,{ >>zv' ' ~" > ';>'. What seems to be the problem?
ImageView iv;
TextView tv;
protected Bitmap _image;
protected Bitmap bmp;
public static String The_path = "/mnt/sdcard/DCIM/100MEDIA/TESS.jpg";
public static String lang = "eng";
public static final String DATA_PATH = Environment.getExternalStorageDirectory().toString() + "/SimpleAndroidOCR/";
private int pageSegmentationMode = TessBaseAPI.PageSegMode.PSM_AUTO;
#Override
public void onCreate(Bundle savedInstanceState) {
try {
AssetManager assetManager = getAssets();
InputStream in = assetManager.open("tessdata/eng.traineddata");
//GZIPInputStream gin = new GZIPInputStream(in);
OutputStream out = new FileOutputStream(DATA_PATH + "tessdata/eng.traineddata");
//Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
//while ((len = gin.read(buf)) > 0) {
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
//gin.close();
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
};
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
iv = (ImageView) findViewById(R.id.imageView1);
tv = (TextView) findViewById(R.id.textView1);
Button but = (Button) findViewById(R.id.button1);
Button but2 = (Button) findViewById(R.id.button2);
but.setOnClickListener(new OnClickListener() {
public void onClick(View v){
//File file = new File( _path );
//Uri outputFileUri = Uri.fromFile( file );
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
//intent.putExtra( MediaStore.EXTRA_OUTPUT, outputFileUri );
startActivityForResult(intent, 0);
}
});
but2.setOnClickListener(new OnClickListener() {
public void onClick(View v){
TessBaseAPI baseApi = new TessBaseAPI();
baseApi.setDebug(true);
baseApi.setPageSegMode(pageSegmentationMode);
baseApi.init(DATA_PATH, lang);
// DATA_PATH = Path to the storage
// lang for which the language data exists, usually "eng"
try {
baseApi.setImage(ReadFile.readBitmap(bmp));
String recognizedText = baseApi.getUTF8Text();
txt(recognizedText);
} catch(RuntimeException e) {
}
baseApi.end();
}
private void txt(String txt) {
// TODO Auto-generated method stub
tv.setText(txt);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile(The_path, options);
try {
ExifInterface exif = new ExifInterface(The_path);
int exifOrientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch (exifOrientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
}
if (rotate != 0) {
// Getting width & height of the given image.
int w = bitmap.getWidth();
int h = bitmap.getHeight();
// Setting pre rotate
Matrix mtx = new Matrix();
mtx.preRotate(rotate);
// Rotating Bitmap
bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, false);
}
bitmap = toGrayscale(bitmap);
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
} catch (IOException e) {
}
_image = (Bitmap) data.getExtras().get("data");
iv.setImageBitmap(_image);
bmp = bitmap;
} public static Bitmap toGrayscale(Bitmap bmpOriginal){
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
here is the new log cat after adding the grayscale function:
(receiving a new set of reoccurring random characters)
01-26 10:21:36.973: D/libEGL(1389): loaded /system/lib/egl/libEGL_adreno200.so
01-26 10:21:36.973: D/libEGL(1389): loaded /system/lib/egl/libGLESv1_CM_adreno200.so
01-26 10:21:36.973: D/libEGL(1389): loaded /system/lib/egl/libGLESv2_adreno200.so
01-26 10:21:36.983: I/Adreno200-EGL(1389): <eglInitialize:269>: EGL 1.4 QUALCOMM build: Nondeterministic AU_full_mako_PARTNER-ANDROID/JB-MR1- DEV_CL2946718_release_AU (CL2946718)
01-26 10:21:36.983: I/Adreno200-EGL(1389): Build Date: 11/04/12 Sun
01-26 10:21:36.983: I/Adreno200-EGL(1389): Local Branch:
01-26 10:21:36.983: I/Adreno200-EGL(1389): Remote Branch: m/partner-android/jb-mr1-dev
01-26 10:21:36.983: I/Adreno200-EGL(1389): Local Patches: NONE
01-26 10:21:36.983: I/Adreno200-EGL(1389): Reconstruct Branch: NOTHING
01-26 10:21:37.043: D/OpenGLRenderer(1389): Enabling debug mode 0
01-26 10:21:45.502: E/BitmapFactory(1389): Unable to decode stream: java.io.FileNotFoundException: /mnt/sdcard/DCIM/100MEDIA/TESS.jpg: open failed: ENOENT (No such file or directory)
01-26 10:21:45.502: E/JHEAD(1389): can't open '/mnt/sdcard/DCIM/100MEDIA/TESS.jpg'
01-26 10:21:45.512: D/AndroidRuntime(1389): Shutting down VM
01-26 10:21:45.512: W/dalvikvm(1389): threadid=1: thread exiting with uncaught exception (group=0x417b0930)
01-26 10:21:45.522: E/AndroidRuntime(1389): FATAL EXCEPTION: main
01-26 10:21:45.522: E/AndroidRuntime(1389): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=0, result=-1, data=Intent { act=inline-data (has extras) }} to activity {com.cam.calc/cam.calc.Main}: java.lang.NullPointerException
01-26 10:21:45.522: E/AndroidRuntime(1389): at android.app.ActivityThread.deliverResults(ActivityThread.java:3319)
01-26 10:21:45.522: E/AndroidRuntime(1389): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3362)
01-26 10:21:45.522: E/AndroidRuntime(1389): at android.app.ActivityThread.access$1100(ActivityThread.java:141)
01-26 10:21:45.522: E/AndroidRuntime(1389): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1282)
01-26 10:21:45.522: E/AndroidRuntime(1389): at android.os.Handler.dispatchMessage(Handler.java:99)
01-26 10:21:45.522: E/AndroidRuntime(1389): at android.os.Looper.loop(Looper.java:137)
01-26 10:21:45.522: E/AndroidRuntime(1389): at android.app.ActivityThread.main(ActivityThread.java:5039)
01-26 10:21:45.522: E/AndroidRuntime(1389): at java.lang.reflect.Method.invokeNative(Native Method)
01-26 10:21:45.522: E/AndroidRuntime(1389): at java.lang.reflect.Method.invoke(Method.java:511)
01-26 10:21:45.522: E/AndroidRuntime(1389): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
01-26 10:21:45.522: E/AndroidRuntime(1389): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
01-26 10:21:45.522: E/AndroidRuntime(1389): at dalvik.system.NativeStart.main(Native Method)
01-26 10:21:45.522: E/AndroidRuntime(1389): Caused by: java.lang.NullPointerException
01-26 10:21:45.522: E/AndroidRuntime(1389): at cam.calc.Main.onActivityResult(Main.java:388)
01-26 10:21:45.522: E/AndroidRuntime(1389): at android.app.Activity.dispatchActivityResult(Activity.java:5293)
01-26 10:21:45.522: E/AndroidRuntime(1389): at android.app.ActivityThread.deliverResults(ActivityThread.java:3315)
01-26 10:21:45.522: E/AndroidRuntime(1389): ... 11 more
You need to process the images before OCR, at least convert the image to black&white (gray scale) can enhance the result :
bitmap = toGrayscale(bitmap);
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
you can user OpenCV or any Image Processing Library, for for simple task like grayscale its enopugh to use
import android.graphics.*;
public static Bitmap toGrayscale(Bitmap bmpOriginal)
{
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
Also if the image is too large you may need to crop the image and get the area that contain the characters & numbers you want to recognize, its also make OCR engine job more easier/more accuracy and sometimes its prevents you from OutOfMemoryException.
Related
I'm trying blur some images 1024x1024 and sometimes I'm getting java.lang.OutOfMemoryError and i don't know why.
I'm testing directly in my tablet Android 4.1.2 and I have always 1.5gb Ram free.
Here the class I'm using:
package com.example.playerclient.blur;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v8.renderscript.*;
public class BlurBuilder {
private static final float BITMAP_SCALE = 0.6f;
public static Bitmap blur(Context context, Bitmap image, float blurRadius) {
Bitmap outputBitmap = null;
if (image != null) {
if (blurRadius == 0) {
return image;
}
if (blurRadius < 1) {
blurRadius = 1;
}
if (blurRadius > 25) {
blurRadius = 25;
}
int width = Math.round(image.getWidth() * BITMAP_SCALE);
int height = Math.round(image.getHeight() * BITMAP_SCALE);
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
outputBitmap = Bitmap.createBitmap(inputBitmap);
RenderScript rs = RenderScript.create(context);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
theIntrinsic.setRadius(blurRadius);
theIntrinsic.setInput(tmpIn);
theIntrinsic.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
}
return outputBitmap;
}
}
Here where I call the method:
public class MusicaActivity extends AppCompatActivity implements View.OnClickListener {
// Others methods here.
private void mostraDadosMusica() {
Intent intent = getIntent();
Musica musica = (Musica)intent.getSerializableExtra(MainActivity.VISUALIZA_PLAYER);
// Where i'm having problems.
Bitmap originalBmp = BitmapFactory.decodeResource(getResources(), musica.getAlbum().getIdCapa());
Bitmap resultBmp = BlurBuilder.blur(this, originalBmp, 15f);
backgroundImageView.setImageBitmap(resultBmp);
}
}
Ande here the exception message:
11-04 22:05:07.453 18928-18928/com.example.playerclient E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:636)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:484)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:512)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:542)
at com.example.playerclient.activity.MusicaActivity.mostraDadosMusica(MusicaActivity.java:48)
at com.example.playerclient.activity.MusicaActivity.onCreate(MusicaActivity.java:87)
at android.app.Activity.performCreate(Activity.java:5188)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
at android.app.ActivityThread.access$700(ActivityThread.java:140)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
I try camera preview capture on android.
use Bitmap.
but occur NullpointerException
java.lang.NullPointerException
at kr.co.mytest.test.video.CameraTextureView.getImage(CameraTextureView.java:167)
at kr.co.mytest.test.video.CameraTextureView.onPreviewFrame(CameraTextureView.java:161)
at android.hardware.Camera$EventHandler.handleMessage(Camera.java:936)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
CameraTextureView.class
public class CameraTextureView extends TextureView implements TextureView.SurfaceTextureListener, Camera.PreviewCallback {
private Camera mCamera;
private CaptureViewer captureView;
.
.
.
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
Log.d(TAG,"CHECK");
YuvImage image = new YuvImage(data, 20, 640 ,480, null);
Rect rect = new Rect(0, 0, 640, 480);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
image.compressToJpeg(rect, 100, bao);
byte[] jpeg = bao.toByteArrary();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap convertedImage = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options);
Log.d(TAG, "convertedImage" + convertedImage); //android.graphics.Bitmap#21ac0b78
getImage(Bitmap.createScaleBitmap(convertedImage, 480, 360, true)); //nullPointerException
}
public void getImage(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
captureView.displayImage(bitmap);
}
CaptureView.class
public class CaptureView extends View {
private Bitmap mBitmap = null;
public void displayImage(Bitmap image) {
mBitmap = Bitmap.createBitmap(image);
postInvalidate();
}
}
displayImage is only showing capture image.
why occur nullpointerException?
onPreviewFrameis Called as preview frames are displayed.
how to process occur nullPointerException?
thanks.!
I want to load the image in ImageView after cropping the image and save it. But when it's resumes it gets crashed, but image is saving on selected location. I think the problem is in selectedImageUri. But I couldn't figure it out how to solve. Please someone help. Thanks in advance.
Code:
public class CatFragment extends Fragment implements OnClickListener{
private DBCreater dbCreate;
private static final int SELECT_PICTURE = 1;
private String selectedImagePath = "android.resource://com.example.abcd/" + R.drawable.pets;
private ImageView img;
//private Button imgBtn;
private Uri mCropImagedUri;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View gv = inflater.inflate(R.layout.new_pet, null);
Spinner sp = (Spinner) gv.findViewById(R.id.ETPetType);
// get reference
sp.setAdapter(new ArrayAdapter<String>(getActivity().getBaseContext(), android.R.layout.simple_spinner_dropdown_item, petType));
Button btnSubmit = (Button) gv.findViewById(R.id.ButtonNext);
btnSubmit.setOnClickListener(this);
img = (ImageView)gv.findViewById(R.id.ImageView01);
((Button) gv.findViewById(R.id.ETPetImg))
.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
try {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 0);
intent.putExtra("aspectY", 0);
intent.putExtra("outputX", 200);
intent.putExtra("outputY", 200);
intent.putExtra("return-data", false);
File f = createNewFile("CROP_");
try {
f.createNewFile();
} catch (IOException ex) {
Log.e("io", ex.getMessage());
}
mCropImagedUri = Uri.fromFile(f);
intent.putExtra(MediaStore.EXTRA_OUTPUT,
mCropImagedUri);
// start the activity - we handle returning in
// onActivityResult
startActivityForResult(intent, SELECT_PICTURE);
} catch (ActivityNotFoundException anfe) {
// display an error message
}
}
});
return gv;
}
private File createNewFile(String prefix){
if(prefix==null || "".equalsIgnoreCase(prefix)){
prefix="IMG_";
}
File newDirectory = new File(Environment.getExternalStorageDirectory()+"/test1/");
if(!newDirectory.exists()){
if(newDirectory.mkdir()){
Log.d(this.getClass().getName(), newDirectory.getAbsolutePath()+" directory created");
}
}
File file = new File(newDirectory,(prefix+System.currentTimeMillis()+".jpg"));
if(file.exists()){
//this wont be executed
file.delete();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri); //To get image path
System.out.println("Image Path : " + selectedImagePath);
img.setImageURI(selectedImageUri);
}
}
}
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
//Cursor cursor = managedQuery(uri, projection, null, null, null);
Cursor cursor = getActivity().getContentResolver().query(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//access the database
dbCreate = new DBCreater(getActivity());
}
#Override
public void onClick(View v) {
displayNextAlert();
}
LogCat:
7214): FATAL EXCEPTION: main
11-15 07:15:38.215: E/AndroidRuntime(27214): java.lang.RuntimeException: Unable to resume activity {com.example.abcd/com.example.abcd.MainActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=android:fragment:0, request=1, result=-1, data=Intent { (has extras) }} to activity {com.example.abcd/com.example.abcd.MainActivity}: java.lang.NullPointerException
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2919)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2948)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2354)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.app.ActivityThread.access$700(ActivityThread.java:159)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.os.Handler.dispatchMessage(Handler.java:99)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.os.Looper.loop(Looper.java:176)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.app.ActivityThread.main(ActivityThread.java:5419)
11-15 07:15:38.215: E/AndroidRuntime(27214): at java.lang.reflect.Method.invokeNative(Native Method)
11-15 07:15:38.215: E/AndroidRuntime(27214): at java.lang.reflect.Method.invoke(Method.java:525)
11-15 07:15:38.215: E/AndroidRuntime(27214): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
11-15 07:15:38.215: E/AndroidRuntime(27214): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
11-15 07:15:38.215: E/AndroidRuntime(27214): at dalvik.system.NativeStart.main(Native Method)
11-15 07:15:38.215: E/AndroidRuntime(27214): Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=android:fragment:0, request=1, result=-1, data=Intent { (has extras) }} to activity {com.example.abcd/com.example.abcd.MainActivity}: java.lang.NullPointerException
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.app.ActivityThread.deliverResults(ActivityThread.java:3500)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2906)
11-15 07:15:38.215: E/AndroidRuntime(27214): ... 12 more
11-15 07:15:38.215: E/AndroidRuntime(27214): Caused by: java.lang.NullPointerException
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1147)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.content.ContentResolver.query(ContentResolver.java:401)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.content.ContentResolver.query(ContentResolver.java:360)
11-15 07:15:38.215: E/AndroidRuntime(27214): at com.example.abcd.NewPetsFragment.getPath(NewPetsFragment.java:155)
11-15 07:15:38.215: E/AndroidRuntime(27214): at com.example.abcd.NewPetsFragment.onActivityResult(NewPetsFragment.java:143)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.app.Activity.dispatchActivityResult(Activity.java:5567)
11-15 07:15:38.215: E/AndroidRuntime(27214): at android.app.ActivityThread.deliverResults(ActivityThread.java:3496)
11-15 07:15:38.215: E/AndroidRuntime(27214): ... 13 more
Edited:
I changed OnActivityResult() like this:
if(data!=null) {
Bitmap thePic = (Bitmap) data.getExtras().get("data");
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity().getBaseContext());
String filename = preferences.getString("file_name", ""); // value to retrieve
String path = Environment.getExternalStorageDirectory()+"/PetSitter/Pet Images/" + filename;
img.setImageURI(Uri.parse(path.toString()));
} else {
// In createNewFile, make sure you already saved the filename (prefix+System.currentTimeMillis()+".jpg"), for example, to sharedpreferences then get the filename and apply in path
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity().getBaseContext());
String filename = preferences.getString("file_name", ""); // value to retrieve
String path = Environment.getExternalStorageDirectory()+"/PetSitter/Pet Images/" + filename;
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inSampleSize = 1;
Bitmap bmp = BitmapFactory.decodeFile(path, bfo);
img.setImageBitmap(bmp);
}
It's seems to be working with image preview and everything. But what do thing? Is it a good practice to do? and how will be the memory usage by using like this?
In OnActivityResult():
if(data!=null) {
Bitmap thePic = (Bitmap) data.getExtras().get("data");
img.setImageBitmap(thePic);
} else {
// In createNewFile, make sure you already saved the filename (prefix+System.currentTimeMillis()+".jpg"), for example, to sharedpreferences then get the filename and apply in path
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity().getBaseContext());
String filename = preferences.getString("file_name", ""); // value to retrieve
String path = Environment.getExternalStorageDirectory()+"/test1/" + filename;
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inSampleSize = 1;
Bitmap bmp = BitmapFactory.decodeFile(path, bfo);
img.setImageBitmap(bmp);
}
In createNewFile
private File createNewFile(String prefix){
if(prefix==null || "".equalsIgnoreCase(prefix)){
prefix="IMG_";
}
File newDirectory = new File(Environment.getExternalStorageDirectory()+"/test1/");
if(!newDirectory.exists()){
if(newDirectory.mkdir()){
Log.d(this.getClass().getName(), newDirectory.getAbsolutePath()+" directory created");
}
}
// modifications applied here
long mDate = System.currentTimeMillis();
File file = new File(newDirectory,(prefix+mDate+".jpg"));
String filename = prefix+mDate+".jpg";
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity().getBaseContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putString("file_name", filename); // value to store
editor.commit();
if(file.exists()){
//this wont be executed
file.delete();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
Uri selectedImageURI = data.getData();
imageFile = new File(getRealPathFromURI(selectedImageURI));
And
private String getRealPathFromURI(Uri contentURI) {
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file path
return contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}
}
Try this in onActivityResult
Bitmap photo = (Bitmap) data.getExtras().get("data");
img.setImageBitmap(photo);
I changed OnActivityResult() like this:
if(data!=null) {
Bitmap thePic = (Bitmap) data.getExtras().get("data");
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity().getBaseContext());
String filename = preferences.getString("file_name", ""); // value to retrieve
String path = Environment.getExternalStorageDirectory()+"/PetSitter/Pet Images/" + filename;
img.setImageURI(Uri.parse(path.toString()));
} else {
// In createNewFile, make sure you already saved the filename (prefix+System.currentTimeMillis()+".jpg"), for example, to sharedpreferences then get the filename and apply in path
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity().getBaseContext());
String filename = preferences.getString("file_name", ""); // value to retrieve
String path = Environment.getExternalStorageDirectory()+"/PetSitter/Pet Images/" + filename;
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inSampleSize = 1;
Bitmap bmp = BitmapFactory.decodeFile(path, bfo);
img.setImageBitmap(bmp);
}
It's seems to be working with image preview and everything.
I'm trying to implement Android-wheel, a library that I can use to imitate a slot machine.
The demo project works fine, it use's android's own drawables => android.R.drawable.*
However when I change the default images to the ones I want it gives me this error :
java.lang.IllegalArgumentException: Cannot draw recycled bitmaps
All I changed was the id's array which contains the reference to the images
from
private final int items[] = new int[] {
android.R.drawable.star_big_on,
android.R.drawable.stat_sys_warning,
android.R.drawable.radiobutton_on_background,
android.R.drawable.ic_delete
};
to
private final int items[] = new int[] {
R.drawable.sunglasses, R.drawable.ball, R.drawable.box};
Here's the rest of the code.
private class SlotMachineAdapter extends AbstractWheelAdapter {
// Image size
final int IMAGE_WIDTH = 267;
final int IMAGE_HEIGHT = 200;
// Slot machine symbols
private final int items[] = new int[] {
R.drawable.sunglasses, R.drawable.ball, R.drawable.box};
// Cached images
private List<SoftReference<Bitmap>> images;
// Layout inflater
private Context context;
/**
* Constructor
*/
public SlotMachineAdapter(Context context) {
this.context = context;
images = new ArrayList<SoftReference<Bitmap>>(items.length);
for (int id : items) {
images.add(new SoftReference<Bitmap>(loadImage(id)));
}
}
/**
* Loads image from resources
*/
private Bitmap loadImage(int id) {
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), id);
Bitmap scaled = Bitmap.createScaledBitmap(bitmap, IMAGE_WIDTH, IMAGE_HEIGHT, true);
bitmap.recycle();
return scaled;
}
#Override
public int getItemsCount() {
return items.length;
}
// Layout params for image view
final LayoutParams params = new LayoutParams(IMAGE_WIDTH, IMAGE_HEIGHT);
#Override
public View getItem(int index, View cachedView, ViewGroup parent) {
ImageView img;
if (cachedView != null) {
img = (ImageView) cachedView;
} else {
img = new ImageView(context);
}
img.setLayoutParams(params);
SoftReference<Bitmap> bitmapRef = images.get(index);
Bitmap bitmap = bitmapRef.get();
if (bitmap == null) {
bitmap = loadImage(items[index]);
images.set(index, new SoftReference<Bitmap>(bitmap));
}
img.setImageBitmap(bitmap);
return img;
}
}
Here's the full stacktrace
java.lang.IllegalArgumentException: Cannot draw recycled bitmaps
at android.view.GLES20Canvas.drawBitmap(GLES20Canvas.java:778)
at android.view.GLES20RecordingCanvas.drawBitmap(GLES20RecordingCanvas.java:117)
at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:393)
at android.widget.ImageView.onDraw(ImageView.java:961)
at android.view.View.draw(View.java:13765)
at android.view.View.draw(View.java:13649)
at android.view.ViewGroup.drawChild(ViewGroup.java:2940)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2810)
at android.view.View.draw(View.java:13768)
at kankan.wheel.widget.WheelView.drawItems(WheelView.java:587)
at kankan.wheel.widget.WheelView.onDraw(WheelView.java:557)
android.view.View.draw(View.java:13765)
at android.view.View.getDisplayList(View.java:12716)
at android.view.View.getDisplayList(View.java:12760)
at android.view.View.draw(View.java:13489)
at android.view.ViewGroup.drawChild(ViewGroup.java:2940)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2810)
at android.view.View.getDisplayList(View.java:12714)
at android.view.View.getDisplayList(View.java:12760)
at android.view.View.draw(View.java:13489)
at android.view.ViewGroup.drawChild(ViewGroup.java:2940)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2810)
at android.view.View.draw(View.java:13768)
at android.view.View.getDisplayList(View.java:12716)
at android.view.View.getDisplayList(View.java:12760)
at android.view.View.draw(View.java:13489)
at android.view.ViewGroup.drawChild(ViewGroup.java:2940)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2810)
at android.view.View.getDisplayList(View.java:12714)
at android.view.View.getDisplayList(View.java:12760)
at android.view.View.draw(View.java:13489)
at android.view.ViewGroup.drawChild(ViewGroup.java:2940)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2810)
at android.view.View.getDisplayList(View.java:12714)
at android.view.View.getDisplayList(View.java:12760)
at android.view.View.draw(View.java:13489)
at android.view.ViewGroup.drawChild(ViewGroup.java:2940)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2810)
at android.view.View.draw(View.java:13768)
at android.widget.FrameLayout.draw(FrameLayout.java:467)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2394)
at android.view.View.getDisplayList(View.java:12716)
at android.view.View.getDisplayList(View.java:12760)
at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1144)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2267)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2139)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1950)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4464)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
at android.view.Choreographer.doCallbacks(Choreographer.java:555)
at android.view.Choreographer.doFrame(Choreographer.java:525)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4895) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761) at dalvik.system.NativeStart.main(Native Method)
I think it is beacause you do bitmap.recycle() too frequently,while the system.gc() is not timely called,so variable bitmap is recycle(), but not really cleared by the system, we can't use it to load the new image. so, just comment bitmap.recycle(),Let the system recycle the gabage by itself.
Try with this -
if(bitmap!=null)
{
bitmap.recycle();
bitmap=null;
}
OK, I am developing an android application that takes a photo using the camera, then uses that image in an ImageView.
The problem that I'm having is that I keep getting an java.lang.OutOfMemoryError exception when I try and load the image.
Code to start camera intent:
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
AlertDialog.Builder builder = new AlertDialog.Builder(AddVehicleActivity.this);
builder.setTitle("Select A Method");
builder.setItems(R.array.array_PhotoMethods, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch(which) {
case 0 :
IMAGE_LOCATION = Utility.setFileName(_session); //Returns image path
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(IMAGE_LOCATION)));
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
break;
}
}
});
builder.show();
}
});
From my understanding, this will allow the image to be saved at the full resolution of the camera which I can confirm through the image details in the gallery. Using my Samsung SIII, my image is about 3.3MB. So, I am able to use the camera and store the image I take using the camera to path I specify. The problem comes when trying to use the image.
To load the image, I use the following:
public static Bitmap Shrink(String file, int width, int height) {
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);
if (heightRatio > 1 || widthRatio > 1) {
bmpFactoryOptions.inSampleSize = (heightRatio > widthRatio) ? heightRatio : widthRatio;
}
return BitmapFactory.decodeFile(file, bmpFactoryOptions);
}
I have rewritten this functions a few different ways and found out that sometimes, I get the memory error when calling BitmapFactory.decodeFile
My stack trace looks like this:
E/dalvikvm-heap(8355): Out of memory on a 31961104-byte allocation.
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:619)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:385)
at com.autopilot.com.objects.Images.Shrink(Images.java:191)
at com.autopilot.com.adapters.ImageAdapter.getView(ImageAdapter.java:90)
at android.widget.AbsListView.obtainView(AbsListView.java:2437)
at android.widget.GridView.onMeasure(GridView.java:1030)
at android.view.View.measure(View.java:15395)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4826)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1396)
at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1038)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:576)
at android.view.View.measure(View.java:15395)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4826)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1396)
at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1038)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:576)
at android.view.View.measure(View.java:15395)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4826)
at android.widget.LinearLayout.forceUniformWidth(LinearLayout.java:926)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:906)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
at android.view.View.measure(View.java:15395)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:617)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:399)
at android.view.View.measure(View.java:15395)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4826)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at android.view.View.measure(View.java:15395)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:833)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
at android.view.View.measure(View.java:15395)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4826)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2362)
at android.view.View.measure(View.java:15395)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1985)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1226)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1399)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1119)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4553)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
at android.view.Choreographer.doCallbacks(Choreographer.java:555)
at android.view.Choreographer.doFrame(Choreographer.java:525)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4950)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771)
at dalvik.system.NativeStart.main(Native Method)
From tracing this through, the memory exception occurs anytime that the original bitmap is loaded. I cannot find a way to set the saved image size and when I try to save the bitmap from the intent extras, it's never big enough, usually thumb nail size.
Any help would be greatly appreciated!
OK, I found the answer, thank you sunil!
public static Bitmap Shrink(String file, int width, int height) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file, options);
options.inSampleSize = calcSize(options, width, height);
options.inJustDecodeBounds = false;
Bitmap bmp = BitmapFactory.decodeFile(file, options);
return bmp;
}
public static int calcSize(BitmapFactory.Options options, int width, int height) {
final int uHeight = options.outHeight;
final int uWidth = options.outWidth;
int inSampleSize = 1;
if (uHeight > height || uWidth > width) {
if (uWidth > uHeight) {
inSampleSize = Math.round((float) uHeight / (float) height);
} else {
inSampleSize = Math.round((float) uWidth / (float) width);
}
}
return inSampleSize;
}