Opened 12 years ago

Closed 11 years ago

#2360 closed defect (fixed)

[GTiff] GTiffOddBitsBand::IWriteBlock crashes with anything different from eDataType=GDTByte

Reported by: Even Rouault Owned by: Even Rouault
Priority: normal Milestone: 1.5.3
Component: default Version: 1.5.0
Severity: normal Keywords: gtiff odd bits band
Cc:

Description

The GTiffOddBitsBand::IWriteBlock method cannot handled the following data types that are well handled by the ::IReadBlock method :

  • float 16
  • float 32
  • int 9, ..., int 15
  • int 17, ..., int 31

This can be demonstrated with the following scenario :

  • cp ../autotest/gcore/data/int10.tif int10.tif
  • gdalwarp ../autotest/gcore/data/int10.tif int10.tif

and the same with int24.tif, float16.tif and float24.tif

I'm wondering what is the most appropriate action as such use case is probably uncommon: preventing from opening such files in update mode (the easiest way) or adding the necessary code.

Change History (2)

comment:1 Changed 11 years ago by Even Rouault

Owner: changed from warmerdam to Even Rouault

comment:2 Changed 11 years ago by Even Rouault

Milestone: 1.5.3
Resolution: fixed
Status: newclosed

In trunk:

  • in r14840, I've commited a fix to enable updating data with NBITS >= 9 and NBITS <= 32, which crashed before. The float case with nBitsPerSample < 32 is not handled, but a proper error is returned. In the process of fixing that, I've also decided to remove the implementations of GTiffBitmapBand::IReadBlock/IWriteBlock to use GTiffOddBitsBand instead (dealt as special cases to keep performance). That made it easier to fix a subtle bug in round-tripping IReadBlock/IWriteBlock which can be shown with the following script :
import gdal
import struct

oldSize = gdal.GetCacheMax()
gdal.SetCacheMax(0)

# NBITS=2 will also fail with GDAL 1.5
ds = gdal.GetDriverByName("GTiff").Create("temp.tif", 10, 10, 1, options = [ 'NBITS=1' ])
ds.GetRasterBand(1).Fill(0)

ds2 = gdal.GetDriverByName("GTiff").Create("temp2.tif", 10, 10, 1)
ds2.GetRasterBand(1).Fill(1)
ones = ds2.ReadRaster(0, 0, 10, 1)

data = ds.ReadRaster(0, 0, 10, 1)

ds.WriteRaster(0, 0, 10, 1, ones)

# This will exhaust the cache
ds3 = gdal.GetDriverByName("GTiff").Create("temp3.tif", 10, 10, 1)
ds3.GetRasterBand(1).Fill(1)

# We expect (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
data = ds.ReadRaster(0, 0, 10, 1)
got = struct.unpack('B' * 10, data)
for i in range(len(got)):
    if got[i] != 1:
        print 'fail'

gdal.SetCacheMax(oldSize)

It is now possible to create and translate files with GDT_UInt16 where NBITS>=9 and NBITS<=15, and with GDT_UInt32 where NBITS>=17 and NBITS<=32

All that is tested in r14841

  • in branches/1.5 in r14842, I've just fixed the tile of this bug, that is to say to error properly when NBITS > 8.
Note: See TracTickets for help on using tickets.