Opened 16 years ago

Closed 16 years ago

#2327 closed defect (fixed)

cubicspline resampling and other resamplers don't work for the entire image

Reported by: sprice Owned by: dron
Priority: normal Milestone: 1.6.0
Component: GDAL_Raster Version: svn-trunk
Severity: normal Keywords: warper cubicspline cubic bilinear near
Cc: dron, martinoty

Description

If I resample a large image (14400x14400px) using cubicspline to be much smaller (1024x1024px), the cubic spline resampling seems to miss some 'strips' of the image. These 'strips' end up looking like nearest neighbor sampling is being used, and look similar to static in my raster set. The strips appear at regular intervals inside the image, and along the edges. This problem does not appear when using cubic interpolation.

These problem 'strips' become quite obvious when using a ZonePlate test image (and ImageMagick): http://www.worldserver.com/turk/opensource/#ZonePlate

I generated my test image using these commands: ./ZonePlate -w 14400 -h 14400 -s 1 -o z14400.gray convert -size 14400x14400 gray:z14400.gray PNG42:z14400.png

Here is the warp command: gdalwarp -r cubicspline -ts 1024 1024 z14400.tif z14400.cs.tif

Attached is the output I get. The input is simply concentric rings of varying frequency. The output should be mostly gray, but instead has strips of black & white running through it.

Attachments (21)

z14400.cs.png (188.3 KB ) - added by sprice 16 years ago.
z14400.conv.png (289.2 KB ) - added by sprice 16 years ago.
The resampled image should look something similar to this. ImageMagick produces this image when resizing. Image pixel size has been reduced so the bug tracker would accept it.
cubicspline.diff (11.9 KB ) - added by sprice 16 years ago.
found a bug, fixed a bug (new line 1807)
Resampling_src.zip (17.5 KB ) - added by martinoty 16 years ago.
code example for downsampling and upsampling
cubicspline2.diff (12.6 KB ) - added by sprice 16 years ago.
Another bug fixed. I found that for many of the chunks the width or height was '0'. Perhaps this is a bug somewhere else in the code? Nonetheless, bug fixed by passing the buck to GWKBilinearResample().
cubicspline2.2.diff (13.2 KB ) - added by sprice 16 years ago.
Fixed another bug. You guys sure feed the function some odd image sizes and source coordinates…
cubicspline3.diff (50.0 KB ) - added by sprice 16 years ago.
more updates and speedups
cubicspline3.2.diff (45.5 KB ) - added by sprice 16 years ago.
new patch ignores white space; should be easier to review
cubicspline3.3.diff (49.6 KB ) - added by sprice 16 years ago.
New patch fixes a segfault and crops sampling at image edge instead of flipping over edge. Resulted in small speedup and better accuracy from what I can tell.
cubicspline3.4.diff (49.7 KB ) - added by sprice 16 years ago.
Fixed another segfault
cubicspline3.5.diff (49.7 KB ) - added by sprice 16 years ago.
Mode implementation bug fix
cubicspline3.6.diff (45.1 KB ) - added by sprice 16 years ago.
diff -ub …
cubicspline3.7.diff (48.5 KB ) - added by sprice 16 years ago.
tabs replaced with spaces
cubicspline3.8.diff (55.8 KB ) - added by sprice 16 years ago.
1, 3 & more comments
cubicspline3.9.diff (50.4 KB ) - added by sprice 16 years ago.
diff -ub …
cubicspline3.10.diff (54.9 KB ) - added by dron 16 years ago.
cubicspline4.diff (5.1 KB ) - added by sprice 16 years ago.
cubicspline5.diff (7.8 KB ) - added by sprice 16 years ago.
all known problems fixed
cubicspline5.2.diff (9.3 KB ) - added by sprice 16 years ago.
I think I got it this time
cubicspline5.3.diff (8.7 KB ) - added by sprice 16 years ago.
No debug code this time
cubicspline6.diff (3.5 KB ) - added by sprice 16 years ago.
GWKBilinearResample()

Download all attachments as: .zip

Change History (60)

by sprice, 16 years ago

Attachment: z14400.cs.png added

by sprice, 16 years ago

Attachment: z14400.conv.png added

The resampled image should look something similar to this. ImageMagick produces this image when resizing. Image pixel size has been reduced so the bug tracker would accept it.

comment:1 by warmerdam, 16 years ago

Cc: dron added
Component: defaultGDAL_Raster
Keywords: warper cubicspline added

Andrey,

Would you want to take this one?

comment:2 by sprice, 16 years ago

I've attached a rather significant diff. Apologies in advance for the quantity of it. I was working on optimizing some code when I noticed the cause of the bug described here, then fixed it. Summary: I've made changes to GWKGetPixelValue() BSpline() and the GWKCubicSplineResample*() functions.

A description of what's changed and the corresponding line numbers:

New lines 915-925 are simply combining two 'if' statements. It gives the compiler a bit more to work with, and the function is sped up a small amount. 5-10% depending on the measurement.

New lines 1596-1609 have been rearranged to remove redundant and expected calculations. The 'if' statements have been rearranged to shortcut each other and avoid unnecessary branch tests. This resulted in a 10-20% speedup of the function, IIRC.

New lines 1748-1761 are simply saving a local integer so the code doesn't have to continually follow pointers. Said integers will be used later inside the loop.

Here is the first part of the fix to this bug. Old lines 1762-1770 have been removed because they were causing the 'static'. The static was simply the use of the bilinear resampler when it may not have been appropriate. The remaining function has been altered to handle the edge case natively.

New line 1766 has had some minor efficiency tweaks. The variable 'jC' was introduced because it's used a few times in the main loop and otherwise had to be calculated.

New lines 1774-1780 are part of the bug fix. I'm adjusting for the edge case by flipping the sample location over the image boundary. I've also moved some invariant calculations from old line 1781 into the if statement to save some cycles.

New line 1782 is analogous to new line 1766 and new lines 1792-1799 are analogous to 1774-1780.

A significant speed boost was had by only computing BSpline() over one row instead of the entire kernel. Because the values are now reused, larger kernels yield larger speedup over the old code.

New lines 1788-1790 are initializing the array values as needing BSpline() for that index. As BSpline() values are needed in lines 1807-1811 they are calculated. They are then reused at line 1813.

Exact speedup values depend on your kernel size, but I believe GWKCubicSplineResample() is at least twice as fast. In my tests the majority of time is now spent in GWKGetPixelValue(), but I don't think I can directly speed that up much.

GWKCubicSplineResampleNoMasksByte() has been altered analogous to GWKCubicSplineResample(). Because we know that nothing is masked out we don't need lines similar to 1788-1790 though. We just calculate all BSpline() values on the first pass and use them an every pass after that.

In my test case, a task which had spent most of it's time in GWKCubicSplineResampleNoMasksByte() was cut from 6 min 30 sec runtime to 1min 35 secs. But that had a large kernel size, so I suspect most speedup won't be quite as dramatic.

GWKCubicSplineResampleNoMasksShort() has changes similar to the others, but I haven't run any tests on it. Please take a look and make sure it runs as expected.

Overall, I've made significant improvement in the cubicspline functions.

I think the next major speedup for my purposes involves finding the outer bounds of the valid source and skipping having to call GWKGetPixelValue() for every pixel in a chunk just to find that it's masked out. That would probably give me a 4x speedup when combining and resampling 4 raster images into one.

In other words: Currently if I use a geographically tiled dataset as source files GDAL calculates the visibility of each file for each pixel in the output image. It spends almost as long calculating the visibility of an image that isn't used in the destination image as one which fills the destination. A fast way to shortcut this would be to calculate the minimum and maximum valid indices of each mask. Then test for any overlap of an entire chunk at a time GWKGeneralCase(), and if there is no overlap, the entire chunk can be skipped.

This, however, is beyond my current time abilities. It also gets quite a bit deeper into GDAL internals than I'm familiar with. ~Seth

by sprice, 16 years ago

Attachment: cubicspline.diff added

found a bug, fixed a bug (new line 1807)

comment:3 by martinoty, 16 years ago

Cc: martinoty added
Keywords: cubic bilinear near added
Summary: cubicspline resampling doesn't work for the entire imagecubicspline resampling and other resamplers don't work for the entire image
Version: unspecifiedsvn-trunk

Thanks for this patch.

As a matter of fact, the other resamplers (near, bilinear, cubic, lanczos) suffer from the same problems you've corrected. Worst, when downsampling, near, bilinear and cubic give wrong results ! Indeed, their kernel sizes remain fixed (for example to 2x2 for bilinear), while they should be 20x20 for a tenfold downsampling for example. The effect of this bug is that for large downsampling, near, bilinear and cubic all give a result looking like a nearest neighbour resampling (whith aliasing, moire, and other artefacts).

In addition, the problem related to the "static" most probably also exist in lanczos (and maybe the others), since the code looks the same.

Finally, I think inefficencies related to kernel computations could also be corrected for the other kernels as you did. In fact, I think the code could be unified from your code, since the only difference is the kernels' sizes and formulae, the rest should remain the same. By creating a "Filter" class for example, containing the formula and size of each kernel, I think one could write a generic code. See for example: http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx and the corresponding attached javascript code.

As you look very proficient in resampling code, do you think you could correct the whole resampling process ?

by martinoty, 16 years ago

Attachment: Resampling_src.zip added

code example for downsampling and upsampling

comment:4 by sprice, 16 years ago

I've noticed the problems with the kernel size in the other methods already. In fact I even started to write a bug report on it, but I figured that the benefit wasn't worth the effort. You never know when there are folks in the community who aren't interested in some of these details decide to make the request difficult.

However, bilinear, for example, will be much more difficult to fix because it's currently optimized for a 2x2 kernel. The code is just a set of 'if' statements instead of (arbitrary sizable) loops. The 'if' statements are much faster though.

I've also been thinking of adding a 'mode' resampling algorithm that computes the most common value over the kernel area. It would be very useful for my land cover classification dataset(s) because the only algorithm that currently works is 'near'.

I noticed some efficency problems with the other resampling methods also, but the inefficiencies aren't as big of a deal because so much time is spent in the GetPixelValue() method, so any speedup isn't as great overall. (Though I haven't looked at the lanczos.)

If you were interested in unifying the kernel computations you could base it on the cubicspline code, but it would go against the statement in the header of the file; specialized functions for the fastest computation. There would need to be a switch statement in the center of the kernel computation to decide which resampling function to run.

Maybe my new GWKCubicSplineResample() function can become GWKResample() which also replaces GWKLanczosResample(). The bilinear and cubic don't look to be setup for running kernels. That may be the best solution for simplifying code while keeping the other functions lightweight and fast.

I'm more proficient in resampling code than I am in having free time. ;) Tendonitis is also an issue, so please don't wait for me to make these changes. I'll help when I'm able to.

After this patch, I think the greatest opportunity for optimization is to 'vectorize' the GetPixelValue() method. Can it be refactored to operate on a line of indices at once? That would take advantage of memory locality while calling the function many fewer times. For example, this is what the new function would look like:

GWKGetPixelValue( GDALWarpKernel *poWK, int iBand, int iSrcOffset, int num, double pdfDensity, double pdfReal, double pdfImag )

The function would calculate values for an entire kernel width of pixels at a time. This would result in minimal overhead because the related data is stored nearby in memory, while the function is called many fewer times.

This, combined with my previous speedup suggestion, would make a significant improvement overall.

by sprice, 16 years ago

Attachment: cubicspline2.diff added

Another bug fixed. I found that for many of the chunks the width or height was '0'. Perhaps this is a bug somewhere else in the code? Nonetheless, bug fixed by passing the buck to GWKBilinearResample().

comment:5 by sprice, 16 years ago

I should also mention that this diff is uploaded separately so the line numbers in my earlier post can be referenced with the line numbers in my earlier diff (although that one has at least one bug).

by sprice, 16 years ago

Attachment: cubicspline2.2.diff added

Fixed another bug. You guys sure feed the function some odd image sizes and source coordinates...

by sprice, 16 years ago

Attachment: cubicspline3.diff added

more updates and speedups

comment:6 by sprice, 16 years ago

The latest patch makes a number of changes which I discussed earlier, including making a GetPixelRow() function and refactoring the code to use it. This resulted in another noticeable speedup. Any further patches will most likely be to fix any bugs we find. Unfortunately my main testing computer is in for repairs, so this patch may be slightly untested.

What do you folks think?

comment:7 by sprice, 16 years ago

I forgot to mention that this patch also includes a draft of a new 'mode' resampling function. GWKModeResampleByte() is intended to operate on byte data. (such as land cover classification datasets) In a given kernel area, if one pixel is grass, one forest, and two pixels water, the end result should be the value of the water class. In kernels with an area of one pixel or less, the resampling is the same as nearest neighbor.

It would be great if someone could add the code in the main GDAL source tree to incorporate this function into the warper.

I should also mention that I don't think I've deciphered your variable name prefix convention, so someone might want to go through my patch and make sure it's consistent.

comment:8 by sprice, 16 years ago

While I'm spamming y'all with requests to take a look at my code, someone should also make sure I have the correct usage of the 'pdfDensity', 'pdfImag' and 'pdfReal' values. I'm not familiar with the significance of these values, but I think I have it right.

comment:9 by warmerdam, 16 years ago

SPrice,

I must confess I'm intimidated by the breadth of your changes. Unfortunately, the warper does not have a good regression test, so it is hard to know if sweeping changes will have unanticipated negative effects. An in depth review will likely take quite a bit of time, and I generally speaking don't have the time to do that.

It might be good to select a few changes that are more easily understood, and demonstrated and get them merged into the code base. Another alternative is that we work to get you commiter access, and just have you proceed with the work with some light monitoring and supervision from others (such as myself). Are you interested in this approach? It would imply your being ready to return to problem reports that come in on the warper in the future.

comment:10 by sprice, 16 years ago

I was a bit worried about the magnitude of changes, for the reasons you mention. I think that the history of patches attached to this bug is a good selection of more easily understood patches getting more involved at each additional attached patch.

I've been doing regression tests by doing a bitwise compare of before and after GeoTIFFs. I've been getting a good result except for a minor change in the latest patch which occurs near the end of the file. While the bits are different, I can't figure out if there is anything wrong with the new file. Using Photoshop to highlight the image differences shows no changes. Of course, this is not a true regression test because of the limited warping options I'm using.

Maybe it's time for someone to write a good regression test? I'll heroically pass the buck to someone else who's more familiar with GDAL's abilities.

I would guess that the changes aren't as significant as the patch file size would lead you to believe. For example, there was a block of cubicspline resampling code which had been commented out using a "#ifdef". I removed it because my code is such a deviation from what was originally there, I thought it strange to leave such outdated code in place.

If anyone wishes to look over the code and ask about the reasoning behind specific changes, I would be happy to provide an explanation while I'm around (this week).

I don't think that committer access would be best at this time. In a few days I leave for Hawaii to help my wife with some ecological field work for the summer, and I start a (remote sensing) PhD program in the fall. I'll be in contact this summer, but it won't be as often or regular as now. I wanted to get these changes into GDAL simply so they're around when I'm working on my PhD.

I would be rather disappointed if my changes didn't make their way back into GDAL, though. For example, with one of my patches above, I reduced the runtime of my cubicspline warping test to a quarter it's original time. Then, with my latest patch, I halved that improved time. That's significant. My changes to GetPixelRow() apply across all resampling functions (except nearest neighbor), with a noticeable speedup even in the bilinear method.

I've been frustrated by GDAL's lack mode-style resampling algorithm for a while. So while I was working on this code, I wanted to make the first step towards implementing one myself.

Again, if anyone has questions about why I made the changes I did I'd be happy to explain. Especially if that allows for better integration into the GDAL code base.

comment:11 by sprice, 16 years ago

I'm not sure how clear I was, but you could start with reviewing the cubicspline2.2.diff patch, because that serves as a foundation for the cubicspline3.diff patch.

Another reason why cubicspline3.diff appears so large is that, as suggested above, I combined the GWKCubicSplineResample() and GWKLanczosResample() functions. This makes for a large patch size, but is actually a simplification of code overall.

by sprice, 16 years ago

Attachment: cubicspline3.2.diff added

new patch ignores white space; should be easier to review

by sprice, 16 years ago

Attachment: cubicspline3.3.diff added

New patch fixes a segfault and crops sampling at image edge instead of flipping over edge. Resulted in small speedup and better accuracy from what I can tell.

by sprice, 16 years ago

Attachment: cubicspline3.4.diff added

Fixed another segfault

by sprice, 16 years ago

Attachment: cubicspline3.5.diff added

Mode implementation bug fix

comment:12 by dron, 16 years ago

Owner: changed from warmerdam to dron

Folks, I am on it. I am assigning it on myself because it is all my stuff that is being touched by the patch. It will take some time to review changes, but it seems sprice did an excellent job digging into our bugs, thanks! Also there are known problems with downsampling (aliasing effects) for some resamplers which is not being fixed because of lack of the time. Time is main issue here, because both problems and solutions are well-known and I just need to sit down and write code for that.

I will try to create some tests before applying the patch. That should fill one more hole in our test suite.

Best regards, Andrey

comment:13 by dron, 16 years ago

Status: newassigned

sprice, could you redo the last patch using the -b with diff? It's hard to sort out all those space changes...

Best regards,

Andrey

comment:14 by dron, 16 years ago

sprice, FYI there is a description of our variable naming scheme:

http://trac.osgeo.org/gdal/wiki/rfc8_devguide

by sprice, 16 years ago

Attachment: cubicspline3.6.diff added

diff -ub ...

by sprice, 16 years ago

Attachment: cubicspline3.7.diff added

tabs replaced with spaces

comment:15 by sprice, 16 years ago

I've attached the patch. However, I'm a little concerned that I might attempt to read past the end of the source pixel array. I've already had the problem of reading before the array, the fix you can see on line 1905 of the new file.

So, if someone can take a look and check if this will/will not be a problem, the fix shouldn't be more difficult than what I already have in place.

comment:16 by dron, 16 years ago

sprice,

I should admit that I totally failed to understand the proposed changes. The first patch (with your comments) was good and I can see what was done, but the last one changes a lot across the warping module and it is hard for me to get the point.

Also you have made a diff against some old GDAL version and it can't be cleanly applied to trunk.

Please, help me to merge your work in upstream and do the following:

  1. Port your changes to the latest GDAL snapshot from the trunk.
  2. Move the small optimizations you did in various places in separate patch that can be safely applied before the patch containing warping kernels changes.
  3. Use our variable naming scheme (http://trac.osgeo.org/gdal/wiki/rfc8_devguide).

Best regards, Andrey

comment:17 by sprice, 16 years ago

I'll try to do 1 & 3, they shouldn't be a problem. I'm away from good computer access, so I'll have problems doing 2.

However, I'll try to add comments like I did earlier. Are there any area(s) in particular which are causing confusion?

comment:18 by dron, 16 years ago

Mainly I need comments on what you do with the old bicubic resampler. Other places more or less clear for me.

by sprice, 16 years ago

Attachment: cubicspline3.8.diff added

1, 3 & more comments

by sprice, 16 years ago

Attachment: cubicspline3.9.diff added

diff -ub ...

comment:19 by sprice, 16 years ago

New patch uploaded. In the resampler I've made four major improvements which are making it difficult to see what happened to the old resampler:

1) I've combined the cubicspline and lanczos resampling code. This has resulted in the 'if' statements at lines 1857, 1932 & 1958.

2) Instead of fetching a single pixel at a time, we now fetch a whole row. Not only do we make far fewer function calls this way, but we take advantage of memory locality (so this method has to wait less to fetch data from RAM).

3) The actual bug is fixed by skipping sampling out-of-bounds pixels (lines 1908 & 1950). The weighting is adjusting for the skipped pixels by division at the end of the function (line 1994; existing code).

4) We had originally been spending a significant amount of time in the BSpline() macro. Basically, we only calculate one value for each 'i' and each 'j'. I saved the calculated 'i' values into a local array so they don't need to be recalculated for each row (line 1960). The actual code is a bit more complicated because we init the local values to be NANs (line 1898) and then we detect for NANs to only compute the weights on demand (line 1956).

The 'on demand' weight computation and checking the entire row for valid data at a time combine to be extremely fast in nodata areas (which used to be much slower).

NOTES: A possible bug is outlined at line 1918. Basically the fact that I'm reading an entire row at once causes issues at the beginning and (maybe) end of the source data array. Someone may want to take a look to see if my concern is justified.

The rest of the switch statement at line 976 needs to be filled in. It corresponds to the switch statement at line 1050 and should be trivial.

comment:20 by dron, 16 years ago

Ok, I have applied the patch with a number of cosmetic changes (also I have completed GWKGetPixelRow()). I did a few timing tests and CubicSpline resampler now works 1.7 times faster than old version; that is really good!

Now the bad news: Lanczos resampler does not work anymore. I am not sure what is wrong with that. That is why I have not checked in this new version. Instead I am attaching the new version of the patch with my corrections. The Lanczos case needs further investigation.

sprice, if you will decide to add more patches, please, do them against the gdalwarpkernel.cpp patched with this cubicspline3.10.diff, so we can easily separate the new changes from the old ones. It seems that everything is working fine now except Lanczos.

Best regards, Andrey

by dron, 16 years ago

Attachment: cubicspline3.10.diff added

comment:21 by dron, 16 years ago

I have created the separate branch to play with the new resampling kernels. It can be obtained with the command

svn co https://svn.osgeo.org/gdal/sandbox/dron/gdal-warptest

The only difference from trunk is the warping code. When all the problems will be solved I will merge it in trunk. What does not work now:

  1. GWKResample(). Lanczos produces something totally wrong and CubicSpline results in image with the lost top left pixel. I am looking into this problem.
  1. I want to get rid of that NAN/isnan() thing. Maybe we can find another solution? This is C99 feature and not widely portable. We are trying to avoid that. For the same reason I have moved counter declaration out of loop bodies everywhere, i.e.
int i;
for (i=0; ...)

instead of

for (int i; ...)

That is for MSVC 6.0 which is not standard compliant in this regard.

comment:22 by sprice, 16 years ago

Hey there, have there been any changes to this since the last message? I'd like to work on getting this finished.

comment:23 by dron, 16 years ago

There wasn't any additional work since then, but your patch has been applied to the branch in my sandbox (see above for the link). Unfortunately I see some regressions in this new code both in CubicSpline and Lanczos, so I can't propagate it into trunk. If you have a time to look into the problem, please, do it using that separate branch.

Also there is a ticket #2414 (against trunk, not this new code) which is probably related to the problem you fixed. The weird thing about #2414 is that it can be reproduced on few systems, e.g. I can't reproduce it on any of my boxes.

by sprice, 16 years ago

Attachment: cubicspline4.diff added

comment:24 by sprice, 16 years ago

Attached is a patch against the branch which fixes a seg fault and your problem 2. I'm having a hard time replicating the problems you listed in 1. Could you post the command you're using?

I would be curious if all this new code fixes #2414. It certainly _looks_ like a similar problem.

comment:25 by dron, 16 years ago

Seth,

Thank you for patch, it is applied into gdal-warptest branch. Also I have synchronized that branch with the main trunk.

To reproduce the problem with Lanczos just get the latest autotest suite:

svn co https://svn.osgeo.org/gdal/trunk/autotest

then go into warp/data directory and use gdal_translate on Lanczos test file:

gdal_translate utmsmall_lanczos.vrt bad.tiff

utmsmall_lanczos.vrt describes in detail what kind of transformation applied to source dataset.

It is also happens that #2414 is not related to this ticket. I have fixed that bug and applied patch both to trunk and gdal-warptest branches.

Best regards,
Andrey

by sprice, 16 years ago

Attachment: cubicspline5.diff added

all known problems fixed

by sprice, 16 years ago

Attachment: cubicspline5.2.diff added

I think I got it this time

comment:26 by sprice, 16 years ago

Here's the latest & greatest patch. The corner cases are the real tricky parts.

by sprice, 16 years ago

Attachment: cubicspline5.3.diff added

No debug code this time

comment:27 by sprice, 16 years ago

Because I didn't specifically mention it: All bugs (that I know of) are fixed.

comment:28 by dron, 16 years ago

Seth,

Great job, thanks! Now everything works just fine for me. I will do some more testing and will merge the test branch into trunk.

Best regards,
Andrey

comment:29 by dron, 16 years ago

Resolution: fixed
Status: assignedclosed

Ok, I have applied the patch to trunk (r15273). Though I have found one more portability problem: the dynamic arrays. Unfortunately it is not supported by MSVC compiler, so I have replaced them with usual heap allocation (I am not keen to use alloca() here, but we may concern its usage). This immediately triggered one more bug, that was fixed too. See r15277 for details.

I am closing the ticket, but feel free to reopen if something will came up.

comment:30 by sprice, 16 years ago

Resolution: fixed
Status: closedreopened

While it's great that it's merged with the trunk, GWKResample() is now making five calls to CPLCalloc() per pixel in the dst image. This is causing the program to take twice as long to run, which eliminates the purpose of the patch in the first place.

Would it be possible to use "#ifdef"s to only use CPCalloc() when being compiled under the MSVC compiler so the rest of us don't have to suffer? Otherwise, we could do some hackery of passing a buffer into GWKResample() so the buffer(s) only need to be allocated once for all the pixels.

Here is my testing command. "z1024.red.tif" is simply a 1024x1024 px image.

gdalwarp -r cubicspline -dstnodata 0 -ts 2000 2000 z1024.red.tif z1024.out.tif

comment:31 by Even Rouault, 16 years ago

Milestone: 1.6.0
Resolution: fixed
Status: reopenedclosed

Instead of allocating the arrays at each call in GWKResample, it's better to allocate them just onece in the calling function.

Done in r15281

comment:32 by sprice, 16 years ago

Excellent! You might also want to use that solution for GWKCubicSplineResampleNoMasksByte() and GWKCubicSplineResampleNoMasksShort() for similar reasons.

comment:33 by sprice, 16 years ago

Yep, now for some tests:

38.1 seconds with CPLCalloc() in GWKCubicSplineResampleNoMasksByte()

31.0 seconds for my original code

gdalwarp -r cubicspline -ts 2000 2000 z1024.red.tif z1024.out.tif

comment:34 by Even Rouault, 16 years ago

r15283 /trunk/gdal/alg/gdalwarpkernel.cpp: Avoid doing array allocation for each destination pixel in GWKCubicSplineResampleNoMasksByte() and GWKCubicSplineResampleNoMasksShort() (#2327)

comment:35 by Even Rouault, 16 years ago

Resolution: fixed
Status: closedreopened

While running Valgrind on warp.py, the following warnings are emitted in warp_12 and warp_13. Look like out of bounds access to arrays.

  TEST: warp_12 ... ==5856==
==5856== Invalid read of size 4
==5856==    at 0x4CFF146: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:1115)
==5856==    by 0x4CFF78B: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1494)
==5856==    by 0x4D018C0: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2540)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==  Address 0x78B5B68 is 0 bytes after a block of size 1,600 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D049A8: GDALWarpOperation::CreateKernelMask(GDALWarpKernel*, int, char const*) (gdalwarpoperation.cpp:1738)
==5856==    by 0x4D05247: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1386)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==
==5856== Invalid read of size 4
==5856==    at 0x4CFF1EF: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:1120)
==5856==    by 0x4CFF78B: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1494)
==5856==    by 0x4D018C0: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2540)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==  Address 0x78B5B6C is 4 bytes after a block of size 1,600 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D049A8: GDALWarpOperation::CreateKernelMask(GDALWarpKernel*, int, char const*) (gdalwarpoperation.cpp:1738)
==5856==    by 0x4D05247: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1386)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==
==5856== Invalid read of size 1
==5856==    at 0x4CFE623: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:983)
==5856==    by 0x4CFF78B: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1494)
==5856==    by 0x4D018C0: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2540)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==  Address 0x44A21E8 is 0 bytes after a block of size 1,200 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D04D99: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1330)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==    by 0x805CA86: PyObject_Call (in /usr/bin/python2.5)
==5856==
==5856== Invalid read of size 1
==5856==    at 0x4CFE64F: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:984)
==5856==    by 0x4CFF78B: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1494)
==5856==    by 0x4D018C0: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2540)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==  Address 0x44A21E9 is 1 bytes after a block of size 1,200 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D04D99: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1330)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==    by 0x805CA86: PyObject_Call (in /usr/bin/python2.5)
==5856==
==5856== Invalid read of size 4
==5856==    at 0x4CFF1EF: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:1120)
==5856==    by 0x4CFF49E: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1461)
==5856==    by 0x4D018C0: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2540)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==  Address 0x78B5B68 is 0 bytes after a block of size 1,600 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D049A8: GDALWarpOperation::CreateKernelMask(GDALWarpKernel*, int, char const*) (gdalwarpoperation.cpp:1738)
==5856==    by 0x4D05247: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1386)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==
==5856== Invalid read of size 1
==5856==    at 0x4CFE64F: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:984)
==5856==    by 0x4CFF49E: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1461)
==5856==    by 0x4D018C0: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2540)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==  Address 0x44A21E8 is 0 bytes after a block of size 1,200 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D04D99: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1330)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==    by 0x805CA86: PyObject_Call (in /usr/bin/python2.5)
==5856==
==5856== Invalid read of size 4
==5856==    at 0x4CFF146: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:1115)
==5856==    by 0x4CFF49E: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1461)
==5856==    by 0x4D018C0: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2540)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==  Address 0x78B5B68 is 0 bytes after a block of size 1,600 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D049A8: GDALWarpOperation::CreateKernelMask(GDALWarpKernel*, int, char const*) (gdalwarpoperation.cpp:1738)
==5856==    by 0x4D05247: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1386)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==
==5856== Invalid read of size 1
==5856==    at 0x4CFE623: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:983)
==5856==    by 0x4CFF49E: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1461)
==5856==    by 0x4D018C0: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2540)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==  Address 0x44A21E8 is 0 bytes after a block of size 1,200 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D04D99: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1330)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==    by 0x805CA86: PyObject_Call (in /usr/bin/python2.5)
success
  TEST: warp_13 ... ==5856==
==5856== Invalid read of size 4
==5856==    at 0x4CFF146: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:1115)
==5856==    by 0x4CFF78B: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1494)
==5856==    by 0x4CFFD00: GWKCubicResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1764)
==5856==    by 0x4D0197F: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2548)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==  Address 0x4474220 is 0 bytes after a block of size 1,600 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D049A8: GDALWarpOperation::CreateKernelMask(GDALWarpKernel*, int, char const*) (gdalwarpoperation.cpp:1738)
==5856==    by 0x4D05247: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1386)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==
==5856== Invalid read of size 4
==5856==    at 0x4CFF1EF: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:1120)
==5856==    by 0x4CFF78B: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1494)
==5856==    by 0x4CFFD00: GWKCubicResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1764)
==5856==    by 0x4D0197F: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2548)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==  Address 0x4474224 is 4 bytes after a block of size 1,600 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D049A8: GDALWarpOperation::CreateKernelMask(GDALWarpKernel*, int, char const*) (gdalwarpoperation.cpp:1738)
==5856==    by 0x4D05247: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1386)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==
==5856== Invalid read of size 1
==5856==    at 0x4CFE623: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:983)
==5856==    by 0x4CFF78B: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1494)
==5856==    by 0x4CFFD00: GWKCubicResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1764)
==5856==    by 0x4D0197F: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2548)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==  Address 0x44D2678 is 0 bytes after a block of size 1,200 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D04D99: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1330)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==    by 0x805CA86: PyObject_Call (in /usr/bin/python2.5)
==5856==
==5856== Invalid read of size 1
==5856==    at 0x4CFE64F: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:984)
==5856==    by 0x4CFF78B: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1494)
==5856==    by 0x4CFFD00: GWKCubicResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1764)
==5856==    by 0x4D0197F: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2548)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==  Address 0x44D2679 is 1 bytes after a block of size 1,200 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D04D99: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1330)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==    by 0x805CA86: PyObject_Call (in /usr/bin/python2.5)
==5856==
==5856== Invalid read of size 4
==5856==    at 0x4CFF1EF: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:1120)
==5856==    by 0x4CFF49E: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1461)
==5856==    by 0x4CFFD00: GWKCubicResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1764)
==5856==    by 0x4D0197F: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2548)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==  Address 0x4474220 is 0 bytes after a block of size 1,600 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D049A8: GDALWarpOperation::CreateKernelMask(GDALWarpKernel*, int, char const*) (gdalwarpoperation.cpp:1738)
==5856==    by 0x4D05247: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1386)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==
==5856== Invalid read of size 1
==5856==    at 0x4CFE64F: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:984)
==5856==    by 0x4CFF49E: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1461)
==5856==    by 0x4CFFD00: GWKCubicResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1764)
==5856==    by 0x4D0197F: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2548)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==  Address 0x44D2678 is 0 bytes after a block of size 1,200 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D04D99: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1330)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==    by 0x805CA86: PyObject_Call (in /usr/bin/python2.5)
==5856==
==5856== Invalid read of size 4
==5856==    at 0x4CFF146: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:1115)
==5856==    by 0x4CFF49E: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1461)
==5856==    by 0x4CFFD00: GWKCubicResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1764)
==5856==    by 0x4D0197F: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2548)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==  Address 0x4474220 is 0 bytes after a block of size 1,600 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D049A8: GDALWarpOperation::CreateKernelMask(GDALWarpKernel*, int, char const*) (gdalwarpoperation.cpp:1738)
==5856==    by 0x4D05247: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1386)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==
==5856== Invalid read of size 1
==5856==    at 0x4CFE623: GWKGetPixelRow(GDALWarpKernel*, int, int, int, double*, double*, double*) (gdalwarpkernel.cpp:983)
==5856==    by 0x4CFF49E: GWKBilinearResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1461)
==5856==    by 0x4CFFD00: GWKCubicResample(GDALWarpKernel*, int, double, double, double*, double*, double*) (gdalwarpkernel.cpp:1764)
==5856==    by 0x4D0197F: GWKGeneralCase(GDALWarpKernel*) (gdalwarpkernel.cpp:2548)
==5856==    by 0x4D02F68: GDALWarpKernel::PerformWarp() (gdalwarpkernel.cpp:639)
==5856==    by 0x4D06108: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1572)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==  Address 0x44D2678 is 0 bytes after a block of size 1,200 alloc'd
==5856==    at 0x4022765: malloc (vg_replace_malloc.c:149)
==5856==    by 0x4CC1B82: VSIMalloc (cpl_vsisimple.cpp:300)
==5856==    by 0x4D04D99: GDALWarpOperation::WarpRegionToBuffer(int, int, int, int, void*, GDALDataType, int, int, int, int) (gdalwarpoperation.cpp:1330)
==5856==    by 0x4BC88AE: VRTWarpedDataset::ProcessBlock(int, int) (vrtwarped.cpp:846)
==5856==    by 0x4BC8CD1: VRTWarpedRasterBand::IReadBlock(int, int, void*) (vrtwarped.cpp:948)
==5856==    by 0x4C5DE3E: GDALRasterBand::GetLockedBlockRef(int, int, int) (gdalrasterband.cpp:1121)
==5856==    by 0x4C737A7: GDALRasterBand::IRasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (rasterio.cpp:217)
==5856==    by 0x4C5C888: GDALRasterBand::RasterIO(GDALRWFlag, int, int, int, int, void*, int, int, GDALDataType, int, int) (gdalrasterband.cpp:241)
==5856==    by 0x4C5C9CC: GDALRasterIO (gdalrasterband.cpp:266)
==5856==    by 0x4CD3613: GDALChecksumImage (gdalchecksum.cpp:147)
==5856==    by 0x452B22C: _wrap_Band_Checksum (gdal_wrap.cpp:3481)
==5856==    by 0x805CA86: PyObject_Call (in /usr/bin/python2.5)

by sprice, 16 years ago

Attachment: cubicspline6.diff added

GWKBilinearResample()

comment:36 by sprice, 16 years ago

New patch to fix buffer overrun problem

comment:37 by sprice, 16 years ago

On second thought: if we just appended a blank array entry after the source image array, it would fix all this edge case stuff. Then we could delete all the end edge case code. The normal image bounds checking would ignore it's value, but it would exist so we wouldn't seg fault when read. It would probably be simpler that way too. Thoughts?

comment:38 by sprice, 16 years ago

For example: one extra sizeof(pixel) on the end of the source array would eliminate the need for the entire last patch (I think).

comment:39 by dron, 16 years ago

Resolution: fixed
Status: reopenedclosed

Seth,

I have applied your patch (see r15289). That patch is fine with me and I am not sure how to implement the "one extra pixel approach" in the most clean way, so I went with the patch.

Note: See TracTickets for help on using tickets.