[FFmpeg-devel] PNG output horrible...

Peter Tap ptrtap at yahoo.com
Mon Sep 10 03:25:35 CEST 2012

Comparing the original file to the generated file, here is what I see:

original.png : PNG image data, 128 x 128, 8-bit/color RGBA, non interlaced

new.png : PNG image data, 128 x 128, 8-bit/color RGB, non interlaced

The original file size is 13017 bytes. The new file size is 6840 bytes.

Perhaps this gives you some more ideas.


----- Original Message -----
From: Peter Tap <ptrtap at yahoo.com>
To: "ffmpeg-devel at ffmpeg.org" <ffmpeg-devel at ffmpeg.org>
Sent: Sunday, September 9, 2012 4:22 PM
Subject: PNG output horrible...


In my application, I open and read a png file and create a new png file as output. However, I am not getting the same quality of output. I would appreciate it if someone can point the mistake in my code. I will walk you through the code. For clarity, I have removed all the error checking.

SaveFrameToFile(AVFrame* pFrame, int width, int height, const char* format) {
    AVCodec* encoderCodec = avcodec_find_encoder_by_name(format);
    AVCodecContext* encoderCtx = avcodec_alloc_context();
    avcodec_open2(encoderCtx, encoderCodec, NULL);

    encoderCtx->width = width;
    encoderCtx->height = height;
    encoderCtx->pix_fmt = PIX_FMT_RGB24; // Is this line really needed? 

    int bufferSize = avpicture_get_size(encoderCtx->pix_fmt, width, height);
    uint8_t* buffer = (uint8_t*) av_malloc(bufferSize);
    int newSize = avcodec_encode_video(encoderCtx, buffer, bufferSize, pFrame);

    FILE* pFile = fopen(...);
    fwrite(buffer, 1, newSize, pFile);

    // Do the necessary cleanup

This method is straight-forward. It encodes the frame in the given format and writes to a file.
AllocAVFrame(PixelFormat fmt, int width, int height) {
   AVFrame* retVal = avcodec_alloc_frame();
   int size = avpicture_get_size(fmt, width, height);
   uint8_t* frameBuf = (uint8_t*) av_malloc(size);
   avpicture_fill((AVPicture*) retVal, frameBuf, fmt, width, height);
   return retVal;

This method is also straight-forward. It just creates a new frame of given format, width, and height.

Now, here is main program loop:

  AVFrame* pFrame = avcodec_alloc_frame();

  AVPacket packet;
  while(av_read_frame(pFormatCtx, &packet) >= 0) {
      int  frameFinished;
      int len = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
      if(frameFinished) {
         PixelFormat fmt = PIX_FMT_RGB24;
         AVFrame* outputFrame = AllocAVFrame(fmt, w, h);
        SwsContext* imgConvertCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
                SWS_BICUBIC,  NULL, NULL, NULL);
          (const uint8_t* const*)pFrame->data,
        SaveFrameToFile(outputFrame, pCodecCtx->width, pCodecCtx->height, "png");
     // Clean up

Here, we decode the input, convert to PIX_FMT_RGB24, and save the frame to a file.

This code works in the sense that when I view the generated file, I do see the original image. However, the quality of the output is very bad. 

I am wondering if anyone can correct my mistake. Is it some bitrate I need to consider?

A higher bitrate would imply a longer buffer size. However, av_picture_get_size does not take bitrate as a parameter. In this case, how would you obtain proper buffer size?

Another related question while we are looking at the code. I have the original frame obtained out of avcodec_decode_video2. If I just try to save this frame to the file, it works partially. The output file contains only a grayscale image and the shape is also a bit crooked. Why?

Thank you in advance for your help.


More information about the ffmpeg-devel mailing list