4

携帯電話のカメラ (8 メガピクセル) で作成した大きな画像を回転させようとしています。ソース Bitmap から回転された Matrix を持つ Bitmap.createBitmap だけで、OutOfMemoryError が発生します。そのため、回転した部分に分割し、それらを再び単一の回転した画像に結合して、2 つの大きなビットマップをメモリに保持しないようにしていますが、Samsung S3 でも最大 10 秒かかります。これを行う他の方法はありますか?

   public static void rotateImage(File file)
            throws FileNotFoundException {
        long time = System.currentTimeMillis();
        List<File> fileList = new ArrayList<File>();

        // For the number of rows and columns
        int rowsCols = 3;

        Matrix matrix = new Matrix();
        matrix.postRotate(-90);

        int chunkHeight, chunkWidth;

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        BitmapFactory.decodeStream(new FileInputStream(file), null, options);

        int height = options.outHeight;
        int width = options.outWidth;

        chunkHeight = height / rowsCols;
        chunkWidth = width / rowsCols;

        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = 1;
        o2.inPurgeable = true;
        o2.inInputShareable = true;
        o2.inPreferredConfig = Bitmap.Config.ARGB_8888;

        Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file),
                null, o2);

        // Cut the small rotated pieces and save to the files
        int yCoord = 0;
        for (int y = 0; y < rowsCols; y++) {
            int xCoord = 0;
            for (int x = 0; x < rowsCols; x++) {
                split(chunkHeight, chunkWidth, yCoord, x, xCoord, y, bitmap,
                        matrix, fileList);
                xCoord += chunkWidth;
            }
            yCoord += chunkHeight;
        }
        bitmap.recycle();
        Bitmap rotatedBitmap = Bitmap.createBitmap(height, width,
                Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(rotatedBitmap);

        // Combine the small pieces into the one output canvas
        int xCoord;
        xCoord = 0;
        for (int x = 0; x < rowsCols; x++) {  
            yCoord = 0;
            for (int y = 0; y < rowsCols; y++) {
                combineIntoCanvas(o2, canvas, xCoord, yCoord, fileList);
                yCoord -= chunkWidth;
            }
            xCoord += chunkHeight;
        }

        //Save the bitmap to the file
        rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 90,
                new FileOutputStream(file, false));
        rotatedBitmap.recycle();
        Log.add("combined in " + (System.currentTimeMillis() - time));
    }

    private static void combineIntoCanvas(BitmapFactory.Options o2,
            Canvas canvas, int xCoord, int yCoord, List<File> fileList)
            throws FileNotFoundException {
        File file = fileList.get(0);
        Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file),
                null, o2);
        canvas.drawBitmap(bitmap, xCoord, yCoord, null);
        bitmap.recycle();
        file.delete();
        fileList.remove(0);
    }

    private static void split(int chunkHeight, int chunkWidth, int yCoord,
            int x, int xCoord, int y, Bitmap bitmap, Matrix matrix,
            List<File> fileList) throws FileNotFoundException {

        Bitmap pieceOfBitmap = Bitmap.createBitmap(bitmap, xCoord, yCoord,
                chunkWidth, chunkHeight, matrix, true);
        File splitFile = new File(Globals.IMAGE_BASE_GALLERY_FOLDER() + "temp"
                + x + "_" + y + "." + "jpg");
        fileList.add(splitFile);

        pieceOfBitmap.compress(Bitmap.CompressFormat.PNG, 0,
                new FileOutputStream(splitFile, false));
        pieceOfBitmap.recycle();
    }
4

3 に答える 3

1

カメラで撮影した写真を撮ろうとすると、写真のサイズが大きくなりすぎて、画像を直接再生し始めると OutOfMemory になります。したがって、イメージをサンプル サイズに変更してから、コードで回転させてみてください。使用するビットマップの数を制御するように努めてください。これを行う場合、コードを最適化すると非常に役立ちます。これは、OutOfMemory がビットマップの一般的な問題であるためです。のコードは、samplesize を使用して画像ファイルをデコードするのに役立ちます。このリンクが役立つ場合があります。

于 2012-10-18T10:34:15.823 に答える
0

For others like me:

you can have the camera perform the rotation, https://stackoverflow.com/a/16010289/755804

于 2013-04-15T10:55:11.890 に答える
0

最も簡単な方法は、OpenGL を使用して、このような大きな画像を表示および操作することです。1. テクスチャ メモリはアプリケーションのメモリ制限に含まれていません 2. 最近のすべてのデバイスでは、このプロセスは GPU によって高速化されています 3. 他の多くのジョブ (スケーリング、移動、アニメーションなど) が容易になります。

于 2013-04-15T11:22:01.843 に答える