[Libav-user] Scaling via sws_scale() produces wrong colourvalues

Johannes Ebersold johannes.ebersold at dfki.de
Wed Jun 29 10:30:03 CEST 2011


Hi,

Aaron, thanks for your advice :)

I tried the different filtering. Using SWS_POINT produces a picture with 
the value 253 for every byte, this is better, but still not optimal. To 
me this seems like a bug? I rather expected that scaling down a complete 
white image shall reproduce another complete white image...

I also wrote a small example to reproduce the issue:

         //setup src and dst
         int w = 1920;
         int h = 1080;
         int size = 3 * w * h;
         unsigned char src[size];
         memset(src,0xFF,size);

         int new_w = 960;// 1920 960
         int new_h = 540;// 1080 540
         int new_size = 3 * new_w * new_h;
         unsigned char dst[new_size];
         //memset(dst, 0x00, new_size);

         //struct SwsContext *sws_getCachedContext(struct SwsContext 
*context, int srcW, int srcH, enum PixelFormat srcFormat, int dstW, int 
dstH, enum PixelFormat dstFormat, int flags, SwsFilter *srcFilter, 
SwsFilter *dstFilter, const double *param);
         m_convert_context = sws_getCachedContext(m_convert_context, w, 
h, PIX_FMT_RGB24, new_w, new_h, PIX_FMT_RGB24, 
SWS_FAST_BILINEAR/*SWS_POINT*/, NULL, NULL, NULL);

         //use arrays of pointers, sws_scale need such an array, despite 
its just one plane
         unsigned char* src_data[3] = {src, NULL, NULL};
         int src_stride[3] = {3*w, 0, 0}; //RGB stride is 3*width
         //use offsets to set pointers
         unsigned char* dst_data[3]= {dst, NULL, NULL};
         int dst_stride[3] = {3*new_w, 0, 0};

         //convert
         //int sws_scale(struct SwsContext *context, const uint8_t* 
const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, 
uint8_t* const dst[], const int dstStride[]);
         int ret = sws_scale(m_convert_context, src_data, src_stride, 0, 
h, dst_data, dst_stride);
         if (ret < 0){std::cout << "sws_scale failed: " << ret << 
std::endl;}
         else{std::cout << "sws_scale succeeded: " << ret << std::endl;}

         //check the values
         for(int x=0; x<new_size; x++){
             if(dst[x]!= 0xFF){std::cout << "wrong value " << (int) 
dst[x] << " at " << x << std::endl;}
         }

Regards ... Johannes

On 06/29/2011 01:43 AM, Aaron Zinghini wrote:
> Just a quick guess but I believe it is because of the filtering (SWS_FAST_BILINEAR). Filtering is used to remove aliasing effects when resizing an image and therefore you won't get a 1-1 mapping of pixels and the filtering will use neighbouring pixels to basically "blend" or smooth the image so it's not blocky after resize.
>
> If there's an option like SWS_NONE or maybe SWS_POINT then they might produce more of a 1-1 mapping.
>
> -----Original Message-----
> From: libav-user-bounces at ffmpeg.org [mailto:libav-user-bounces at ffmpeg.org] On Behalf Of Johannes Ebersold
> Sent: Wednesday, 29 June 2011 1:54 AM
> To: libav-user at ffmpeg.org
> Subject: [Libav-user] Scaling via sws_scale() produces wrong colourvalues
>
> Hi,
>
> I'm currently trying to scale a RGB picture using libswscale.
> I tested my application by creating a complete white image, set every
> byte to 255. But in the output after the scaling every pixel got the
> value "254 251 251". I don't know what i got wrong and would be thankful
> for any advice.
>
> My Code is part of a larger project, i will just paste a snippet here...
> So far i think, that i got something wrong initializing or using the
> swscale.
>
> m_convert_context = sws_getCachedContext(m_convert_context,
> src_res.first, src_res.second, PIX_FMT_RGB24, m_dst_res.first,
> m_dst_res.second, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
>
> //src = Pointer to a packed RGB image with
> unsigned char* src_data[3] = {src, NULL, NULL};
> int src_stride[3] = {3*src_res.first, 0, 0}; //RGB stride is 3*width
>
> /use offsets to set pointers, dst is just a pointer to some memory,
> where the resulting image will be...
> unsigned char* dst_data[3]= {dst, NULL, NULL};
> int dst_stride[3] = {3*m_dst_res.first, 0, 0};
>
> //convert
> int ret = sws_scale(m_convert_context, src_data, src_stride, 0,
> src_res.second, dst_data, dst_stride);
>
> Thanks for any help!
> Johannes
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user



More information about the Libav-user mailing list