multiple rasters && mapview
Jonathan Coles
jonathan at jpcoles.com
Tue Jan 18 00:33:58 CET 2005
Am Freitag, den 14.01.2005, 15:22 -0500 schrieb Russell Nelson:
> Jonathan Coles writes:
> > are you going to be looking into changing ProjectRasterFile to return a
> > wxImage?
>
> I need more experience with wxWindows, so I'm going to work on the
> Terra Raster Layer first. It would be great if you could do it.
well, i spent the majority of saturday working on this, and i think i've
got a nice solution.
quick overview
==============
o Faster rendering:
- Changed the output format of ProjectRasterFile to an
array of RGB values, which eliminates the need for
wxImageFromStream. If the format is something else
then continue to use wxImageFromStream.
- Instead of using the custom gdal driver, use the in-memory
driver already provided and do a quick data translation.
o NO_DATA support from gdal. parts of a projected image that
aren't "real" are colored in a fixed color which can
optionally be masked off when the image is draw.
o Smaller code size. the changes actually greatly simplified
the code, allowing me to remove several support files.
o Small memory leak in ProjectRasterFile found and fixed.
detailed explanation
====================
it isn't possible to return a wxImage from ProjectRasterFile
because a wxImage at the C++ level is very different from the wxImage in
python. however, it is possible to return an array of RGB values where
the length of the array equals 3*width*height. this may not sound much
different from before, but wxImage has a method called SetData which
expects an array just like the one i described. calling SetData is a
fast operation, unlike wxImageFromStream, which was uncompressing a BMP
file.
before i could return an array like this, i ripped out the old gdal
driver i had written/modified. the driver was the gdal BMP driver that
had been changed so instead of writing data to a file it would write it
to memory. the modifications had required that i also implement my own
version of the file I/O interface to hide a linked list. i discovered a
much better way.
gdal already has an in-memory driver which writes the data to memory.
the only problem is that the organization of the data is not in RGB
format. i wrote the function GetImageData that translates the data from
the raster band format with color table lookup into a contiguous array
of RGB values. doing this meant i could throw away my BMP driver and
memory I/O code (files bmpdataset.cpp and cpl_mfile.* can be deleted). i
did have to copy over the file memdataset.h from the gdal source since
it is not available in the debian development package. i'm attaching the
file, which needs to be put in libraries/thuban.
you may wonder if it is worth writing a specialized memory driver that
stores the data in the proper format as soon as the driver's write
function is called. i thought about this and came to the conclusion that
the only savings would be a bit of memory because an additional array
has to allocated to perform the copy. there would be no real speed
difference since the same translation code would have to execute in the
write function. whether the translation occurs as the data is written or
afterwards makes no difference. if the memory problem really becomes an
issue in the future, then this may be the way to go, but for now the
trouble of writing and then maintaining such code is not worth it (IMO).
after all of these changes, almost all of the time that is being spent
in ProjectRasterFile is spent calling GDALSimpleImageWarp(). on tests i
ran with the Thuban window very large and the iceland sample at full
extent, a call to GDALSimpleImageWarp took, on average, 0.4 seconds. i'm
not sure what can be done to improve this, as a call to
GDALSimpleImageWarp may be a hard limit.
on the python end of things, i kept the changes i made earlier in the
week which attempted to use the bounding box of the raster layer, rather
than the extents of the whole window. this is known not to be accurate
and i agree with bernhard herzog that the best way around this is using
a mask (more on this later). a simple 'if' in the code toggles between
the two methods. the code has to be modified directly to see the
difference.
i also changed the calling signature of draw_raster_data to
draw_raster_data(self, x, y, data, format="BMP", mask = None). there is
a new format called "RAW". i thought about making this the default,
since that is what gdal returns, but decided to hold off on that until i
get some feedback. in the implementation of draw_raster_data in
renderer.py the RAW format is handled by creating and empty image and
then calling SetData with the raw image data. this is much faster than
calling wxImageFromData with BMP file data. the other formats are still
supported, but they still go through the old, slower method of calling
wxImageFromData. some of the test cases had to be updated to account for
these changes.
the mask parameter is documented in the function description, but
basically, it allows a few methods of supplying masking information: the
simplest of which is to specify a color that isn't to be drawn. not
surprisingly, using the mask slows down the call to DrawBitmap. when no
using a mask there is almost no slow down in rendering the final image.
all the time is spent warping it.
it will be possible in the future to add support for alpha blending if
that is desired. newer versions of wxWindows supports this and it would
be very easy to modify GetImageData to create an array of alpha data to
supply to a wxImage.
currently, ProjectRasterFile calls GDALSimpleImageWarp. in fact, most
of gdalwarp.cpp was taken from the sample application
gdalwarpsimple.cpp. it is called "simple" because it only supports 8-bit
images and limited warping options. there is a more complex version that
supports any datatype and significantly more options. the sample
application is called gdalwarp.cpp and comes with the gdal source code.
Thuban would, obviously, benefit to use the complex version.
if the parameters to and results from a call to ProjectRasterData were
cached, as was suggested, this would improve the case when the user is
just resizing the window or, in some cases, panning. care would need to
be taken in doing so, because if a layer is removed the cached image
data should be deleted too.
i removed the optimizations in layer drawing that drew the top most
raster layer and then only layers above that. i did this with the
anticipation of supporting multiple raster layers where the bounding box
is not the whole screen or a mask is used.
i've only been able to run tests using the iceland sample. i don't have
any data with multiple, overlapping raster layers. if anyone does have
such data and can send it to me, that would be great.
ok, i think that's all for now :) i'm attaching the cvs diff and
memdataset.h
--jonathan
--
=====================================================================
Jonathan Coles http://www.jpcoles.com
jonathan at jpcoles.com GnuPG Key: /gpg_pub_key.asc
=====================================================================
-------------- next part --------------
A non-text attachment was scrubbed...
Name: memdataset.h
Type: text/x-chdr
Size: 5598 bytes
Desc: not available
Url : http://www.intevation.de/pipermail/thuban-devel/attachments/20050117/6827d2ee/memdataset.h
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cvs.diff
Type: text/x-patch
Size: 19337 bytes
Desc: not available
Url : http://www.intevation.de/pipermail/thuban-devel/attachments/20050117/6827d2ee/cvs.diff
More information about the Thuban-devel
mailing list
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)