time | Calls | line |
---|
| | 1 | function writepng(data, map, filename, varargin)
|
| | 2 | %WRITEPNG Write a PNG file to disk.
|
| | 3 | % WRITEPNG(I,[],FILENAME) writes the grayscale image I
|
| | 4 | % to the file specified by the string FILENAME.
|
| | 5 | %
|
| | 6 | % WRITEPNG(RGB,[],FILENAME) writes the truecolor image
|
| | 7 | % represented by the M-by-N-by-3 array RGB.
|
| | 8 | %
|
| | 9 | % WRITEPNG(X,MAP,FILENAME) writes the indexed image X with
|
| | 10 | % colormap MAP. The resulting file will contain the equivalent
|
| | 11 | % truecolor image.
|
| | 12 | %
|
| | 13 | % WRITEPNG(...,PARAM,VAL,...) sets the specified parameters.
|
| | 14 | %
|
| | 15 | % See also IMREAD, IMWRITE, IMFINFO.
|
| | 16 |
|
| | 17 | % Copyright 1984-2018 The MathWorks, Inc.
|
| | 18 |
|
| | 19 | % Parse the inputs
|
0.026 | 10 | 20 | [results, unmatched] = parseInputs(data,map,filename,varargin{:});
|
| | 21 |
|
0.007 | 10 | 22 | if ((ndims(data) > 3) || (~ismember(size(data,3), [1 3])))
|
| | 23 | error(message('MATLAB:imagesci:writepng:wrongImageDimensions'));
|
< 0.001 | 10 | 24 | end
|
| | 25 |
|
< 0.001 | 10 | 26 | alpha = results.alpha;
|
| | 27 |
|
| | 28 | % Identify color type
|
< 0.001 | 10 | 29 | isTruecolor = (size(data,3) == 3);
|
< 0.001 | 10 | 30 | paletteUsed = ~isempty(map) && ~isTruecolor;
|
< 0.001 | 10 | 31 | colorUsed = paletteUsed || isTruecolor;
|
< 0.001 | 10 | 32 | alphaUsed = ~isempty(alpha);
|
< 0.001 | 10 | 33 | colortype = paletteUsed + 2*colorUsed + 4*alphaUsed;
|
< 0.001 | 10 | 34 | if (colortype == 7)
|
| | 35 | error(message('MATLAB:imagesci:writepng:alphaNotSupportedForIndexed'));
|
< 0.001 | 10 | 36 | end
|
| | 37 |
|
| | 38 | % Set default bitdepth if not specified
|
< 0.001 | 10 | 39 | bitdepth = results.bitdepth;
|
< 0.001 | 10 | 40 | if (isempty(bitdepth))
|
< 0.001 | 10 | 41 | switch class(data)
|
< 0.001 | 10 | 42 | case 'logical'
|
| | 43 | bitdepth = 1;
|
| | 44 |
|
< 0.001 | 10 | 45 | case {'uint8', 'double', 'single'}
|
< 0.001 | 10 | 46 | bitdepth = 8;
|
| | 47 |
|
| | 48 | case 'uint16'
|
| | 49 | bitdepth = 16;
|
< 0.001 | 10 | 50 | end
|
< 0.001 | 10 | 51 | end
|
| | 52 |
|
| | 53 |
|
| | 54 | % Color type values (as in PNG library defs)
|
< 0.001 | 10 | 55 | PNG_COLOR_TYPE_GRAY = 0;
|
< 0.001 | 10 | 56 | PNG_COLOR_TYPE_RGB = 2;
|
< 0.001 | 10 | 57 | PNG_COLOR_TYPE_PALETTE = 3;
|
< 0.001 | 10 | 58 | PNG_COLOR_TYPE_GRAY_ALPHA = 4;
|
< 0.001 | 10 | 59 | PNG_COLOR_TYPE_RGB_ALPHA = 6;
|
| | 60 |
|
| | 61 |
|
| | 62 | % Validate bitdepth
|
< 0.001 | 10 | 63 | switch colortype
|
< 0.001 | 10 | 64 | case PNG_COLOR_TYPE_GRAY
|
| | 65 | if (~ismember(bitdepth, [1 2 4 8 16]))
|
| | 66 | error(message('MATLAB:imagesci:writepng:invalidGrayscaleBitDepth'));
|
| | 67 | end
|
| | 68 |
|
< 0.001 | 10 | 69 | case { PNG_COLOR_TYPE_RGB, PNG_COLOR_TYPE_RGB_ALPHA }
|
0.001 | 10 | 70 | if (~ismember(bitdepth, [8 16]))
|
| | 71 | error(message('MATLAB:imagesci:writepng:invalidRgbBitDepth'));
|
< 0.001 | 10 | 72 | end
|
| | 73 |
|
| | 74 | case PNG_COLOR_TYPE_PALETTE
|
| | 75 | if (~ismember(bitdepth, [1 2 4 8]))
|
| | 76 | error(message('MATLAB:imagesci:writepng:invalidIndexedBitDepth'));
|
| | 77 | end
|
| | 78 |
|
| | 79 | case PNG_COLOR_TYPE_GRAY_ALPHA
|
| | 80 | if (~ismember(bitdepth, [8 16]))
|
| | 81 | error(message('MATLAB:imagesci:writepng:invalidGrayscaleAlphaBitDepth'));
|
| | 82 | end
|
| | 83 |
|
< 0.001 | 10 | 84 | end
|
| | 85 |
|
| | 86 | %
|
| | 87 | % Scale image if necessary to match requested bitdepth
|
| | 88 | %
|
< 0.001 | 10 | 89 | switch class(data)
|
< 0.001 | 10 | 90 | case {'double', 'single'}
|
| | 91 | if (colortype == PNG_COLOR_TYPE_PALETTE)
|
| | 92 | data = data - 1;
|
| | 93 | data = uint8(data);
|
| | 94 |
|
| | 95 | else
|
| | 96 | % Grayscale or RGB; clamp data to [0,1] dynamic range before
|
| | 97 | % scaling, rounding, and casting.
|
| | 98 | data = max(min(data,1),0);
|
| | 99 | switch bitdepth
|
| | 100 | case 8
|
| | 101 | data = uint8(255*data);
|
| | 102 |
|
| | 103 | case 16
|
| | 104 | data = uint16(65535*data);
|
| | 105 |
|
| | 106 | case 4
|
| | 107 | data = uint8(15*data);
|
| | 108 |
|
| | 109 | case 2
|
| | 110 | data = uint8(3*data);
|
| | 111 |
|
| | 112 | case 1
|
| | 113 | data = uint8(data ~= 0);
|
| | 114 | end
|
| | 115 | end
|
| | 116 |
|
< 0.001 | 10 | 117 | case 'uint8'
|
< 0.001 | 10 | 118 | if (colortype == PNG_COLOR_TYPE_PALETTE)
|
| | 119 | % Nothing to do
|
| | 120 |
|
< 0.001 | 10 | 121 | else
|
< 0.001 | 10 | 122 | switch bitdepth
|
< 0.001 | 10 | 123 | case 16
|
| | 124 | data = uint16(data);
|
| | 125 | data = bitor(bitshift(data,8),data);
|
| | 126 |
|
< 0.001 | 10 | 127 | case 8
|
| | 128 | % Nothing to do
|
| | 129 |
|
| | 130 | case 4
|
| | 131 | data = bitshift(data,-4);
|
| | 132 |
|
| | 133 | case 2
|
| | 134 | data = bitshift(data,-6);
|
| | 135 |
|
| | 136 | case 1
|
| | 137 | % Nothing to do
|
< 0.001 | 10 | 138 | end
|
< 0.001 | 10 | 139 | end
|
| | 140 |
|
| | 141 | case 'uint16'
|
| | 142 | switch bitdepth
|
| | 143 | case 16
|
| | 144 | % Nothing to do
|
| | 145 |
|
| | 146 | case 8
|
| | 147 | data = uint8(bitshift(data,-8));
|
| | 148 |
|
| | 149 | case 4
|
| | 150 | data = uint8(bitshift(data,-12));
|
| | 151 |
|
| | 152 | case 2
|
| | 153 | data = uint8(bitshift(data,-14));
|
| | 154 |
|
| | 155 | case 1
|
| | 156 | data = uint8(data ~= 0);
|
| | 157 | end
|
< 0.001 | 10 | 158 | end
|
| | 159 |
|
< 0.001 | 10 | 160 | if (ismember(colortype, [PNG_COLOR_TYPE_GRAY_ALPHA, ...
|
| 10 | 161 | PNG_COLOR_TYPE_RGB_ALPHA]))
|
| | 162 | %
|
| | 163 | % Scale alpha data if necessary to match data class
|
| | 164 | %
|
| | 165 | switch bitdepth
|
| | 166 | case 8
|
| | 167 | switch class(alpha)
|
| | 168 | case {'double', 'single'}
|
| | 169 | alpha = max(min(alpha,1),0);
|
| | 170 | alpha = uint8(255 * alpha);
|
| | 171 |
|
| | 172 | case 'uint16'
|
| | 173 | alpha = uint8(bitshift(alpha, -8));
|
| | 174 |
|
| | 175 | case 'uint8'
|
| | 176 | % nothing to do
|
| | 177 |
|
| | 178 | end
|
| | 179 |
|
| | 180 | case 16
|
| | 181 | switch class(alpha)
|
| | 182 | case {'double', 'single'}
|
| | 183 | alpha = max(min(alpha,1),0);
|
| | 184 | alpha = uint16(65535 * alpha);
|
| | 185 |
|
| | 186 | case 'uint16'
|
| | 187 | % nothing to do
|
| | 188 |
|
| | 189 | case 'uint8'
|
| | 190 | alpha = uint16(alpha);
|
| | 191 | alpha = bitor(bitshift(alpha, 8), alpha);
|
| | 192 |
|
| | 193 | end
|
| | 194 | end
|
< 0.001 | 10 | 195 | end
|
| | 196 |
|
< 0.001 | 10 | 197 | sigbits = results.significantbits;
|
< 0.001 | 10 | 198 | transparency = results.transparency;
|
< 0.001 | 10 | 199 | background = results.background;
|
< 0.001 | 10 | 200 | gamma = results.gamma;
|
< 0.001 | 10 | 201 | chromaticities = results.chromaticities;
|
< 0.001 | 10 | 202 | xres = results.xresolution;
|
< 0.001 | 10 | 203 | yres = results.yresolution;
|
< 0.001 | 10 | 204 | if ischar(results.resolutionunit)
|
0.006 | 10 | 205 | resunit = validatestring(results.resolutionunit,{'unknown','meter'});
|
| | 206 | else
|
| | 207 | resunit = results.resolutionunit;
|
< 0.001 | 10 | 208 | end
|
0.002 | 10 | 209 | interlace = validatestring(results.interlacetype,{'none','adam7'});
|
< 0.001 | 10 | 210 | imagemodtime = results.imagemodtime;
|
| | 211 |
|
< 0.001 | 10 | 212 | textchunks = cell(0,2);
|
< 0.001 | 10 | 213 | strs = {'Title','Author','Description','Copyright','Software', ...
|
| | 214 | 'Disclaimer', 'Warning','Source','Comment'};
|
< 0.001 | 10 | 215 | for j = 1:numel(strs)
|
< 0.001 | 90 | 216 | param_name = lower(strs{j});
|
< 0.001 | 90 | 217 | if isfield(results,lower(param_name))
|
0.001 | 90 | 218 | param_value = results.(param_name);
|
< 0.001 | 90 | 219 | if ~isempty(param_value)
|
< 0.001 | 10 | 220 | textchunks{end+1,1} = strs{j}; %#ok<AGROW>
|
0.002 | 10 | 221 | textItem = CheckTextItem(param_value);
|
< 0.001 | 10 | 222 | textchunks{end,2} = textItem;
|
< 0.001 | 90 | 223 | end
|
< 0.001 | 90 | 224 | end
|
< 0.001 | 90 | 225 | end
|
| | 226 |
|
| | 227 |
|
< 0.001 | 10 | 228 | if ~isempty(results.creationtime)
|
< 0.001 | 10 | 229 | keyword = 'Creation Time';
|
< 0.001 | 10 | 230 | ctime = results.creationtime;
|
< 0.001 | 10 | 231 | if ischar(ctime)
|
0.047 | 10 | 232 | textItem = datestr(datenum(ctime), 0);
|
| | 233 | else
|
| | 234 | textItem = datestr(ctime, 0);
|
< 0.001 | 10 | 235 | end
|
< 0.001 | 10 | 236 | textchunks{end+1,1} = keyword;
|
< 0.001 | 10 | 237 | textchunks{end,2} = textItem;
|
< 0.001 | 10 | 238 | end
|
< 0.001 | 10 | 239 | if ~isempty(results.imagemodtime)
|
| | 240 | try
|
| | 241 | imagemodtime = fix(datevec(results.imagemodtime));
|
| | 242 | catch me
|
| | 243 | error(message('MATLAB:imagesci:writepng:invalidImageModTime'));
|
| | 244 | end
|
| | 245 |
|
| | 246 | if (numel(imagemodtime) > 6)
|
| | 247 | error(message('MATLAB:imagesci:writepng:tooMuchImageModTimeData'))
|
| | 248 | end
|
< 0.001 | 10 | 249 | end
|
| | 250 |
|
| | 251 | % validate and process any unmatched parameters.
|
< 0.001 | 10 | 252 | if ~isempty(unmatched)
|
< 0.001 | 10 | 253 | param_names = fields(unmatched);
|
< 0.001 | 10 | 254 | nelts = numel(param_names);
|
< 0.001 | 10 | 255 | for j = 1:nelts
|
| | 256 | param_name = param_names{j};
|
| | 257 | keyword = CheckKeyword(param_name);
|
| | 258 | item = CheckTextItem(unmatched.(param_name));
|
| | 259 | textchunks{end+1,1} = keyword; %#ok<AGROW>
|
| | 260 | textchunks{end,2} = item;
|
| | 261 | end
|
< 0.001 | 10 | 262 | end
|
| | 263 |
|
| | 264 | % Be friendly about specifying resolutions
|
< 0.001 | 10 | 265 | if (~isempty(xres) && isempty(yres))
|
| | 266 | yres = xres;
|
| | 267 |
|
< 0.001 | 10 | 268 | elseif (~isempty(yres) && isempty(xres))
|
| | 269 | xres = yres;
|
< 0.001 | 10 | 270 | end
|
| | 271 |
|
< 0.001 | 10 | 272 | if (~isempty(xres) && isempty(resunit))
|
| | 273 | resunit = 'unknown';
|
< 0.001 | 10 | 274 | end
|
| | 275 |
|
< 0.001 | 10 | 276 | if (isempty(xres) && isempty(yres) && ~isempty(resunit))
|
| | 277 | error(message('MATLAB:imagesci:writepng:resolutionsRequired'));
|
< 0.001 | 10 | 278 | end
|
| | 279 |
|
0.633 | 10 | 280 | pngwritec(data, map, filename, colortype, bitdepth, ...
|
| 10 | 281 | sigbits, alpha, interlace, ...
|
| 10 | 282 | transparency, background, gamma, ...
|
| 10 | 283 | chromaticities, xres, yres, ...
|
| 10 | 284 | resunit, textchunks, imagemodtime);
|
Other subfunctions in this file are not included in this listing.