カメラからキャプチャした画像を取り、その上にフォトフレームまたはオーバーレイを配置しようとしています。フォトフレームは基本的に、SurfaceView も含むImageView
内に配置された png 画像です。FrameLayout
問題は、キャプチャされた写真イメージ上の正確な位置にオーバーレイを配置するために、写真イメージとフォト フレーム イメージを含むビューの結果のビットマップのいずれかまたは両方をスケーリングする必要があることです。しかし、それらは縦横比が異なるため、写真やオーバーレイが歪むことなくこれを行う方法を理解するのに途方に暮れています. ビットマップ操作を処理するコードは次のとおりです。さらに、ビットマップのサイズが大きいために OutofMemory 例外が発生することがあります。使ってみたMappedByteBuffer
しかし、それもうまく機能しませんでした...ため息。とにかく、私が間違っていることについての提案や、これを達成するためのより良い方法を示すコードサンプルは大歓迎です!
private void saveTempPhoto(byte[] data) {
// Need to flip back the photo frame on front facing camera.
if (this.isCameraFront)
this.flipPhotoFrame();
findViewById(R.id.close_button).setVisibility(View.INVISIBLE);
findViewById(R.id.flash_button).setVisibility(View.INVISIBLE);
findViewById(R.id.focus_button).setVisibility(View.INVISIBLE);
findViewById(R.id.take_photo).setVisibility(View.INVISIBLE);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
options.inDither = false;
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[32 * 1024];
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inJustDecodeBounds = true;
Bitmap bitmapPhoto = null;
Bitmap bitmapPhotoFrame = null;
Bitmap bitmapCanvas = null;
View view = findViewById(R.id.top_photo_frame); //view containing the photoframe
try {
int photoFrameWidth = view.getWidth();
int photoFrameHeight = view.getHeight();
BitmapFactory.decodeByteArray(data, 0, data.length, options);
if (orientation == 90 || orientation == 270) {
//Swap height and width
int temp = options.outWidth;
options.outWidth = options.outHeight;
options.outHeight = temp;
}
// Calculate the best sample size to use based on the ratio of the captured image to the photoframe.
// This is done to prevent OutofMemoryExceptions from occurring, as the bitmap allocations can use up a lot of heap space.
float ratioWidth = (float)options.outWidth / (float)photoFrameWidth;
float ratioHeight = (float)options.outHeight / (float)photoFrameHeight;
float ratio = Math.min(ratioWidth, ratioHeight);
if (ratioWidth > 1 || ratioHeight > 1) {
double power = Math.log(ratio) / Math.log(2);
options.inSampleSize = (int) Math.pow(2, Math.round(power));
}
options.inJustDecodeBounds = false;
Bitmap bitmapPhotoPreRotate = BitmapFactory.decodeByteArray(data, 0, data.length, options);
int postRotation = isCameraFront ? -orientation : orientation;
if (orientation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(postRotation);
bitmapPhoto = Bitmap.createBitmap(bitmapPhotoPreRotate, 0, 0, bitmapPhotoPreRotate.getWidth(), bitmapPhotoPreRotate.getHeight(), matrix, true);
bitmapPhotoPreRotate.recycle();
}
else
bitmapPhoto = bitmapPhotoPreRotate;
Log.d("PhotoFrameActivity", String.format("Photo bitmap has width %d and height %d", bitmapPhoto.getWidth(), bitmapPhoto.getHeight()));
Log.d("PhotoFrameActivity", String.format("PhotoFrame bitmap has width %d and height %d", view.getWidth(), view.getHeight()));
int photoWidth = bitmapPhoto.getWidth();
int photoHeight = bitmapPhoto.getHeight();
Bitmap.Config photoConfig = bitmapPhoto.getConfig();
bitmapCanvas = Bitmap.createBitmap(photoWidth,
photoHeight, photoConfig);
if (bitmapCanvas != null) {
Canvas canvas = new Canvas(bitmapCanvas);
canvas.drawBitmap(bitmapPhoto, new Matrix(), null);
bitmapPhoto.recycle();
bitmapPhoto = null;
System.gc(); //Try to force GC here to free up some memory
bitmapPhotoFrame = Bitmap.createScaledBitmap(
this.loadBitmapFromView(view),
photoWidth,
photoHeight,
true);
canvas.drawBitmap(bitmapPhotoFrame, 0, 0, null);
bitmapPhotoFrame.recycle();
Log.d("PhotoFrameActivity", String.format("Combined bitmap has width %d and height %d", bitmapCanvas.getWidth(), bitmapCanvas.getHeight()));
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmapCanvas.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] jpegWithPhotoFrame = stream.toByteArray();
try {
createPhotoFile();
FileOutputStream fos = new FileOutputStream(photoFile);
fos.write(jpegWithPhotoFrame);
fos.close();
Log.d("PhotoFrameActivity", String.format("Image file saved to %s", photoFile.getPath()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (bitmapCanvas != null)
bitmapCanvas.recycle();
if (bitmapPhoto != null)
bitmapPhoto.recycle();
if (bitmapPhotoFrame != null)
bitmapPhotoFrame.recycle();
}
}
catch (OutOfMemoryError e) {
// Put up out of memory alert
AlertDialog dialogError = new AlertDialog.Builder(this).create();
dialogError.setButton(DialogInterface.BUTTON_POSITIVE,"OK",
new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
finish();
}
}
);
dialogError.setMessage("Out of memory!");
dialogError.show();
}
catch (Exception e) {
e.printStackTrace();
}
}