def dither_1(): drv = gdal.GetDriverByName('GTiff') src_ds = gdal.Open('../gdrivers/data/rgbsmall.tif') r_band = src_ds.GetRasterBand(1) g_band = src_ds.GetRasterBand(2) b_band = src_ds.GetRasterBand(3) dst_ds = drv.Create('tmp/rgbsmall.tif', src_ds.RasterXSize, src_ds.RasterYSize, 1, gdal.GDT_Byte) dst_band = dst_ds.GetRasterBand(1) ct = gdal.ColorTable() nColors = 8 gdal.ComputeMedianCutPCT(r_band, g_band, b_band, nColors, ct) dst_band.SetRasterColorTable(ct) gdal.DitherRGB2PCT(r_band, g_band, b_band, dst_band, ct) cs_expected = 8803 cs = dst_band.Checksum() dst_band = None dst_ds = None if ct.GetCount() != nColors: gdaltest.post_reason('color table size wrong') return 'fail' ref_ct = [(36, 48, 32, 255), (92, 120, 20, 255), (88, 96, 20, 255), (92, 132, 56, 255), (0, 0, 0, 255), (96, 152, 24, 255), (60, 112, 32, 255), (164, 164, 108, 255)] for i in range(nColors): ct_data = ct.GetColorEntry(i) ref_data = ref_ct[i] for j in range(4): if ct_data[j] != ref_data[j]: gdaltest.post_reason('color table mismatch') for k in range(nColors): print(ct.GetColorEntry(k)) print(ref_ct[k]) return 'fail' if cs == cs_expected \ or gdal.GetConfigOption( 'CPL_DEBUG', 'OFF' ) != 'ON': drv.Delete('tmp/rgbsmall.tif') if cs != cs_expected: print('Got: ', cs) gdaltest.post_reason('got wrong checksum') return 'fail' else: return 'success'
tif_ds.GetRasterBand(1).SetRasterColorTable(ct) # ---------------------------------------------------------------------------- # We should copy projection information and so forth at this point. tif_ds.SetProjection(src_ds.GetProjection()) tif_ds.SetGeoTransform(src_ds.GetGeoTransform()) if src_ds.GetGCPCount() > 0: tif_ds.SetGCPs(src_ds.GetGCPs(), src_ds.GetGCPProjection()) # ---------------------------------------------------------------------------- # Actually transfer and dither the data. err = gdal.DitherRGB2PCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), tif_ds.GetRasterBand(1), ct, callback=gdal.TermProgress_nocb) tif_ds = None if tif_filename != dst_filename: tif_ds = gdal.Open(tif_filename) dst_driver.CreateCopy(dst_filename, tif_ds) tif_ds = None os.close(tif_filedesc) gtiff_driver.Delete(tif_filename)
tif_ds.GetRasterBand(1).SetRasterColorTable( ct ) # ---------------------------------------------------------------------------- # We should copy projection information and so forth at this point. tif_ds.SetProjection( src_ds.GetProjection() ) tif_ds.SetGeoTransform( src_ds.GetGeoTransform() ) if src_ds.GetGCPCount() > 0: tif_ds.SetGCPs( src_ds.GetGCPs(), src_ds.GetGCPProjection() ) # ---------------------------------------------------------------------------- # Actually transfer and dither the data. err = gdal.DitherRGB2PCT( src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), tif_ds.GetRasterBand(1), ct, callback = gdal.TermProgress, callback_data = 'Generate PCT' ) tif_ds = None if tif_filename != dst_filename: tif_ds = gdal.Open( tif_filename ) dst_driver.CreateCopy( dst_filename, tif_ds ) tif_ds = None os.close(tif_filedesc) gtiff_driver.Delete( tif_filename )
def doit(pct_filename=None, src_filename=None, dst_filename=None, color_count=256, frmt=None): # Open source file src_ds = gdal.Open(src_filename) if src_ds is None: print('Unable to open %s' % src_filename) return None, 1 if src_ds.RasterCount < 3: print('%s has %d band(s), need 3 for inputs red, green and blue.' % (src_filename, src_ds.RasterCount)) return None, 1 # Ensure we recognise the driver. if frmt is None: frmt = GetOutputDriverFor(dst_filename) dst_driver = gdal.GetDriverByName(frmt) if dst_driver is None: print('"%s" driver not registered.' % frmt) return None, 1 # Generate palette ct = gdal.ColorTable() if pct_filename is None: err = gdal.ComputeMedianCutPCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), color_count, ct, callback=gdal.TermProgress_nocb) else: pct_ds = gdal.Open(pct_filename) ct = pct_ds.GetRasterBand(1).GetRasterColorTable().Clone() # Create the working file. We have to use TIFF since there are few formats # that allow setting the color table after creation. if format == 'GTiff': tif_filename = dst_filename else: import tempfile tif_filedesc, tif_filename = tempfile.mkstemp(suffix='.tif') gtiff_driver = gdal.GetDriverByName('GTiff') tif_ds = gtiff_driver.Create(tif_filename, src_ds.RasterXSize, src_ds.RasterYSize, 1) tif_ds.GetRasterBand(1).SetRasterColorTable(ct) # ---------------------------------------------------------------------------- # We should copy projection information and so forth at this point. tif_ds.SetProjection(src_ds.GetProjection()) tif_ds.SetGeoTransform(src_ds.GetGeoTransform()) if src_ds.GetGCPCount() > 0: tif_ds.SetGCPs(src_ds.GetGCPs(), src_ds.GetGCPProjection()) # ---------------------------------------------------------------------------- # Actually transfer and dither the data. err = gdal.DitherRGB2PCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), tif_ds.GetRasterBand(1), ct, callback=gdal.TermProgress_nocb) if tif_filename == dst_filename: dst_ds = tif_ds else: dst_ds = dst_driver.CreateCopy(dst_filename, tif_ds) tif_ds = None gtiff_driver.Delete(tif_filename) os.close(tif_filedesc) return dst_ds, err
def rgb2pct(self, src_filename, dst_filename, driver, color_count=256): """Convert a 24bit RGB image to 8bit paletted. From GDAL: https://gdal.org/programs/rgb2pct.html. Compute an optimal pseudo-color table for a given RGB image using a median cut algorithm on a downsampled RGB histogram. Then it converts the image into a pseudo-colored image using the color table. This conversion utilizes Floyd-Steinberg dithering (error diffusion) to maximize output image visual quality. Arguments: src_filename (str): The input RGB file path. dst_filename (str): The output path of the pseudo-colored file that will be created. driver (str): The driver to open the input RGB file. Keyword Arguments: color_count (number): The number of colors in the generated color table. Must be between 2 and 256. (default: {256}) """ src_ds = gdal.Open(src_filename) ct = gdal.ColorTable() err = gdal.ComputeMedianCutPCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), color_count, ct, callback=gdal.TermProgress_nocb) # Create the working file. We have to use TIFF since there are few formats # that allow setting the color table after creation. if driver.ShortName == 'GTiff': tif_filename = dst_filename else: import tempfile tif_filedesc, tif_filename = tempfile.mkstemp(suffix='.tif') gtiff_driver = gdal.GetDriverByName('GTiff') tif_ds = gtiff_driver.Create(tif_filename, src_ds.RasterXSize, src_ds.RasterYSize, 1) tif_ds.GetRasterBand(1).SetRasterColorTable(ct) # ---------------------------------------------------------------------------- # We should copy projection information and so forth at this point. tif_ds.SetProjection(src_ds.GetProjection()) tif_ds.SetGeoTransform(src_ds.GetGeoTransform()) if src_ds.GetGCPCount() > 0: tif_ds.SetGCPs(src_ds.GetGCPs(), src_ds.GetGCPProjection()) # ---------------------------------------------------------------------------- # Actually transfer and dither the data. err = gdal.DitherRGB2PCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), tif_ds.GetRasterBand(1), ct, callback=gdal.TermProgress_nocb) tif_ds = None if tif_filename != dst_filename: tif_ds = gdal.Open(tif_filename) driver.CreateCopy(dst_filename, tif_ds) tif_ds = None os.close(tif_filedesc) gtiff_driver.Delete(tif_filename)
def rgb2pct(src_filename: PathLikeOrStr, pct_filename: Optional[PathLikeOrStr] = None, dst_filename: Optional[PathLikeOrStr] = None, color_count: int = 256, driver_name: Optional[str] = None): # Open source file src_ds = open_ds(src_filename) if src_ds is None: raise Exception(f'Unable to open {src_filename}') if src_ds.RasterCount < 3: raise Exception( f'{src_filename} has {src_ds.RasterCount} band(s), need 3 for inputs red, green and blue.' ) # Ensure we recognise the driver. if not driver_name: driver_name = GetOutputDriverFor(dst_filename) dst_driver = gdal.GetDriverByName(driver_name) if dst_driver is None: raise Exception(f'"{driver_name}" driver not registered.') # Generate palette if pct_filename is None: ct = gdal.ColorTable() err = gdal.ComputeMedianCutPCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), color_count, ct, callback=gdal.TermProgress_nocb) else: ct = get_color_table(pct_filename) # Create the working file. We have to use TIFF since there are few formats # that allow setting the color table after creation. if driver_name.lower() == 'gtiff': tif_filename = dst_filename else: import tempfile tif_filedesc, tif_filename = tempfile.mkstemp(suffix='.tif') gtiff_driver = gdal.GetDriverByName('GTiff') tif_ds = gtiff_driver.Create(tif_filename, src_ds.RasterXSize, src_ds.RasterYSize, 1) tif_ds.GetRasterBand(1).SetRasterColorTable(ct) # ---------------------------------------------------------------------------- # We should copy projection information and so forth at this point. tif_ds.SetProjection(src_ds.GetProjection()) tif_ds.SetGeoTransform(src_ds.GetGeoTransform()) if src_ds.GetGCPCount() > 0: tif_ds.SetGCPs(src_ds.GetGCPs(), src_ds.GetGCPProjection()) # ---------------------------------------------------------------------------- # Actually transfer and dither the data. err = gdal.DitherRGB2PCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), tif_ds.GetRasterBand(1), ct, callback=gdal.TermProgress_nocb) if err != gdal.CE_None: raise Exception('DitherRGB2PCT failed') if tif_filename == dst_filename: dst_ds = tif_ds else: dst_ds = dst_driver.CreateCopy(dst_filename or '', tif_ds) tif_ds = None os.close(tif_filedesc) gtiff_driver.Delete(tif_filename) return dst_ds
def main(argv): color_count = 256 frmt = None src_filename = None dst_filename = None pct_filename = None gdal.AllRegister() argv = gdal.GeneralCmdLineProcessor(argv) if argv is None: sys.exit(0) # Parse command line arguments. i = 1 while i < len(argv): arg = argv[i] if arg == '-of' or arg == '-f': i = i + 1 frmt = argv[i] elif arg == '-n': i = i + 1 color_count = int(argv[i]) elif arg == '-pct': i = i + 1 pct_filename = argv[i] elif src_filename is None: src_filename = argv[i] elif dst_filename is None: dst_filename = argv[i] else: Usage() i = i + 1 if dst_filename is None: Usage() # Open source file src_ds = gdal.Open(src_filename) if src_ds is None: print('Unable to open %s' % src_filename) sys.exit(1) if src_ds.RasterCount < 3: print('%s has %d band(s), need 3 for inputs red, green and blue.' % (src_filename, src_ds.RasterCount)) sys.exit(1) # Ensure we recognise the driver. if frmt is None: frmt = GetOutputDriverFor(dst_filename) dst_driver = gdal.GetDriverByName(frmt) if dst_driver is None: print('"%s" driver not registered.' % frmt) sys.exit(1) # Generate palette ct = gdal.ColorTable() if pct_filename is None: err = gdal.ComputeMedianCutPCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), color_count, ct, callback=gdal.TermProgress_nocb) else: pct_ds = gdal.Open(pct_filename) ct = pct_ds.GetRasterBand(1).GetRasterColorTable().Clone() # Create the working file. We have to use TIFF since there are few formats # that allow setting the color table after creation. if format == 'GTiff': tif_filename = dst_filename else: import tempfile tif_filedesc, tif_filename = tempfile.mkstemp(suffix='.tif') gtiff_driver = gdal.GetDriverByName('GTiff') tif_ds = gtiff_driver.Create(tif_filename, src_ds.RasterXSize, src_ds.RasterYSize, 1) tif_ds.GetRasterBand(1).SetRasterColorTable(ct) # ---------------------------------------------------------------------------- # We should copy projection information and so forth at this point. tif_ds.SetProjection(src_ds.GetProjection()) tif_ds.SetGeoTransform(src_ds.GetGeoTransform()) if src_ds.GetGCPCount() > 0: tif_ds.SetGCPs(src_ds.GetGCPs(), src_ds.GetGCPProjection()) # ---------------------------------------------------------------------------- # Actually transfer and dither the data. err = gdal.DitherRGB2PCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), tif_ds.GetRasterBand(1), ct, callback=gdal.TermProgress_nocb) tif_ds = None if tif_filename != dst_filename: tif_ds = gdal.Open(tif_filename) dst_driver.CreateCopy(dst_filename, tif_ds) tif_ds = None os.close(tif_filedesc) gtiff_driver.Delete(tif_filename) return err