Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [C]how to zoom an image with bilinear-interpolation

This thread is locked; no one can reply to it. rss feed Print
[C]how to zoom an image with bilinear-interpolation
jack_folla
Member #11,098
June 2009

hi,
I'm writing to know if exist some function in allegro library for
enlarging an image (BW) with bilinear-intepolation
THANKS???

Tobias Dammers
Member #2,604
August 2002
avatar

Not in the 4.2 branch, no.
You have several options:
a) use the 4.9 allegro branch instead
b) use allegrogl and ideally some opengl calls to render your graphics (opengl gives you a lot of control over resizing algorithms and such)
c) see if you can find an add-on for allegro that does this in software (but be prepared that software resizing is a lot slower)
d) code your own routine that does this; this is probably the worst solution, unless you are a graphics programming wizard of some sort

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

jack_folla
Member #11,098
June 2009

i add some useful information:
-i need to scale up an image (black&white) into anotherone with no pre-defined scale-up ratio
(the dimension of the output image is known)
-i need to do this using c language
(i need to use this code into matlab throw mex-file)
-what do you mean for 4.9 allegro branch?
thanks

Tobias Dammers
Member #2,604
August 2002
avatar

-i need to scale up an image (black&white) into anotherone with no pre-defined scale-up ratio
(the dimension of the output image is known)

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.
Some background on this: The current stable version of allegro is 4.2.something, and development on that has pretty much come to a halt. Some bugfix releases may be made, but I doubt even that is going to happen.
The next stable release will be a major rewrite with a new API, which will be incompatible with previous versions; the version number is probably going to be 5.0. The 'unstable' versions preceding it carry numbers starting with 4.9, just like the unstable versions leading to 4.2.x are 4.1.x.
The allegro rewrite includes hardware acceleration (through OpenGL and, if you're on windows, DirectX), and will take advantage of it wherever this makes sense.

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.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Oscar Giner
Member #2,207
April 2002
avatar

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 :D). If you need any help using it just ask.

jack_folla
Member #11,098
June 2009

i've just seen your implementation of the software bilinear re-size,but there were some problem:
-my image is no a bitmap file but a matrix of double
- i dont need to scale up an RGB image,my object as i've just said is a matrix of double and it represents a B&W image
is it possible to easily adapt your code?in wich way?
thanks

Thomas Harte
Member #33
April 2000
avatar

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
  }

Oscar Giner
Member #2,207
April 2002
avatar

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.

Go to: