1

カメラからキャプチャした画像を取り、その上にフォトフレームまたはオーバーレイを配置しようとしています。フォトフレームは基本的に、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();
    }
}
4

0 に答える 0