For those looking for the same thing, below is my simple implementation. It
uses bilinear interpolation and works with 2D arrays of Real-s and
Integer-s (tested on Uint8 matrices mostly). Usage example:

 using Images
 using ImageView
 im = imread("...")
 dat = convert(Array, im)   # say, dat is a Matrix of size (256, 256)
 new_dat = imresize(dat, 128, 128)
 view(new_dat)

Resizing from (256, 256) to (128, 128) takes ~1.5ms on my machine, while
resizing same (256, 256) image to (512, 512) takes as long as ~60ms. So
it's definitely not high-performance implementation, but it does its work
and handles most frequent use cases.

---------------------------

# interpolate point at (x, y) from 4 nearby pixel values
function interp_bilinear{T <: Union(Real, Integer)}(dat::Array{T, 2},
                                                    x::Float64, y::Float64,
                                                    x1, x2, y1, y2)
    q11 = dat[y1, x1]
    q12 = dat[y2, x1]
    q21 = dat[y1, x2]
    q22 = dat[y2, x2]
    if x1 != x2
        r1 = (x2 - x) / (x2 - x1) * q11 + (x - x1) / (x2 - x1) * q21
        r2 = (x2 - x) / (x2 - x1) * q12 + (x - x1) / (x2 - x1) * q22
    else
        # special case of x1 == x2, no interpolation needed
        r1 = q11
        r2 = q12
    end
    if y1 != y2
        r = (y - y1) / (y2 - y1) * r1 + (y2 - y) / (y2 - y1) * r2
    else
        # special case of y1 == y2, no interpolation needed
        r = r1
    end
    if typeof(r) <: Real
        r = round(r)
    end
    r = convert(T, r)
    return r
end


function imresize{T <: Union(Real, Integer)}(dat::Array{T, 2},
                                             new_size::(Int, Int))
    new_dat = similar(dat, new_size)
    h, w = size(dat)
    new_h, new_w = new_size
    for new_j=1:new_w, new_i=1:new_h
        # coordinates in original image
        x = new_j * w / new_w
        y = new_i * h / new_h
        # coordinates of 4 points to interpolate from
        x1, x2 = max(1, floor(x)), min(w, ceil(x))
        y1, y2 = max(1, floor(y)), min(h, ceil(y))
        new_dat[new_i, new_j] = interp_bilinear(dat, x, y, x1, x2, y1, y2)
    end
    return new_dat
end


function imresize{T <: Union(Real, Integer)}(dat::Array{T, 2},
                                             new_size...)
    return imresize(dat, new_size)
end

---------------



On Wed, Jul 30, 2014 at 1:14 AM, Andrei Zh <[email protected]>
wrote:

>
>
> ...and Ron, Kevin, Lucas, etc ...
>>
>
> Surely, I'm just referring to someone I see on the mailing list very often
> :)
>
>
> Yeah, it's a pretty obvious omission, but to be truthful it's never come
>> up
>> for me so I've never implemented it. I will get to it eventually, but in
>> the
>> meantime if you need it soon it might be worth considering putting
>> something
>> together yourself. If you use Grid to do it (+ smoothing with imfilter or
>> imfilter_gaussian if you're downsizing and don't want aliasing), it
>> shouldn't
>> be more than 20 lines or so. But there are other approaches, see
>> http://stackoverflow.com/questions/384991/what-is-the-
>> best-image-downscaling-algorithm-quality-wise
>> which might involve more effort but also yield higher quality/speed.
>>
>
> I'm not so concerned about high quality, so I think I will dive into your
> code and maybe come up with a general solution.
>
>
>

Reply via email to