@@ -532,6 +532,11 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,
532
532
QgsDebugMsg ( " thePixelHeight = " + QString::number ( thePixelHeight ) );
533
533
QgsDebugMsg ( " theExtent: " + theExtent.toString () );
534
534
535
+ for ( int i = 0 ; i < 6 ; i++ )
536
+ {
537
+ QgsDebugMsg ( QString ( " transform : %1" ).arg ( mGeoTransform [i] ) );
538
+ }
539
+
535
540
// TODO: fill block with no data values
536
541
537
542
QgsRectangle myRasterExtent = theExtent.intersect ( &mExtent );
@@ -589,46 +594,57 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,
589
594
double center, centerRaster;
590
595
int rasterTop, rasterBottom, rasterLeft, rasterRight;
591
596
597
+ // We have to extend destination grid for GDALRasterIO to keep resolution:
598
+ double topSpace, bottomSpace, leftSpace, rightSpace;
599
+
592
600
// top
593
601
center = myRasterExtent.yMaximum () - yRes/2 ;
594
602
// center in raster space
595
603
// GDAL states that mGeoTransform[3] is top, but probably it can be also bottom
596
- // if mGeoTransform[5] is negative
597
- if ( mGeoTransform [5 ] > 0 )
604
+ // if mGeoTransform[5] is negative ??? No, mGeoTransform[5] is negative normaly
605
+ // - vice versa?
606
+ // if ( mGeoTransform[5] > 0 )
607
+ if ( mGeoTransform [5 ] < 0 )
598
608
{
599
- centerRaster = ( mGeoTransform [3 ] - center ) / mGeoTransform [5 ];
609
+ centerRaster = - 1 . * ( mGeoTransform [3 ] - center ) / mGeoTransform [5 ];
600
610
}
601
611
else
602
612
{
603
613
centerRaster = ( center - mGeoTransform [3 ] ) / mGeoTransform [5 ];
604
614
}
605
615
rasterTop = static_cast <int > ( floor ( centerRaster ) );
616
+ topSpace = (mGeoTransform [3 ] + rasterTop*mGeoTransform [5 ])- myRasterExtent.yMaximum ();
606
617
607
618
// bottom
608
619
center = myRasterExtent.yMinimum () + yRes/2 ;
609
- if ( mGeoTransform [5 ] > 0 )
620
+ // if ( mGeoTransform[5] > 0 )
621
+ if ( mGeoTransform [5 ] < 0 )
610
622
{
611
- centerRaster = ( mGeoTransform [3 ] - center ) / mGeoTransform [5 ];
623
+ centerRaster = - 1 . * ( mGeoTransform [3 ] - center ) / mGeoTransform [5 ];
612
624
}
613
625
else
614
626
{
615
627
centerRaster = ( center - mGeoTransform [3 ] ) / mGeoTransform [5 ];
616
628
}
617
629
rasterBottom = static_cast <int > ( floor ( centerRaster ) );
630
+ bottomSpace = myRasterExtent.yMinimum () - ( mGeoTransform [3 ] + (rasterBottom+1 )*mGeoTransform [5 ] );
618
631
619
632
// left
620
633
center = myRasterExtent.xMinimum () + xRes/2 ;
621
634
centerRaster = ( center - mGeoTransform [0 ] ) / mGeoTransform [1 ];
622
635
rasterLeft = static_cast <int > ( floor ( centerRaster ) );
636
+ leftSpace = myRasterExtent.xMinimum () - (mGeoTransform [0 ] + rasterLeft * mGeoTransform [1 ] );
623
637
624
638
// right
625
639
center = myRasterExtent.xMaximum () - xRes/2 ;
626
640
centerRaster = ( center - mGeoTransform [0 ] ) / mGeoTransform [1 ];
627
641
rasterRight = static_cast <int > ( floor ( centerRaster ) );
642
+ rightSpace = (mGeoTransform [0 ] + (rasterRight+1 )*mGeoTransform [1 ]) - myRasterExtent.xMaximum ();
628
643
629
644
QgsDebugMsg ( QString (" rasterTop = %1 rasterBottom = %2 rasterLeft = %3 rasterRight = %4" ).arg (rasterTop).arg (rasterBottom).arg (rasterLeft).arg (rasterRight) );
630
645
631
- // Allocate temporary block
646
+ QgsDebugMsg ( QString (" topSpace = %1 bottomSpace = %2 leftSpace = %3 rightSpace = %4" ).arg (topSpace).arg (bottomSpace).arg (leftSpace).arg (rightSpace) );
647
+
632
648
int width = right - left + 1 ;
633
649
int height = bottom - top + 1 ;
634
650
@@ -637,6 +653,29 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,
637
653
638
654
QgsDebugMsg ( QString (" width = %1 height = %2 rasterWidth = %3 rasterHeight = %4" ).arg (width).arg (height).arg (rasterWidth).arg (rasterHeight) );
639
655
656
+
657
+ double rasterXRes = extent ().width () / xSize ();
658
+ double rasterYRes = extent ().height () / ySize ();
659
+
660
+ // TODO: what is better floor/ceil, can be negative?
661
+ // should be similar
662
+ // double xAdd = rasterWidth*rasterXRes - width*xRes;
663
+ double xAdd = leftSpace + rightSpace;
664
+ int xAddPixels = static_cast <int > ( round ( xAdd / xRes ) );
665
+ int leftAddPixels = static_cast <int > ( round ( leftSpace / xRes ) );
666
+
667
+ // double leftAdd = rasterWidth*rasterXRes - width*xRes;
668
+ double yAdd = topSpace + bottomSpace;
669
+ int yAddPixels = static_cast <int > ( round ( yAdd / yRes ) );
670
+ int topAddPixels = static_cast <int > ( round ( topSpace / yRes ) );
671
+
672
+ QgsDebugMsg ( QString (" xAddPixels = %1 yAddPixels = %2 leftAddPixels = %3 topAddPixels = %4" ).arg (xAddPixels).arg (yAddPixels).arg (leftAddPixels).arg (topAddPixels) );
673
+
674
+ int totalWidth = width + xAddPixels;
675
+ int totalHeight = height + yAddPixels;
676
+
677
+ QgsDebugMsg ( QString (" totalWidth = %1 totalHeight = %2" ).arg (totalWidth).arg (totalHeight) );
678
+
640
679
int size = dataTypeSize (theBandNo) / 8 ;
641
680
642
681
// fill with null values
@@ -650,7 +689,11 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,
650
689
}
651
690
652
691
GDALRasterBandH gdalBand = GDALGetRasterBand ( mGdalDataset , theBandNo );
692
+ GDALDataType type = ( GDALDataType )mGdalDataType [theBandNo-1 ];
693
+ CPLErrorReset ();
653
694
695
+ // This can be probably used if xAddPixels and yAddPixels are 0 to avoid memcpy
696
+ #if 0
654
697
// Calc beginnig of data if raster does not start at top
655
698
block = (char *) theBlock;
656
699
if ( top != 0 )
@@ -663,23 +706,40 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,
663
706
if ( left != 0 ) {
664
707
block += size * left;
665
708
}
666
-
667
- GDALDataType type = ( GDALDataType )mGdalDataType [theBandNo-1 ];
668
-
669
- CPLErrorReset ();
670
709
CPLErr err = GDALRasterIO( gdalBand, GF_Read,
671
710
rasterLeft, rasterTop, rasterWidth, rasterHeight,
672
711
(void *)block,
673
712
width, height, type,
674
713
0, nLineSpace );
714
+ #endif
715
+
716
+ // Allocate temporary block
717
+ void *tmpBlock = malloc ( size * totalWidth * totalHeight );
718
+
719
+ CPLErrorReset ();
720
+ CPLErr err = GDALRasterIO ( gdalBand, GF_Read,
721
+ rasterLeft, rasterTop, rasterWidth, rasterHeight,
722
+ (void *)tmpBlock,
723
+ totalWidth, totalHeight, type,
724
+ 0 , 0 );
675
725
676
726
if ( err != CPLE_None )
677
727
{
678
728
QgsLogger::warning ( " RasterIO error: " + QString::fromUtf8 ( CPLGetLastErrorMsg () ) );
679
729
QgsDebugMsg ( " RasterIO error: " + QString::fromUtf8 ( CPLGetLastErrorMsg () ) );
730
+ free ( tmpBlock );
731
+ return ;
732
+ }
733
+
734
+ for ( int i = 0 ; i < height; i++ ) {
735
+ int r = i + topAddPixels;
736
+ char *src = (char *)tmpBlock + size*r*totalWidth + size*leftAddPixels;
737
+ char *dst = (char *)theBlock + size*(top+i)*thePixelWidth + size*(left);
738
+ memcpy ( dst, src, size*width );
680
739
}
681
-
682
740
741
+ free ( tmpBlock );
742
+ return ;
683
743
}
684
744
685
745
// this is old version which was using GDALWarpOperation, unfortunately
0 commit comments