Main GraphicsMagick source repository
Revision | 743f1bcf3052910b4ee5cdd231d7598255f3f0d2 (tree) |
---|---|
Time | 2022-01-17 02:57:59 |
Author | Bob Friesenhahn <bfriesen@Grap...> |
Commiter | Bob Friesenhahn |
HEIF: Take row stride into account when reading pixel rows. Add support for 'ping' mode. Add header magic detection. Add module aliases. Add useful traces.
@@ -1,3 +1,9 @@ | ||
1 | +2022-01-16 Bob Friesenhahn <bfriesen@simple.dallas.tx.us> | |
2 | + | |
3 | + * coders/heif.c (ReadHEIFImage): Take row stride into account when | |
4 | + reading pixel rows. Add support for 'ping' mode. Add header magic | |
5 | + detection. Add module aliases. Add useful traces. | |
6 | + | |
1 | 7 | 2022-01-15 Bob Friesenhahn <bfriesen@simple.dallas.tx.us> |
2 | 8 | |
3 | 9 | * coders/jxl.c: Added preliminary JPEG XL support written by |
@@ -10,5 +10,5 @@ | ||
10 | 10 | |
11 | 11 | #define public MagickPackageName "GraphicsMagick" |
12 | 12 | #define public MagickPackageVersion "1.4" |
13 | -#define public MagickPackageVersionAddendum ".020220115" | |
14 | -#define public MagickPackageReleaseDate "snapshot-20220115" | |
13 | +#define public MagickPackageVersionAddendum ".020220116" | |
14 | +#define public MagickPackageReleaseDate "snapshot-20220116" |
@@ -34,7 +34,50 @@ | ||
34 | 34 | |
35 | 35 | #if defined(HasHEIF) |
36 | 36 | #include <libheif/heif.h> |
37 | + | |
38 | +/* | |
39 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
40 | +% % | |
41 | +% % | |
42 | +% % | |
43 | +% I s H E I F % | |
44 | +% % | |
45 | +% % | |
46 | +% % | |
47 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
48 | +% | |
49 | +% Method IsHEIF returns True if the image format type, identified by the | |
50 | +% magick string, is supported by this HEIF reader. | |
51 | +% | |
52 | +% The format of the IsHEIF method is: | |
53 | +% | |
54 | +% unsigned int IsHEIF(const unsigned char *magick,const size_t length) | |
55 | +% | |
56 | +% A description of each parameter follows: | |
57 | +% | |
58 | +% o status: Method IsHEIF returns True if the image format type is HEIF. | |
59 | +% | |
60 | +% o magick: This string is generally the first few bytes of an image file | |
61 | +% or blob. | |
62 | +% | |
63 | +% o length: Specifies the length of the magick string. | |
64 | +% | |
65 | +% | |
66 | +*/ | |
67 | +static unsigned int IsHEIF(const unsigned char *magick,const size_t length) | |
68 | +{ | |
69 | + enum heif_filetype_result | |
70 | + heif_filetype; | |
37 | 71 | |
72 | + if (length < 12) | |
73 | + return(False); | |
74 | + | |
75 | + heif_filetype = heif_check_filetype(magick, (int) length); | |
76 | + if (heif_filetype == heif_filetype_yes_supported) | |
77 | + return True; | |
78 | + | |
79 | + return(False); | |
80 | +} | |
38 | 81 | /* |
39 | 82 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
40 | 83 | % % |
@@ -109,6 +152,11 @@ | ||
109 | 152 | unsigned char* |
110 | 153 | profile; |
111 | 154 | |
155 | + if (image->logging) | |
156 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
157 | + "Profile \"%s\" with size %" MAGICK_SIZE_T_F "u bytes", | |
158 | + profile_name, (MAGICK_SIZE_T) profile_size); | |
159 | + | |
112 | 160 | profile=MagickAllocateResourceLimitedArray(unsigned char*,profile_size, |
113 | 161 | sizeof(*profile)); |
114 | 162 | if (profile == (unsigned char*) NULL) |
@@ -121,6 +169,10 @@ | ||
121 | 169 | |
122 | 170 | if (err.code != heif_error_Ok) |
123 | 171 | { |
172 | + if (image->logging) | |
173 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
174 | + "heif_image_handle_get_metadata() reports error \"%s\"", | |
175 | + err.message); | |
124 | 176 | MagickFreeResourceLimitedMemory(profile); |
125 | 177 | MagickFreeResourceLimitedMemory(ids); |
126 | 178 | ThrowReaderException(CorruptImageError, |
@@ -210,7 +262,13 @@ | ||
210 | 262 | || heif_status.code == heif_error_Unsupported_feature) |
211 | 263 | ThrowHEIFReaderException(CoderError, ImageTypeNotSupported, image); |
212 | 264 | if (heif_status.code != heif_error_Ok) |
213 | - ThrowHEIFReaderException(CorruptImageError, AnErrorHasOccurredReadingFromFile, image); | |
265 | + { | |
266 | + if (image->logging) | |
267 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
268 | + "heif_context_read_from_memory() reports error \"%s\"", | |
269 | + heif_status.message); | |
270 | + ThrowHEIFReaderException(CorruptImageError, AnErrorHasOccurredReadingFromFile, image); | |
271 | + } | |
214 | 272 | |
215 | 273 | /* no support for reading multiple images but could be added */ |
216 | 274 | if (heif_context_get_number_of_top_level_images(heif) != 1) |
@@ -220,30 +278,68 @@ | ||
220 | 278 | if (heif_status.code == heif_error_Memory_allocation_error) |
221 | 279 | ThrowHEIFReaderException(ResourceLimitError,MemoryAllocationFailed,image); |
222 | 280 | if (heif_status.code != heif_error_Ok) |
223 | - ThrowHEIFReaderException(CorruptImageError, AnErrorHasOccurredReadingFromFile, image); | |
281 | + { | |
282 | + if (image->logging) | |
283 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
284 | + "heif_context_get_primary_image_handle() reports error \"%s\"", | |
285 | + heif_status.message); | |
286 | + ThrowHEIFReaderException(CorruptImageError, AnErrorHasOccurredReadingFromFile, image); | |
287 | + } | |
224 | 288 | |
225 | 289 | image->columns=heif_image_handle_get_width(heif_image_handle); |
226 | 290 | image->rows=heif_image_handle_get_height(heif_image_handle); |
227 | 291 | if (heif_image_handle_has_alpha_channel(heif_image_handle)) |
228 | 292 | image->matte=MagickTrue; |
229 | 293 | |
294 | + if (image->logging) | |
295 | + { | |
296 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
297 | + "Geometry: %lux%lu", image->columns, image->rows); | |
298 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
299 | + "Matte: %s", image->matte ? "True" : "False"); | |
300 | + } | |
301 | + | |
230 | 302 | if (!ReadMetadata(heif_image_handle, image, exception)) |
231 | 303 | { |
232 | 304 | HEIFReadCleanup(); |
233 | 305 | return NULL; |
234 | 306 | } |
235 | 307 | |
308 | + if (image_info->ping) | |
309 | + { | |
310 | + image->depth = 8; | |
311 | + HEIFReadCleanup(); | |
312 | + CloseBlob(image); | |
313 | + return image; | |
314 | + } | |
315 | + | |
316 | + if (CheckImagePixelLimits(image, exception) != MagickPass) | |
317 | + ThrowHEIFReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); | |
318 | + | |
319 | + /* FIXME: Add decoding options support such as a progress monitor */ | |
236 | 320 | heif_status=heif_decode_image(heif_image_handle, &heif_image, |
237 | 321 | heif_colorspace_RGB, image->matte ? heif_chroma_interleaved_RGBA : |
238 | - heif_chroma_interleaved_RGB, NULL); | |
322 | + heif_chroma_interleaved_RGB, | |
323 | + /* const struct heif_decoding_options* */ NULL ); | |
239 | 324 | if (heif_status.code == heif_error_Memory_allocation_error) |
240 | 325 | ThrowHEIFReaderException(ResourceLimitError,MemoryAllocationFailed,image); |
241 | 326 | if (heif_status.code != heif_error_Ok) |
242 | - ThrowHEIFReaderException(CorruptImageError, AnErrorHasOccurredReadingFromFile, image); | |
327 | + { | |
328 | + if (image->logging) | |
329 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
330 | + "heif_decode_image() reports error \"%s\"", | |
331 | + heif_status.message); | |
332 | + ThrowHEIFReaderException(CorruptImageError, AnErrorHasOccurredReadingFromFile, image); | |
333 | + } | |
243 | 334 | |
244 | 335 | image->depth=heif_image_get_bits_per_pixel(heif_image, heif_channel_interleaved); |
245 | 336 | /* the requested channel is interleaved there depth is a sum of all channels |
246 | 337 | split it up again: */ |
338 | + if (image->logging) | |
339 | + { | |
340 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
341 | + "heif_image_get_bits_per_pixel: bits_per_pixel=%u", image->depth); | |
342 | + } | |
247 | 343 | if (image->depth == 32 && image->matte) |
248 | 344 | image->depth = 8; |
249 | 345 | else if (image->depth == 24 && !image->matte) |
@@ -255,18 +351,26 @@ | ||
255 | 351 | if (!pixels) |
256 | 352 | ThrowHEIFReaderException(CoderError, NoDataReturned, image); |
257 | 353 | |
354 | + if (image->logging) | |
355 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
356 | + "heif_image_get_plane_readonly: bytes-per-line=%d", | |
357 | + row_stride); | |
358 | + | |
359 | + /* Transfer pixels to image, using row stride to find start of each row. */ | |
258 | 360 | for (y=0; y < (long)image->rows; y++) |
259 | 361 | { |
362 | + const uint8_t *line; | |
260 | 363 | q=SetImagePixelsEx(image,0,y,image->columns,1,exception); |
261 | 364 | if (q == (PixelPacket *) NULL) |
262 | 365 | ThrowHEIFReaderException(ResourceLimitError,MemoryAllocationFailed,image); |
366 | + line=pixels+y*row_stride; | |
263 | 367 | for (x=0; x < (long)image->columns; x++) |
264 | 368 | { |
265 | - SetRedSample(q,ScaleCharToQuantum(*pixels++)); | |
266 | - SetGreenSample(q,ScaleCharToQuantum(*pixels++)); | |
267 | - SetBlueSample(q,ScaleCharToQuantum(*pixels++)); | |
369 | + SetRedSample(q,ScaleCharToQuantum(*line++)); | |
370 | + SetGreenSample(q,ScaleCharToQuantum(*line++)); | |
371 | + SetBlueSample(q,ScaleCharToQuantum(*line++)); | |
268 | 372 | if (image->matte) { |
269 | - SetOpacitySample(q,MaxRGB-ScaleCharToQuantum(*pixels++)); | |
373 | + SetOpacitySample(q,MaxRGB-ScaleCharToQuantum(*line++)); | |
270 | 374 | } else { |
271 | 375 | SetOpacitySample(q,OpaqueOpacity); |
272 | 376 | } |
@@ -332,6 +436,7 @@ | ||
332 | 436 | entry=SetMagickInfo("HEIF"); |
333 | 437 | #if defined(HasHEIF) |
334 | 438 | entry->decoder=(DecoderHandler) ReadHEIFImage; |
439 | + entry->magick=(MagickHandler) IsHEIF; | |
335 | 440 | #endif |
336 | 441 | entry->description=description; |
337 | 442 | entry->adjoin=False; |
@@ -345,6 +450,7 @@ | ||
345 | 450 | entry=SetMagickInfo("HEIC"); |
346 | 451 | #if defined(HasHEIF) |
347 | 452 | entry->decoder=(DecoderHandler) ReadHEIFImage; |
453 | + entry->magick=(MagickHandler) IsHEIF; | |
348 | 454 | #endif |
349 | 455 | entry->description=description; |
350 | 456 | entry->adjoin=False; |
@@ -27,6 +27,7 @@ | ||
27 | 27 | coders/gif.c |
28 | 28 | coders/gradient.c |
29 | 29 | coders/gray.c |
30 | +coders/heif.c | |
30 | 31 | coders/histogram.c |
31 | 32 | coders/hrz.c |
32 | 33 | coders/html.c |
@@ -35,6 +36,7 @@ | ||
35 | 36 | coders/info.c |
36 | 37 | coders/jbig.c |
37 | 38 | coders/jnx.c |
39 | +coders/jpx.c | |
38 | 40 | coders/jp2.c |
39 | 41 | coders/jpeg.c |
40 | 42 | coders/label.c |
@@ -60,6 +60,7 @@ | ||
60 | 60 | { |
61 | 61 | #define MAGIC(name,offset,magic) {name,(const unsigned char * const)magic,sizeof(magic)-1,offset} |
62 | 62 | MAGIC("WEBP", 8, "WEBP"), |
63 | + MAGIC("AVIF", 4, "ftypavif"), | |
63 | 64 | /* MAGIC("AVI", 0, "RIFF"), */ |
64 | 65 | MAGIC("8BIMWTEXT", 0, "8\000B\000I\000M\000#"), |
65 | 66 | MAGIC("8BIMTEXT", 0, "8BIM#"), |
@@ -90,6 +91,9 @@ | ||
90 | 91 | MAGIC("FITS", 0, "SIMPLE"), |
91 | 92 | MAGIC("FPX", 0, "\320\317\021\340"), |
92 | 93 | MAGIC("GIF", 0, "GIF8"), |
94 | + MAGIC("HEIC", 4, "ftypheic"), | |
95 | + MAGIC("HEIC", 4, "ftypheix"), | |
96 | + MAGIC("HEIC", 4, "ftypmif1"), | |
93 | 97 | MAGIC("HDF", 1, "HDF"), |
94 | 98 | MAGIC("HPGL", 0, "IN;"), |
95 | 99 | MAGIC("HTML", 1, "HTML"), |
@@ -35,6 +35,7 @@ | ||
35 | 35 | MODULEALIAS("APP1","META"), |
36 | 36 | MODULEALIAS("APP1JPEG","META"), |
37 | 37 | MODULEALIAS("ARW","DCRAW"), |
38 | + MODULEALIAS("AVIF","HEIF"), | |
38 | 39 | MODULEALIAS("B","GRAY"), |
39 | 40 | MODULEALIAS("BIE","JBIG"), |
40 | 41 | MODULEALIAS("BIGTIFF","TIFF"), |
@@ -72,9 +73,9 @@ | ||
72 | 73 | MODULEALIAS("GRAYA","GRAY"), |
73 | 74 | MODULEALIAS("GROUP4RAW","TIFF"), |
74 | 75 | MODULEALIAS("H","LOGO"), |
76 | + MODULEALIAS("HEIC","HEIF"), | |
75 | 77 | MODULEALIAS("HTM","HTML"), |
76 | 78 | MODULEALIAS("HTTP","URL"), |
77 | - MODULEALIAS("HEIC","HEIF"), | |
78 | 79 | MODULEALIAS("ICB","TGA"), |
79 | 80 | MODULEALIAS("ICC","META"), |
80 | 81 | MODULEALIAS("ICM","META"), |
@@ -38,8 +38,8 @@ | ||
38 | 38 | #define MagickLibVersion 0x262300 |
39 | 39 | #define MagickLibVersionText "1.4" |
40 | 40 | #define MagickLibVersionNumber 26,23,0 |
41 | -#define MagickChangeDate "20220115" | |
42 | -#define MagickReleaseDate "snapshot-20220115" | |
41 | +#define MagickChangeDate "20220116" | |
42 | +#define MagickReleaseDate "snapshot-20220116" | |
43 | 43 | |
44 | 44 | /* |
45 | 45 | The MagickLibInterfaceNewest and MagickLibInterfaceOldest defines |
@@ -35,6 +35,11 @@ | ||
35 | 35 | <div class="document"> |
36 | 36 | |
37 | 37 | |
38 | +<p>2022-01-16 Bob Friesenhahn <<a class="reference external" href="mailto:bfriesen%40simple.dallas.tx.us">bfriesen<span>@</span>simple<span>.</span>dallas<span>.</span>tx<span>.</span>us</a>></p> | |
39 | +<blockquote> | |
40 | +* coders/heif.c (ReadHEIFImage): Take row stride into account when | |
41 | +reading pixel rows. Add support for 'ping' mode. Add header magic | |
42 | +detection. Add module aliases. Add useful traces.</blockquote> | |
38 | 43 | <p>2022-01-15 Bob Friesenhahn <<a class="reference external" href="mailto:bfriesen%40simple.dallas.tx.us">bfriesen<span>@</span>simple<span>.</span>dallas<span>.</span>tx<span>.</span>us</a>></p> |
39 | 44 | <blockquote> |
40 | 45 | <p>* coders/jxl.c: Added preliminary JPEG XL support written by |