Преобразуйте необработанный буфер изображения в JPEG, используя LIBAVCODEC

У меня есть необработанный буфер изображения (в памяти), снятый с камеры, который я хочу преобразовать в JPEG (для уменьшения размера). Проблема в том, что сохранение этих изображений в формате .pgm приводит к огромному размеру файла, который я не могу себе позволить из-за ограничений памяти и задержки, связанных с сохранением огромного файла такого размера (ограничение в приложении, над которым я работаю) .

Я хочу знать, как сжать/кодировать буфер изображения в формат .jpg с помощью LIBAVCODEC? Мой код захвата изображения написан на C.


person user846400    schedule 20.02.2012    source источник
comment
Есть ли причина, по которой вам нужно использовать libav вместо библиотеки для изображений или даже для jpeg?   -  person blahdiblah    schedule 29.02.2012


Ответы (1)


этот код работает с необработанными изображениями YUV. Я получил segfault, пытаясь закодировать необработанное изображение 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;
}
person arash kordi    schedule 24.09.2012