From richard.spindler at gmail.com Sun Apr 2 06:35:06 2006 From: richard.spindler at gmail.com (Richard Spindler) Date: Sun Apr 2 06:35:09 2006 Subject: [linux-graphics-dev] Fast 2x2 Downscaling Message-ID: <4af8d6ff0604020335n447af83agb7c800f4ebb3cd9d@mail.gmail.com> Hi, I'm looking for a code snipped that provides fast downscaling of RGB Images. It should only provide scaling to width/2 and height/2, arbitrary scaling factors are not needed. Example: 768x576 -> 384x288 Any pointers? -Richard From sjbaker1 at airmail.net Sat Apr 1 22:58:17 2006 From: sjbaker1 at airmail.net (steve) Date: Sun Apr 2 11:57:58 2006 Subject: [linux-graphics-dev] Fast 2x2 Downscaling In-Reply-To: <4af8d6ff0604020335n447af83agb7c800f4ebb3cd9d@mail.gmail.com> References: <4af8d6ff0604020335n447af83agb7c800f4ebb3cd9d@mail.gmail.com> Message-ID: <442F4BD9.4060301@airmail.net> Richard Spindler wrote: > Hi, > > I'm looking for a code snipped that provides fast downscaling of RGB > Images. It should only provide scaling to width/2 and height/2, > arbitrary scaling factors are not needed. > > Example: > 768x576 -> 384x288 It's not exactly rocket science. But there are some questions to be asked: 1) Does it have to deal with images that are an odd number of pixels across? 2) Is it sufficient to simply take every alternate pixel from every alternate row? Alternatively, do you require to average together four pixels from the input image in order to make the corresponding pixel in the output image? 3) Is the image in a linear colour space? If not (eg if it's gamma corrected) then simple averaging of pixels isn't the right thing to do. The simplest thing (assuming colours are stored as three consecutive bytes in the input array and you want to average the pixels together to get at least some semblance of quality and that the input image has always got an even number of rows and columns) would be: /* optr is a pointer to a place to store the output image. iptr is a pointer to the input image. iw and ih are the width and height of the input image respectively. */ void halve_image ( unsigned char *optr, unsigned char *iptr, int iw, int ih ) { int ow = iw >> 1 ; int oh = ih >> 1 ; int iw3 = iw * 3 ; /* Offset to get to the pixel below */ int iw33 = iw * 3 + 3 ; /* Offset to get to the pixel below/right */ for ( int i = 0 ; i < oh ; i++ ) { for ( int j = 0 ; j < ow ; j++ ) { /* Average red/green/blue for each pixel */ *optr++=(*iptr+*(iptr+3)+*(iptr+iw3)+*(iptr_3+iw33))>>2;iptr++; *optr++=(*iptr+*(iptr+3)+*(iptr+iw3)+*(iptr_3+iw33))>>2;iptr++; *optr++=(*iptr+*(iptr+3)+*(iptr+iw3)+*(iptr_3+iw33))>>2;iptr++; iptr += 3 ; /* Skip to the next pixel */ } iptr += iw3 ; /* Skip to the next row of pixels */ } } I havn't tested it - but it looks pretty good. If you need more speed, you could possibly unwrap the inner loop some more - or perhaps do red, green and blue in three separate passes of the image to reduce the number of pointer additions...but I doubt that'll buy you much because you're going to be memory bound for all but the smallest of images and the code above has better cache coherency. From richard.spindler at gmail.com Sun Apr 2 14:55:23 2006 From: richard.spindler at gmail.com (Richard Spindler) Date: Sun Apr 2 14:55:46 2006 Subject: [linux-graphics-dev] Fast 2x2 Downscaling In-Reply-To: <442F4BD9.4060301@airmail.net> References: <4af8d6ff0604020335n447af83agb7c800f4ebb3cd9d@mail.gmail.com> <442F4BD9.4060301@airmail.net> Message-ID: <4af8d6ff0604021155i369e6fbck2c24043dfd30d27f@mail.gmail.com> 2006/4/2, steve : > 2) Is it sufficient to simply take every alternate pixel from every > alternate row? Alternatively, do you require to average together > four pixels from the input image in order to make the corresponding > pixel in the output image? This depends on the users machine, it should be fast enough to do this in realtime, (25 fps), So some runtime detection might be appropriate. > I havn't tested it - but it looks pretty good. If you need more speed, > you could possibly unwrap the inner loop some more - or perhaps do > red, green and blue in three separate passes of the image to reduce > the number of pointer additions...but I doubt that'll buy you much > because you're going to be memory bound for all but the smallest of > images and the code above has better cache coherency. Thanks for the code, this should do exactly what I want. :) Maybe I can apply some libiol magic to enhance it further. -Richard From sjbaker1 at airmail.net Sun Apr 2 03:30:51 2006 From: sjbaker1 at airmail.net (steve) Date: Sun Apr 2 15:30:39 2006 Subject: [linux-graphics-dev] Fast 2x2 Downscaling In-Reply-To: <4af8d6ff0604021155i369e6fbck2c24043dfd30d27f@mail.gmail.com> References: <4af8d6ff0604020335n447af83agb7c800f4ebb3cd9d@mail.gmail.com> <442F4BD9.4060301@airmail.net> <4af8d6ff0604021155i369e6fbck2c24043dfd30d27f@mail.gmail.com> Message-ID: <442F7DAB.40503@airmail.net> Richard Spindler wrote: > 2006/4/2, steve : > >>2) Is it sufficient to simply take every alternate pixel from every >> alternate row? Alternatively, do you require to average together >> four pixels from the input image in order to make the corresponding >> pixel in the output image? > > > This depends on the users machine, it should be fast enough to do this > in realtime, (25 fps), So some runtime detection might be appropriate. If you need to do it in realtime - for the purposes of displaying the image - then you should consider stuffing the images into the graphics card as texture maps and just drawing them smaller. Some graphics cards support an extension to perform MIPmapping in hardware...that might be appropriate in some circumstances. From richard.spindler at gmail.com Sun Apr 2 15:39:18 2006 From: richard.spindler at gmail.com (Richard Spindler) Date: Sun Apr 2 15:39:30 2006 Subject: [linux-graphics-dev] Fast 2x2 Downscaling In-Reply-To: <442F7DAB.40503@airmail.net> References: <4af8d6ff0604020335n447af83agb7c800f4ebb3cd9d@mail.gmail.com> <442F4BD9.4060301@airmail.net> <4af8d6ff0604021155i369e6fbck2c24043dfd30d27f@mail.gmail.com> <442F7DAB.40503@airmail.net> Message-ID: <4af8d6ff0604021239h47ee75c0r7d8daacc2e4435ce@mail.gmail.com> 2006/4/2, steve : > If you need to do it in realtime - for the purposes of displaying > the image - then you should consider stuffing the images into the > graphics card as texture maps and just drawing them smaller. That's what I'm doing, but some graphics boards are limited in their texture size. -Richard