|
|
| [C]how to zoom an image with bilinear-interpolation |
|
jack_folla
Member #11,098
June 2009
|
hi, |
|
Tobias Dammers
Member #2,604
August 2002
|
Not in the 4.2 branch, no. --- |
|
jack_folla
Member #11,098
June 2009
|
i add some useful information: |
|
Tobias Dammers
Member #2,604
August 2002
|
jack_folla said:
-i need to scale up an image (black&white) into anotherone with no pre-defined scale-up ratio The ratio can be calculated from the source and destination image sizes, so this is pretty irrelevant. Quote: -i need to do this using c language All the solutions I mentioned are possible using C. Allegro, AllegroGL, and OpenGL are all C libraries. Quote: -what do you mean for 4.9 allegro branch?
What I said. The 4.9 branch, that is, versions starting with 4.9. The 4.2 versions don't have hardware acceleration (at least not beyond some fairly limited video-video blitting and special CPU operations), but you can use the alleggl add-on to enable the GFX_OPENGL driver, and use OpenGL commands to draw things (including textured quads, which is exactly what you need to scale an image). If real-time performance is not required, I recommend you write the conversion routine yourself. It's not THAT hard, really, especially when it's just black & white. --- |
|
Oscar Giner
Member #2,207
April 2002
|
If it doesn't need to be realtime, you can check my implementation of a software bilinear re-size, which can be found in the allegro wiki. If you only want magnifying then forget about the reduce_mipmap function, that's only useful (for better quality) for scaling down. It's pretty optimized, but probably it still cannot be used for realtime resizing (though I haven't tested with a modern computer, when I wrote this I was using a Pentium 166 -- |
|
jack_folla
Member #11,098
June 2009
|
i've just seen your implementation of the software bilinear re-size,but there were some problem: |
|
Thomas Harte
Member #33
April 2000
|
In bilinear upscaling, the pixel drawn from (x, y) of the original image can be found by (in pseudocode): colourTopLeft = pixel at floor(x), floor(y) colourTopRight = pixel at ceil(x), floor(y) colourBottomLeft = pixel at floor(x), ceil(y) colourBottomRight = pixel at ceil(x), ceil(y) offsetX = fmod(x, 1) offsetY = fmod(y, 1) topRowColour = colourTopRight*offsetX + colourTopLeft*(1 - offsetX) bottomRowColour = colourBottomRight*offsetX + colourBottomLeft*(1 - offsetX) pixelColour = bottomRowColour*offsetY + topRowColour*(1 - offsetY) There are potentially some issues with wrapping and texel alignment. I've put the lit bit on the top left of each square and the wrapping relates to, for example drawing pixels from the extreme right-hand side of the source image. Bilinear filtering assumes it can always find four colours that surround the location you're querying, but at some point you go so far right that you have only the two colours to the left and nothing to the right — usually you'll either wrap around back to the lefthand side or 'clamp' values so that you end up with a linear filter on the edges rather than a bilinear one. Exactly how you want to deal with those issues is application specific, if you're doing anything sufficiently rigourous to require doubles then I'm sure you'll be able to figure out what you want. It will be far from the most speedy implementation, but if you step through the output pixels, scale them to their location in the source then apply the above, you'll get the number you want. So maybe do that and optimise up from there if speed is an issue? E.g. for(int outputx = 0; outputx < outputwidth; outputx++) for(int outputy = 0; outputy < outputheight; outputy++) { // yes, I'm casting too much double sourcex = (double)outputx * (double)sourcewidth / (double)outputwidth; double sourcey = (double)outputy * (double)sourceheight / (double)outputheight; <apply above code to get pixelColour> let colour at (outputx, outputy) = pixelColour }
[My site] [Tetrominoes] |
|
Oscar Giner
Member #2,207
April 2002
|
If it's just an array of doubles then what you need is much simpler than my code, since accesing the bitmap data is the complex part (specially doing it in an efficient way). Just change all the code that reads and writes to the bitmap and whenever you find r, g and b values, you just have one in your case (the formulas are the same, but you only apply them to one value). Remove any code wraped inside an #ifdef ALGO_1, since that code is an optimization that would only apply when reading from allegro Bitmaps. -- |
|
|