在 onPictureTaken 之后旋转 JPEG 的字节数组

Posted

技术标签:

【中文标题】在 onPictureTaken 之后旋转 JPEG 的字节数组【英文标题】:Rotate byte array of JPEG after onPictureTaken 【发布时间】:2013-05-15 03:32:26 【问题描述】:

有没有办法旋转字节数组而不将其解码为位图?

目前在 jpeg PictureCallback 中,我只是将字节数组直接写入文件。但是图片是旋转的。我想在不解码为位图的情况下旋转它们,希望这样可以节省我的记忆。

    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeByteArray(data, 0, data.length, o);

    int orientation;
    if (o.outHeight < o.outWidth) 
        orientation = 90;
     else 
        orientation = 0;
    

    File photo = new File(tmp, "demo.jpeg");

    FileOutputStream fos;
    BufferedOutputStream bos = null;
    try 
        fos = new FileOutputStream(photo);
        bos = new BufferedOutputStream(fos);
        bos.write(data);
        bos.flush();
     catch (IOException e) 
        Log.e(TAG, "Failed to save photo", e);
     finally 
        IOUtils.closeQuietly(bos);
    

【问题讨论】:

嗨。你做到了吗?谢谢大佬。 @Paul:见***.com/a/16655188/192373 如何使用androidmediautil来解决这个问题? 【参考方案1】:

试试这个。它会解决目的。

Bitmap storedBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, null);

Matrix mat = new Matrix();                        
mat.postRotate("angle");  // angle is the desired angle you wish to rotate            
storedBitmap = Bitmap.createBitmap(storedBitmap, 0, 0, storedBitmap.getWidth(), storedBitmap.getHeight(), mat, true);

【讨论】:

请阅读问题 - 我需要旋转字节数组而不将其解码为位图。 明确提到旋转需要不解码。【参考方案2】:

您可以通过 Exif 标头设置 JPEG 旋转,而无需对其进行解码。这是最有效的方法,但某些观看者可能仍会显示旋转的图像。

或者,您可以使用JPEG lossless rotation。 不幸的是,我不知道这个算法的免费 Java 实现。

更新在SourceForge上,有一个Java开源类LLJTran。 Android 端口位于GitHub。

【讨论】:

您尝试过适用于 Android 的 LLJtran 吗?旋转在三星 Galaxy S1 上测试的 2M jpeg 文件需要 16 秒。无论如何要缩短处理时间? 哦,太糟糕了。感谢分享。有空我看看。 请查看this,看看我是否对库做错了什么。 有没有更简单的方法来旋转和存储字节数组中的全尺寸图像而不将其转换为位图@AlexCohn @therealprashant:不幸的是,似乎没有。正如许多评论者所注意到的,LLJTran 无法应对当今典型图片大小、内存和 CPU 的挑战。【参考方案3】:

我不认为有这种可能性。字节顺序取决于图片编码(png、jpeg)。所以你不得不解码图像来处理它。

【讨论】:

但 Android 文档指出 public final void takePicture (Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg)。所以在Camera.PictureCallback jpeg我总会收到JPEG图片数据。 但是没有旋转jpeg的方法。您可以做的最好的事情是更改 Exif 数据。并非所有东西都支持这一点,而且它不会是真正的旋转。【参考方案4】:

这样试试,

private byte[] rotateImage(byte[] data, int angle) 
    Log.d("labot_log_info","CameraActivity: Inside rotateImage");
    Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length, null);
    Matrix mat = new Matrix();
    mat.postRotate(angle);
    bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);
    return stream.toByteArray();

您可以通过提供从onPictureTaken 方法获取的图像数据和旋转角度来调用rotateImage

例如:rotateImage(data, 90);

【讨论】:

以上是关于在 onPictureTaken 之后旋转 JPEG 的字节数组的主要内容,如果未能解决你的问题,请参考以下文章

Android:三星设备自动旋转图像

从 onPictureTaken 结果裁剪圆形图像

PictureCallback 在“onPictureTaken”中获取字节 [] 数据,但它与我在 CameraView 中看到的图像不匹配。

onPictureTaken 和 onPreviewFrame 的数据字节数组大小不同

Android camera , onPictureTaken(byte[] imgData, Camera camera) 方法和 PictureCallback 从未调用

onPictureTaken 方法中的位图不是垃圾收集的