简体   繁体   中英

Converting QImage to YUV420P pixel format

Has anybody solved this problem earlier? I need simple and fast method to convert QImage::bits() buffer from RGB32 to YUV420P pixel format. Can you help me?

libswscale , part of the ffmpeg project has optimized routines to perform colorspace conversions, scaling, and filtering. If you really want speed, I would suggest using it unless you cannot add the extra dependency. I haven't actually tested this code, but here is the general idea:

QImage img = ...     //your image in RGB32

//allocate output buffer.  use av_malloc to align memory.  YUV420P 
//needs 1.5 times the number of pixels (Cb and Cr only use 0.25 
//bytes per pixel on average)
char* out_buffer = (char*)av_malloc((int)ceil(img.height() * img.width() * 1.5));

//allocate ffmpeg frame structures
AVFrame* inpic = avcodec_alloc_frame();
AVFrame* outpic = avcodec_alloc_frame();

//avpicture_fill sets all of the data pointers in the AVFrame structures
//to the right places in the data buffers.  It does not copy the data so
//the QImage and out_buffer still need to live after calling these.
avpicture_fill((AVPicture*)inpic, 
               img.bits(), 
               AV_PIX_FMT_ARGB, 
               img.width(), 
               img.height());
avpicture_fill((AVPicture*)outpic, 
               out_buffer, 
               AV_PIX_FMT_YUV420P, 
               img.width(),
               img.height());

//create the conversion context.  you only need to do this once if
//you are going to do the same conversion multiple times.
SwsContext* ctx = sws_getContext(img.width(), 
                                 img.height(), 
                                 AV_PIX_FMT_ARGB, 
                                 img.width(), 
                                 img.height(), 
                                 AV_PIX_FMT_YUV420P, 
                                 SWS_BICUBIC, 
                                 NULL, NULL, NULL);

//perform the conversion
sws_scale(ctx, 
          inpic->data, 
          inpic->linesize, 
          0, 
          img.height(), 
          outpic->data, 
          outpic->linesize);

//free memory
av_free(inpic);
av_free(outpic);

//...

//free output buffer when done with it 
av_free(out_buffer);

Like I said, I haven't tested this code so it may require some tweaks to get it working.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM