I'm using Google's CameraPreview sample demo. Here, I have the cameraPreview, and an overlayed image over cameraPreview.
When I take the photo, only the cameraPreview is saved, but I need the overlay image to be saved too over the cameraPreview.
This is the way I save cameraPreview's photo, but I need to know what would be the best way for overlaying booth images and save them into one.
public void onPictureTaken(byte[] data, Camera camera) {
String photoPath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/miFoto.jpg";
try {
FileOutputStream fos = new FileOutputStream(photoPath);
fos.write(data);
fos.close();
} catch (IOException e) {
Toast.makeText(this, "Pic not saved", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(this, "Pic saved in: " + photoPath, Toast.LENGTH_SHORT).show();
camera.startPreview();
}
I finally made it this way:
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap cameraBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap cameraScaledBitmap = Bitmap.createScaledBitmap(cameraBitmap, 1280, 720, true);
int wid = cameraScaledBitmap.getWidth();
int hgt = cameraScaledBitmap.getHeight();
Bitmap newImage = Bitmap.createBitmap(wid, hgt, Bitmap.Config.ARGB_8888);
Bitmap overlayScaledBitmap = Bitmap.createScaledBitmap(overlayBitmap, wid, hgt, true);
Canvas canvas = new Canvas(newImage);
canvas.drawBitmap(cameraScaledBitmap , 0, 0, null);
canvas.drawBitmap(overlayScaledBitmap , 0, 0, null);
File storagePath = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
storagePath.mkdirs();
String finalName = Long.toString(System.currentTimeMillis());
File myImage = new File(storagePath, finalName + ".jpg");
String photoPath = Environment.getExternalStorageDirectory().getAbsolutePath() +"/" + finalName + ".jpg";
try {
FileOutputStream fos = new FileOutputStream(myImage);
newImage.compress(Bitmap.CompressFormat.JPEG, 80, fos);
fos.close();
} catch (IOException e) {
Toast.makeText(this, "Pic not saved", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(this, "Pic saved in: " + photoPath, Toast.LENGTH_SHORT).show();
camera.startPreview();
newImage.recycle();
newImage = null;
cameraBitmap.recycle();
cameraBitmap = null;
}
Related
I am taking an image from camera using:
mCamera.takePicture(null, null,
new PhotoHandler(getApplicationContext()));
But the image I am taking is landscape and I want it portrait, I tried converting the file into bitmap, rotate it and then save it again, here is my onPictureTaken() function and rotate() function inside PhotoHandler.class:
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d("Error", "Can't create directory to save image.");
Toast.makeText(context, "Can't create directory to save image.",
Toast.LENGTH_LONG).show();
return;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
pictureFile = new File(filename);
st1 = pictureFile.getAbsolutePath();
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast.makeText(context, "New Image saved:" + photoFile,
Toast.LENGTH_LONG).show();
} catch (Exception error) {
Log.d("Error", "File" + filename + "not saved: "
+ error.getMessage());
Toast.makeText(context, "Image could not be saved.",
Toast.LENGTH_LONG).show();
}
Bitmap b = rotate(BitmapFactory.decodeFile(pictureFile.getAbsolutePath()),270);
FileOutputStream out = null;
try {
out = new FileOutputStream(pictureFile);
b.compress(Bitmap.CompressFormat.PNG, 100, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
CameraPreview.safeToTakePicture = true;
galleryAddPic();
}
public static Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
mtx.setRotate(degree);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
Anyway, it takes too long, I tried using mCamera.setDisplayOrientation(90); but it changes only the preview of the camera, the picture taken is still the same, I also tried getting the parameters of the camera and changing it like here:
Camera.Parameters parameters = mCamera.getParameters();
parameters.set("orientation", "portrait");
mCamera.setParameters(parameters);
Without success, any help will be appreciated.
EDIT :
New code:
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d("Error", "Can't create directory to save image.");
Toast.makeText(context, "Can't create directory to save image.",
Toast.LENGTH_LONG).show();
return;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
pictureFile = new File(filename);
st1 = pictureFile.getAbsolutePath();
Bitmap b = rotate(BitmapFactory.decodeByteArray(data,0,data.length),270);
FileOutputStream out = null;
try {
out = new FileOutputStream(pictureFile);
b.compress(Bitmap.CompressFormat.PNG, 100, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
CameraPreview.safeToTakePicture = true;
galleryAddPic();
}
Anyway, it takes too long
Your current algorithm looks like this:
Start with the photo in memory
Save the photo to disk, which is slow
Read the photo back in from disk to memory, which is slow
Rotate the reloaded photo
A more efficient approach would be:
Start with the photo in memory
Rotate the photo
BitmapFactory has decodeByteArray() to get a Bitmap back for rotation purposes.
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 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 {
}
}
}
}); }
I want to take a picture with my app and send it to Instagram, but I'm with some problem because when I shot the photo my app has some delay to save.
My app is doing in this way
First I take a picture with my app and save this picture in the gallery.
After the user will approve or not the image. If he approves he clicks on a button and send it to Instagram, but I don't know why the app is taking some seconds to save my image.
My method to get the image I want to use is to get the last picture I saved on my folder's gallery.
This is the code I call to take a picture.
camera = cameraSurfaceView.getCamera();
camera.takePicture(new ShutterCallback() {
#Override
public void onShutter() {
AudioManager mgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mgr.playSoundEffect(AudioManager.FLAG_PLAY_SOUND);
}
}, null, new HandlePictureStorage(preview,cameraSurfaceView.getFront()));
imageSelected = false;
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
Here is the class I use to get the picture and save
public class HandlePictureStorage implements PictureCallback {
FrameLayout preview;
int wid = 0;
Bitmap bitmapFinal;
boolean front;
File storagePath = new File(Environment.getExternalStorageDirectory() + "/Tubagram/");
public HandlePictureStorage(FrameLayout preview, boolean front){
this.preview = preview;
this.front = front;
}
#Override
public void onPictureTaken(byte[] picture, Camera camera) {
Matrix matrix = new Matrix();
if (front){
matrix.postRotate(270);
}else{
matrix.postRotate(90);
}
Bitmap cameraBitmap = BitmapFactory.decodeByteArray(picture, 0, picture.length);
wid = cameraBitmap.getWidth();
Bitmap scaledBitmap = Bitmap.createScaledBitmap(cameraBitmap, wid, wid, true);
Bitmap imagemRotacionada = Bitmap.createBitmap(scaledBitmap,0,0,scaledBitmap.getWidth(),scaledBitmap.getHeight(),matrix,true);
Bitmap newImage = Bitmap.createBitmap
(612, 612, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newImage);
canvas.drawBitmap(imagemRotacionada, 0f, 0f, null);
Drawable drawable = preview.getForeground();
drawable.setBounds(0, 0, 612, 612);
drawable.draw(canvas);
File myImage = new File(storagePath,"TUBAGRAM_" + System.currentTimeMillis() +".png");
try
{
FileOutputStream out = new FileOutputStream(myImage);
newImage.compress(Bitmap.CompressFormat.PNG, 100, out);
bitmapFinal = newImage;
out.flush();
out.close();
Log.i("Imagem Tubagram salva em ", ""+ myImage);
}
catch(FileNotFoundException e)
{
Log.d("In Saving File", e + "");
}
catch(IOException e)
{
Log.d("In Saving File", e + "");
}
drawable = null;
// newImage.recycle();
newImage = null;
cameraBitmap.recycle();
cameraBitmap = null;
}
And here is the code when I accept the photo and send to Instagram
if (verificaInstagram()){
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("image/*");
Cursor c1 = pickLastPhotoAlbum();
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://"+Environment.getExternalStorageDirectory()+ "/Tubagram/" + c1.getString(1)+".png"));
shareIntent.setPackage("com.instagram.android");
c1.close();
startActivity(shareIntent);
}else{
Toast.makeText(v.getContext(), "Você não possui o Instagram no seu smartphone!", Toast.LENGTH_SHORT).show();
}
Anyone can help me with this?
Ok. I solved this question by doing this.
The class I use to save the picture I changed this part...
FileOutputStream out = new FileOutputStream(myImage);
newImage.compress(Bitmap.CompressFormat.PNG, 100, out);
bitmapFinal = newImage;
out.flush();
and now I use this one...
String nomeImagem = "TUBAGRAM_" + System.currentTimeMillis();
url = MediaStore.Images.Media.insertImage(preview.getContext().getContentResolver(), newImage ,nomeImagem, null);
And the code I use to accept the photo and send to Instagram I changed to
caminhoImagens = getRealPathFromURI(Uri.parse(hps.getUrl()));
Log.i("Caminho imagem: ", caminhoImagens);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + caminhoImagens));
shareIntent.setPackage("com.instagram.android");
And retire the cursor.