Neat!
The easiest way to share this with others would be to submit a pull request to
Images using Pkg.submit("Images"). There are a couple of things that could be
done pretty easily to generalize this, and we could punt on anything hard---
better to have an implementation that works for many types. We could discuss
them if you decide to move forward.
Best,
--Tim
On Sunday, August 03, 2014 04:34:18 PM Andrei wrote:
> 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.