【问题标题】:ByteBuffer convert Bitmap crashByteBuffer 转换 Bitmap 崩溃
【发布时间】:2023-02-07 14:06:02
【问题描述】:

您好我想将字节数组转换为位图并在 ImageView 中显示图像。我编写了以下代码,但出现异常,提示缓冲区不够大以容纳像素。

Image resolution : 480*640
ARGB = 480*640\*4 = 1228800????
bitmap = Bitmap.createBitmap(480,640, Bitmap.Config.ARGB_8888);
byte[] temp = Arrays.copyOfRange(bytes,745488,1228800);
ByteBuffer buffer = ByteBuffer.wrap(temp);
bitmap.copyPixelsFromBuffer(buffer);
imageView.setImageBitmap(bitmap);

错误:

java.lang.RuntimeException:缓冲区的像素不够大 android.graphics.Bitmap.copyPixelsFromBuffer(Bitmap.java:567) 在 com.example.scratch.HomeActivity$3.run(HomeActivity.java:119) 在 android.os.Handler.handleCallback(Handler.java:751) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6121) 在 java.lang.reflect.Method.invoke(本机方法)位于 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)

【问题讨论】:

  • 你认为Arrays.copyOfRange(bytes,745488,1228800); 返回了什么?由于您的图像在 32 位具有 307200 个像素,因此需要 1228800 个字节。现在您正在创建一个 483312 字节的字节数组 - 为什么?如果您提供该数组作为输入,您知道为什么会报告“缓冲区不够大”吗?
  • 参数看错了,我以为第三个参数是长度。

标签: java android android-bitmap


【解决方案1】:

安卓/Java:

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.blendmode);
        app = (MessiApplication) this.getApplication();
        blendModeRawStreamBitmap = Bitmap.createBitmap(app.getVideoWidth(),app.getVideoHeight(), Bitmap.Config.ARGB_8888);
        blendModeColorStreamBitmap = Bitmap.createBitmap(app.getVideoWidth(),app.getVideoHeight(), Bitmap.Config.ARGB_8888);
        blendModeRawStreamImageView = findViewById(R.id.blend_mode_raw_video_view_id);
        blendModeColorStreamImageView = findViewById(R.id.blend_mode_color_video_view_id);
        videoStreamInfo = new VideoStreamInfo(app.getVideoWidth() , app.getVideoHeight(), app.getRawPseudoOffset(), 0);
    }

    private int _onAllVideoFrame(int cmd, String [] path, byte[] rawBytes, byte[] colorBytes)
    {
        runOnUiThread(new Runnable(){
            @Override
            public void run() {
                ByteBuffer rawStreamBuffer = ByteBuffer.wrap(rawBytes);
                blendModeRawStreamBitmap.copyPixelsFromBuffer(rawStreamBuffer);
                blendModeRawStreamImageView.setImageBitmap(blendModeRawStreamBitmap);

                ByteBuffer colorStreamBuffer = ByteBuffer.wrap(colorBytes);
                blendModeColorStreamBitmap.copyPixelsFromBuffer(colorStreamBuffer);
                blendModeColorStreamImageView.setImageBitmap(blendModeColorStreamBitmap);
            }
        });
        return 0;
    }

Jni/C++:

jbyteArray color_frame_buffer = NULL;
jbyteArray raw_frame_buffer = NULL;

        raw_frame_buffer = (jbyteArray)cb->env->GetObjectField(cb->video_stream_obj, cb->raw_buffer_dield_id);
        if(raw_frame_buffer == NULL)
        {
            ALOGE("Fail to get raw_frame_buffer field");
            return -1;
        }

        cb->env->SetByteArrayRegion(raw_frame_buffer,0, cb->raw_stream_buffer_size,(jbyte *)req.text + cb->raw_stream_buffer_offset);
        cb->env->SetDoubleField(cb->video_stream_obj,cb->raw_fps_dield_id,video_stream_info.fps);
        cb->env->SetDoubleField(cb->video_stream_obj,cb->raw_jitter_dield_id,video_stream_info.jitter);

        color_frame_buffer = (jbyteArray)cb->env->GetObjectField(cb->video_stream_obj,cb->color_buffer_dield_id);
        if(color_frame_buffer == NULL)
        {
            ALOGE("Fail to get color_frame_buffer field");
            return -1;
        }

        rgba_buffer = (uint8_t*)malloc(cb->color_stream_buffer_size);
        if(rgba_buffer == nullptr)
        {
            ALOGE("Not enough memory field.");
            return -1;
        }
        memset(rgba_buffer, 0, cb->color_stream_buffer_size);
        Yuv422ToRgba(cb->color_video_width, cb->color_video_height, (uint8_t*)req.text + cb->color_stream_buffer_offset, rgba_buffer);
        cb->env->SetByteArrayRegion(color_frame_buffer,0, cb->color_stream_buffer_size, (jbyte *)rgba_buffer);
        cb->env->CallIntMethod(cb->obj,cb->on_frame_function_id,cmd,jpath_obj, raw_frame_buffer, color_frame_buffer);

YuvToRgba

void Yuv422ToRgba(int width, int heigth, uint8_t *yuv_buffer, uint8_t* rbga_buffer)
{
    int pixel_size = width*heigth;
    uint32_t *pixel_ptr = (uint32_t *)rbga_buffer;
    uint8_t *y1_byte, *y2_byte, *u_byte, *v_byte;
    uint8_t r_byte, g_byte, b_byte;

    for (int y_itr = 0; y_itr  < pixel_size * 2; y_itr += 4)
    {
        u_byte = yuv_buffer + y_itr;
        y1_byte = yuv_buffer + y_itr + 1;
        v_byte = yuv_buffer + y_itr + 2;
        y2_byte = yuv_buffer + y_itr + 3;

        r_byte = *y1_byte + 1.4023 * (*v_byte-128.0);
        g_byte = *y1_byte - 0.3456 * (*u_byte-128.0) - 0.7145 * (*v_byte-128.0);
        b_byte = *y1_byte + 1.771 * (*u_byte-128.0);
        *pixel_ptr = 0x00000000 | r_byte << 16 | g_byte << 8 | b_byte;
        pixel_ptr ++;

        r_byte = *y2_byte + 1.4023 * (*v_byte-128.0);
        g_byte = *y2_byte - 0.3456 * (*u_byte-128.0) - 0.7145 * (*v_byte-128.0);
        b_byte = *y2_byte + 1.771 * (*u_byte-128.0);
        *pixel_ptr = 0x00000000 | r_byte << 16 | g_byte << 8 | b_byte;
        pixel_ptr ++;
    }
}

【讨论】:

    猜你喜欢
    • 2021-10-20
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    相关资源
    最近更新 更多