@@ -37,6 +37,8 @@ QgsRasterBlock::QgsRasterBlock()
37
37
, mData( 0 )
38
38
, mImage( 0 )
39
39
, mNoDataBitmap( 0 )
40
+ , mNoDataBitmapWidth( 0 )
41
+ , mNoDataBitmapSize( 0 )
40
42
{
41
43
}
42
44
@@ -51,6 +53,8 @@ QgsRasterBlock::QgsRasterBlock( QGis::DataType theDataType, int theWidth, int th
51
53
, mData( 0 )
52
54
, mImage( 0 )
53
55
, mNoDataBitmap( 0 )
56
+ , mNoDataBitmapWidth( 0 )
57
+ , mNoDataBitmapSize( 0 )
54
58
{
55
59
reset ( mDataType , mWidth , mHeight );
56
60
}
@@ -66,6 +70,8 @@ QgsRasterBlock::QgsRasterBlock( QGis::DataType theDataType, int theWidth, int th
66
70
, mData( 0 )
67
71
, mImage( 0 )
68
72
, mNoDataBitmap( 0 )
73
+ , mNoDataBitmapWidth( 0 )
74
+ , mNoDataBitmapSize( 0 )
69
75
{
70
76
reset ( mDataType , mWidth , mHeight , mNoDataValue );
71
77
}
@@ -312,8 +318,11 @@ bool QgsRasterBlock::isNoData( size_t index )
312
318
// no data are not defined
313
319
return false ;
314
320
}
315
- size_t byte = index / 8 ;
316
- int bit = index % 8 ;
321
+ // TODO: optimize
322
+ int row = index / mWidth ;
323
+ int column = index % mWidth ;
324
+ size_t byte = ( size_t )row * mNoDataBitmapWidth + column / 8 ;
325
+ int bit = column % 8 ;
317
326
int mask = 0b10000000 >> bit;
318
327
// int x = mNoDataBitmap[byte] & mask;
319
328
// QgsDebugMsg ( QString("byte = %1 bit = %2 mask = %3 nodata = %4 is nodata = %5").arg(byte).arg(bit).arg(mask, 0, 2 ).arg( x, 0, 2 ).arg( (bool)(x) ) );
@@ -382,50 +391,215 @@ bool QgsRasterBlock::setIsNoData( size_t index )
382
391
{
383
392
return setValue ( index, mNoDataValue );
384
393
}
385
- if ( mNoDataBitmap == 0 )
394
+ else
386
395
{
387
- if ( ! createNoDataBitmap () )
396
+ if ( mNoDataBitmap == 0 )
388
397
{
389
- return false ;
398
+ if ( !createNoDataBitmap () )
399
+ {
400
+ return false ;
401
+ }
390
402
}
403
+ // TODO: optimize
404
+ int row = index / mWidth ;
405
+ int column = index % mWidth ;
406
+ size_t byte = ( size_t )row * mNoDataBitmapWidth + column / 8 ;
407
+ int bit = column % 8 ;
408
+ int nodata = 0b10000000 >> bit;
409
+ // QgsDebugMsg ( QString("set byte = %1 bit = %2 no data by %3").arg(byte).arg(bit).arg(nodata, 0,2 ) );
410
+ mNoDataBitmap [byte] = mNoDataBitmap [byte] | nodata;
411
+ return true ;
391
412
}
392
- size_t byte = index / 8 ;
393
- int bit = index % 8 ;
394
- int nodata = 0b10000000 >> bit;
395
- // QgsDebugMsg ( QString("set byte = %1 bit = %2 no data by %3").arg(byte).arg(bit).arg(nodata, 0,2 ) );
396
- mNoDataBitmap [byte] = mNoDataBitmap [byte] | nodata;
397
- return true ;
398
413
}
399
414
400
415
bool QgsRasterBlock::setIsNoData ()
401
416
{
402
- if ( mHasNoDataValue )
417
+ QgsDebugMsg ( " Entered" );
418
+ if ( typeIsNumeric ( mDataType ) )
419
+ {
420
+ if ( mHasNoDataValue )
421
+ {
422
+ if ( !mData )
423
+ {
424
+ QgsDebugMsg ( " Data block not allocated" );
425
+ return false ;
426
+ }
427
+
428
+ QgsDebugMsg ( " set mData to mNoDataValue" );
429
+ int dataTypeSize = typeSize ( mDataType );
430
+ QByteArray noDataByteArray = valueBytes ( mDataType , mNoDataValue );
431
+
432
+ char *nodata = noDataByteArray.data ();
433
+ for ( size_t i = 0 ; i < ( size_t )mWidth *mHeight ; i++ )
434
+ {
435
+ memcpy (( char * )mData + i*dataTypeSize, nodata, dataTypeSize );
436
+ }
437
+ }
438
+ else
439
+ {
440
+ // use bitmap
441
+ if ( mNoDataBitmap == 0 )
442
+ {
443
+ if ( !createNoDataBitmap () )
444
+ {
445
+ return false ;
446
+ }
447
+ }
448
+ QgsDebugMsg ( " set mNoDataBitmap to 1" );
449
+ memset ( mNoDataBitmap , 0b11111111 , mNoDataBitmapSize );
450
+ }
451
+ return true ;
452
+ }
453
+ else
403
454
{
404
- if ( !mData )
455
+ // image
456
+ if ( !mImage )
405
457
{
406
- QgsDebugMsg ( " Data block not allocated" );
458
+ QgsDebugMsg ( " Image not allocated" );
407
459
return false ;
408
460
}
461
+ QgsDebugMsg ( " Fill image" );
462
+ mImage ->fill ( qRgba ( 0 , 0 , 0 , 0 ) );
463
+ return true ;
464
+ }
465
+ }
409
466
410
- int dataTypeSize = typeSize ( mDataType );
411
- QByteArray noDataByteArray = valueBytes ( mDataType , mNoDataValue );
467
+ bool QgsRasterBlock::setIsNoDataExcept ( const QRect & theExceptRect )
468
+ {
469
+ int top = theExceptRect.top ();
470
+ int bottom = theExceptRect.bottom ();
471
+ int left = theExceptRect.left ();
472
+ int right = theExceptRect.right ();
473
+ if ( top < 0 ) top = 0 ;
474
+ if ( left < 0 ) left = 0 ;
475
+ if ( bottom >= mHeight ) bottom = mHeight - 1 ;
476
+ if ( right >= mWidth ) right = mWidth - 1 ;
412
477
413
- char *nodata = noDataByteArray.data ();
414
- for ( size_t i = 0 ; i < ( size_t )mWidth *mHeight ; i++ )
478
+ QgsDebugMsg ( " Entered" );
479
+ if ( typeIsNumeric ( mDataType ) )
480
+ {
481
+ if ( mHasNoDataValue )
482
+ {
483
+ if ( !mData )
484
+ {
485
+ QgsDebugMsg ( " Data block not allocated" );
486
+ return false ;
487
+ }
488
+
489
+ QgsDebugMsg ( " set mData to mNoDataValue" );
490
+ int dataTypeSize = typeSize ( mDataType );
491
+ QByteArray noDataByteArray = valueBytes ( mDataType , mNoDataValue );
492
+
493
+ char *nodata = noDataByteArray.data ();
494
+ char nodataRow[mWidth ]; // full row of no data
495
+ for ( int c = 0 ; c < mWidth ; c ++ )
496
+ {
497
+ memcpy ( nodataRow + c*dataTypeSize, nodata, dataTypeSize );
498
+ }
499
+
500
+ // top and bottom
501
+ for ( int r = 0 ; r < mHeight ; r++ )
502
+ {
503
+ if ( r >= top && r <= bottom ) continue ; // middle
504
+ size_t i = ( size_t )r * mWidth ;
505
+ memcpy (( char * )mData + i*dataTypeSize, nodataRow, dataTypeSize*mWidth );
506
+ }
507
+ // middle
508
+ for ( int r = top; r <= bottom; r++ )
509
+ {
510
+ size_t i = r * mWidth ;
511
+ // middle left
512
+ memcpy (( char * )mData + i*dataTypeSize, nodataRow, dataTypeSize*left );
513
+ // middle right
514
+ i += right + 1 ;
515
+ int w = mWidth - right;
516
+ memcpy (( char * )mData + i*dataTypeSize, nodataRow, dataTypeSize*w );
517
+ }
518
+ }
519
+ else
415
520
{
416
- memcpy (( char * )mData + i*dataTypeSize, nodata, dataTypeSize );
521
+ // use bitmap
522
+ if ( mNoDataBitmap == 0 )
523
+ {
524
+ if ( !createNoDataBitmap () )
525
+ {
526
+ return false ;
527
+ }
528
+ }
529
+ QgsDebugMsg ( " set mNoDataBitmap to 1" );
530
+
531
+ char nodataRow[mNoDataBitmapWidth ]; // full row of no data
532
+ memset ( nodataRow, 0 , mNoDataBitmapWidth );
533
+ for ( int c = 0 ; c < mWidth ; c ++ )
534
+ {
535
+ int byte = c / 8 ;
536
+ int bit = c % 8 ;
537
+ int nodata = 0b10000000 >> bit;
538
+ memset ( nodataRow + byte, nodataRow[byte] | nodata, 1 );
539
+ }
540
+
541
+ // top and bottom
542
+ for ( int r = 0 ; r < mHeight ; r++ )
543
+ {
544
+ if ( r >= top && r <= bottom ) continue ; // middle
545
+ size_t i = ( size_t )r * mNoDataBitmapWidth ;
546
+ memcpy ( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
547
+ }
548
+ // middle
549
+ memset ( nodataRow, 0 , mNoDataBitmapWidth );
550
+ for ( int c = 0 ; c < mWidth ; c ++ )
551
+ {
552
+ if ( c >= left && c <= right ) continue ; // middle
553
+ int byte = c / 8 ;
554
+ int bit = c % 8 ;
555
+ int nodata = 0b10000000 >> bit;
556
+ memset ( nodataRow + byte, nodataRow[byte] | nodata, 1 );
557
+ }
558
+ for ( int r = top; r <= bottom; r++ )
559
+ {
560
+ size_t i = ( size_t )r * mNoDataBitmapWidth ;
561
+ memcpy ( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
562
+ }
417
563
}
564
+ return true ;
418
565
}
419
- // use bitmap
420
- if ( mNoDataBitmap == 0 )
566
+ else
421
567
{
422
- if ( !createNoDataBitmap () )
568
+ // image
569
+ if ( !mImage )
423
570
{
571
+ QgsDebugMsg ( " Image not allocated" );
424
572
return false ;
425
573
}
574
+ QgsDebugMsg ( " Fill image" );
575
+ QRgb nodataRgba = qRgba ( 0 , 0 , 0 , 0 );
576
+ QRgb nodataRow[mWidth ]; // full row of no data
577
+ int rgbSize = sizeof ( QRgb );
578
+ for ( int c = 0 ; c < mWidth ; c ++ )
579
+ {
580
+ nodataRow[c] = nodataRgba;
581
+ }
582
+
583
+ // top and bottom
584
+ for ( int r = 0 ; r < mHeight ; r++ )
585
+ {
586
+ if ( r >= top && r <= bottom ) continue ; // middle
587
+ size_t i = ( size_t )r * mWidth ;
588
+ memcpy (( void * )( mImage ->bits () + rgbSize*i ), nodataRow, rgbSize*mWidth );
589
+ }
590
+ // middle
591
+ for ( int r = top; r <= bottom; r++ )
592
+ {
593
+ size_t i = r * mWidth ;
594
+ // middle left
595
+ memcpy (( void * )( mImage ->bits () + rgbSize*i ), nodataRow, rgbSize*left );
596
+ // middle right
597
+ i += right + 1 ;
598
+ int w = mWidth - right;
599
+ memcpy (( void * )( mImage ->bits () + rgbSize*i ), nodataRow, rgbSize*w );
600
+ }
601
+ return true ;
426
602
}
427
- memset ( mNoDataBitmap , 0b11111111 , sizeof ( mNoDataBitmap ) );
428
- return true ;
429
603
}
430
604
431
605
char * QgsRasterBlock::bits ( size_t index )
@@ -651,14 +825,45 @@ QByteArray QgsRasterBlock::valueBytes( QGis::DataType theDataType, double theVal
651
825
652
826
bool QgsRasterBlock::createNoDataBitmap ()
653
827
{
654
- size_t size = mWidth * mHeight / 8 + 1 ;
655
- QgsDebugMsg ( QString ( " allocate %1 bytes" ).arg ( size ) );
656
- mNoDataBitmap = ( char * )qgsMalloc ( size );
828
+ mNoDataBitmapWidth = mWidth / 8 + 1 ;
829
+ mNoDataBitmapSize = ( size_t )mNoDataBitmapWidth * mHeight ;
830
+ QgsDebugMsg ( QString ( " allocate %1 bytes" ).arg ( mNoDataBitmapSize ) );
831
+ mNoDataBitmap = ( char * )qgsMalloc ( mNoDataBitmapSize );
657
832
if ( mNoDataBitmap == 0 )
658
833
{
659
- QgsDebugMsg ( QString ( " Couldn't allocate no data memory of %1 bytes" ).arg ( size ) );
834
+ QgsDebugMsg ( QString ( " Couldn't allocate no data memory of %1 bytes" ).arg ( mNoDataBitmapSize ) );
660
835
return false ;
661
836
}
662
- memset ( mNoDataBitmap , 0 , size );
837
+ memset ( mNoDataBitmap , 0 , mNoDataBitmapSize );
663
838
return true ;
664
839
}
840
+
841
+ QRect QgsRasterBlock::subRect ( const QgsRectangle & theExtent, int theWidth, int theHeight, const QgsRectangle & theSubExtent )
842
+ {
843
+ double xRes = theExtent.width () / theWidth;
844
+ double yRes = theExtent.height () / theHeight;
845
+
846
+ int top = 0 ;
847
+ int bottom = theHeight - 1 ;
848
+ int left = 0 ;
849
+ int right = theWidth - 1 ;
850
+
851
+ if ( theSubExtent.yMaximum () < theExtent.yMaximum () )
852
+ {
853
+ top = qRound (( theExtent.yMaximum () - theSubExtent.yMaximum () ) / yRes );
854
+ }
855
+ if ( theSubExtent.yMinimum () > theExtent.yMinimum () )
856
+ {
857
+ bottom = qRound (( theExtent.yMaximum () - theSubExtent.yMinimum () ) / yRes ) - 1 ;
858
+ }
859
+
860
+ if ( theSubExtent.xMinimum () > theExtent.xMinimum () )
861
+ {
862
+ left = qRound (( theSubExtent.xMinimum () - theExtent.xMinimum () ) / xRes );
863
+ }
864
+ if ( theSubExtent.xMaximum () < theExtent.xMaximum () )
865
+ {
866
+ right = qRound (( theSubExtent.xMaximum () - theExtent.xMinimum () ) / xRes ) - 1 ;
867
+ }
868
+ return QRect ( left, top, right - left + 1 , bottom - top + 1 );
869
+ }
0 commit comments