使用 LIBAVCODEC 将原始图像缓冲区转换为 JPEG

发布于 2025-01-07 08:25:55 字数 208 浏览 0 评论 0原文

我有一个从相机捕获的原始图像缓冲区(在内存中),我想将其转换为 JPEG(以减小尺寸)。问题在于,将这些图像保存为 .pgm 格式会导致文件大小巨大,由于保存这种大小的大文件所涉及的内存限制和延迟(我正在开发的应用程序中的一个限制),我无法承受这种巨大的文件大小。

我想知道如何使用 LIBAVCODEC 将图像缓冲区压缩/编码为 .jpg 格式?我的图像捕获代码是用 C 语言编写的。

I have a raw image buffer (in memory) captured from a camera that I want to convert into JPEG (for reducing size). The problem is that saving these images into .pgm format results into a huge file size that I can't afford due to the memory limitations and latency involved in saving a huge file of this size (a constraint in the application I am working on).

I want to know how do I compress/encode an image buffer into .jpg format using LIBAVCODEC? My image capture code is in C.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

归属感 2025-01-14 08:25:55

此代码适用于 YUV 原始图像。我在尝试对 RGB 原始图像进行编码时遇到段错误。但您可以使用 swscale() 将 RGB 转换为 YUV

int main()
{
    int ret;
    AVFrame *frame;
    AVPacket pkt;

    av_register_all();

    AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
    if (!codec)
    {
        printf("Codec not found\n");
        exit(1);
    }

    AVCodecContext* c = avcodec_alloc_context3(codec);
    if (!c)
    {
        printf("Could not allocate video codec context\n");
        exit(1);
    }

    c->bit_rate = 400000;
    c->width = 320;
    c->height = 200;
    c->time_base= (AVRational){1,25};
    c->pix_fmt = AV_PIX_FMT_YUVJ420P;

    if (avcodec_open2(c, codec, NULL) < 0)
    {
        printf("Could not open codec\n");
        exit(1);
    }

    frame = avcodec_alloc_frame();
    if (!frame)
    {
        printf("Could not allocate video frame\n");
        exit(1);
    }
    frame->format = c->pix_fmt;
    frame->width  = c->width;
    frame->height = c->height;

    ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, c->pix_fmt, 32);
    if (ret < 0)
    {
        printf("Could not allocate raw picture buffer\n");
        exit(1);
    }

    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;

    /* prepare a dummy image */
    /* Y */
    for(int y=0;y<c->height;y++) {
        for(int x=0;x<c->width;x++) {
            frame->data[0][y * frame->linesize[0] + x] = x + y;
        }
    }

    /* Cb and Cr */
    for(int y=0;y<c->height/2;y++) {
        for(int x=0;x<c->width/2;x++) {
            frame->data[1][y * frame->linesize[1] + x] = 128 + y;
            frame->data[2][y * frame->linesize[2] + x] = 64 + x;
        }
    }


    frame->pts = 1;

    int got_output = 0;
    ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
    if (ret < 0)
    {
        printf("Error encoding frame\n");
        exit(1);
    }

    if (got_output)
    {
        printf("got frame\n");
        FILE* f = fopen("x.jpg", "wb");
        fwrite(pkt.data, 1, pkt.size, f);
        av_free_packet(&pkt);
    }

    avcodec_close(c);
    av_free(c);
    av_freep(&frame->data[0]);
    avcodec_free_frame(&frame);
    printf("\n");

    return 0;
}

this code works with YUV raw images. I got segfault trying to encode an RGB raw image. but you can use swscale() to convert RGB to YUV

int main()
{
    int ret;
    AVFrame *frame;
    AVPacket pkt;

    av_register_all();

    AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
    if (!codec)
    {
        printf("Codec not found\n");
        exit(1);
    }

    AVCodecContext* c = avcodec_alloc_context3(codec);
    if (!c)
    {
        printf("Could not allocate video codec context\n");
        exit(1);
    }

    c->bit_rate = 400000;
    c->width = 320;
    c->height = 200;
    c->time_base= (AVRational){1,25};
    c->pix_fmt = AV_PIX_FMT_YUVJ420P;

    if (avcodec_open2(c, codec, NULL) < 0)
    {
        printf("Could not open codec\n");
        exit(1);
    }

    frame = avcodec_alloc_frame();
    if (!frame)
    {
        printf("Could not allocate video frame\n");
        exit(1);
    }
    frame->format = c->pix_fmt;
    frame->width  = c->width;
    frame->height = c->height;

    ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, c->pix_fmt, 32);
    if (ret < 0)
    {
        printf("Could not allocate raw picture buffer\n");
        exit(1);
    }

    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;

    /* prepare a dummy image */
    /* Y */
    for(int y=0;y<c->height;y++) {
        for(int x=0;x<c->width;x++) {
            frame->data[0][y * frame->linesize[0] + x] = x + y;
        }
    }

    /* Cb and Cr */
    for(int y=0;y<c->height/2;y++) {
        for(int x=0;x<c->width/2;x++) {
            frame->data[1][y * frame->linesize[1] + x] = 128 + y;
            frame->data[2][y * frame->linesize[2] + x] = 64 + x;
        }
    }


    frame->pts = 1;

    int got_output = 0;
    ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
    if (ret < 0)
    {
        printf("Error encoding frame\n");
        exit(1);
    }

    if (got_output)
    {
        printf("got frame\n");
        FILE* f = fopen("x.jpg", "wb");
        fwrite(pkt.data, 1, pkt.size, f);
        av_free_packet(&pkt);
    }

    avcodec_close(c);
    av_free(c);
    av_freep(&frame->data[0]);
    avcodec_free_frame(&frame);
    printf("\n");

    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文