Bilinear interpolation: Difference between revisions
Content added Content deleted
Line 655: | Line 655: | ||
Lenna100.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, baseline, precision 8, 512x512, frames 3 |
Lenna100.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, baseline, precision 8, 512x512, frames 3 |
||
Lenna100-larger.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 96x96, segment length 16, comment: "CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality", baseline, precision 8, 820x820, frames 3</pre> |
Lenna100-larger.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 96x96, segment length 16, comment: "CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality", baseline, precision 8, 820x820, frames 3</pre> |
||
=={{header|Phix}}== |
|||
Gui app with slider for between 2 and 200% scaling. Various bits of this code scavenged from C#/Go/Kotlin/Wikipedia. |
|||
<lang Phix>-- demo\rosetta\Bilinear_interpolation.exw |
|||
include pGUI.e |
|||
function interpolate(atom s, e, f) |
|||
-- |
|||
-- s,e are the start and end values (one original pixel apart), |
|||
-- f is a fraction of some point between them, 0(==s)..1(==e). |
|||
-- eg s=91 (f=0.2) e=101, we want 0.8 of the 91 + 0.2 of 101, |
|||
-- aka if f is 4 times closer to s than e, we want 4 times as |
|||
-- much of s as we want of e, with sum(fractions_taken)==1. |
|||
-- |
|||
return s + (e-s)*f -- aka s*(1-f) + e*f |
|||
end function |
|||
function bilinear(integer c00, c10, c01, c11, atom fx, fy) |
|||
-- |
|||
-- for some output pixel, we have calculated the exact point |
|||
-- on the original, and extracted the four pixels surrounding |
|||
-- that, with fx,fy as the fractional x,y part of the 1x1 box. |
|||
-- Like a capital H, we want some fraction on the left and the |
|||
-- same on the right, then some fraction along the horizontal. |
|||
-- It would be equivalent to do top/bottom then the vertical, |
|||
-- which is handy since I am no longer certain which of those |
|||
-- the following actually does, especially since we got the |
|||
-- pixels from original[y,x] rather than original[x,y]. |
|||
-- |
|||
atom left = interpolate(c00,c10,fx), |
|||
right = interpolate(c01,c11,fx) |
|||
return floor(interpolate(left,right,fy)) |
|||
end function |
|||
function scale_image(imImage img, atom scaleX, scaleY) |
|||
integer width = im_width(img), |
|||
height = im_height(img), |
|||
new_width = floor(width * scaleX)-1, |
|||
new_height = floor(height * scaleY)-1 |
|||
atom mx = (width-1)/new_width, |
|||
my = (height-1)/new_height |
|||
sequence original = repeat(repeat(0,width),height) |
|||
sequence new_image = repeat(repeat(0,new_width),new_height) |
|||
-- Extract the original pixels from the image [about |
|||
-- twice as fast as 4*im_pixel() in the main loop.] |
|||
for y=height-1 to 0 by -1 do |
|||
for x=0 to width-1 do |
|||
original[height-y,x+1] = im_pixel(img, x, y) |
|||
end for |
|||
end for |
|||
for x=0 to new_width-1 do |
|||
for y=0 to new_height-1 do |
|||
atom ax = x*mx, -- map onto original |
|||
ay = y*my |
|||
integer ix = floor(ax), -- top left |
|||
iy = floor(ay) |
|||
ax -= ix -- fraction of the 1x1 box |
|||
ay -= iy |
|||
integer {r00,g00,b00} = original[iy+1,ix+1], |
|||
{r10,g10,b10} = original[iy+1,ix+2], |
|||
{r01,g01,b01} = original[iy+2,ix+1], |
|||
{r11,g11,b11} = original[iy+2,ix+2], |
|||
r = bilinear(r00,r10,r01,r11,ax,ay), |
|||
g = bilinear(g00,g10,g01,g11,ax,ay), |
|||
b = bilinear(b00,b10,b01,b11,ax,ay) |
|||
new_image[y+1,x+1] = {r,g,b} |
|||
end for |
|||
end for |
|||
new_image = flatten(new_image) -- (as needed by IupImageRGB) |
|||
Ihandle new_img = IupImageRGB(new_width, new_height, new_image) |
|||
return new_img |
|||
end function |
|||
IupOpen() |
|||
constant w = machine_word() |
|||
atom pError = allocate(w) |
|||
imImage im1 = imFileImageLoadBitmap("Lena.ppm",0,pError) |
|||
if im1=NULL then |
|||
?{"error opening image",peekNS(pError,w,1)} |
|||
{} = wait_key() |
|||
abort(0) |
|||
end if |
|||
Ihandle dlg, |
|||
scale = IupValuator(NULL,"MIN=2,MAX=200,VALUE=160"), |
|||
redraw = IupButton("redraw (160%)") |
|||
Ihandln image1 = IupImageFromImImage(im1), |
|||
image2 = scale_image(im1,1.6,1.6), |
|||
label1 = IupLabel(), |
|||
label2 = IupLabel() |
|||
IupSetAttributeHandle(label1, "IMAGE", image1) |
|||
IupSetAttributeHandle(label2, "IMAGE", image2) |
|||
function valuechanged_cb(Ihandle /*scale*/) |
|||
atom v = IupGetDouble(scale,"VALUE") |
|||
IupSetStrAttribute(redraw,"TITLE","redraw (%d%%)",{v}) |
|||
return IUP_DEFAULT |
|||
end function |
|||
IupSetCallback(scale,"VALUECHANGED_CB",Icallback("valuechanged_cb")) |
|||
function redraw_cb(Ihandle /*redraw*/) |
|||
IupSetAttributeHandle(label2, "IMAGE", NULL) |
|||
IupDestroy(image2) |
|||
atom v = IupGetDouble(scale,"VALUE")/100 |
|||
image2 = scale_image(im1,v,v) |
|||
IupSetAttributeHandle(label2, "IMAGE", image2) |
|||
IupSetAttribute(dlg,"SIZE",NULL) |
|||
IupRefresh(dlg) |
|||
return IUP_DEFAULT |
|||
end function |
|||
IupSetCallback(redraw,"ACTION",Icallback("redraw_cb")) |
|||
dlg = IupDialog(IupVbox({IupHbox({scale, redraw}), |
|||
IupHbox({label1, label2})})) |
|||
IupSetAttribute(dlg, "TITLE", "Bilinear interpolation") |
|||
IupCloseOnEscape(dlg) |
|||
IupShow(dlg) |
|||
IupMainLoop() |
|||
IupClose()</lang> |
|||
=={{header|Python}}== |
=={{header|Python}}== |