I am creating a photo editing app and trying to capture a photo from android camera. I use following code onPictureTaken :
#Override
public void onPictureTaken(byte[] data, Camera camera) {
BitmapFactory.Options opt;
opt = new BitmapFactory.Options();
opt.inTempStorage = new byte[16 * 1024];
Parameters parameters = camera.getParameters();
Size size = parameters.getPictureSize();
int height11 = size.height;
int width11 = size.width;
float mb = (width11 * height11) / 1024000;
if (mb > 4f)
opt.inSampleSize = 4;
else if (mb > 3f)
opt.inSampleSize = 2;
Bitmap bitmapPicture = null;
bitmapPicture = BitmapFactory.decodeByteArray(data, 0, data.length,opt);
bitmapPicture=Bitmap.createScaledBitmap(bitmapPicture,(int)CaptureImage.screen_width,(int)CaptureImage.screen_height,false);
if(((CaptureImage)context).cameraType==1){
Matrix matrix = new Matrix();
if(((CaptureImage)context).screenType==0)
matrix.postRotate(180);
bitmapPicture = Bitmap.createBitmap(bitmapPicture, 0, 0,
bitmapPicture.getWidth(), bitmapPicture.getHeight(), matrix,
true);
}
// write captured image in sd card
new File(Constants.IMAGES_PATH).mkdirs();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
photoFile = "Picture_" + date + ".jpg";
File pictureFile = new File(Constants.IMAGES_PATH, photoFile);
imgUri = Uri.fromFile(pictureFile);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
bitmapPicture.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.write(data);
fos.close();
ExifInterface exif = new ExifInterface(pictureFile.getAbsolutePath());
if(((CaptureImage)context).screenType==0){
if(((CaptureImage)context).cameraType==0)
exif.setAttribute(ExifInterface.TAG_ORIENTATION,""+ExifInterface.ORIENTATION_ROTATE_90);
if(((CaptureImage)context).cameraType==1)
exif.setAttribute(ExifInterface.TAG_ORIENTATION,""+ExifInterface.ORIENTATION_ROTATE_90);
}
else{
//if(((CaptureImage)context).cameraType==0)
// exif.setAttribute(ExifInterface.TAG_ORIENTATION,""+ExifInterface.ORIENTATION_ROTATE_270);
// if(((CaptureImage)context).cameraType==1)
//exif.setAttribute(ExifInterface.TAG_ORIENTATION,""+ExifInterface.ORIENTATION_ROTATE_180);
}
exif.saveAttributes();
} catch (IOException exception) {
Log.v("Error", exception.getMessage());
}
Intent intent = new Intent(context, Home.class);
intent.putExtra(Constants.CAPTURED_IMAGE,imgUri);
context.startActivity(intent);
((Activity) context).finish();
}
Above code is working on all phones but on nexus 4 when I use this code image is not getting saved and a blank screen is shown.
Related
I'm building an android tesseract app. It was reading the data fine until I was taking photos from the default camera app. Now, I needed to implement my own custom camera, that caused it to start giving wrong result.
public class getButtonClicked implements View.OnClickListener{
public void onClick(View arg0) {
DATA_PATH = Environment.getExternalStorageDirectory().toString() + "/MyOCRApp/";
File tessdata = new File(DATA_PATH);
if (!tessdata.isDirectory()){
throw new IllegalArgumentException("Data path must contain subfolder tessdata!");
}
TessBaseAPI baseApi = new TessBaseAPI();
baseApi.setDebug(true);
baseApi.init(DATA_PATH, lang);
if (newImg == null){
baseApi.setImage(imageBitmap);
}
else{
baseApi.setImage(newImg);
}
String recognizedText = baseApi.getUTF8Text();
// 1. Instantiate an AlertDialog.Builder with its constructor
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// 2. Chain together various setter methods to set the dialog characteristics
builder.setMessage("Recognized Text:\n\n" + recognizedText);
// 3. Get the AlertDialog from create()
AlertDialog dialog = builder.create();
dialog.show();
//baseApi.end();
}
}
This is the code that calls the tesseract APIs.
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d("Error creating file" ,"!");
return;
}
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int screenHeight = getResources().getDisplayMetrics().heightPixels;
bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
// Notice that width and height are reversed
Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true);
int w = scaled.getWidth();
int h = scaled.getHeight();
// Setting post rotate to 90
Matrix mtx = new Matrix();
mtx.postRotate(90);
// Rotating Bitmap
MainActivity.imageBitmap = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true);
}else{// LANDSCAPE MODE
//No need to reverse width and height
Bitmap scaled = Bitmap.createScaledBitmap(bm, screenWidth,screenHeight , true);
MainActivity.imageBitmap = scaled;
}
Calendar c = Calendar.getInstance();
String time = Integer.toString(c.get(Calendar.DATE));
//MediaStore.Images.Media.insertImage(getContentResolver(), MainActivity.imageBitmap, time+"MyOCR", "Hello!!");
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/MyOCRApp");
if (! myDir.exists()){
if (! myDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return;
}
}
String fname = "Image-" +time+ ".jpg";
File file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
MainActivity.imageBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
} catch (Exception e) {
e.printStackTrace();
}
surfaceDestroyed(mSurfaceHolder);
}
};
This is the code in my camera class. I even debugged and checked that the picture was perfectly fine, when the tesseract APIs are called. I can't post photos, otherwise I have posted one. What should I do??
I am experimenting with tesseract on android as well. Try to rescale your image. An image taken by the camera activity maybe to big. Additionaly you probably have to pre-process the image (contrast, horizontal alignment of text, ...)
I inserted on my App a option to take a photo and save it on a directory.
But when I check the taken photo it appears turned. The horizontal photos appears vertical, and the vertical photos appears horizontal.
how can change my code and automatically rotate the photos?
My code:
if (options[item].equals("Take Photo"))
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(android.os.Environment.getExternalStorageDirectory(), "temp.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
startActivityForResult(intent, 1);
}
...
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
File f = new File(Environment.getExternalStorageDirectory().toString());
for (File temp : f.listFiles()) {
if (temp.getName().equals("temp.jpg")) {
f = temp;
break;
}
}
try {
Bitmap bitmap;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(),
bitmapOptions);
int nh = (int) ( bitmap.getHeight() * (612.0 / bitmap.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(bitmap, 612, nh, true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
scaled.compress(Bitmap.CompressFormat.JPEG, 90, stream);
byte [] byte_arr = stream.toByteArray();
String image_str = Base64.encodeBytes(byte_arr);
viewImage.setScaleType(ScaleType.CENTER);
viewImage.setImageBitmap(scaled);
task = new getinfo();
task.execute(image_str);
String path = android.os.Environment
.getExternalStorageDirectory()
+ File.separator
+ "Phoenix" + File.separator + "default";
f.delete();
OutputStream outFile = null;
File file = new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg");
try {
outFile = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, outFile);
outFile.flush();
outFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
This piece helped me to do the same task
private Bitmap rotateImage(String pathToImage) {
// 1. figure out the amount of degrees
int rotation = getImageRotation();
// 2. rotate matrix by postconcatination
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
// 3. create Bitmap from rotated matrix
Bitmap sourceBitmap = BitmapFactory.decodeFile(pathToImage);
return Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), matrix, true);
}
Also check this,this and this for more details.
I am trying to capture the preview of the camera on a surfaceview ,to save it as a JPEG in the internal memory. I found some code here on this site, that does mostly I want but saves the image to the SD Card. I changed that, and came up with the following code.
Camera.PreviewCallback mPrevCallback = new Camera.PreviewCallback()
{
#Override
public void onPreviewFrame( byte[] data, Camera Cam ) {
//Log.d(TAG, "FRAME");
Camera.Parameters parameters = Cam.getParameters();
int format = parameters.getPreviewFormat();
//Log.d(TAG, "FORMAT:" + format);
//YUV formats require more conversion
if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
int w = parameters.getPreviewSize().width;
int h = parameters.getPreviewSize().height;
// Get the YuV image
YuvImage yuv_image = new YuvImage(data, format, w, h, null);
// Convert YuV to Jpeg
Rect rect = new Rect(0, 0, w, h);
ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
yuv_image.compressToJpeg(rect, 100, output_stream);
byte[] byt = output_stream.toByteArray();
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream("/data/data/com.example.max.camtest/files/test"+System.currentTimeMillis()+".jpg");
outStream.write(byt);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
};
The preview is shown on the surfaceview and the mPrevCallback is triggered.It successfully saves pictures that have diffrent sizes (250~500Kb) but they are all black. When I try to capture a picture with the camera.takePicture function is it also black.
What Am I doing wrong? How can I debug this?
Thanks!
Use this intent to take picture
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(android.os.Environment.getExternalStorageDirectory(), AppInfo.getInstance().getCurrentLoginUserInfo().getId()+".jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
intent.putExtra("return-data", true);
startActivityForResult(intent, 1);
and on Your Activity Result.... Note Bitmap bitmap = getScaledBitmap(uri.getPath(), 200, true); 200 is your max image size.
if(requestCode == 1)
{
String base = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
final String imgPath = base + "/" +AppInfo.getInstance().getCurrentLoginUserInfo().getId()+".jpg";
File file = new File(imgPath);
if (file.exists())
{
Uri uri = Uri.fromFile(file);
Log.d(TAG, "Image Uri path: " + uri.getPath());
Bitmap bitmap = getScaledBitmap(uri.getPath(), 200, true);
}}
This method ll return image bitmap after resizing it-
private Bitmap getScaledBitmap(String imagePath, float maxImageSize, boolean filter) {
FileInputStream in;
BufferedInputStream buf;
try {
in = new FileInputStream(imagePath);
buf = new BufferedInputStream(in);
Bitmap realImage = BitmapFactory.decodeStream(buf);
float ratio = Math.min(
(float) maxImageSize / realImage.getWidth(),
(float) maxImageSize / realImage.getHeight());
int width = Math.round((float) ratio * realImage.getWidth());
int height = Math.round((float) ratio * realImage.getHeight());
Bitmap newBitmap = Bitmap.createScaledBitmap(realImage, width, height, filter);
return newBitmap;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Now you have scaled bitmap image.
Hope this ll help you.
I have an Android Camera application thats taken picture in portrait mode, The camera preview is fine ... but when i taken picture its saved in landscape mode ... its rotate 90 degrees : that my code onPictureTaken():
PictureCallback jpegCallback = new PictureCallback() {
#Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator
+ photoFile;
Log.e("path", filename.toString());
File pictureFile = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(arg0);
fos.close();
Bitmap bm = BitmapFactory.decodeFile(filename);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 90, bao);
byte[] ba = bao.toByteArray();
// sba1 = Base64.encodeBytes(ba);
int flag = 0; // you can pass the default 0 = Base64.DEFAULT
String ba1 = Base64.encodeToString(ba, flag);
// Log.e("base64", "-----" + ba1);
Toast.makeText(AndroidCamera.this,
"New Image saved 22222:" + photoFile, Toast.LENGTH_LONG)
.show();
Intent intent = new Intent(AndroidCamera.this,
UploadActivity.class);
fileUri = Uri.fromFile(pictureFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent,
CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
launchUploadActivity(true);
} catch (Exception error) {
// Log.d(MakePhotoActivity.DEBUG_TAG, "File" + filename +
// "not saved: "
// + error.getMessage());
Toast.makeText(AndroidCamera.this, "Image could not be saved.",
Toast.LENGTH_LONG).show();
}
}
};
You can rotate a bitmap 90 degrees like this:
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
In your specific example, you need to save it back to the original path:
Bitmap bm = BitmapFactory.decodeFile(filename);
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
FileOutputStream fos = new FileOutputStream(pictureFile);
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.close();
You can also use Camera.Parameters.setRotation()
I am creating a program that uses twice the takepicture function, like this:
mCamera.takePicture(null, null, mPicture);
But only once it enter the PictureCallback loop:
private PictureCallback mPicture = new PictureCallback(){
// Bitmap readyToGo;
#Override
public void onPictureTaken(byte[] data, Camera camera){
Log.d(TAG, "entrei no picture callback");
//-----OUT OF MEMORY ERROR
pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
mPreview.setDrawingCacheEnabled(true);
mPreview.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_AUTO);
BitmapFactory.Options options = new BitmapFactory.Options();
//options.inPurgeable = true;
//options.inInputShareable = true;
options.inJustDecodeBounds = true;
options.inSampleSize = 5;
options.inJustDecodeBounds = false;
Bitmap bitmap = mPreview.getDrawingCache();
//---------------------------------------------------
bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
//combine the two bitmaps!!!!-------------
Log.d("main", "antes overlay");
combination = overlay(bmp, bitmap);
Log.d("main", "depois overlay");
//------------------ROTATION---------------------
if(pictureFile == null)
{
Log.d(TAG, "Error creating media file, check storages permissions. ");
return;
}
try
{
ExifInterface exif = new ExifInterface(pictureFile.getAbsolutePath()); //Since API Level 5
String exifOrientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
Log.d("main", "exif orientation= "+exifOrientation);
FileOutputStream fos = new FileOutputStream(pictureFile);
Log.d(TAG, "ALO!!!");
combination.compress(CompressFormat.JPEG, 100, fos);//troquei bitmap por combination
fos.flush();
fos.close();
//------------------------------
clearBitmap(combination);
clearBitmap(bmp);
//------------------------------
}
catch(FileNotFoundException e)
{
Log.d(TAG, "File not found: "+e.getMessage());
}
catch(IOException e)
{
Log.d(TAG, "Error accessing file: "+e.getMessage());
}
}
};
Does anyobody know what happen, can I call it twice?
call thread to pause for 2 seconds and then recall it
or You can use your above code with this picture callback
public void takeSnapPhoto() {
camera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
int format = parameters.getPreviewFormat();
//YUV formats require more conversion
if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
int w = parameters.getPreviewSize().width;
int h = parameters.getPreviewSize().height;
// Get the YuV image
YuvImage yuv_image = new YuvImage(data, format, w, h, null);
// Convert YuV to Jpeg
Rect rect = new Rect(0, 0, w, h);
ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
yuv_image.compressToJpeg(rect, 100, output_stream);
byte[] byt = output_stream.toByteArray();
FileOutputStream outStream = null;
try {
// Write to SD Card
File file = createFileInSDCard(FOLDER_PATH, "Image_"+System.currentTimeMillis()+".jpg");
//Uri uriSavedImage = Uri.fromFile(file);
outStream = new FileOutputStream(file);
outStream.write(byt);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
}); }