4

I need to convert a Float32 tiff image to 8bit format in order to display the image in a web page. In order to do that I need a jpg image but this conversion is not correctly done with GDAL because the image is Float32 type. So I want to convert to 8bit type with Python.

Can you help me?

I've tried something like this:

gdal.AllRegister()  
src = gdal.Open(str(input_file)) 
src_data = src.ReadAsArray()
cols = src.RasterXSize
rows = scr.RasterYSize
driver = gdal.GetDriverByName("GTiff")
dst = driver.Create(str(output_file), cols, rows, 1, gdal.GDT_Byte)
dst.GetRasterBand(1).WriteArray(src_data)
#dst = drv.CreateCopy(output_file, src, 0, saveOptions)

I try with Create() and CreateCopy() but I always get a black image.

  • Do you definitely want to do it with Python and not with a gdal_translate command? – user30184 Apr 22 '15 at 15:56
  • I need to solve it inside an application (a script) so I prefer with Python. It is possible? – Bárbara Duarte Apr 22 '15 at 15:57
  • For sure it is possible but I am not the one who knows how. I would first study the histogram of the original and the all black image you have with gdalinfo -stats. 32 bit images often have data only on the lower end of the scale which make them look like totally black if they are viewed without stretching the histogram. Then you may need to find an equivalent to -scale option of gdal_translate gdal.org/gdal_translate.html for Python. – user30184 Apr 22 '15 at 16:03
  • I try what you said and the black image as the same information about the original image. But it appears in black. How do I correct that? – Bárbara Duarte Apr 23 '15 at 14:44
  • Much easier than to explain is to show an example with real data. Do you have some test data to be used as input? – user30184 Apr 23 '15 at 14:52
3

The most easy way to do this in a script is to use the subprocess module and gdal_translate

import subprocess

image_in = "path_input_image"
image_out = "path_output_image.tif"
subprocess.call(["gdal_translate.exe","-co", "TILED=YES", "-co", "COMPRESS=LZW" "-ot", "Byte", "-scale", image_in, image_out ])

f you are in Linux, you don't need the ".exe" after gdal_translate, and if gdal is not installed, you might need to provide the full path to the application

alternatively, this can be done with OTBApplication

#!/usr/bin/python

# Import the otb applications package
import otbApplication

image_in = "path_input_image"
image_out = "path_output_image.tif"

# The following line creates an instance of the Rescale application
Rescale = otbApplication.Registry.CreateApplication("Rescale")

# The following lines set all the application parameters:
Rescale.SetParameterString("in",image_in )

Rescale.SetParameterString("out",image_out )
Rescale.SetParameterOutputImagePixelType("out", ImagePixelType_uint8)

Rescale.SetParameterFloat("outmin", 0)

Rescale.SetParameterFloat("outmax", 255)

# The following line execute the application
Rescale.ExecuteAndWriteOutput()
5

You can do that directly in QGIS with Raster -> Conversion -> Translate (Convert Format). To test it, I used a Float64 (Sixty four bit floating point) raster (named test) loaded in the Map View of QGIS. To convert it to Byte (8 bit type), I named it first at the "output file space" as test_byte.tif and afterward, I click in the icon pencil of "Translate Window" to modify gdal_translate command to:

gdal_translate -ot Byte -of GTiff /home/zeito/proyectosR/test.tif /home/zeito/proyectosR/test_byte.tif

as in the following image:

enter image description here

After click in OK, it can be observed at the layer properties of test_byte.tif that this raster is "Eight bit unsigned integer":

enter image description here

Editing Note:

This code works (to change the data type) in my bash console (in Windows is necessary to use IDLE Python GUI):

from osgeo import gdal, osr

dataset = gdal.Open('tiznados_canoa.tif')

geotransform = dataset.GetGeoTransform()

prj=dataset.GetProjection()

values = dataset.ReadAsArray()

band = dataset.GetRasterBand(1)

#Get minimum and maximum values of raster
min = band.GetMinimum()
max = band.GetMaximum()

#if not exist minimum and maximum values
if min is None or max is None:
    (min,max) = band.ComputeRasterMinMax(1)

print "Min=%.3f, Max=%.3f" % (min,max) #print minimum and maximum values

# Set output file
output_file = "out.tif"

# Create new GTiff (Byte type)
driver = gdal.GetDriverByName("GTiff")
dst_ds = driver.Create(output_file, band.XSize, band.YSize, 1, gdal.GDT_Byte)

print "rows = ", band.YSize, "columns = ", band.XSize

print "Executing..."

for i in range(band.YSize):
    for j in range(band.XSize):

        values[i][j]

dst_ds.GetRasterBand(1).WriteArray( values )

# top left x, w-e pixel resolution, rotation, top left y, rotation, n-s pixel resolution
dst_ds.SetGeoTransform( [ geotransform[0], geotransform[1], 0, geotransform[3], 0, geotransform[5] ] )

# set projection of new raster
dst_ds.SetProjection( prj )

dataset = None
  • Yes, I know how to do it in QGIS but I want python code to insert in a script. That's my dificulty. – Bárbara Duarte Apr 23 '15 at 16:12
  • As you said "I need to convert a Float32 tiff image to 8 bit format in order to display the image in a web page", for this requirement you don't need Python and the reason of my answer. However, it's not difficult to do that. – xunilk Apr 23 '15 at 16:20
  • Yes, but the process is inside an application. So I need to automatize the process. I try to use the command gdal_translate in python script through os.system and subprocess.call but without success. – Bárbara Duarte Apr 23 '15 at 16:56
  • You have my code with GDAL (See my Editing Note). – xunilk Apr 23 '15 at 19:07
  • By the way, subprocess doesn't work in my system after actualization of my QGIS to 2.8 version. For this reason I used GDAL library in Python. – xunilk Apr 23 '15 at 19:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.