I choose a file from gallery or camera. Then I'll upload them to the server. But I can't reduce their size. Image quality does not matter. Can you tell me the best method? I'm a beginner and I don't know how to use the code. So please give details.
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.myapplication.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) {
Glide.with(this).load(currentPhotoPath).into(iv);
} else if (requestCode == SELECT_A_PHOTO && resultCode == RESULT_OK){
selectedPhoto = data.getData();
Glide.with(this).load(selectedPhoto).into(iv);
}
private void galleryIntent()
{
Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i,SELECT_A_PHOTO);
}
My file sizes look like this
I found the answer.This method allows you to reduce the size.
// Get the data from an ImageView as bytes
imageView.setDrawingCacheEnabled(true);
imageView.buildDrawingCache();
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] data = baos.toByteArray();
New image size
This function takes in the image path and converts into a bitmap. 700 is the basic threshold for height/width set by me here. You can change it accordingly and create a scaled bitmap (The lower the number, lower is the image size). Each iteration of the while loop reduces the image to half. You can remodify it as per your requirement.
private Bitmap reduce_image_to_bitmap(String file_path){
Bitmap bit_map = BitmapFactory.decodeFile(file_path);
int h = bit_map.getHeight();
int w = bit_map.getWidth();
while(h > 700 || w > 700){
h = h/2;
w = w/2;
}
Bitmap out = Bitmap.createScaledBitmap(bit_map, w, h, false);
return out;
}
Make sure to convert the bitmap to a file and then proceed to send the file to your server.
Use this library: Compressor
Compressor is a lightweight and powerful android image compression library. Compressor will allow you to compress large photos into smaller sized photos with very less or negligible loss in quality of the image.
First of all you need to process this image so that you can reduce the size but quality you can maintain. You need to run a background task so that during big image process device doesn't fizz.
Then you can show a progress dialog during this process just add this code into your onCreate activity.
public ProgressDialog progressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressDialog = new ProgressDialog(MyProfileEidtActivity.this);
progressDialog.setMessage("Loading ...");
// just execute this process
new ImageProcessing().execute("YOUR IMAGE PATH");
}
public class ImageProcessing extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setMessage("Image Processing");
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected String doInBackground(String... strings) {
Bitmap mainImage = null;
Bitmap converetdImage = null;
ByteArrayOutputStream bos = null;
byte[] bt = null;
String encodeString = null;
try {
mainImage = BitmapFactory.decodeFile(strings[0]);
/// 500 means image size will be maximum 500 kb
converetdImage = getResizedBitmap(mainImage, 500);
bos = new ByteArrayOutputStream();
converetdImage.compress(Bitmap.CompressFormat.JPEG, 50, bos);
bt = bos.toByteArray();
encodeString = Base64.encodeToString(bt, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return encodeString;
}
#Override
protected void onPostExecute(String image) {
super.onPostExecute(s);
progressDialog.dismiss();
// this image will be your reduced image path
}
}
public Bitmap getResizedBitmap(Bitmap image, int maxSize) {
int width = image.getWidth();
int height = image.getHeight();
float bitmapRatio = (float) width / (float) height;
if (bitmapRatio > 1) {
width = maxSize;
height = (int) (width / bitmapRatio);
} else {
height = maxSize;
width = (int) (height * bitmapRatio);
}
return Bitmap.createScaledBitmap(image, width, height, true);
}
Related
My code implements TFlite and I have two classes:
1) Deals with camera activity and processing of image
2) Deals with specifics of the model and detector.
I have a method in the extended class which runs the model.
I am trying to call that method from within the main class. I am new to Java so I don't quite know why I keep getting java.lang.NullPointerException error.
See code below (I will leave lots of white-space and comment around the pieces that are relevant):
Method which makes the call:
// Class was called
Classifier classifier;
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Called when image was captured from camera
// ...
// Obtains bitmap image from camera and processes it to a new Bitmap variable: rotatedBitmap
// ...
/* Here is where the issue begins.
I can obtain the processed image and set it to my ImageView no problem, so the variable rotatedBitmap
is NOT null. But when I try to pass it to classifier.recognizeImage() it throws the null pointer error
and crashes the app
*/
if (resultCode == RESULT_OK) {
// Set the image captured to our ImageView
mImageView.setImageBitmap(rotatedBitmap);
if (rotatedBitmap != null) {
float[][] result = classifier.recognizeImage(rotatedBitmap); // Says that rotatedBitmap is null
// Display results
String message = Arrays.toString(result[0]);
Snackbar mySnackbar = Snackbar.make(findViewById(R.id.myCoordinatorLayout), message,
Snackbar.LENGTH_SHORT);
mySnackbar.show();
}
}
}
Full Code:
public class CameraActivity extends AppCompatActivity {
private static final int PERMISSION_CODE = 1000;
private static final int IMAGE_CAPTURE_CODE = 1001;
Classifier classifier;
Button mCaptureBtn;
ImageView mImageView;
Uri image_uri;
public Bitmap rotatedBitmap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = findViewById(R.id.image_view);
mCaptureBtn = findViewById(R.id.capture_image_btn);
mCaptureBtn.setOnClickListener(new View.OnClickListener() {
// 1: Create the button
// 2: Create an instance of OnClickListener to wait for the click
// 3: Override the onClick method
#Override
public void onClick(View v) {
// If the operating system is newer or equal to Marshmello
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Check for permissions
if (checkSelfPermission(Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_DENIED ||
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
PackageManager.PERMISSION_DENIED) {
// Permission not enables so request it
String[] permission = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permission, PERMISSION_CODE);
} else {
// Permission already granted
openCamera();
}
} else {
openCamera();
}
}
});
}
private void openCamera() {
// ContentValues creates a set-type object that can store values that ContentResolver can access
ContentValues values = new ContentValues();
// Store values
values.put(MediaStore.Images.Media.TITLE, "New Picture");
values.put(MediaStore.Images.Media.DESCRIPTION, "From the camera");
// Obtain the uri(uniform resource identifier) using the ContentValues previously made
image_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
// Camera intent
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// The EXTRA_OUTPUT constraint outputs the full-sized image data to the uri
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri);
if (cameraIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(cameraIntent, IMAGE_CAPTURE_CODE);
}
}
// Handling permission request
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
// THis method is called whenever the user presses allow or deny from the Perm Req prompt
switch (requestCode){
case PERMISSION_CODE:{
if (grantResults.length > 0 && grantResults[0] ==
PackageManager.PERMISSION_GRANTED) {
// permission from popup was granted
openCamera();
}
else {
// permission from popup was denied
Toast.makeText(this, "Permission denied...", Toast.LENGTH_SHORT).show();
}
}
}
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Called when image was captured from camera
// Obtain the image from the uri
Bitmap bitmap = null;
int orientation;
// Make sure we have an image_uri
try {
// Convert uri to an InputStream
InputStream in = getContentResolver().openInputStream(image_uri);
// Obtain Exif info from the InputStream
ExifInterface ei = new ExifInterface(in);
// Get bitmap depending on version
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
try {
bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(getContentResolver(), image_uri));
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), image_uri);
} catch (IOException e) {
e.printStackTrace();
}
}
// Obtain orientation information from image
orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
// Rotate the image (if needed) to portrait mode
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotatedBitmap = rotateImage(bitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotatedBitmap = rotateImage(bitmap, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotatedBitmap = rotateImage(bitmap, 270);
break;
case ExifInterface.ORIENTATION_NORMAL:
default:
rotatedBitmap = bitmap;
}
}
catch (IOException e) {
e.printStackTrace();
}
/* Here is where the issue begins.
I can obtain the processed image and set it to my ImageView no problem, so the variable rotatedBitmap
is NOT null. But when I try to pass it to classifier.recognizeImage() it throws the null pointer error
and crashes the app
*/
if (resultCode == RESULT_OK) {
// Set the image captured to our ImageView
//mImageView.setImageURI(image_uri);
mImageView.setImageBitmap(rotatedBitmap);
if (rotatedBitmap != null) {
float[][] result = classifier.recognizeImage(rotatedBitmap);
String message = Arrays.toString(result[0]);
Snackbar mySnackbar = Snackbar.make(findViewById(R.id.myCoordinatorLayout), message,
Snackbar.LENGTH_SHORT);
mySnackbar.show();
}
}
}
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
}
}
public class Classifier extends CameraActivity {
private int inputSize = 300;
private int pixelSize = 3;
private int imageMean = 0;
private float imageStd = 255.0f;
private int maxResult = 3;
private float threshHold = 0.4f;
private List<String> labelList;
private Interpreter interpreter;
public static final String PREFIX = "stream2file";
public static final String SUFFIX = ".tmp";
public File stream2file (InputStream in) throws IOException {
final File tempFile = File.createTempFile(PREFIX, SUFFIX);
tempFile.deleteOnExit();
try (FileOutputStream out = new FileOutputStream(tempFile)) {
IOUtils.copy(in, out);
}
return tempFile;
}
public void init() {
Interpreter.Options options = new Interpreter.Options();
options.setNumThreads(5);
options.setUseNNAPI(true);
// Obtain the model from assets folder
final AssetManager assets = getApplicationContext().getAssets();
try {
InputStream in = assets.open("detect.tflite");
File file = stream2file(in);
interpreter = new Interpreter(file, options);
labelList = loadLabels("labelmap.txt", assets);
} catch (IOException e) {
e.printStackTrace();
}
}
public List loadLabels(String labelPath, AssetManager assetManager) throws IOException {
InputStream in = assetManager.open("labelmap.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
List outList = new ArrayList();
String line;
while( (line = br.readLine()) != null)
{
outList.add(line);
}
return outList;
}
/*
Here is the recognizeImage method that I wish to call from the CameraActivity class.
-
-
-
*/
public float[][] recognizeImage(final Bitmap bitmap) {
// Scale the bitmap to the appropriate shape
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, inputSize, inputSize, false);
ByteBuffer byteBuffer = convertBitmapToByteBuffer(scaledBitmap);
final float[][] result = new float[1][labelList.size()];
interpreter.run(byteBuffer, result);
return result;
}
public ByteBuffer convertBitmapToByteBuffer(Bitmap bitmap) {
//bitmap = Bit
// Preallocate memory for bytebuffer
ByteBuffer byteBuffer = ByteBuffer.allocate(4*inputSize*inputSize*pixelSize);
byteBuffer.order(ByteOrder.nativeOrder());
// Initialize pixel data array and populate from bitmap
int [] intArray = new int[inputSize*inputSize];
bitmap.getPixels(intArray, 0, bitmap.getWidth(), 0 , 0,
bitmap.getWidth(), bitmap.getHeight());
int pixel = 0; // pixel indexer
for (int i=0; i<inputSize; i++) {
for (int j=0; j<inputSize; j++) {
int input = intArray[pixel++];
byteBuffer.putFloat((((input >> 16 & 0x000000FF) - imageMean) / imageStd));
byteBuffer.putFloat((((input >> 8 & 0x000000FF) - imageMean) / imageStd));
byteBuffer.putFloat((((input & 0x000000FF) - imageMean) / imageStd));
}
}
return byteBuffer;
}
}
Change Classifier so that it does not extend anything.
Initialize this object with:
Classifier classifier = new Classifier();
classifier.init();
before you call the method you need.
I'm trying to load pictures taken with build-in camera in LG G8 phone.
Code works for front camera, but throws Null Pointer Exception if I switch it to back.
static final int DESIRED_WIDTH = 640;
static final int DESIRED_HIGH = 480;
private Bitmap retrieveBitmap(){
// Get the dimensions of the bitmap
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
//decode only size
bitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(currentPhotoPath, bitmapOptions);
//returns 0 x 0
int photoW = bitmapOptions.outWidth;
int photoH = bitmapOptions.outHeight;
// Determine how much to scale down the image
float scaleFactor = Math.min( (float) photoW/ (float) DESIRED_WIDTH,
(float) photoH/ (float) DESIRED_HIGH);
// Decode the image file into a Bitmap of given size
bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
bitmapOptions.inJustDecodeBounds = false;
bitmapOptions.inSampleSize = (int) scaleFactor;
//returns null
Bitmap bitmap = BitmapFactory.decodeFile(currentPhotoPath, bitmapOptions);
return bitmap;
}
Camera app is invoked as in this example using "Save the full-size photo" method. Android reports NullPointerException after first call to BitmapFactory.decodeFile() as if file produced from main camera didn't exist.
E/BitmapFactory: Unable to decode stream: java.lang.NullPointerException
A while ago i too used the guide that you mentioned to be able to use the phone camera to take photos and save them.
The code below activates the phone camera on a button click and allowes both front and back camara to take a photo, then procede to save them. It also displays the photo taken in a ImageView. Hope it helps.
public class MainActivity extends AppCompatActivity {
static final int REQUEST_IMAGE_CAPTURE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
galleryAddPic();
ImageView img = findViewById(R.id.img);
Bitmap bitm = BitmapFactory.decodeFile(mCurrentPhotoPath);
img.setImageBitmap(bitm);
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
ex.printStackTrace();
}
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider", photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
String mCurrentPhotoPath;
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
private void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
public void cameraClick(View v){
dispatchTakePictureIntent();
}
}
Answering my own question:
turns out phone needs some time before large pictures are accessible. Adding a wait loop makes it work:
private Bitmap retrieveBitmap(){
// Get the dimensions of the bitmap
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
//decode only size
bitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(currentPhotoPath, bitmapOptions);
int i = 0;
while( bitmapOptions.outWidth == 0 && bitmapOptions.outHeight == 0){
//wait for 4 seconds for resource to be available, otherwise fail
try{
wait(1000);
}catch (Exception ex){
ex.printStackTrace();
return null;
}
BitmapFactory.decodeFile(currentPhotoPath, bitmapOptions);
i++;
//give up trying
if( i == 4) break;
}
//returns 0 x 0
int photoW = bitmapOptions.outWidth;
int photoH = bitmapOptions.outHeight;
// Determine how much to scale down the image
float scaleFactor = Math.min( (float) photoW/ (float) DESIRED_WIDTH,
(float) photoH/ (float) DESIRED_HIGH);
// Decode the image file into a Bitmap of given size
bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
bitmapOptions.inJustDecodeBounds = false;
bitmapOptions.inSampleSize = (int) scaleFactor;
return BitmapFactory.decodeFile(currentPhotoPath, bitmapOptions);
}
Please pardon any bad English as this is my first time posting question on stackoverflow.
I would like to create a OCR Android Application using tesseract OCR engine and faced the following error, I have tried to search around but however did not find any solution, would appreciate your help. Thanks.
Codes I am trying:
TessBaseAPI baseApi = new TessBaseAPI();
baseApi.init(Environment.getExternalStorageDirectory().toString()+"/", `"eng");`
I have already created a tessdata folder in my device root with the eng.traineddata file inside, but I was prompted the following error when I access the function.
Could not initialize Tesseract API with language=eng!
I am using Android 6.0.1, API 23
Would appreciate any help! Thanks in advance~
Try this code out . It allows you to take a picture and displays the text .There are minor bugs in this code .Try this code on letters typed in notepad
Ignore the various files being placed in the tessdata folder . I am trying to read maths equation hence i need those . I have commented out the other files, it shouldn't bother you. If you are willing to try , try Mobile Vision API.
Hope this helps :)
public class MainActivity extends AppCompatActivity {
String imgPath;
Bitmap imgBitmap;
Uri imgUri;
InputStream trainDataInputStream;
OutputStream trainDataOutputStream;
AssetManager assetManager;
String externalDataPath;
TextView t;
String[] fileToBeCopied = {"eng.cube.bigrams", "eng.cube.fold", "eng.cube.lm", "eng.cube.nn", "eng.cube.params", "eng.cube.size", "eng.cube.word-freq", "eng.tesseract_cube.nn", "eng.traineddata","equ.traineddata"};
ProgressDialog pDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t = (TextView) findViewById(R.id.text);
new CopyFile().execute();
//placeFileFromAssetsToExternalStorage();
takePicture();
}
class CopyFile extends AsyncTask {
#Override
protected void onPreExecute() {
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Fetching image...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Object doInBackground(Object[] objects) {
//placeFileFromAssetsToExternalStorage(fileToBeCopied[0]);
//placeFileFromAssetsToExternalStorage(fileToBeCopied[1]);
//placeFileFromAssetsToExternalStorage(fileToBeCopied[2]);
//placeFileFromAssetsToExternalStorage(fileToBeCopied[3]);
//placeFileFromAssetsToExternalStorage(fileToBeCopied[4]);
//placeFileFromAssetsToExternalStorage(fileToBeCopied[5]);
//placeFileFromAssetsToExternalStorage(fileToBeCopied[6]);
//placeFileFromAssetsToExternalStorage(fileToBeCopied[7]);
placeFileFromAssetsToExternalStorage(fileToBeCopied[8]);
//placeFileFromAssetsToExternalStorage(fileToBeCopied[9]);
return null;
}
#Override
protected void onPostExecute(Object o) {
pDialog.dismiss();
}
}
private void takePicture() {
File photoFile = null;
Intent iPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (iPicture.resolveActivity(getPackageManager()) != null) {
try {
photoFile = createImageFile();
} catch (Exception e) {
e.printStackTrace();
}
//if photo file is created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(getApplicationContext(), "com.scorpio.fileprovider", photoFile);
System.out.println(imgPath);
iPicture.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(iPicture, 1);
}
}
}
private File createImageFile() {
File imgFile = null;
String fileStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File storageDir = Environment.getExternalStorageDirectory();
try {
imgFile = File.createTempFile(fileStamp, ".jpeg", storageDir);
} catch (IOException e) {
e.printStackTrace();
}
imgPath = imgFile.getAbsolutePath();
return imgFile;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1 && resultCode == RESULT_OK) {
galleryAddPic();
}
}
private void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(imgPath);
System.out.println("Image path ->" + imgPath);
Uri contentUri = Uri.fromFile(f);
imgUri = contentUri;
System.out.println("Image uri " + imgUri);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
ocrImage();
}
public void ocrImage() {
try {
//getting image for ocr
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
imgBitmap = BitmapFactory.decodeFile(imgPath, options);
} catch (Exception e) {
e.printStackTrace();
}
ExifInterface exif = null;
try {
exif = new ExifInterface(imgPath);
} catch (IOException e) {
e.printStackTrace();
}
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) {
int w = imgBitmap.getWidth();
int h = imgBitmap.getHeight();
// Setting pre rotate
Matrix mtx = new Matrix();
mtx.preRotate(rotate);
// Rotating Bitmap & convert to ARGB_8888, required by tess
imgBitmap = Bitmap.createBitmap(imgBitmap, 0, 0, w, h, mtx, false);
}
imgBitmap = imgBitmap.copy(Bitmap.Config.ARGB_8888, true);
TessBaseAPI baseApi = new TessBaseAPI();
baseApi.init(externalDataPath, "eng");
baseApi.setImage(imgBitmap);
String ocrResult = baseApi.getUTF8Text();
System.out.println(ocrResult);
baseApi.end();
t.setText(ocrResult);
}
public void placeFileFromAssetsToExternalStorage(String filename) {
System.out.println("Running DataRunnable class ");
assetManager = getResources().getAssets();
externalDataPath = Environment.getExternalStorageDirectory() + "/tessdata";
System.out.println("external data path " + externalDataPath);
//creating eng.trainedData
File f = new File(externalDataPath);
try {
if (!f.exists()) {
f.mkdir();
}
externalDataPath = externalDataPath + "/" + filename;
f = new File(externalDataPath);
if (!f.exists())
f.createNewFile();
externalDataPath = Environment.getExternalStorageDirectory().toString();
trainDataInputStream = assetManager.open(filename);
trainDataOutputStream = new FileOutputStream(f);
byte[] buffer = new byte[1024];
int read;
while ((read = trainDataInputStream.read(buffer)) != -1) {
trainDataOutputStream.write(buffer, 0, read);
}
trainDataOutputStream.flush();
trainDataOutputStream.close();
trainDataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I am working on a project where i click on a button which opens the camera and takes a picture and on coming back to the project it is shown in an imageview.I am saving the image onto a file and when i open the image from my phone's directory it is shown as a big size.How do i make the image shown bigger in the imageview?
The code:
btncamera.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
captureImage();
}
});
private void captureImage() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// if the result is capturing Image
if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
if (resultCode ==getActivity().RESULT_OK) {
// successfully captured the image
// display it in image view
//image_uri=data.getData().toString();
previewCapturedImage();
} else if (resultCode == getActivity().RESULT_CANCELED) {
// user cancelled Image capture
image_path=null;
Toast.makeText(getActivity(),
"User cancelled image capture", Toast.LENGTH_SHORT)
.show();
} else {
// failed to capture image
Toast.makeText(getActivity(),
"Sorry! Failed to capture image", Toast.LENGTH_SHORT)
.show();
}
}
}
private void previewCapturedImage() {
try {
// bimatp factory
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),options);
ExifInterface exif = null;
try {
exif = new ExifInterface(fileUri.getPath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer.parseInt(orientString) : ExifInterface.ORIENTATION_NORMAL;
int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) rotationAngle = 90;
if (orientation == ExifInterface.ORIENTATION_ROTATE_180) rotationAngle = 180;
if (orientation == ExifInterface.ORIENTATION_ROTATE_270) rotationAngle = 270;
Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle, (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, options.outWidth, options.outHeight, matrix, true);
iv_preview.setImageBitmap(rotatedBitmap);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
public Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/*
* returning image / video
*/
private File getOutputMediaFile(int type) {
// External sdcard location
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY_NAME);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create "
+ IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
// Create a media file name
// String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
// Locale.getDefault()).format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
//change image_path file name required for marina with the name of the file
mediaFile = new File(mediaStorageDir.getPath()+File.separator+user_id+"_"+job_object.job_id+"_"+task_id+".jpg");
// if(mediaFile.exists())
// {
// mediaFile.delete();
// mediaFile = new File(mediaStorageDir.getPath()+File.separator+user_id+"_"+job_object.job_id+"_"+task_id+".jpg");
// }
//IF YOU MAKE CHANGE TO THE FILE NAME PATH ALSO CHANGE IN loadpreviousimage method
image_path=mediaStorageDir.getPath() + File.separator+user_id+"_"+job_object.job_id+"_"+task_id+".jpg";
} else {
return null;
}
return mediaFile;
}
Is it because of this line options.inSampleSize = 4;, that i am getting a small image?
How do i fix the issue?
Yes, inSampleSize if being >1 it will sub sample your image; used to downsize images who are quite large. Source here. And, you could use
android:scaleType="fitXY" in ImageView to fit your image in your ImageView
use this method for decode,
public Bitmap decodeFile(String path) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 70//put size you want;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE)
scale *= 2;
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeFile(path, o2);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
hope this will help you
I'm trying to encode an image to 64 base ,
after choosing the image from gallery and trying to save it I am getting this error:
outOfMemory Exception
can any one suggest how to to get this image to base 64 without memory error?
MotorImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent i = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, RESULT_LOAD_IMAGE);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) {
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
//
ImageView imageView = (ImageView) findViewById(R.id.imageView1);
imageView.setImageBitmap(BitmapFactory.decodeFile(picturePath));
String imageString = null;
try {
Bitmap bm = BitmapFactory.decodeFile(picturePath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); //bm is the bitmap object
bm.recycle();
byte[] b = baos.toByteArray();
imageString = Base64.encodeToString(b, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), imageString, Toast.LENGTH_SHORT).show();
I suspect you need to scale and resample your image to fit within the constraints on the device, try something like this
// decodes image and scales it to reduce memory consumption
private Bitmap decodeImage(String picturePath) {
try {
File file = new File(picturePath);
// Get image size
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(file), null, opts);
// The new size we want to scale to
final int MIN_SIZE = 70;
// Find the correct scale value.
int scale = 1;
while (((opts.outWidth / scale) >> 1) >= MIN_SIZE
&& ((opts.outHeight / scale) >> 1) >= MIN_SIZE) {
scale <<= 1;
}
BitmapFactory.Options opts2 = new BitmapFactory.Options();
opts2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(file), null, opts2);
} catch (FileNotFoundException e) {
}
return null;
}
Try to use android:largeHeap="true" inside the application tag on AndroidManifest, then your app will have more ram available and will not throw a oom exception.
If you read the official document of android you will come to know that this is a common issue with android and the recommended solution is to resize image according to your need. you can refer developer.android for this as well