Search code examples
cmdgdal

Using "gdal_translate" from .TIF to .JPG how to set background to white?


I tried using the following line:

gdal_translate -of jpeg -a_nodata 0 -b 1 -b 2 -b 3 c:\myfolder\mytif.tif c:\myfolder\myNewtif.jpg

This produces the image with wanted specs, but turns the background to black (transparency?), eventhough the original has white. Can I accomplish a white background with just gdal_translate?

File dump of a file with mask: https://filebin.net/f15v63to2x3cc4z0

File dump of a file with no a mask: https://filebin.net/kc940hqotcoeny0w

gdalinfo output of a Tif that produces white background as expected:

Driver: GTiff/GeoTIFF
Files: test.tif
Size is 4799, 3196
Metadata:
  TIFFTAG_RESOLUTIONUNIT=2 (pixels/inch)
  TIFFTAG_XRESOLUTION=300
  TIFFTAG_YRESOLUTION=300
Image Structure Metadata:
  COMPRESSION=LZW
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  (    0.0,    0.0)
Lower Left  (    0.0, 3196.0)
Upper Right ( 4799.0,    0.0)
Lower Right ( 4799.0, 3196.0)
Center      ( 2399.5, 1598.0)
Band 1 Block=4799x1 Type=Byte, ColorInterp=Red
Band 2 Block=4799x1 Type=Byte, ColorInterp=Green
Band 3 Block=4799x1 Type=Byte, ColorInterp=Blue

Tif that produces black background:

Warning 1: TIFFFetchNormalTag:Incompatible type for "RichTIFFIPTC"; tag ignored
Driver: GTiff/GeoTIFF
Files: 100011_1.tif
Size is 1640, 2401
Metadata:
  TIFFTAG_DATETIME=2020:01:13 12:29:55
  TIFFTAG_RESOLUTIONUNIT=2 (pixels/inch)
  TIFFTAG_SOFTWARE=Adobe Photoshop 21.0 (Windows)
  TIFFTAG_XRESOLUTION=300
  TIFFTAG_YRESOLUTION=300
Image Structure Metadata:
  COMPRESSION=LZW
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  (    0.0,    0.0)
Lower Left  (    0.0, 2401.0)
Upper Right ( 1640.0,    0.0)
Lower Right ( 1640.0, 2401.0)
Center      (  820.0, 1200.5)
Band 1 Block=1640x39 Type=Byte, ColorInterp=Red
  Mask Flags: PER_DATASET ALPHA
Band 2 Block=1640x39 Type=Byte, ColorInterp=Green
  Mask Flags: PER_DATASET ALPHA
Band 3 Block=1640x39 Type=Byte, ColorInterp=Blue
  Mask Flags: PER_DATASET ALPHA
Band 4 Block=1640x39 Type=Byte, ColorInterp=Alpha

Also of the following images that have black background after translate, gdal produces this warning "Warning 1: TIFFFetchNormalTag: Incompatible type for "RichTIFFIPTC"; tag ignored"


Solution

  • The file that you have shared on filebin contains an "alpha" mask, as you can see in the output of gdalinfo. The mask of this file says that the background is masked, while the rest of the image is not.

    If you display the tiff with the default Ubuntu viewer, for example, you can see that the background pixels are masked out (they appear as a checker board) masked tiff

    If you inspect the raster data, you also see that the underlying pixels from the background are black, not white. That is why gdal_translate generates a jpeg with black pixels in the background, it is because they really are black (but masked out) in the original tiff file.

    If you absolutely want the background to be white, you can do so with a few lines of Python using the rasterio library for example, by explicitly setting the masked pixels to white:

    import rasterio
    
    with rasterio.open("101679_1.tif") as src:
        arr = src.read(masked=True)
    
        # Convert all masked values to white
        arr[arr.mask] = 255
    
        # Write to jpeg file
        profile = src.profile
        profile["count"] = 3
        profile["driver"] = "jpeg"
        with rasterio.open("test.jpeg", "w", **profile) as dst:
            dst.write(arr[:3])
    

    This should give the following jpeg file:

    jpeg with white background

    The code snippet I have included above will also work on TIF files which already have a white background, because the arr[arr.mask] = 255 line will not do anything if the file contains no mask. To process a directory full of .tif files, you can do:

    from glob import glob
    import rasterio
    
    for tif in glob("*.tif"):
        with rasterio.open(tif) as src:
            arr = src.read(masked=True)
    
            # Convert all masked values to white
            arr[arr.mask] = 255
    
            # Write to jpeg file
            profile = src.profile
            profile["count"] = 3
            profile["driver"] = "jpeg"
            with rasterio.open(tif.replace(".tif", ".jpeg"), "w", **profile) as dst:
                dst.write(arr[:3])