Is there a way to write a GeoTiff file with Color and Alpha Channel Data using geotiffwrite?

Is there a way to write a GeoTiff file with Color and Alpha Channel Data using geotiffwrite? I tried defining a TiffTag for "ExtraSamples" as shown below, but I got an warning message. The image (img) is a n x m x 4 RGB image where the 4 index on dimension 3 is the alpha channel.
geotiffwrite('img.tif', img, R, 'TiffTags', struct('ExtraSamples', Tiff.ExtraSamples.Unspecified))
Warning Message:
Warning: Sum of Photometric color channels and ExtraSamples does not match the value specified in SamplesPerPixel.
Writing with this configuration will error in a future release. To correct the configuration, define the non-color channels as ExtraSamples.
I get an error if I try defining the "SamplesPerPixel" TiffTag as 4. I don't know how to define the non-color channels as ExtraSamples using geotiffwrite.
I used the following example for Tiff objects to try to create the alpha channel data:

Answers (1)

Hi Sonoma,
Yes, it is possible to write a GeoTiff file with color and alpha channel data using geotiffwrite function in MATLAB. However, you need to correctly define the "ExtraSamples" TiffTag in order to do so.
From the error and warning messages you received, it seems like the "ExtraSamples" TiffTag was not defined correctly. Instead of defining it as "Unspecified", you can define the non-color channels as "ExtraSamples". For example, you can modify the "TiffTags" struct as follows:
TiffTags.Photometric = Tiff.Photometric.RGB;
TiffTags.BitsPerSample = 8;
TiffTags.SamplesPerPixel = 4;
TiffTags.ExtraSamples = Tiff.ExtraSamples.UnassociatedAlpha;
This sets the "Photometric" tag to RGB, "BitsPerSample" to 8 (assuming your image has 8-bit color depth), "SamplesPerPixel" to 4 (indicating that there are 4 color channels), and "ExtraSamples" to "UnassociatedAlpha" (indicating that the extra channel is an alpha channel that is not associated with any specific color).
Then, you can pass this "TiffTags" struct to the geotiffwrite function like this:
geotiffwrite('img.tif', img, R, 'TiffTags', TiffTags);
This should allow you to write a GeoTiff file with color and alpha channel data using geotiffwrite function in MATLAB.

10 Comments

Shubham,
when I run the script using your suggestion, I get the following error:
Error using geotiffwrite (line 245)
Expected TiffTags.BitsPerSample to match one of these values:
'Artist', 'Compression', 'Copyright', 'DateTime', 'DocumentName', 'DotRange', 'ExtraSamples', 'FillOrder', 'Group3Options',
'Group4Options', 'HalfToneHints', 'HostComputer', 'ICCProfile', 'ImageDepth', 'ImageDescription', 'InkNames', 'InkSet', 'JPEGColorMode',
'JPEGQuality', 'Make', 'MaxSampleValue', 'MinSampleValue', 'Model', 'NumberOfInks', 'Orientation', 'PageName', 'PageNumber',
'PhotometricInterpretation', 'Photoshop', 'PlanarConfiguration', 'PrimaryChromaticities', 'RPCCoefficientTag', 'ReferenceBlackWhite',
'ResolutionUnit', 'RichTIFFIPTC', 'RowsPerStrip', 'SGILogDataFmt', 'SMaxSampleValue', 'SMinSampleValue', 'SToNits', 'Software',
'TargetPrinter', 'Thresholding', 'TileLength', 'TileWidth', 'TransferFunction', 'WhitePoint', 'XMP', 'XPosition', 'XResolution',
'YCbCrCoefficients', 'YCbCrPositioning', 'YCbCrSubSampling', 'YPosition', 'YResolution', 'ZipQuality'
The input, 'BitsPerSample', did not match any of the valid values.
I am running Matlab 2020b. It this feature used on later versions of Matlab.
I also had the same issue and have not found a solution. Shubham could you provide more information?
Its possible to modify a tiff object (T) as you describe. This can then be used to create a tiff image write(T,rgb_with_alpha). Although I don't think there is a way to convert the tiff object to a geotiff.
setTag(T,'BitsPerSample',8);
setTag(T,'SamplesPerPixel',4);
setTag(T,'ExtraSamples',Tiff.ExtraSamples.UnassociatedAlpha);
Creating a TiffTags Structure does gives the error described by Sonoma Rich
TiffTags.Photometric = Tiff.Photometric.RGB;
TiffTags.BitsPerSample = 8;
TiffTags.SamplesPerPixel = 4;
TiffTags.ExtraSamples = Tiff.ExtraSamples.UnassociatedAlpha;
geotiffwrite('file.tif', img, R, 'TiffTags', TiffTags);
Thanks for any support.
I stumbled upon a very easy solution... geotiffwrite will create transparency for all grid cells that have RGB=[NaN NaN NaN]. I used QGIS to load the file. Hope this helps someone else.
Do you use a double type image ( [nxmx3] where al values are type double?). I haven't been able to read in an image to Google earth. I have tried setting all the pixels in my alpha layer to NaN, but I am unable to view in PhotoViewer, GoogleEarth or any program other than MATLAB.
scaledpict = gray2ind(mat2gray(image,climits),size(cmap,1));
outpict = ind2rgb(scaledpict,cmap);
geotiffwrite(filename,outpict,R);%,'TiffTags',TiffTags);% outpict is a 811x1493x3 type double ranging from 0 to 1
Most tools will not read a floating-point TIFF correctly. Off the top of my head, I don't know of any which do.
That said, you're generating a dithered pseudocolor image. I don't see why you even need to use 64b float for that. If you don't absolutely need double, just cast and scale the output to something reasonable.
outpict = im2uint8(outpict);
Will this create the alpha layer as mentioned in @Taylor Shropshire's question? I need the alpha layer.
geotiffwrite() reserves a number of TIFF tags which it sets internally. These are two of those tags, so trying to set them externally causes an error. It's arguably a confusing error, since it sounds like it's complaining about the value when it's actually complaining about the tag name.
% these are exclusively set internally
% trying to set them externally will cause an error
TiffTags.BitsPerSample = 8; % depends strictly on class
TiffTags.SamplesPerPixel = 4; % depends strictly on size(inpict,3)
That said, we don't need to set either of these tags. They'll be set internally to match whatever the class and depth of the incoming image is.
The problem is that if we feed it an RGBA image with the ExtraSamples tag set appropriately, it'll throw a different error.
if isfield(TiffTags, 'Photometric') ...
&& TiffTags.Photometric == Tiff.Photometric.RGB
map.internal.assert(ndims(A) == 3 && size(A,3) == 3, ...
'map:geotiff:imageSizeNotRGB', 'PhotometricInterpretation')
end
While we can set ExtraSamples to support attached alpha, this part of the validation routine prevents us from being able to even supply the attached alpha.
Is this an issue strictly with geotiffwrite(), or is it a consequence on prevailing expectations of what should be supported in a GeoTIFF across other software? I don't know, but as far as I see it, there isn't a neat way to do it. I don't really use GeoTIFF, so maybe I'm missing something.
You can either modify geotiffwrite(), or you can abuse other photometric modes (e.g. 'separated') to cram the extra channel in there, though most decoders will then probably treat it like CMYK or something. Similarly, you could probably treat it as indexed and reserve an index for alpha, but again, no decoder would magically know what index you wanted to be transparent. You'd have to post-process the incoming data after reading it.
If you're writing stuff that you intend to strictly be using in MATLAB, you might also just be able to throw everything into a .mat file and avoid the problem entirely.
This response seems very complicated and much different than my original question. I want to use the technique mentioned by @Taylor Shropshire
geotiffwrite will create transparency for all grid cells that have RGB=[NaN NaN NaN]
However, I don't see how this is possible as the when the data is typed as uint8. What am I missing?
Oh. I thought you were referring to the earlier comment.
geotiffwrite() doesn't do what @Taylor Shropshire suggests it's doing. Inserting NaN doesn't implicitly create alpha data. It just inserts NaNs, which may be treated strangely when rendered onscreen.
You're right in that it's not possible with integer-class images. I see why you were after using double now.
% the source image
infile = 'boston_ovr.jpg';
inpict = imread(infile);
outpict = im2double(inpict); % it needs to be float if we want to use NaN
% use a mask to insert some NaNs as pseudo-transparency
sz = size(inpict);
[x y] = meshgrid(1:sz(2),1:sz(1));
mk = repmat(x + y > sz(1),[1 1 size(inpict,3)]);
outpict(mk) = NaN;
% write the geotiff
worldfile = getworldfilename(infile);
R = worldfileread(worldfile, 'geographic', sz);
outfile = 'test.tif';
TiffTags.Photometric = Tiff.Photometric.RGB;
geotiffwrite(outfile, outpict, R, 'TiffTags', TiffTags)
% read the file back
[recpict R] = geotiffread(outfile);
imshow(recpict)
% it's full of NaNs still
nnz(isnan(recpict))
% all the NaNs are exactly as they were
isequal(isnan(outpict),isnan(recpict))
% the non-NaN content also remains unchanged
isequal(outpict(~mk),recpict(~mk))
% try to use imread to double-check that there's no alpha
% we can also check the metadata of the written file
[recpict2,~,alpha] = imread(outfile);
size(alpha) % it's empty
I can't run this on the forum, since for some reason all the map toolbox demo images are missing. When run, this should show that the process of writing the TIFF does not create any actual alpha data. It's up to the application to choose how to render non-numeric data. Unless given extra info, tools like imshow() will render it as black. I don't know what other viewers render it as, since I don't have anything else that can open float TIFFs. If QGIS renders them as transparent (or merely as the same color as the GUI background), then maybe it simply gives that illusion.
As to what's a better choice, I don't know. Like I said, I don't really use mapping toolbox stuff. There may be a way to store the image data and non-image data in separate files, such as would allow the use of a PNG that would be well-suited to simple integer-class RGBA content. That might not be the case, and it might not suit your workflow anyway.
I successfully relicated @Taylor Shropshire results when using geotiffwrite with an Index Image. The image imports into Google Earth my alpha layer. I don't beleive it is a true alpha layer as I use a binary mask (alpha=0 or 1). I suspect Google Earth is treating a border of 0's as background, thus hiding this part of the image from the viewer.
image is a [mxn] double array where the data I want to hide are NaNs.
climits = 2e-3*[0 1];% in my case
cmap = jet;% in my case
R is a georefcell structure.
rgb = double2rgb(image,cmap,climits);
[X,cmap] = rgb2ind(rgb,256);
geotiffwrite(filename,X,cmap,R);
Thank you for all the help

Sign in to comment.

Products

Release

R2020b

Asked:

on 3 Apr 2023

Commented:

on 19 Aug 2025

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!