I've implemented Grid-based version, but it seems much slower than both -
Cairo and mine. Am I using Grid the wrong way? Or does Grid just take care
of more use cases?
-----
function imresize_grid{T <: Float64}(dat::Array{T, 2}, new_size::(Int, Int))
new_dat = similar(dat, new_size)
h, w = size(dat)
new_h, new_w = new_size
grid = InterpGrid(dat, BCnil, InterpLinear)
for new_j=1:new_w, new_i=1:new_h
# coordinates in original image
i = new_i * h / new_h
j = new_j * w / new_w
new_dat[new_i, new_j] = grid[i, j]
end
return new_dat
end
----
And here are performance tests (imf64 is an Array{Float64, 2}, while imu32
is the same image converted to Array{Uint32, 2}):
julia> @time for i=1:1000 imresize(imf64, (128, 128)) end
elapsed time: 0.697520586 seconds (131184000 bytes allocated, 15.41% gc
time)
julia> @time for i=1:1000 imresize_cairo(imu32, (128, 128)) end
elapsed time: 0.288527903 seconds (393616000 bytes allocated, 24.78% gc
time)
julia> @time for i=1:1000 imresize_grid(imf64, (128, 128)) end
elapsed time: 4.759103481 seconds (1443800000 bytes allocated, 14.29% gc
time)
On Thu, Aug 7, 2014 at 4:21 AM, Tim Holy <[email protected]> wrote:
> I bet we can meet or beat Cairo; I've never found Cairo to be terribly
> fast.
> But of course one doesn't know until one tries.
>
> Given that the main issue is really interpolation, it (and some of the
> refactoring that's currently under discussion) seems relevant. There's some
> work brewing on a new version of Grid, and being able to do this
> performantly
> and easily can become a goal there. Grid already has more interpolation
> options than Cairo does.
>
> --Tim
>
> On Thursday, August 07, 2014 01:41:39 AM Andrei wrote:
> > @Andreas: thanks and sorry for late reply.
> >
> > Using your code, I created testable function that works almost 10x times
> > faster then my naive implementation! Right now, though, it rotates image
> 90
> > degrees to the left for some reason I don't really understand, but I
> > believe it's fixable.
> >
> > Here's a code for (not fully correct) function:
> >
> > function imresize_cairo(dat::Array{Uint32, 2}, new_size::(Int, Int))
> > cs = CairoImageSurface(dat, 0)
> > new_dat = zeros(Uint32, new_size)
> > new_cs = CairoImageSurface(new_dat, 0)
> > pat = CairoPattern(cs)
> > pattern_set_filter(pat, Cairo.FILTER_BILINEAR)
> > c = CairoContext(new_cs)
> > h, w = size(dat)
> > new_h, new_w = new_size
> > scale(c, new_h / h, new_w / w)
> > set_source(c, pat)
> > paint(c)
> > return new_cs.data
> > end
> >
> >
> > I'm pretty satisfied with this version (or what it should turn into)
> both -
> > because of its speed and possibility to use different interpolation
> > schemas. Though, one disadvantage of using it in public package like
> > Images.jl is that it brings additional dependency, and we all know how
> > annoying these dependencies may be sometimes. We could implement 2
> versions
> > - one with Cairo and fast and another simple and slow - and then load
> > appropriate function via macros. But since simple version doesn't support
> > interpolation other than bilinear, we will have to restrict Cairo version
> > to this type too to keep same interface. Or we can just 2 different
> > functions, but it may be pretty confusing for new users.
> >
> > Some opinions on a better approach would be helpful here.
> >
> >
> >
> >
> > On Tue, Aug 5, 2014 at 11:24 AM, Andreas Lobinger <[email protected]>
> >
> > wrote:
> > > An example looks like this:
> > >
> > > using Cairo
> > >
> > > # prepapration, an image of 2x2 pixels, an target of 8x8 pixels
> > >
> > > d = [8 4; 2 1];
> > > d0 = reinterpret(Uint32,d);
> > > cs0 = Cairo.CairoImageSurface(d0,0); # 0 as FORMAT_ARGB32
> > > show(cs0.data)
> > > print('\n')
> > >
> > > d2 = zeros(Uint32,8,8);
> > > cs2 = Cairo.CairoImageSurface(d2,0);
> > >
> > > p = Cairo.CairoPattern(cs0);
> > >
> > > # just scale by using FILTER_NEAREST
> > >
> > > pattern_set_filter(p,Cairo.FILTER_NEAREST);
> > > c = Cairo.CairoContext(cs2);
> > > scale(c,4,4);
> > > set_source(c,p);
> > > paint(c);
> > > show(cs2.data)
> > > print('\n')
> > >
> > > # now interpolate
> > >
> > > d3 = zeros(Uint32,8,8);
> > > cs3 = Cairo.CairoImageSurface(d3,0);
> > >
> > > pattern_set_filter(p,Cairo.FILTER_GOOD);
> > > c = Cairo.CairoContext(cs3);
> > > scale(c,4,4);
> > > set_source(c,p);
> > > paint(c);
> > > show(cs3.data)
> > > print('\n')
> > >
> > > and gives on my command line:
> > >
> > > julia> include("ca.jl")
> > > Uint32[8 2
> > >
> > > 4 1]
> > >
> > > Uint32[8 8 8 8 2 2 2 2
> > >
> > > 8 8 8 8 2 2 2 2
> > > 8 8 8 8 2 2 2 2
> > > 8 8 8 8 2 2 2 2
> > > 4 4 4 4 1 1 1 1
> > > 4 4 4 4 1 1 1 1
> > > 4 4 4 4 1 1 1 1
> > > 4 4 4 4 1 1 1 1]
> > >
> > > Uint32[3 4 4 3 2 1 1 0
> > >
> > > 4 6 6 5 3 2 1 1
> > > 4 6 6 5 3 2 1 1
> > > 4 5 5 4 3 2 1 1
> > > 3 4 4 3 2 1 1 0
> > > 2 3 4 3 2 1 0 0
> > > 2 3 3 2 1 1 0 0
> > > 1 2 2 1 1 0 0 0]
> > >
> > > But this is just how to handle the data. For interpreting the pixels
> > > correctly you need to read little bit about the colormodel and pixel
> > > formats.
> > >
> > >
> > > Wishing a happy day,
> > >
> > > Andreas
>
>