GVKun编程网logo

Android Camera2 API YUV_420_888为JPEG

19

如果您想了解AndroidCamera2APIYUV_420_888为JPEG的相关知识,那么本文是一篇不可错过的文章,我们将为您提供关于Android2.2下camera应用程序支持GPS信息写入j

如果您想了解Android Camera2 API YUV_420_888为JPEG的相关知识,那么本文是一篇不可错过的文章,我们将为您提供关于Android 2.2 下 camera 应用程序支持 GPS 信息写入 jpeg 文件、Android Camera 采集的 YUV420 源数据怎么提取 y、u、v 分量啊、Android Camera2 API JPEG_QUALITY不可用、Android Camera2 API – 恢复时缺少权限的有价值的信息。

本文目录一览:

Android Camera2 API YUV_420_888为JPEG

Android Camera2 API YUV_420_888为JPEG

我正在使用OnImageAvailableListener获得预览帧:

@Overridepublic void onImageAvailable(ImageReader reader) {    Image image = null;    try {        image = reader.acquireLatestImage();        Image.Plane[] planes = image.getPlanes();        ByteBuffer buffer = planes[0].getBuffer();        byte[] data = new byte[buffer.capacity()];        buffer.get(data);        //data.length=332803; width=3264; height=2448        Log.e(TAG, "data.length=" + data.length + "; width=" + image.getWidth() + "; height=" + image.getHeight());        //TODO data processing    } catch (Exception e) {        e.printStackTrace();    }    if (image != null) {        image.close();    }}

每次数据长度不同,但图像的宽度和高度相同。
主要问题:data.length对于3264x2448之类的分辨率而言太小。
数据数组的大小应为3264 * 2448 = 7,990,272,而不是300,000-600,000。
怎么了?


imageReader = ImageReader.newInstance(3264, 2448, ImageFormat.JPEG, 5);

答案1

小编典典

我通过使用
YUV_420_888
图像格式并将其手动转换为
JPEG
图像格式解决了此问题。

imageReader = ImageReader.newInstance(MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT,                                       ImageFormat.YUV_420_888, 5);imageReader.setOnImageAvailableListener(this, null);

Surface imageSurface = imageReader.getSurface();List<Surface> surfaceList = new ArrayList<>();//...add other surfacespreviewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);previewRequestBuilder.addTarget(imageSurface);            surfaceList.add(imageSurface);cameraDevice.createCaptureSession(surfaceList,                    new CameraCaptureSession.StateCallback() {//...implement onConfigured, onConfigureFailed for StateCallback}, null);

@Overridepublic void onImageAvailable(ImageReader reader) {    Image image = reader.acquireLatestImage();    if (image != null) {        //converting to JPEG        byte[] jpegData = ImageUtils.imageToByteArray(image);        //write to file (for example ..some_path/frame.jpg)        FileManager.writeFrame(FILE_NAME, jpegData);        image.close();    }}

public final class ImageUtil {    public static byte[] imageToByteArray(Image image) {        byte[] data = null;        if (image.getFormat() == ImageFormat.JPEG) {            Image.Plane[] planes = image.getPlanes();            ByteBuffer buffer = planes[0].getBuffer();            data = new byte[buffer.capacity()];            buffer.get(data);            return data;        } else if (image.getFormat() == ImageFormat.YUV_420_888) {            data = NV21toJPEG(                    YUV_420_888toNV21(image),                    image.getWidth(), image.getHeight());        }        return data;    }    private static byte[] YUV_420_888toNV21(Image image) {        byte[] nv21;        ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();        ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();        ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();        int ySize = yBuffer.remaining();        int uSize = uBuffer.remaining();        int vSize = vBuffer.remaining();        nv21 = new byte[ySize + uSize + vSize];        //U and V are swapped        yBuffer.get(nv21, 0, ySize);        vBuffer.get(nv21, ySize, vSize);        uBuffer.get(nv21, ySize + vSize, uSize);        return nv21;    }    private static byte[] NV21toJPEG(byte[] nv21, int width, int height) {        ByteArrayOutputStream out = new ByteArrayOutputStream();        YuvImage yuv = new YuvImage(nv21, ImageFormat.NV21, width, height, null);        yuv.compressToJpeg(new Rect(0, 0, width, height), 100, out);        return out.toByteArray();    }}

public final class FileManager {    public static void writeFrame(String fileName, byte[] data) {        try {            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileName));            bos.write(data);            bos.flush();            bos.close();//            Log.e(TAG, "" + data.length + " bytes have been written to " + filesDir + fileName + ".jpg");        } catch (IOException e) {            e.printStackTrace();        }    }}

Android 2.2 下 camera 应用程序支持 GPS 信息写入 jpeg 文件

Android 2.2 下 camera 应用程序支持 GPS 信息写入 jpeg 文件

一、概述

在Android2.2中,Camera的应用程序并不支持将GPS信息写入到JPEG文件中,但如果要实现这个功能,有如下两种方式:

1、修改底层camera驱动。在拍照时,一般都是使用硬件去进行JPEG编码,这样就需要修改JPEG编码器,使其可以将GPS信息写入JPEG文件的头部,即EXIF部分。这种方式使用与手机驱动开发者。

2、修改camera应用程序。Camera应用程序本身不支持该功能,但是android系统中提供了支持该功能的类—— ExifInterface。本文介绍如何使用该类进行GPS信息的写入。这种方法的不足在于,每次写入GPS功能,都会把原有的JPEG文件读出,修改 了Exif header部分后再写入文件。

二、实现GPS写入功能

首先来看看文件ImageManager.java,该文件位于:

/package/apps/Camera/src/com/android/camera/

该文件中,有个addImage()函数,其定义为:

public static Uri addImage(ContentResolver cr, String title, long dateTaken,
 
        Location location, String directory, String filename,
        Bitmap source, byte[] jpegData, int[] degree) {
        。。。。。。
        String filePath = directory + "/" + filename;
        。。。。。。
        if (location != null) {
            values.put(Images.Media.LATITUDE, location.getLatitude());
            values.put(Images.Media.LONGITUDE, location.getLongitude());        
           }
       }
    return cr.insert(STORAGE_URI, values);
}

此处,当location不等于null时,表示已经开启存储位置的功能,并且该手机的GPS功能已开启并且正常。在这里,我们就可以把GPS的信息写入JPEG文件中。其具体code如下:

public static Uri addImage(ContentResolver cr, String title, long dateTaken,
            Location location, String directory, String filename,
            Bitmap source, byte[] jpegData, int[] degree) {
        。。。。。。
        String filePath = directory + "/" + filename;
        。。。。。。
 
        if (location != null) {
            values.put(Images.Media.LATITUDE, location.getLatitude());
            values.put(Images.Media.LONGITUDE, location.getLongitude());
           ExifInterface exif = null;
        try {
            exif = new ExifInterface(filePath);
        } catch (IOException ex) {
            Log.e(TAG, "cannot read exif", ex);
           }
         exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, Double.toString(location.getLatitude()));        
           exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, Double.toString(location.getLongitude()));
           try{
               if(exif != null)
              exif.saveAttributes();
           } catch (IOException ex) {
              Log.e(TAG, "Fail to exif.saveAttributes().");
           }
       }
    return cr.insert(STORAGE_URI, values);
}

三、分析GPS写入功能的实现

首先看看类ExifInterface的构造函数,其位于:

/framework/base/media/java/android/media/ ExifInterface.java

其具体实现为:

public ExifInterface(String filename) throws IOException {
        mFilename = filename;
        loadAttributes();
}

其功能是从指定的文件中获取其Exif信息。函数loadAttributes()的定义为:

private void loadAttributes() throws IOException {
        // format of string passed from native C code:
        // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
        // example:
        // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
        mAttributes = new HashMap<String, String>();
 
        String attrStr;
        synchronized (sLock) {
            attrStr = getAttributesNative(mFilename);
        }
        ……
}

该函数从文件中读取Exif信息,并将其写入mAttributes中。函数

getAttributesNative(mFilename),调用了JNI接口,其定义位于:/external/jhead/main.c

static JNINativeMethod methods[] = {
  {"saveAttributesNative", "(Ljava/lang/String;Ljava/lang/String;)V", (void*)saveAttributes },
  {"getAttributesNative", "(Ljava/lang/String;)Ljava/lang/String;", (void*)getAttributes },
  {"appendThumbnailNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*)appendThumbnail },
  {"commitChangesNative", "(Ljava/lang/String;)V", (void*)commitChanges },
  {"getThumbnailNative", "(Ljava/lang/String;)[B", (void*)getThumbnail },
};

函数setAttribute()的实现如下:
public void setAttribute(String tag, String value) {
        mAttributes.put(tag, value);
}

向mAttributes写入对应的项,比如经度和纬度信息。

最重要的函数saveAttributes(),它也是调用JNI接口。它负责将所有的Exif项写入到JPEG文件中。由于时间关系,就不做介绍了,具体代码请大家自己看,有问题的话,一起讨论。

文章出处:http://blog.csdn.net/wxzking/article/details/6584224

Android Camera 采集的 YUV420 源数据怎么提取 y、u、v 分量啊

Android Camera 采集的 YUV420 源数据怎么提取 y、u、v 分量啊

我想将 Android Camera 采集的 Y420 数据源直接纹理贴图,可是不知道怎么提取 y、u、v 分量。求大牛帮助~~

Android Camera2 API JPEG_QUALITY不可用

Android Camera2 API JPEG_QUALITY不可用

我正在尝试使用 Android Camera2 API处理我的Nexus 5x,而我正在使用 googlesamples android-Camera2Basic

我的问题是JPEG图像的质量太低,而且它的尺寸远小于我用手机相机应用拍摄的常规图像.

根据谷歌文档,CaptureRequest和CaptureResult中都应该有一个关键的JPEG_QUALITY:

JPEG_QUALITY

Added in API level 21

Key JPEG_QUALITY

Compression quality of the final JPEG image.

85-95 is typical usage range.

Range of valid values:

1-100; larger is higher quality

This key is available on all devices.

但是,当我要求可用的键时,JPEG_QUALITY键不可用,所以我不知道如何知道我目前使用的JPEG压缩质量是什么以及如何更改它.

我在里面做的代码:

CameraCaptureSession.CaptureCallback CaptureCallback
                = new CameraCaptureSession.CaptureCallback() {

            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session,@NonNull CaptureRequest request,@NonNull TotalCaptureResult result) {


                //_TEST_DEBUG
                List<CaptureRequest.Key<?>> requestKeys = request.getKeys();
                List<CaptureResult.Key<?>> resultKeys = result.getKeys();

requestKeys& resultKeys有许多键,包括JPEG_ORIENTATION但不包含JPEG_QUALITY键.

知道我做错了什么吗?
为什么我找不到如何更改JPEG压缩质量?

谢谢,
家伙

解决方法

我通过在Android 5.1 Lollipop上使用Tesco Hudl 2平板电脑将其添加为googlesamples android-camera2Basic中的CaptureRequest.Builder的密钥,从而提高了JPEG质量.

JPEG质量在Camer2BasicFragment的captureStillPicture()方法中设置,如下所示:

// This is the CaptureRequest.Builder that we use to take a picture.
        final CaptureRequest.Builder captureBuilder =
                mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureBuilder.addTarget(mImageReader.getSurface());

        //Set the JPEG quality here like so
        captureBuilder.set(CaptureRequest.JPEG_QUALITY,(byte)90);

我希望这有帮助.

Android Camera2 API – 恢复时缺少权限

Android Camera2 API – 恢复时缺少权限

我正在使用Camera2 API开发应用程序.我的问题看起来像这样:
 当我在相机片段工作时按下设备的睡眠按钮,之后我唤醒设备,应用程序重新启动

12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime: FATAL EXCEPTION: main
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime: Process: com.snapsportz.nexus5camera.app,PID: 5081
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime: java.lang.RuntimeException: Unable to pause activity {com.snapsportz.nexus5camera.app/com.snapsportz.handheldcamera.app.CameraActivity}: java.lang.SecurityException: Lacking privileges to access camera service
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3381)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3340)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread.handlerelaunchActivity(ActivityThread.java:4047)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread.-wrap15(ActivityThread.java)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:148)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5417)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:  Caused by: java.lang.SecurityException: Lacking privileges to access camera service
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.hardware.camera2.utils.CamerabinderDecorator.throwOnError(CamerabinderDecorator.java:108)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.hardware.camera2.utils.CamerabinderDecorator$CamerabinderDecoratorListener.onAfterInvocation(CamerabinderDecorator.java:73)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.hardware.camera2.utils.Decorator.invoke(Decorator.java:81)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at java.lang.reflect.Proxy.invoke(Proxy.java:393)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at $Proxy1.cancelRequest(UnkNown Source)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.hardware.camera2.impl.CameraDeviceImpl.stopRepeating(CameraDeviceImpl.java:899)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.hardware.camera2.impl.CameraCaptureSessionImpl.close(CameraCaptureSessionImpl.java:373)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at com.snapsportz.handheldcamera.app.Camera2BasicFragment.closeCamera(Camera2BasicFragment.java:899)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at com.snapsportz.handheldcamera.app.Camera2BasicFragment.onPause(Camera2BasicFragment.java:771)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.Fragment.performPause(Fragment.java:2379)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.FragmentManagerImpl.movetoState(FragmentManager.java:1019)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.FragmentManagerImpl.movetoState(FragmentManager.java:1148)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.FragmentManagerImpl.movetoState(FragmentManager.java:1130)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.FragmentManagerImpl.dispatchPause(FragmentManager.java:1967)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.FragmentController.dispatchPause(FragmentController.java:185)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.Activity.performPause(Activity.java:6346)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1311)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3367)
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3340) 
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread.handlerelaunchActivity(ActivityThread.java:4047) 
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread.-wrap15(ActivityThread.java) 
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350) 
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102) 
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:148) 
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5417) 
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method) 
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
12-10 10:59:10.423 5081-5081/com.snapsportz.nexus5camera.app E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

我相信它不是缺少清单文件中的相机权限,因为它包含在其中并且应用程序工作正常,除非我试图唤醒它.

任何暗示我都会很高兴.

解决方法

如果您使用的是Google Camera2Basic示例应用程序 – issue #42似乎描述了该问题.解决方案是在您的片段中检查您对onResume方法的使用 – 并在onResume()中调用openCamera()之前调用closeCamera().似乎在我的Camera2Basic测试中解决了这个问题.

今天的关于Android Camera2 API YUV_420_888为JPEG的分享已经结束,谢谢您的关注,如果想了解更多关于Android 2.2 下 camera 应用程序支持 GPS 信息写入 jpeg 文件、Android Camera 采集的 YUV420 源数据怎么提取 y、u、v 分量啊、Android Camera2 API JPEG_QUALITY不可用、Android Camera2 API – 恢复时缺少权限的相关知识,请在本站进行查询。

本文标签: