From d7be1a5563a6bf59a8e9074287d4f7b6a64c8329 Mon Sep 17 00:00:00 2001 From: hj kim Date: Thu, 13 Dec 2018 16:00:00 +0900 Subject: [PATCH] Imported Upstream version 1.3.31 Change-Id: I2c7294cf2abd64840c9513bbaed3c148dc673e1c --- ChangeLog | 2706 +++++++- ChangeLog.2016 | 911 +++ ChangeLog.2017 | 1108 +++ Copyright.txt | 38 +- Magick++/demo/analyze.cpp | 12 +- Magick++/demo/button.cpp | 2 +- Magick++/demo/demo.cpp | 66 +- Magick++/demo/detrans.cpp | 16 +- Magick++/demo/flip.cpp | 2 +- Magick++/demo/gravity.cpp | 2 +- Magick++/demo/piddle.cpp | 2 +- Magick++/demo/shapes.cpp | 2 +- Magick++/demo/zoom.cpp | 85 +- Magick++/lib/Blob.cpp | 1 - Magick++/lib/BlobRef.cpp | 2 +- Magick++/lib/Color.cpp | 178 +- Magick++/lib/Drawable.cpp | 18 +- Magick++/lib/Exception.cpp | 1 - Magick++/lib/Geometry.cpp | 62 +- Magick++/lib/Image.cpp | 415 +- Magick++/lib/ImageRef.cpp | 2 +- Magick++/lib/Magick++/CoderInfo.h | 18 +- Magick++/lib/Magick++/Color.h | 44 +- Magick++/lib/Magick++/Drawable.h | 72 +- Magick++/lib/Magick++/Exception.h | 8 +- Magick++/lib/Magick++/Geometry.h | 10 +- Magick++/lib/Magick++/Image.h | 134 +- Magick++/lib/Magick++/ImageRef.h | 8 +- Magick++/lib/Magick++/Include.h | 20 +- Magick++/lib/Magick++/Montage.h | 18 +- Magick++/lib/Magick++/Options.h | 40 +- Magick++/lib/Magick++/Pixels.h | 20 +- Magick++/lib/Magick++/STL.h | 302 +- Magick++/lib/Magick++/Thread.h | 10 +- Magick++/lib/Magick++/TypeMetric.h | 2 +- Magick++/lib/Options.cpp | 45 +- Magick++/lib/Pixels.cpp | 18 +- Magick++/lib/STL.cpp | 10 +- Magick++/tests/appendImages.cpp | 29 +- Magick++/tests/attributes.cpp | 854 +-- Magick++/tests/averageImages.cpp | 17 +- Magick++/tests/coalesceImages.cpp | 3 +- Magick++/tests/coderInfo.cpp | 2 +- Magick++/tests/color.cpp | 98 +- Magick++/tests/colorHistogram.cpp | 3 +- Magick++/tests/exceptions.cpp | 40 +- Magick++/tests/montageImages.cpp | 43 +- Magick++/tests/morphImages.cpp | 13 +- Magick++/tests/readWriteBlob.cpp | 26 +- Magick++/tests/readWriteImages.cpp | 103 +- Makefile.am | 14 + Makefile.in | 85 +- NEWS.txt | 646 +- PerlMagick/Magick.pm | 22 +- PerlMagick/Magick.pm.in | 22 +- PerlMagick/Magick.xs | 183 +- PerlMagick/Makefile.PL.in | 36 +- PerlMagick/Makefile.nt | 11 +- PerlMagick/t/jpeg/input.jnx | Bin 0 -> 17099 bytes PerlMagick/t/jpeg/read.t | 15 +- PerlMagick/t/reference/jpeg/read_jnx.miff | 235 + PerlMagick/t/wmf/fulltest.wmf | Bin 0 -> 4200 bytes README.txt | 22 +- TclMagick/ChangeLog | 5 + TclMagick/generic/TclMagick.c | 10341 ++++++++++++++-------------- TclMagick/generic/TclMagick.h | 6 +- TclMagick/generic/TclMagickAppInit.c | 62 +- TclMagick/generic/TkMagick.c | 106 +- TclMagick/generic/libttkcommon.c | 1 - aclocal.m4 | 1 + coders/Makefile.am | 16 +- coders/art.c | 26 +- coders/avs.c | 35 +- coders/bmp.c | 638 +- coders/cals.c | 20 +- coders/cineon.c | 88 +- coders/cmyk.c | 349 +- coders/cut.c | 76 +- coders/dcm.c | 370 +- coders/dcraw.c | 6 +- coders/dib.c | 335 +- coders/dps.c | 6 +- coders/dpx.c | 717 +- coders/emf.c | 7 +- coders/ept.c | 232 +- coders/fax.c | 8 +- coders/fits.c | 793 ++- coders/fpx.c | 4 +- coders/gif.c | 526 +- coders/gray.c | 140 +- coders/histogram.c | 15 +- coders/hrz.c | 4 +- coders/html.c | 8 +- coders/icon.c | 6 +- coders/identity.c | 50 +- coders/info.c | 64 +- coders/jbig.c | 12 +- coders/jnx.c | 141 +- coders/jp2.c | 276 +- coders/jpeg.c | 1495 ++-- coders/locale.c | 5 +- coders/logo.c | 4380 ++++++------ coders/mac.c | 52 +- coders/map.c | 15 +- coders/mat.c | 730 +- coders/matte.c | 2 +- coders/meta.c | 176 +- coders/miff.c | 186 +- coders/mono.c | 4 +- coders/mpc.c | 89 +- coders/mpeg.c | 6 +- coders/msl.c | 40 +- coders/mtv.c | 30 +- coders/mvg.c | 72 +- coders/null.c | 2 +- coders/otb.c | 4 +- coders/palm.c | 221 +- coders/pcd.c | 211 +- coders/pcl.c | 57 +- coders/pcx.c | 99 +- coders/pdb.c | 229 +- coders/pdf.c | 404 +- coders/pict.c | 370 +- coders/pix.c | 40 +- coders/plasma.c | 6 +- coders/png.c | 1640 +++-- coders/pnm.c | 2191 +++--- coders/ps.c | 63 +- coders/ps2.c | 46 +- coders/ps3.c | 64 +- coders/psd.c | 38 +- coders/pwp.c | 47 +- coders/rgb.c | 321 +- coders/rla.c | 68 +- coders/rle.c | 844 +-- coders/sct.c | 2 +- coders/sfw.c | 51 +- coders/sgi.c | 1176 ++-- coders/stegano.c | 4 +- coders/sun.c | 74 +- coders/svg.c | 1469 +++- coders/tga.c | 118 +- coders/tiff.c | 1895 +++-- coders/tile.c | 3 +- coders/tim.c | 536 +- coders/topol.c | 381 +- coders/txt.c | 444 +- coders/uil.c | 6 +- coders/url.c | 4 +- coders/uyvy.c | 4 +- coders/vicar.c | 4 +- coders/viff.c | 61 +- coders/wbmp.c | 10 +- coders/webp.c | 220 +- coders/wmf.c | 56 +- coders/wpg.c | 838 ++- coders/xbm.c | 123 +- coders/xcf.c | 478 +- coders/xpm.c | 88 +- coders/xwd.c | 4 +- coders/yuv.c | 19 +- common.shi.in | 3 +- config/compile | 13 +- config/config.guess | 679 +- config/config.sub | 304 +- config/delegates.mgk.in | 9 + config/depcomp | 10 +- config/install-sh | 47 +- config/missing | 16 +- config/tap-driver.sh | 10 +- config/test-driver | 10 +- configure | 1011 ++- configure.ac | 743 +- filters/analyze.c | 115 +- locale/C.mgk | 56 +- m4/pkg.m4 | 275 + magick/Makefile.am | 1 + magick/PreRvIcccm.h | 4 +- magick/alpha_composite.h | 115 +- magick/analyze.c | 118 +- magick/analyze.h | 6 +- magick/animate.c | 12 +- magick/animate.h | 4 +- magick/annotate.c | 173 +- magick/api.h | 4 +- magick/attribute.c | 1926 +++--- magick/attribute.h | 4 +- magick/average.c | 35 +- magick/average.h | 4 +- magick/bit_stream.c | 148 +- magick/bit_stream.h | 30 +- magick/blob.c | 1352 ++-- magick/blob.h | 29 +- magick/cdl.c | 106 +- magick/channel.c | 70 +- magick/channel.h | 4 +- magick/color.c | 8 +- magick/color.h | 28 +- magick/color_lookup.c | 544 +- magick/color_lookup.h | 4 +- magick/colormap.c | 46 +- magick/colormap.h | 29 +- magick/colorspace.c | 144 +- magick/colorspace.h | 6 +- magick/command.c | 1648 ++--- magick/command.h | 6 +- magick/common.h | 29 +- magick/compare.c | 72 +- magick/compare.h | 4 +- magick/composite.c | 779 +-- magick/composite.h | 6 +- magick/compress.c | 50 +- magick/compress.h | 6 +- magick/confirm_access.c | 4 +- magick/confirm_access.h | 14 +- magick/constitute.c | 324 +- magick/constitute.h | 8 +- magick/decorate.c | 76 +- magick/decorate.h | 4 +- magick/delegate.c | 116 +- magick/delegate.h | 6 +- magick/deprecate.c | 13 +- magick/deprecate.h | 4 +- magick/describe.c | 59 +- magick/describe.h | 4 +- magick/display.c | 33 +- magick/display.h | 4 +- magick/draw.c | 98 +- magick/draw.h | 48 +- magick/effect.c | 856 +-- magick/effect.h | 4 +- magick/enhance.c | 302 +- magick/enhance.h | 4 +- magick/enum_strings.c | 23 +- magick/enum_strings.h | 85 +- magick/error.c | 25 +- magick/error.h | 4 +- magick/export.c | 4825 ++++++------- magick/floats.c | 952 +-- magick/floats.h | 4 +- magick/forward.h | 4 +- magick/fx.c | 349 +- magick/fx.h | 4 +- magick/gem.c | 104 +- magick/gem.h | 4 +- magick/gradient.c | 30 +- magick/gradient.h | 4 +- magick/hclut.c | 69 +- magick/hclut.h | 4 +- magick/image.c | 592 +- magick/image.h | 73 +- magick/import.c | 5590 +++++++-------- magick/list.c | 7 +- magick/list.h | 22 +- magick/locale.c | 114 +- magick/locale_c.h | 2386 +++---- magick/log.c | 9 +- magick/log.h | 12 +- magick/magic.c | 94 +- magick/magic.h | 4 +- magick/magick.c | 125 +- magick/magick.h | 12 +- magick/magick_config.h.in | 9 +- magick/magick_endian.c | 80 +- magick/magick_endian.h | 4 +- magick/magick_types.h | 12 +- magick/map.c | 23 +- magick/map.h | 4 +- magick/memory.c | 39 +- magick/memory.h | 30 +- magick/module.c | 659 +- magick/module.h | 31 +- magick/module_aliases.h | 149 + magick/monitor.c | 108 +- magick/monitor.h | 18 +- magick/montage.c | 13 +- magick/montage.h | 4 +- magick/nt_base.c | 345 +- magick/nt_base.h | 29 +- magick/nt_feature.c | 52 +- magick/nt_feature.h | 4 +- magick/omp_data_view.c | 18 +- magick/omp_data_view.h | 14 +- magick/operator.c | 222 +- magick/paint.c | 14 +- magick/paint.h | 4 +- magick/pixel_cache.c | 712 +- magick/pixel_cache.h | 35 +- magick/pixel_iterator.c | 217 +- magick/pixel_iterator.h | 4 +- magick/plasma.h | 6 +- magick/prefetch.h | 2 +- magick/profile.c | 162 +- magick/profile.h | 8 +- magick/quantize.c | 20 +- magick/quantize.h | 4 +- magick/random-private.h | 4 +- magick/random.c | 16 +- magick/random.h | 4 +- magick/registry.h | 4 +- magick/render.c | 2820 ++++++-- magick/render.h | 71 +- magick/resize.c | 222 +- magick/resize.h | 4 +- magick/resource.c | 104 +- magick/resource.h | 4 +- magick/segment.c | 92 +- magick/semaphore.c | 166 +- magick/semaphore.h | 4 +- magick/shear.c | 385 +- magick/shear.h | 4 +- magick/signature.h | 6 +- magick/spinlock.h | 6 +- magick/static.c | 665 +- magick/static.h | 6 +- magick/statistics.c | 33 +- magick/statistics.h | 6 +- magick/studio.h | 11 +- magick/symbols.h | 73 +- magick/tempfile.c | 6 +- magick/tempfile.h | 4 +- magick/texture.c | 76 +- magick/texture.h | 6 +- magick/timer.h | 4 +- magick/transform.c | 251 +- magick/transform.h | 4 +- magick/tsd.c | 2 +- magick/tsd.h | 2 +- magick/type.h | 4 +- magick/unix_port.c | 4 +- magick/unix_port.h | 4 +- magick/utility.c | 645 +- magick/utility.h | 44 +- magick/version.h | 22 +- magick/version.h.in | 10 +- magick/widget.c | 165 +- magick/widget.h | 4 +- magick/xwindow.c | 286 +- magick/xwindow.h | 6 +- scripts/gmsymbols.sh | 43 + scripts/html_fragments.py | 2 +- tests/rwblob.c | 249 +- tests/rwblob.tap | 12 +- tests/rwfile.c | 261 +- tests/rwfile.tap | 34 +- utilities/Makefile.am | 6 +- utilities/gm.1 | 137 +- version.sh | 21 +- wand/GraphicsMagickWand-config.1 | 8 +- wand/drawing_wand.c | 152 +- wand/drawing_wand.h | 36 +- wand/drawtest.c | 44 +- wand/magick_compat.c | 5 +- wand/magick_wand.c | 267 +- wand/magick_wand.h | 21 +- wand/pixel_wand.h | 34 +- wand/wand_api.h | 2 +- wand/wand_symbols.h | 58 +- wand/wandtest.c | 6 +- www/ChangeLog-2017.html | 1283 ++++ www/ChangeLog-2017.rst | 1108 +++ www/Changelog.html | 2863 +++++++- www/Changelog.rst | 2706 +++++++- www/Changes.html | 9 +- www/Changes.rst | 18 +- www/Copyright.html | 4 +- www/FAQ.html | 2 +- www/FAQ.rst | 2 +- www/GraphicsMagick.html | 91 +- www/Hg.html | 2 +- www/Hg.rst | 2 +- www/INSTALL-unix.html | 11 +- www/INSTALL-unix.rst | 14 +- www/INSTALL-windows.html | 6 +- www/INSTALL-windows.rst | 6 +- www/ImageMagickObject.html | 2 +- www/ImageMagickObject.rst | 2 +- www/Magick++/Blob.html | 2 +- www/Magick++/Blob.rst | 3 +- www/Magick++/COPYING | 7 +- www/Magick++/CoderInfo.html | 2 +- www/Magick++/CoderInfo.rst | 11 +- www/Magick++/Color.html | 2 +- www/Magick++/Color.rst | 39 +- www/Magick++/Drawable.html | 2 +- www/Magick++/Drawable.rst | 5 +- www/Magick++/Enumerations.html | 2 +- www/Magick++/Enumerations.rst | 9 +- www/Magick++/Exception.html | 2 +- www/Magick++/Exception.rst | 23 +- www/Magick++/FormatCharacters.html | 2 +- www/Magick++/FormatCharacters.rst | 3 +- www/Magick++/Geometry.html | 2 +- www/Magick++/Geometry.rst | 41 +- www/Magick++/Image.html | 824 +-- www/Magick++/Image.rst | 283 +- www/Magick++/ImageDesign.html | 2 +- www/Magick++/ImageDesign.rst | 3 +- www/Magick++/Montage.html | 2 +- www/Magick++/Montage.rst | 7 +- www/Magick++/PixelPacket.html | 2 +- www/Magick++/PixelPacket.rst | 2 +- www/Magick++/Pixels.html | 2 +- www/Magick++/Pixels.rst | 15 +- www/Magick++/TypeMetric.html | 2 +- www/Magick++/TypeMetric.rst | 5 +- www/Magick++/index.html | 2 +- www/Magick++/index.rst | 3 +- www/Makefile.am | 5 + www/NEWS.html | 677 +- www/OpenMP.html | 2 +- www/OpenMP.rst | 2 +- www/README.html | 21 +- www/api/api.html | 2 +- www/api/api.rst | 2 +- www/api/attribute.html | 2 +- www/api/blob.html | 154 +- www/api/constitute.html | 19 +- www/api/draw.html | 16 +- www/api/error.html | 2 + www/api/image.html | 327 +- www/api/list.html | 3 +- www/api/monitor.html | 12 +- www/api/render.html | 60 +- www/api/types.html | 2 +- www/api/types.rst | 3 +- www/authors.html | 23 +- www/authors.rst | 152 +- www/benchmarks.html | 2 +- www/benchmarks.rst | 2 +- www/bugs.html | 13 +- www/bugs.rst | 15 +- www/contribute.html | 2 +- www/contribute.rst | 2 +- www/download.html | 4 +- www/download.rst | 4 +- www/formats.html | 5 +- www/formats.rst | 6 +- www/gm.html | 107 +- www/index.html | 8 +- www/index.rst | 61 +- www/links.html | 61 +- www/links.rst | 11 +- www/miff.html | 2 +- www/miff.rst | 2 +- www/mission.html | 2 +- www/mission.rst | 2 +- www/motion-picture.html | 2 +- www/motion-picture.rst | 2 +- www/perl.html | 2 +- www/perl.rst | 2 +- www/process.html | 2 +- www/process.rst | 2 +- www/programming.html | 2 +- www/programming.rst | 2 +- www/project.html | 2 +- www/project.rst | 2 +- www/quantize.html | 2 +- www/quantize.rst | 3 +- www/reference.html | 2 +- www/reference.rst | 2 +- www/security.html | 182 +- www/security.rst | 183 +- www/thanks.html | 3 +- www/thanks.rst | 5 +- www/tools.html | 2 +- www/tools.rst | 2 +- www/utilities.html | 2 +- www/utilities.rst | 3 +- www/version.html | 20 +- www/wand/magick_wand.html | 1557 +++-- 471 files changed, 61666 insertions(+), 37376 deletions(-) create mode 100644 ChangeLog.2016 create mode 100644 ChangeLog.2017 create mode 100644 PerlMagick/t/jpeg/input.jnx create mode 100644 PerlMagick/t/reference/jpeg/read_jnx.miff create mode 100644 PerlMagick/t/wmf/fulltest.wmf create mode 100644 m4/pkg.m4 create mode 100644 magick/module_aliases.h create mode 100755 scripts/gmsymbols.sh create mode 100644 www/ChangeLog-2017.html create mode 100644 www/ChangeLog-2017.rst diff --git a/ChangeLog b/ChangeLog index 64271c2..4f746d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,252 +1,2612 @@ -2017-07-04 Bob Friesenhahn +2018-11-17 Bob Friesenhahn - * NEWS.txt: Make sure is up to date. + * www/index.rst: Update in preparation for 1.3.31 release. - * www/index.rst: Update for 1.3.26 release. + * version.sh: Update library versioning in preparation for + 1.3.31 release. - * version.sh: Update library versioning for 1.3.26 release. + * NEWS.txt: Update news in preparation for 1.3.31 release. - * magick/command.c (BatchCommand): Add ferror() checks around - batch input loop. +2018-11-15 Bob Friesenhahn -2017-07-03 Glenn Randers-Pehrson + * magick/command.c (BenchmarkUsage): Document the benchmark + command better. - * coders/png.c: Reject a PNG file if the file size is too small - (less than 61 bytes). Reject a JNG file if it is too small (less - than 147 bytes). - * coders/jpeg.c: Reject a JPEG file if the file size is too small - (less than 107 bytes). +2018-11-14 Bob Friesenhahn -2017-07-02 Bob Friesenhahn + * magick/resize.c (HorizontalFilter, VerticalFilter): quantum is a + pointer so it's value can not be usefully flushed. Use a local + variable and then update quantum pointer when done. - * coders/dpx.c (ReadDPXImage): Compute required file size and - verify that sufficient data exists in file before allocating - memory to decode the image data. Resolves problem with DPX file - with valid header (but a huge claimed image width) provided - provided via email on Thu, 29 Jun 2017 by LCatro. This issue has - been assigned CVE-2017-10799. +2018-11-11 Bob Friesenhahn -2016-07-02 Fojtik Jaroslav + * magick/*: Changed row_count tallying to use 'omp atomic' and + status update to use 'omp flush' for progress and error + indication. This replaces most use of 'omp critical' for this + purpose. Changed some lumpy algorithms which were using 'static' + scheduling to 'guided' scheduling due to observing better results. + Also added prolific 'restrict' annotations where they were + missing. - * coders/mat.c Check whether reported object size overflows file size. + * www/security.rst: Documented a PGP private key for file signing + or private correspondence. -2016-07-01 Fojtik Jaroslav +2018-11-10 Bob Friesenhahn - * coders/mat.c Safety check for forged and or corrupted data. - This issue has been assigned CVE-2017-10800. + * www/authors.rst: Moved "Glenn Randers-Pehrson" and "Gregory J + Wolfe" to the "Former Contributor" category. -2017-07-01 Bob Friesenhahn +2018-11-09 Bob Friesenhahn - * coders/tiff.c ("QuantumTransferMode"): Use a generalized method - to enforce that buffer overflow can not happen while importing - pixels. Resolves problem with RGB TIFF claiming only one sample - per pixel provided via email on Thu, 29 Jun 2017 by LCatro. This - issue has been assigned CVE-2017-10794. + * Added many GCC function annotations in the libraries and coders. -2017-06-29 Bob Friesenhahn +2018-11-07 Bob Friesenhahn - * magick/command.c: Convert bare 'unsigned int' to MagickPassFail - where suitable to make intentions clear. Convert True/False to - MagickTrue/MagickFalse or MagickPass/MagickFail according to - purpose. This is a continuation of a gradual migration and does - not represent an API change. + * configure.ac: Use printf rather than echo to portably expand tab + requests in configuration summary. -2017-06-25 Glenn Randers-Pehrson +2018-11-01 Bob Friesenhahn - * coders/png.c: Avoid NULL dereference when MAGN chunk processing - fails (https://sourceforge.net/p/graphicsmagick/bugs/426/). Expand - TABs. + * configure.ac: Use pkg-config data as the initial choice when + configuring for FreeType 2.0 and libxml-2.0. Only fall back to + invoking an external script (and then traditional methods) if + pkg-config fails. -2017-06-25 Bob Friesenhahn + * coders/msl.c (ProcessMSLScript): Release msl_image if OpenBlob + fails. Similar to ImageMagick CVE-2018-18544. Problem was + reported to us via email from Petr Gajdos on Thu, 1 Nov 2018. - * NEWS.txt: Update NEWS with changes since the previous release. +2018-10-27 Bob Friesenhahn - * www/programming.rst: Switch the Lua link to - https://github.com/arcapos/luagraphicsmagick, which is a more - complete and direct interface from Lua to GraphicsMagick's Wand - API. + * coders/miff.c (WriteMIFFImage): Only run + strlen(attribute->value) once per attribute since the length won't + change. May address oss-fuzz 11158 + "graphicsmagick/coder_MIFF_fuzzer: Timeout in + graphicsmagick_coder_MIFF_fuzzer". (Credit to OSS-Fuzz) -2017-06-24 Bob Friesenhahn + * Fix compilation warnings observed with GCC 8.2.0. - * VisualMagick/installer/gm-foo-dll.iss: Remove PerlMagick from - the slim Inno Setup installer builder and remove mention of - PerlMagick from the installer documentation. +2018-10-26 Bob Friesenhahn - * TclMagick/generic/TclMagick.c (magickCmd): Resolve SourceForge - patch #51 "TclMagick: memory access error; possible segfault". - (newMagickObj): Fix formatting of pointer value so it is 64-bit - safe. Resolves SourceForge patch #50 "TclMagick: 64-bit - portability issue". + * magick/pixel_iterator.c (PixelIterateMonoModifyImplementation): + Use atomic and flush rather than critical construct for a small + speedup. - * coders/pict.c (ReadPICTImage): Avoid possible use of negative - value when indexing array, which would cause buffer overflow. - Resolves SourceForge issue #427 "One possible buffer overflow - vulnerability in - GraphicsMagick-1.3.25/coders/pict.c:ReadPICTImage()". + * magick/monitor.c (MagickMonitorFormatted): Serialize calls to + the progress monitor so that the caller does not need to perform + this serialization. + (MagickMonitor): Serialize calls to the progress monitor so that + the caller does not need to perform this serialization. This + function is now marked as deprecated. + (InitializeMagickMonitor): New private function to initialize + monitor functionality. + (DestroyMagickMonitor): New private function to destroy monitor + functionality. -2017-06-22 Glenn Randers-Pehrson +2018-10-23 Bob Friesenhahn - * coders/png.c: Stop memory leak when reading invalid JNG image. - Fixes CVE-2017-8350. + * coders/gif.c (ReadGIFImage): Improve the efficiency of storing a + GIF comment in order to avoid a DOS opportunity. Fixes oss-fuzz + 11096 "graphicsmagick/coder_GIF_fuzzer: Timeout in + graphicsmagick_coder_GIF_fuzzer". (Credit to OSS-Fuzz) -2017-06-18 Bob Friesenhahn +2018-10-21 Bob Friesenhahn - * coders/png.c: Fix lcms2.h inclusion logic. + * PerlMagick/Makefile.PL.in: Use MAGICK_API_LIBS to obtain the + list of libraries to use when linking. - * wand/magick_wand.c (MagickSetImageOrientation): Eliminate use of - snprintf, which is not supported by older Visual Studio. + * configure.ac: OpenMP library is normally supplied due to a + CFLAGS option so only supply it in cases where the CFLAGS option + may be lost or it might not be used. Otherwise the compiler may + apply the library twice when linking. -2017-06-09 Glenn Randers-Pehrson +2018-10-20 Bob Friesenhahn - * coders/png.c: Accept exIf chunks whose data segment - erroneously begins with "Exif\0\0". + * configure.ac: Remove Ghostscript library support (--with-gslib) + from configure script. The 'HasGS' pre-processor defines which + were enabled by this remain in the source code so it is still + possible to use this library if absolutely necessary + (e.g. CPPFLAGS=-DHasGS LIBS=-lgs). -2017-06-01 Glenn Randers-Pehrson + * tests/rwfile.tap: Test TIFF format with all supported + compression options. - * coders/png.c: Removed experimental zxIF chunk support. That - proposal is dead. + * tests/{rwblob.c, rwfile.c} (main): Use StringToCompressionType() + to parse compression option. Also consider requested compression + algorithm when deciding if format is lossy. -2017-05-27 Bob Friesenhahn + * coders/tiff.c (WriteTIFFImage): WebP compression needs + PHOTOMETRIC_RGB. Fix wrong rows-per-strip calculation when using + LZMA compression. - * config/log.mgk: Added documentation suggested by SourceForge - issue #419 "Consider a small patch to log.mgk". + * tests/rwblob.tap: Added a rwblob test to verify that lower-case + magick works. - * www/Changes.rst: Add missing link to most recent changes. + * magick/static.c (OpenModule): Upper case magick string before + searching static modules list. Fixes Debian bug 911386 + "libgraphicsmagick-q16-3: graphicsmagick 1.3.30 has made formats + case-sensitive at the API level". -2017-05-24 Bob Friesenhahn + * filters/analyze.c (AnalyzeImage): X and y should be unsigned + long to match image rows/columns type. Calculate total pixels by + simple multiplication rather than counting. - * www/Magick++/Image.rst: Improve documentation for Magick++ - Image::iccColorProfile() and Image::renderingIntent(). +2018-10-14 Bob Friesenhahn -2017-05-21 Bob Friesenhahn + * coders/tiff.c (WriteTIFFImage): Support WebP compression in + TIFF. This requires a libtiff release after 4.0.9. - * tiff: Update to libtiff 4.0.8. + * magick/image.h ("C"): WebPCompression added to CompressionType + enumeration. -2017-03-19 Glenn Randers-Pehrson +2018-10-13 Bob Friesenhahn - * coders/png.c: Quieted a new Coverity complaint about a potential - text buffer overrun. + * configure.ac: Configure for the Zstd library. Use + --without-zstd to disable searching for this library. Libtiff may + require this library to successfully link so static linkage could + fail if searching for libzstd is disabled. -2017-03-19 Bob Friesenhahn + * magick/image.h ("C"): ZSTDCompression added to CompressionType + enumeration. - * magick/image.c (SetImageInfo): Ignore empty magic prefix - specification and do not remove colon character from start of - filename. Resolves SourceForge bug #415 "Inconsistent Behavior w/ - input_file Parameter". + * coders/tiff.c (WriteTIFFImage): Support Zstd compression in + TIFF. This requires a libtiff release after 4.0.9. -2017-03-18 Glenn Randers-Pehrson +2018-10-10 Bob Friesenhahn - * coders/png.c: Added new private orNT PNG chunk, to - preserve image->orientation when it is defined and not - the default TopLeft. - * coders/jpeg.c: Mention image->orientation in the log when - writing a JPEG. + * magick/command.c (GMCommandSingle): Add 'compare' to the list of + command names that gm will support as a command if copied to or + linked from that name. There was already a 'compare' link + installed when the '--enable-magick-compat' configure option is + used, but it could not possibly function without being blessed by + this list. Related to Debian bug #910652 + "graphicsmagick-imagemagick-compat: Doesn't ship a compare tool". -2017-03-15 Glenn Randers-Pehrson +2018-09-30 Bob Friesenhahn - * coders/png.c (WriteOnePNGImage): Add version info about - gm, libpng, zlib, and lcms to the PNG debug log. + * Magick++/lib/Magick++/Drawable.h: Block unused-private-field + warnings from Clang due to _dummy members which were intentionally + included in some parent class definitions. -2017-03-04 Bob Friesenhahn + * magick/widget.c (XEditText): Fix compilation warnings about + cases which fall-through. - * magick/command.c (ImportImageCommand): Fix handling of -frame - options. Option handling was incorrect due to option checking the - frame option after it had been freed. Checking the frame dash - option before freeing the argument solves the problem. From patch - provided by Victor Ananjevsky as SourceForge patch #49 "-frame - doesn't work in gm import". + * magick/display.c (MagickXAnnotateEditImage): Fix compilation + warnings about cases which fall-through. - * Magick++/lib/Image.cpp (attribute): Added Image attribute method - which accepts a 'char *' argument, and will remove the attribute - if the value argument is NULL. From patch provided by "Gints" as - SourceForge patch #46 "C++ api - method to clear/remove - attribute". + * coders/pict.c (WritePICTImage): Add more checks to memory + allocation calculations. - * VisualMagick/configure/configure.cpp (InitInstance): Applied - patch by Paul McConkey to allow the quantum command line argument - to set the default value in the wizard drop list. This allows - setting the quantum depth when the /nowizard argument was - supplied. Resolves SourceForge patch #48 "When running from the - command line configure.exe does not use the quantum argument". - The provided configure.exe still needs to be rebuilt to - incorporate this change. + * magick/pixel_cache.c (DestroyCacheInfo): Eliminate intentional + fall-through logic in switch statement which results in compiler + warnings. Eliminate switch statements entirely and split + unrelated logic. - * magick/command.c (MogrifyImage): The -orient command now also - updates the orientation in the EXIF profile, if it exists. + * coders/txt.c (ReadTXTImage): Fix comparison between pointer and + '\0' rather than NULL as was obviously intended. - * Magick++/lib/Image.cpp (orientation): Update orientation in EXIF - profile, if it exists. + * coders/msl.c (MSLStartElement): Add missing 'break' statements + after ThrowException() calls. Otherwise execution falls through + into unrelated switch cases and throws a redundant exception. -2017-03-03 Bob Friesenhahn +2018-09-29 Bob Friesenhahn - * coders/jp2.c: Support PGX JPEG 2000 format for reading and - writing (within the bounds of what JasPer supports). + * coders/meta.c (parse8BIM): Eliminate repeated use of strlen() + which scans the entire remaining string on each cycle. Fixes + oss-fuzz 10667 "graphicsmagick/coder_IPTCTEXT_fuzzer: Timeout in + graphicsmagick_coder_IPTCTEXT_fuzzer". (Credit to OSS-Fuzz) -2017-02-23 Bob Friesenhahn +2018-09-26 Bob Friesenhahn - * coders/tiff.c (QuantumTransferMode): Fix out of bounds read when - reading CMYKA TIFF which claims to have only 2 samples per pixel. - Problem was reported via email on February 15, 2017 by Valon - Chu. This issue was assigned CVE-2017-6335. + * magick/utility.c (MagickGetToken): Fix possible read up to four + bytes beyond end of stack allocated token buffer. Fixes oss-fuzz + 10653 "graphicsmagick/coder_MVG_fuzzer: Stack-buffer-overflow in + MagickGetToken". (Credit to OSS-Fuzz) -2017-01-29 Bob Friesenhahn +2018-09-22 Bob Friesenhahn - * doc/options.imdoc (-geometry): Geometry documentation changes - suggested by Jon Wong. + * fuzzing/coder_fuzzer.cc (LLVMFuzzerTestOneInput): Limit the + maximum number of JPEG progressive scans to 50. -2017-01-26 Glenn Randers-Pehrson + * coders/jpeg.c (ReadJPEGImage): Apply a default limit of 100 + progressive scans before the reader quits with an error. This + limit may be adjusted using the -define mechanism like -define + JPEG:max-scan-number=500. Also respond more quickly to files + which exceed the maximum image dimensions. Fixes oss-fuzz 10258 + "graphicsmagick/coder_JPEG_fuzzer: Timeout in + graphicsmagick_coder_JPEG_fuzzer". (Credit to OSS-Fuzz) - * coders/png.c: Added support for a proposed new PNG chunk - (zxIf, read-only) that is currently being discussed on the - png-mng-misc at lists.sourceforge.net mailing list. Enable - exIf and zxIf with CPPFLAGS="-DexIf_SUPPORTED -DxzIf_SUPPORTED". - If exIf is enabled, only the uncompressed exIF chunk will be - written and the hex-encoded zTXt chunk containing the raw Exif - profile won't be written. +2018-09-20 Bob Friesenhahn -2017-01-25 Bob Friesenhahn + * coders/png.c (ReadMNGImage): mng_LOOP chunk must be at least 5 + bytes long. Fixes oss-fuzz 10455 + "graphicsmagick/coder_MNG_fuzzer: Use-of-uninitialized-value in + ReadMNGImage". (Credit to OSS-Fuzz) - * coders/msl.c (MSLStartElement): Change test for NULL image - pointer to before it is used rather than after it is used. - Problem reported by Petr Gajdos on 2017-01-25. +2018-09-15 Bob Friesenhahn -2017-01-22 Bob Friesenhahn + * magick/render.c (TraceEllipse): Detect arithmetic overflow when + computing the number of points to allocate for an ellipse. Fixes + oss-fuzz 10306 "graphicsmagick/coder_MVG_fuzzer: + Heap-buffer-overflow in TracePoint". (Credit to OSS-Fuzz) - * TclMagick/unix/m4/tcl.m4: Update tcl.m4 to TEA 3.10. File - supplied by Massimo Manghi. +2018-09-12 Bob Friesenhahn -2017-01-21 Glenn Randers-Pehrson + * magick/attribute.c (GenerateEXIFAttribute): Eliminate undefined + shift. Also right-sized involved data types. Fixes oss-fuzz + 10309 "graphicsmagick/coder_JPG_fuzzer: Undefined-shift in + Read32s". (Credit to OSS-Fuzz) - * coders/png.c: Added support for a proposed new PNG - chunk (exIf read-write, eXIf read-only) that is currently - being discussed on the png-mng-misc at lists.sourceforge.net - mailing list. +2018-09-09 Bob Friesenhahn -2017-01-21 Glenn Randers-Pehrson + * magick/render.c (DrawClipPath): Fix Coverity 319663 "Null + pointer dereferences". Totally insignificant. - * coders/png.c: Added read_user_chunk_callback() function - and used it to implement a private PNG caNv (canvas) chunk - for remembering the original dimensions and offsets when an - image is cropped. Previously we used the oFFs chunk for this - purpose, but this had potential conflicts with other applications - that also use the oFFs chunk. + * coders/wpg.c (ReadWPGImage): Mask/fix Coverity 319664 "Error + handling issues". -2017-01-07 Bob Friesenhahn + * magick/attribute.c (FindEXIFAttribute): Change size types from + signed to unsigned and check for unsigned overflow. + (GenerateEXIFAttribute): Change size types from signed to unsigned + and check for unsigned overflow. Fixes oss-fuzz 10283 + "graphicsmagick/coder_JPG_fuzzer: Integer-overflow in + GenerateEXIFAttribute". (Credit to OSS-Fuzz) - * TclMagick/Makefile.am (AM_DISTCHECK_CONFIGURE_FLAGS): Applied - patch by Massimo Manghi to set AM_DISTCHECK_CONFIGURE_FLAGS so - that 'make distcheck' remembers configuration options, and also to - uninstall pkgIndex.tcl. + * coders/sfw.c (ReadSFWImage): Enforce that file is read using the + JPEG reader. (Credit to OSS-Fuzz) - * magick/image.c (SetImageEx): Use PixelIterateMonoSet() for - possibly improved efficiency. + * coders/miff.c (ReadMIFFImage): Fix leak of 'values' buffer due + to change made yesterday. - * magick/pixel_iterator.c (PixelIterateMonoSet): New pixel - iterator intended for use when initializing image pixels, without - regard to existing values. + * coders/mpc.c (ReadMPCImage): Fix leak of 'values' buffer due to + change made yesterday. Fixes oss-fuzz 10277 + "graphicsmagick/coder_MPC_fuzzer: Direct-leak in + ReadMPCImage". (Credit to OSS-Fuzz) -2017-01-01 Bob Friesenhahn +2018-09-08 Bob Friesenhahn - * Copyright.txt: Bump copyright years and rotate ChangeLog. + * coders/miff.c (ReadMIFFImage): Support legacy keyword + 'color-profile' for ICC color profile as was used by ImageMagick + 4.2.9. + + * coders/mpc.c (ReadMPCImage): Require that first keyword/value be + id=MagickCache + + * coders/miff.c (ReadMIFFImage): Require that first keyword/value + be id=ImageMagick. + +2018-09-06 Bob Friesenhahn + + * coders/dcm.c (DCM_ReadElement): Add more size checks. + + * coders/jnx.c (ExtractTileJPG): Enforce that JPEG tiles are read + by the JPEG coder. Fixes oss-fuzz 10147 + "graphicsmagick/coder_JNX_fuzzer: Use-of-uninitialized-value in + funcDCM_PhotometricInterpretation". (Credit to OSS-Fuzz) + +2018-09-10 Fojtik Jaroslav + + * coders/wpg.c Zero fill raster error recovery. + +2018-08-29 Bob Friesenhahn + + * magick/render.c (ConvertPrimitiveToPath): Second attempt to + prevent heap write overflow of PathInfo array. Fixes oss-fuzz + 10096 "Heap-buffer-overflow in ConvertPrimitiveToPath". (Credit to + OSS-Fuzz) + +2018-08-25 Bob Friesenhahn + + * coders/tiff.c ("QuantumTransferMode"): CIE Log images with an + alpha channel are not supported. Fixes oss-fuzz 10013 + "graphicsmagick/coder_TIFF_fuzzer: Use-of-uninitialized-value in + DisassociateAlphaRegion". (Credit to OSS-Fuzz) + + * magick/render.c (DrawImage): SetImageAttribute() appends new + text to any existing value, leading to every increasing memory + consumption if the existing value is not deleted first by the + unwary. Fixes oss-fuzz 9983 "graphicsmagick/coder_MVG_fuzzer: + Timeout in graphicsmagick_coder_MVG_fuzzer" and oss-fuzz 10016 + "graphicsmagick/coder_MVG_fuzzer: Out-of-memory in + graphicsmagick_coder_MVG_fuzzer". (Credit to OSS-Fuzz) + + * magick/utility.c (TranslateTextEx): Fix off-by-one in loop + bounds check which allowed a one-byte stack write overflow. Fixes + oss-fuzz 10055 "graphicsmagick/coder_MVG_fuzzer: + Stack-buffer-overflow in TranslateTextEx". (Credit to OSS-Fuzz) + + * magick/render.c (DrawImage): Be more precise about error + detection and reporting, and return from an error more quickly. + Also added MAX_DRAWIMAGE_RECURSION pre-processor definition to + allow adjusting the drawing recursion limit. The drawing + recursion limit is still 100, which seems exceptionally generous. + + * magick/constitute.c (WriteImage): Produce a more useful error + message if an encoding delegate is not available. + + * magick/nt_base.h (isnan): Try adding a MSVC replacement for + missing isnan() function. Not yet tested. + +2018-08-25 Fojtik Jaroslav + + * coders/wpg.c This should fix intentional 64 bit file offset + overflow as depictedin OSS-fuzz-9936. Thanks to OSS-Fuzz. + +2018-08-22 Bob Friesenhahn + + * magick/render.c (ConvertPrimitiveToPath): Need to enlarge + PathInfo array allocation to avoid possible heap write overflow. + Fixes oss-fuzz 9651 "graphicsmagick/coder_MVG_fuzzer: + Heap-buffer-overflow in ConvertPrimitiveToPath". (Credit to + OSS-Fuzz) + +2018-08-20 Bob Friesenhahn + + * coders/mpc.c (ReadMPCImage): Insist that the format be + identified prior to any comment, and that there is only one + comment. + + * coders/miff.c (ReadMIFFImage): Insist that the format be + identified prior to any comment, and that there is only one + comment. Fixes oss-fuzz 9979 "graphicsmagick/coder_MIFF_fuzzer: + Timeout in graphicsmagick_coder_MIFF_fuzzer". This is not a + serious issue, but the code runs slowly under UBSAN. (Credit to + OSS-Fuzz) + +2018-08-19 Bob Friesenhahn + + * magick/utility.c (MagickAtoFChk): Add additional validation + checks for floating point values. NAN and +/- INFINITY values + also map to 0.0. Fixes oss-fuzz 9630 + "graphicsmagick/coder_MVG_fuzzer: Integer-overflow in + IsNexusInCore" and oss-fuzz 9612 "graphicsmagick/coder_MVG_fuzzer: + Integer-overflow in SetCacheNexus". (Credit to OSS-Fuzz) + + * magick/render.c (DrawImage): Add missing error-reporting logic + to return immediately upon memory reallocation failure. Apply + memory resource limits to PrimitiveInfo array allocation. Fixes + oss-fuzz 9576 "graphicsmagick/coder_MVG_fuzzer: Null-dereference + READ in DrawImage", oss-fuzz 9593 + "graphicsmagick/coder_MVG_fuzzer: Out-of-memory in + graphicsmagick_coder_MVG_fuzzer", oss-fuzz 9648 + "graphicsmagick/coder_MVG_fuzzer: Unknown signal in + DrawImage". (Credit to OSS-Fuzz) + +2018-08-16 Fojtik Jaroslav + + * coder/mat.c Explicitly reject non-seekable streams. + +2018-08-15 Fojtik Jaroslav + + * coder/mat.c Correctly check GetBlobSize(image) even for zipstreams. + +2018-08-14 Fojtik Jaroslav + + * coders/mat.c More aggresive data corruption checking. + +2018-08-09 Bob Friesenhahn + + * coders/xbm.c (XBMInteger): Limit the number of hex digits parsed + to avoid signed integer overflow. Fixes oss-fuzz 9746 + "graphicsmagick/coder_XBM_fuzzer: Undefined-shift in + XBMInteger". (Credit to OSS-Fuzz) + +2018-08-07 Fojtik Jaroslav + + * coders/mat.c Typecast difference to quantum. + +2018-08-05 Bob Friesenhahn + + * coders/mat.c (InsertComplexFloatRow): Avoid signed + overflow. Fixes oss-fuzz 9667 "graphicsmagick/coder_MAT_fuzzer: + Integer-overflow in InsertComplexFloatRow". (Credit to OSS-Fuzz) + + * coders/xbm.c (ReadXBMImage): Add validations for row and column + dimensions. Fixes oss-fuzz 9736 "graphicsmagick/coder_XBM_fuzzer: + Out-of-memory in graphicsmagick_coder_XBM_fuzzer". (Credit to + OSS-Fuzz) + +2018-08-04 Fojtik Jaroslav + + * coders/wpg.c Add mechanism to approve embedded subformats in + WPG. This should mute oss-fuzz 9559. (Credit to OSS-Fuzz) + +2018-07-24 Bob Friesenhahn + + * coders/mvg.c (ReadMVGImage): Fix memory leak added on + 2018-07-21. Fixes oss-fuzz 9548 "graphicsmagick/coder_MVG_fuzzer: + Direct-leak in CloneDrawInfo". (Credit to OSS-Fuzz) + +2018-07-23 Bob Friesenhahn + + * coders/cineon.c (ReadCINEONImage): Fix SourceForge issue 571 + "Unexpected hang on a crafted Cineon image" by detecting and + quitting on EOF appropriately, and verifying that file size is + sufficient for claimed pixel dimensions when possible. + + * fuzzing/oss-fuzz-build.sh, fuzzing/dictionaries/MVG.dict: Added + MVG fuzzing dictionary by Alex Gaynor. + +2018-07-22 Bob Friesenhahn + + * magick/pixel_cache.c (SetNexus): For requests one pixel tall, + SetNexus() was wrongly using pixels in-core rather than using a + staging area for the case where the nexus rows extend beyond the + image raster boundary, leading to heap overflow. This can happen + when virtual pixels outside the image bounds are accessed. Fixes + oss-fuzz 9512 "graphicsmagick/graphicsmagick_coder_MVG_fuzzer: + Heap-buffer-overflow in AcquireCacheNexus". (Credit to OSS-Fuzz) + + * magick/render.c (ExtractTokensBetweenPushPop): + ExtractTokensBetweenPushPop() needs to always return a valid + pointer into the primitive string. Fixes oss-fuzz 9511 + "graphicsmagick/graphicsmagick_coder_MVG_fuzzer: Null-dereference + READ in DrawImage". (Credit to OSS-Fuzz) + (DrawPolygonPrimitive): Fix leak of polygon set when object is + completely outside image. Fixes oss-fuzz 9513 + "graphicsmagick/graphicsmagick_coder_MVG_fuzzer: Direct-leak in + AllocateThreadViewDataSet". (Credit to OSS-Fuzz) + +2018-07-21 Bob Friesenhahn + + * magick/blob.c (FileToBlob): Use confirm access APIs to verify + that read access to this path is allowed by policy. Check that + file is a regular file before proceeding to open and read from it. + + * coders/mvg.c (ReadMVGImage): Don't allow MVG files to side-load + a file as the drawing primitive using '@' syntax. Fixes oss-fuzz + 9494 "graphicsmagick/coder_MVG_fuzzer: Sanitizer CHECK failure in + "((0)) != (0)" (0x0, 0x0)". (Credit to OSS-Fuzz) + +2018-07-19 Bob Friesenhahn + + * coders/mvg.c (ReadMVGImage): Don't assume that in-memory MVG + blob is a null-terminated C string. Fixes oss-fuzz 9469 + "graphicsmagick/coder_MVG_fuzzer: Heap-buffer-overflow in + AllocateString". (Credit to OSS-Fuzz) + +2018-07-12 Bob Friesenhahn + + * coders/miff.c (ReadMIFFImage): Detect EOF when reading using + ReadBlobZC() and avoid subsequent heap read overflow. Fixes + oss-fuzz 9357 "graphicsmagick/coder_MIFF_fuzzer: + Heap-buffer-overflow in ImportRGBQuantumType". (Credit to + OSS-Fuzz) + +2018-07-11 Bob Friesenhahn + + * fuzzing/oss-fuzz-build.sh (CFLAGS): Try disabling SIMD + instructions in libjpeg-turbo build. + +2018-07-10 Bob Friesenhahn + + * coders/png.c (WriteOnePNGImage): Free png_pixels as soon as + possible. This might help with oss-fuzz 9334 + "graphicsmagick/coder_PNG8_fuzzer: Direct-leak in + WriteOnePNGImage", which we have yet to reproduce. It is not + clear if png_pixels is being clobbered by longjmp or if something + else is going on. + +2018-06-26 Bob Friesenhahn + + * coders/jpeg.c (ReadJPEGImage): Provide a memory resource limit + (of 1/5th the memory resource limit for Graphicsmagick) to libjpeg + to limit how much memory it might consume for itself while reading + a file. Fixes oss-fuzz 9096 "graphicsmagick/coder_JPEG_fuzzer: + Timeout in graphicsmagick_coder_JPEG_fuzzer". (Credit to + OSS-Fuzz) + (ReadJPEGImage): Make sure that JPEG pixels array is initialized + in case libjpeg fails to completely initialize it. May fix + oss-fuzz 9115 "graphicsmagick/coder_JPEG_fuzzer: + Use-of-uninitialized-value in ReadJPEGImage". We are not sure + since the problem was not reproduced. (Credit to OSS-Fuzz) + +2018-06-23 Bob Friesenhahn + + * version.sh: Update library versioning for 1.3.30 release. + + * NEWS.txt: Update news for 1.3.30 release. + +2018-06-22 Bob Friesenhahn + + * coders/dpx.c (ReadDPXImage): Report exception on EOF file + reading DPX pixel data. Fixes oss-fuzz 8104 + "graphicsmagick/coder_DPX_fuzzer: Use-of-uninitialized-value in + WriteDPXImage", oss-fuzz 8297 "graphicsmagick/enhance_fuzzer: + Use-of-uninitialized-value in EnhanceImage", and oss-fuzz 8133 + "graphicsmagick/coder_DPX_fuzzer: Use-of-uninitialized-value in + RGBTransformPackets". (Credit to OSS-Fuzz) + +2018-06-20 Bob Friesenhahn + + * coders/cmyk.c (ReadCMYKImage): Free scanline buffer in error + path. Fixes SourceForge issue #567 "small memory leak in rgb.c, + gray.c and cmyk.c" reported by Petr Gajdos. + + * coders/gray.c (ReadGRAYImage): Free scanline buffer in error + path. Fixes SourceForge issue #567 "small memory leak in rgb.c, + gray.c and cmyk.c" reported by Petr Gajdos. + + * coders/rgb.c (ReadRGBImage): Free scanline buffer in error + path. Fixes SourceForge issue #567 "small memory leak in rgb.c, + gray.c and cmyk.c" reported by Petr Gajdos. + + * coders/jpeg.c (ReadJPEGImage): Avoid memory leak of profile + buffer when longjmp-based exception is thrown while reading a + profile. Fixes oss-fuzz 8957 "graphicsmagick/enhance_fuzzer: + Direct-leak in ReadGenericProfile". (Credit to OSS-Fuzz) + +2018-06-17 Bob Friesenhahn + + * coders/xcf.c (load_level): Make sure to free 'tile_image' before + returning exception. Fixes oss-fuzz 8935 + "graphicsmagick/coder_XCF_fuzzer: Indirect-leak in + CloneImage". (Credit to OSS-Fuzz) + + * coders/jpeg.c (ReadJPEGImage): Allow three warnings of any given + type before promoting the next warning of the same type to a hard + error. The warning limit may be adjusted by the user using + -define jpeg:max-warnings=. Fixes oss-fuzz 8704 + "graphicsmagick/coder_JPG_fuzzer: Out-of-memory in + graphicsmagick_coder_JPG_fuzzer". (Credit to OSS-Fuzz) + + * coders/png.c (ReadPNGImage): Detect EOF when reading + magic_number. Fixes oss-fuzz 8944 + "graphicsmagick/coder_PNG_fuzzer: Use-of-uninitialized-value in + ReadPNGImage". (Credit to OSS-Fuzz) + (ReadPNGImage, ReadJNGImage): Makes sure that return value of + ReadBlob() is always checked to detect EOF. + +2018-06-16 Bob Friesenhahn + + * coders/tiff.c (ReadTIFFImage): Re-structure exception reporting + so that QuantumTransferMode() exceptions thrown for + PLANARCONFIG_SEPARATE images are handled immediately. Fixes + oss-fuzz 8896 "graphicsmagick/coder_BIGTIFF_fuzzer: + Use-of-uninitialized-value in DisassociateAlphaRegion". (Credit to + OSS-Fuzz) + (ReadTIFFImage): tsize_t is a signed type so be prepared for + unexpected negative values produced by libtiff size functions. + Fixes oss-fuzz 8934 "graphicsmagick/coder_TIFF_fuzzer: Sanitizer + CHECK failure in "((0)) != (0)" (0x0, 0x0)". (Credit to OSS-Fuzz) + +2018-06-16 Fojtik Jaroslav + + * coders/wpg.c Fix oss-fuzz 7735 "graphicsmagick/coder_WPG_fuzzer: + Use-of-uninitialized-value in ReadWPGImage". (Credit to OSS-Fuzz) + +2018-06-11 Bob Friesenhahn + + * coders/png.c (ReadMNGImage): ENDL chunk must be at least one + byte in size. Fixes oss-fuzz 8832 + "graphicsmagick/coder_MNG_fuzzer: Null-dereference READ in + ReadMNGImage". (Credit to OSS-Fuzz) + (ReadMNGImage): Length of DISC chunk must be evenly divisible by + 2. Fixes oss-fuzz 8834 "graphicsmagick/coder_MNG_fuzzer: + Heap-buffer-overflow in ReadMNGImage". (Credit to OSS-Fuzz) + +2018-06-10 Bob Friesenhahn + + * coders/mpc.c (ReadMPCImage): Detect end of file while reading + image directory. Similar to MIFF fixes for ImageMagick + CVE-2017-18272. + (RegisterMPCImage): Require seekable stream since MPC is strictly + a file-based format and so GetBlobSize() is assured to work. + Similar to MIFF behavior. Claimed to be part of the resolution + for ImageMagick CVE CVE-2017-11449. Suggested by Petr Gajdos via + email on January 3, 2018. + +2018-06-09 Bob Friesenhahn + + * coders/miff.c (ReadMIFFImage): Detect end of file while reading + image directory. Fixes SourceForge issue 565 "ImageMagick + CVE-2017-18272 applies to GraphicsMagick". Thanks to Petr Gajdos + for reporting this issue to us. + + * magick/import.c (ImportViewPixelArea): Use appropriate + bits_per_sample validations for FloatQuantumSampleType. Fixes + oss-fuzz 8780 "graphicsmagick/coder_PTIF_fuzzer: + Use-of-uninitialized-value in HorizontalFilter". (Credit to + OSS-Fuzz) + +2018-06-09 Fojtik Jaroslav + + * coders/mat.c More than 4GiB are not supported in MAT! + +2018-06-09 Bob Friesenhahn + + * coders/mat.c (ReadMATImage): Add casts to avoid arithmetic + overflow when computing size and offsets. Fixes oss-fuzz 8801 + "graphicsmagick/coder_MAT_fuzzer: Timeout in + graphicsmagick_coder_MAT_fuzzer". (Credit to OSS-Fuzz) + + * magick/blob.c (ReadBlobLSBDoubles, ReadBlobMSBDoubles): Only + byte-swap doubles or test doubles for NAN if we have read enough + bytes for at least one double value. + (ReadBlob): Add an assertion to enforce that ReadBlob() will never + report reading more bytes than requested due to some + implementation issue. + +2018-06-08 Bob Friesenhahn + + * magick/blob.c (ReadBlob, WriteBlob): gzread(), BZ2_bzread(), + gzwrite(), BZ2_bzwrite() return type 'int' rather than 'size_t' + like their stdio equivalents. Use correct signed type to avoid + returning a negative value into an unsigned type, forming a huge + positive value. Fixes oss-fuzz 8600 + "graphicsmagick/coder_MAT_fuzzer: Heap-buffer-overflow in + ReadBlobLSBDoubles". (Credit to OSS-Fuzz) + +2018-06-07 Bob Friesenhahn + + * coders/png.c (png_read_raw_profile): Try to shore up parsing of + raw profile reading to avoid heap read overruns. Fixes oss-fuzz + 8763 "graphicsmagick/coder_PNG32_fuzzer: Heap-buffer-overflow in + png_read_raw_profile". (Credit to OSS-Fuzz) + +2018-06-07 Fojtik Jaroslav + + * coders/mat.c Reduce stack usage for 64 bit architecture. + +2018-06-06 Fojtik Jaroslav + + * coders/wpg.c Check return values of SeekBlob for more safety. + +2018-06-06 Bob Friesenhahn + + * coders/png.c (ReadOneJNGImage): Use DestroyImageList() rather + than DestroyImage() on returned Image from supposed read of JPEG + data, in case multiple frames were unexpectedly returned. Also + add "JPEG:" prefix to filename when reading from temporary file to + force that it can only be read as a JPEG file, disabling format + auto-detection based on file header. Fixes oss-fuzz 8755 + "graphicsmagick/coder_JNG_fuzzer: Indirect-leak in + AllocateImage". (Credit to OSS-Fuzz) + +2018-06-05 Bob Friesenhahn + + * magick/blob.c (EOFBlob): Implement EOF detection for ZipStream. + Does some archaic zlib not provide gzeof()? Fixes oss-fuzz 8550 + "graphicsmagick/coder_MAT_fuzzer: Timeout in + graphicsmagick_coder_MAT_fuzzer". (Credit to OSS-Fuzz) + +2018-06-04 Bob Friesenhahn + + * coders/png.c (ReadOnePNGImage): Skip adding empty raw profile. + Fixes oss-fuzz "graphicsmagick/coder_PNG_fuzzer: + Heap-buffer-overflow in png_read_raw_profile". (Credit to + OSS-Fuzz) + +2018-06-03 Bob Friesenhahn + + * NEWS.txt: Update NEWS with latest changes. + + * coders/dcm.c (DCM_ReadRGBImage): Force the image to DirectClass + to avoid later use of uninitialized indexes. Fixes oss-fuzz 8602 + "graphicsmagick/coder_DCM_fuzzer: Use-of-uninitialized-value in + DCM_PostRescaleImage". (Credit to OSS-Fuzz) + (DCM_ReadPlanarRGBImage): Force the image to DirectClass to avoid + later use of uninitialized indexes. + + * coders/png.c (ReadMNGImage): Free chunk memory in error + reporting path to avoid leak. Fixes oss-fuzz 8721 + "graphicsmagick/coder_MNG_fuzzer: Direct-leak in + ReadMNGImage". (Credit to OSS-Fuzz) + +2018-06-02 Bob Friesenhahn + + * magick/constitute.c (ReadImage): Assure that an error exception + is thrown if coder returns null without properly reporting an + exception. + + * magick/blob.c (BlobToImage): Assure that an error exception is + thrown if coder returns null without properly reporting an + exception. + + * coders/png.c (ReadMNGImage): Disable mystery "linked list is + corrupted" code. Assure that exceptions are reported to the + correct place so they are not lost. Fixes oss-fuzz 8710 + "graphicsmagick/coder_MNG_fuzzer: Indirect-leak in + AllocateImage". (Credit to OSS-Fuzz) + + * coders/tiff.c (ReadTIFFImage): Initialize allocated scanline, + strip, or tile to zero in order to avoid complaint about use of + uninitialized data if libtiff fails to write all the bytes. Fixes + oss-fuzz 8551 "graphicsmagick/coder_TIFF_fuzzer: + Use-of-uninitialized-value in ImportGrayQuantumType". (Credit to + OSS-Fuzz) + + * magick/annotate.c (RenderFreetype): Throw an exception if + DrawInfo font is null. Should fix oss-fuzz 8557 + "graphicsmagick/coder_PCD_fuzzer: Unknown signal in + RenderFreetype" and may fix oss-fuzz 8544 + "graphicsmagick/coder_PCD_fuzzer: Null-dereference READ in + RenderFreetype". (Credit to OSS-Fuzz) + + * coders/jpeg.c (ReadGenericProfile): Add/improve tracing for + profile size and when JPEG header is being read. + +2018-06-01 Bob Friesenhahn + + * coders/png.c (ReadOneJNGImage): Report a useful exception for + the case when the JNG file fails to provide the necessary image + chunks to allocate the color image. Inspired by oss-fuzz 8666 + "graphicsmagick/coder_JNG_fuzzer: ASSERT: data != (const char *) + NULL" although the reported issue was not reproduced. + +2018-05-31 Bob Friesenhahn + + * coders/png.c (ReadMNGImage): Fix off-by-one in length validation + for TERM chunk which allowed one byte heap read overflow. Fixes + oss-fuzz 8615 "graphicsmagick/coder_MNG_fuzzer: + Heap-buffer-overflow in mng_get_long". (Credit to OSS-Fuzz) + (ReadMNGImage): Fix leak of MngInfo in error reporting path. + Fixes oss-fuzz 8604 "graphicsmagick/coder_MNG_fuzzer: Direct-leak + in ReadMNGImage". (Credit to OSS-Fuzz) + (ReadMNGImage): Verify that claimed chunk size does not exceed + input size. Fixes oss-fuzz 8564 "graphicsmagick/coder_MNG_fuzzer: + Out-of-memory in graphicsmagick_coder_MNG_fuzzer". (Credit to + OSS-Fuzz) + + * coders/tiff.c (ReadTIFFImage): Reject files with excessive + samples-per-pixel or extra-samples. Avoids potential issues + observed in oss-fuzz 8634 "graphicsmagick/coder_BIGTIFF_fuzzer: + Undefined-shift in ImportAlphaQuantumType". (Credit to OSS-Fuzz) + +2018-05-30 Bob Friesenhahn + + * coders/png.c (ReadMNGImage): Assure that object id index is + always less than MNG_MAX_OBJECTS to avoid overflow. Fixes + oss-fuzz 8596 "graphicsmagick/coder_MNG_fuzzer: + Index-out-of-bounds in ReadMNGImage" and likely other issues yet + to be reported. (Credit to OSS-Fuzz) + +2018-05-30 Greg Wolfe + + * magick/render.c (CompareEdges): Per ticket #562, + function CompareEdges() did not conform to the qsort() + requirement that if CompareEdges(edge0,edge1) returns + -1 (i.e., edge0 "less than" edge1), then + CompareEdges(edge1,edge0) should return 1 (edge1 + "greater than" edge0). This has been fixed. + +2018-05-30 Bob Friesenhahn + + * coders/png.c (ReadOneJNGImage): Deal with JDAA JNG chunk with + length zero. Fixes oss-fuzz 8562 + "graphicsmagick/coder_JNG_fuzzer: ASSERT: data != (const char *) + NULL". (Credit to OSS-Fuzz) + + * coders/tiff.c (ReadTIFFImage): Check that the bits-per-sample is + supported by the implementation before attempting to decode the + image. Fixes oss-fuzz 8554 "graphicsmagick/coder_BIGTIFF_fuzzer: + Undefined-shift in MagickBitStreamMSBWrite". (Credit to OSS-Fuzz) + + * coders/png.c (ReadMNGImage): Eliminate use of uninitialized + header magic data by checking for EOF first. Fixes oss-fuzz 8597 + "graphicsmagick/coder_MNG_fuzzer: Use-of-uninitialized-value in + ReadMNGImage". (Credit to OSS-Fuzz) + +2018-05-25 Bob Friesenhahn + + * fuzzing/oss-fuzz-build.sh: More fixes based on what is observed + in oss-fuzz build log. + +2018-05-24 Fojtik Jaroslav + + * coders/jnx.c The attribute should belong to only one scene and + not to whole image list. + +2018-05-24 Bob Friesenhahn + + * fuzzing/oss-fuzz-build.sh: Changes to add CPPFLAGS to configure + executions to hopefully get oss-fuzz build closer to success. + +2018-05-23 Bob Friesenhahn + + * PerlMagick/t/jpeg/read.t: Add a JNX reader test case. + + * coders/jnx.c (ReadJNXImage): JNX image depth should be 8. + + * fuzzing/oss-fuzz-build.sh: Apply patch from Alex Gaynor to + switch libpng to autotools build system, as well as configure + GraphicsMagick with '--with-quantum-depth=16'. + +2018-05-22 Bob Friesenhahn + + * coders/tiff.c (ReadTIFFImage): Validate tile memory requests for + the TIFFReadRGBATile() case in the same way as the TIFFReadTile() + case. Fixes oss-fuzz 8434 "graphicsmagick/coder_BIGTIFF_fuzzer: + Out-of-memory in graphicsmagick_coder_BIGTIFF_fuzzer". (Credit to + OSS-Fuzz) + +2018-05-21 Bob Friesenhahn + + * coders/tile.c (ReadTILEImage): Remove any existing size request + when while image to tile. This avoids size being used for both + the input image size and the tile image size. Fixes SourceForge + issue #563 "tile: appears to blow image up by 100% before + applying tiling". + +2018-05-20 Bob Friesenhahn + + * fuzzing/oss-fuzz-build.sh: Patch from Paul Kehrer to disable + libpng test programs and binaries while building libpng in support + of oss-fuzz testing. + + * coders/dcm.c (DCM_ReadGrayscaleImage): If a palette was + provided, the image may be in PseudoClass but we need DirectClass + for gray image when GRAYSCALE_USES_PALETTE is not defined. Fixes + oss-fuzz 7550 "graphicsmagick/coder_DCM_fuzzer: + Use-of-uninitialized-value in SyncImageCallBack". (Credit to + OSS-Fuzz) + (ReadDCMImage): Restore use of DCM_PostRescaleImage() in order to + obtain suitably scaled DICOM again. Hopefully it is more robust + now. + (DCM_ReadPaletteImage): Assure that DirectClass pixels are + initialized. + +2018-05-19 Bob Friesenhahn + + * coders/tiff.c (ReadTIFFImage): Remove strange addition of + image->columns to pixel buffer offsets which now causes a heap + overflow since the buffer has been right-sized. Perhaps the extra + offset plus the over-sized allocation was some attempt to avoid + buffer over/underflows due to bugs in libtiff. Fixes oss-fuzz 8384 + "graphicsmagick/coder_BIGTIFF_fuzzer: Heap-buffer-overflow in + put1bitbwtile" which is described to be a regression. (Credit to + OSS-Fuzz) + + * magick/render.c (DrawImage): Fix wrong range checks which caused + spurious "Parsing of SVG images fail with "Non-conforming drawing + primitive definition (push)" failure. Fixes SourceForge issue 561 + "Parsing of SVG images fail with "Non-conforming drawing primitive + definition (push)"" which is due to problems caused by the fix for + SourceForge issue 517. + + * coders/tiff.c (WritePTIFImage): Use '-define + ptif:minimum-geometry=' to specify the smallest + subresolution frame which is produced by the PTIF (Pyramid TIFF) + writer. + +2018-05-18 Bob Friesenhahn + + * coders/tiff.c (WritePTIFImage): Allow 1x1 input image to be + supported. + + * coders/png.c (ReadOneJNGImage): Unconditionally free JDAT chunk + memory. Fixes oss-fuzz 8366 "graphicsmagick/coder_JNG_fuzzer: + Direct-leak in ReadOneJNGImage". (Credit to OSS-Fuzz) + + * coders/tiff.c (WritePTIFImage): Fix leak of pyramid Image list + if ResizeImage() fails. Fixes oss-fuzz 8364 + "graphicsmagick/coder_PTIF_fuzzer: Indirect-leak in + CloneImage". (Credit to OSS-Fuzz) + +2018-05-17 Bob Friesenhahn + + * coders/tiff.c (WriteTIFFImage): Add and use + ThrowTIFFWriterException() macro to consistently clean-up when + throwing writer exception. May fix oss-fuzz 8321 + "graphicsmagick/coder_EPT_fuzzer: Direct-leak in + TIFFClientOpen". (Credit to OSS-Fuzz) + (ReadTIFFImage): Add and use ThrowTIFFReaderException() macro to + consistently clean-up when throwing reader exception. + +2018-05-16 Greg Wolfe + + * magick/alpha_composite.h (AlphaCompositePixel): The + macro definition for MagickAlphaCompositeQuantum in + alpha_composite.h computes an expression of the form: + + a * b + c * d * e + + Code in function AlphaCompositePixel() (also in + alpha_composite.h) multiplies the result of this macro + by variable "delta" as follows: + + delta * a * b + c * d * e + + However, the intended result is actually: + + delta * ( a * b + c * d * e ) + + The macro definition has been modified to enclose the + entire expression in parentheses. + + The effects of this bug were particularly evident at the + boundary between a stroked polygon and a transparent + black region. More generally, an incorrect composited + pixel value was being computed by AlphaCompositePixel() + whenever the output alpha value was not 100% opaque. + +2018-05-16 Bob Friesenhahn + + * tests/rwblob.tap: Add a test for PTIF format. + + * coders/tiff.c (WritePTIFImage): Fix Image blob referencing in + order to avoid double-free when writing PTIF to memory BLOB. Fixes + oss-fuzz 8280 "graphicsmagick/coder_PTIF_fuzzer: Heap-double-free + in Magick::BlobRef::~BlobRef". (Credit to OSS-Fuzz) + +2018-05-14 Bob Friesenhahn + + * coders/tiff.c (WriteTIFFImage): Use libtiff's + TIFFDefaultStripSize() function rather than an old porting macro + required by some defunct libtiff version. Expected to fix + oss-fuzz 8248 "graphicsmagick/coder_EPT_fuzzer: + Floating-point-exception in WriteTIFFImage". (Credit to OSS-Fuzz) + +2018-05-13 Fojtik Jaroslav + + * coders/mat.c Fix potentional leak when compressed object is + corrupted. Fixes oss-fuzz 8251 (Credit to OSS-Fuzz) + +2018-05-13 Bob Friesenhahn + + * coders/tiff.c (ReadTIFFImage): Fix leak of Image when + TIFFReadRGBAImage() reports failure. Also harden buffer + allocation calculation. Fixes oss-fuzz 8275 + "graphicsmagick/coder_BIGTIFF_fuzzer: Indirect-leak in + AllocateImage". (Credit to OSS-Fuzz) + + * coders/ept.c (ReadEPTImage): Add validations of 'count' and + 'filesize' read from EPT file. In response to oss-fuzz 8248 + "graphicsmagick/coder_EPT_fuzzer: Floating-point-exception in + WriteTIFFImage" but we are unable to recreate the oss-fuzz issue + since the EPT reader already immediately reports an EOF exception. + +2018-05-12 Bob Friesenhahn + + * fuzzing/oss-fuzz-build.sh: Apply SourceForge patch #57 "Add + fuzzing support for jpeg + freetype delegates" by Alex Gaynor. + + * coders/png.c (read_user_chunk_callback): Fix memory leak and use + of uninitialized memory when handling eXIf chunk. Fixes oss-fuzz + 8247 "graphicsmagick/coder_PNG24_fuzzer: Direct-leak in + png_malloc". (Credit to OSS-Fuzz) + +2018-05-11 Bob Friesenhahn + + * fuzzing/oss-fuzz-build.sh: Apply SourceForge patch #56 "Use a + few delegate libraries in fuzzing" by Alex Gaynor. + +2018-05-10 Bob Friesenhahn + + * tests/rwfile.tap: MIFF zip and bzip compression tests do not + fail if zlib and bzlib are not available because the compression + request is silently changed to no compression. +2018-05-07 Greg Wolfe + * magick/render.c (DrawImage, InsertAttributeIntoInputStream): + For a reference such as 'class="classname"', the "classname" + is now allowed to be undefined. + + * coders.svg.c (ProcessStyleClassDefs): Class definitions + defined within a . + */ + break; + } if (LocaleCompare((char *) name,"svg") == 0) { + svg_info->svgPushCount++; MVGPrintf(svg_info->file,"push graphic-context\n"); + /* + Per the SVG spec, initialize the MVG coder with the following + SVG defaults: + - svg-compliant: "1" (note: internal to GM, not an SVG element) + - fill color: "black" + - fill-opacity value: "1" + - stroke color: "none" + - stroke-width value: "1" + - stroke-opacity value: "1" + - fill-rule value: "nonzero" + */ + MVGPrintf(svg_info->file,"svg-compliant 1\n"); + MVGPrintf(svg_info->file,"fill 'black'\n"); + MVGPrintf(svg_info->file,"fill-opacity 1\n"); + MVGPrintf(svg_info->file,"stroke 'none'\n"); + MVGPrintf(svg_info->file,"stroke-width 1\n"); + MVGPrintf(svg_info->file,"stroke-opacity 1\n"); + MVGPrintf(svg_info->file,"fill-rule 'nonzero'\n"); break; } break; @@ -1122,34 +1547,33 @@ SVGStartElement(void *context,const xmlChar *name, { if (LocaleCompare((char *) name,"text") == 0) { + IsTextOrTSpan = MagickTrue; + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "push id" if warranted */ + MVGPrintf(svg_info->file,"push id '%s'\n",id); MVGPrintf(svg_info->file,"push graphic-context\n"); + /* update text current position */ + MVGPrintf(svg_info->file,"textx %g\n",svg_info->bounds.x); + MVGPrintf(svg_info->file,"texty %g\n",svg_info->bounds.y); break; } if (LocaleCompare((char *) name,"tspan") == 0) { + IsTextOrTSpan = MagickTrue; Strip(svg_info->text); if (*svg_info->text != '\0') { - DrawInfo - *draw_info; - - TypeMetric - metrics; - char *text; text=EscapeString(svg_info->text,'\''); - MVGPrintf(svg_info->file,"text %g,%g '%s'\n",svg_info->bounds.x, - svg_info->bounds.y,text); + MVGPrintf(svg_info->file,"textc '%s'\n",text); MagickFreeMemory(text); - draw_info=CloneDrawInfo(svg_info->image_info,(DrawInfo *) NULL); - draw_info->pointsize=svg_info->pointsize; - draw_info->text=AllocateString(svg_info->text); - (void) ConcatenateString(&draw_info->text," "); - (void) GetTypeMetrics(svg_info->image,draw_info,&metrics); - svg_info->bounds.x+=metrics.width; - DestroyDrawInfo(draw_info); + /* + The code that used to be here to compute the next text position has been eliminated. + The reason is that at this point in the code we may not know the font or font size + (they may be hidden in a "class" definition), so we can't really do that computation. + This functionality is now handled by DrawImage() in render.c. + */ *svg_info->text='\0'; } MVGPrintf(svg_info->file,"push graphic-context\n"); @@ -1157,6 +1581,17 @@ SVGStartElement(void *context,const xmlChar *name, } break; } + case 'U': + case 'u': + { + if (LocaleCompare((char *) name,"use") == 0) + { + /* "use" behaves like "g" */ + MVGPrintf(svg_info->file,"push graphic-context\n"); + break; + } + break; + } default: break; } @@ -1184,6 +1619,20 @@ SVGStartElement(void *context,const xmlChar *name, case 'C': case 'c': { + if (LocaleCompare(keyword,"class") == 0) + {/*"class=classname"*/ + char * pClassNames = (char * ) value; + do + { + (void) MagickGetToken(pClassNames,&pClassNames,token,MaxTextExtent); + if ( *token == ',' ) + (void) MagickGetToken(pClassNames,&pClassNames,token,MaxTextExtent); + if ( *token != '\0' ) + MVGPrintf(svg_info->file,"class '%s'\n",token); + } + while ( *token != '\0' ); + break; + }/*"class=classname"*/ if (LocaleCompare(keyword,"clip-path") == 0) { MVGPrintf(svg_info->file,"clip-path '%s'\n",value); @@ -1229,14 +1678,34 @@ SVGStartElement(void *context,const xmlChar *name, } if (LocaleCompare(keyword,"dx") == 0) { - svg_info->bounds.x+= - GetUserSpaceCoordinateValue(svg_info,1,value,MagickFalse); + double dx=GetUserSpaceCoordinateValue(svg_info,1,value,MagickFalse); + svg_info->bounds.x+=dx; /* preserve previous behavior */ + /* update text current position for text or tspan */ + if ( IsTextOrTSpan ) + { + char * pUnit; + (void) MagickGetToken(value,&pUnit,token,MaxTextExtent); + if ( *pUnit && ((LocaleNCompare(pUnit,"em",2) == 0) || (LocaleNCompare(pUnit,"ex",2) == 0)) ) + MVGPrintf(svg_info->file,"textdx %s\n",value); /* postpone interpretation of "em" or "ex" until we know point size */ + else + MVGPrintf(svg_info->file,"textdx %g\n",dx); + } break; } if (LocaleCompare(keyword,"dy") == 0) { - svg_info->bounds.y+= - GetUserSpaceCoordinateValue(svg_info,-1,value,MagickFalse); + double dy=GetUserSpaceCoordinateValue(svg_info,-1,value,MagickFalse); + svg_info->bounds.y+=dy; /* preserve previous behavior */ + /* update text current position for text or tspan */ + if ( IsTextOrTSpan ) + { + char * pUnit; + (void) MagickGetToken(value,&pUnit,token,MaxTextExtent); + if ( *pUnit && ((LocaleNCompare(pUnit,"em",2) == 0) || (LocaleNCompare(pUnit,"ex",2) == 0)) ) + MVGPrintf(svg_info->file,"textdy %s\n",value); /* postpone interpretation of "em" or "ex" until we know point size */ + else + MVGPrintf(svg_info->file,"textdy %g\n",dy); + } break; } break; @@ -1325,7 +1794,7 @@ SVGStartElement(void *context,const xmlChar *name, affine, current, transform; - + IdentityAffine(&transform); (void) LogMagickEvent(CoderEvent,GetMagickModule()," "); tokens=GetTransformTokens(context,value,&number_tokens); @@ -1382,7 +1851,7 @@ SVGStartElement(void *context,const xmlChar *name, { double angle; - + angle=GetUserSpaceCoordinateValue(svg_info,0,value,MagickFalse); affine.sx=cos(DegreesToRadians(fmod(angle,360.0))); affine.rx=sin(DegreesToRadians(fmod(angle,360.0))); @@ -1488,7 +1957,19 @@ SVGStartElement(void *context,const xmlChar *name, } if (LocaleCompare(keyword,"href") == 0) { - (void) CloneString(&svg_info->url,value); + /* process "#identifier" as if it were "url(#identifier)" */ + if ( value[0] == '#' ) + { + /* reallocate the needed memory once */ + size_t NewSize = strlen(value) + 6; /* 6 == url() */ + MagickReallocMemory(char *,svg_info->url,NewSize); + memcpy(svg_info->url,"url(",4); + strcpy(svg_info->url+4,value); + svg_info->url[NewSize-2] = ')'; + svg_info->url[NewSize-1] = '\0'; + } + else + (void) CloneString(&svg_info->url,value); break; } break; @@ -1502,6 +1983,11 @@ SVGStartElement(void *context,const xmlChar *name, GetUserSpaceCoordinateValue(svg_info,1,value,MagickFalse); break; } + if (LocaleCompare(keyword,"mask") == 0) /* added mask */ + { + MVGPrintf(svg_info->file,"mask '%s'\n",value); + break; + } if (LocaleCompare(keyword,"minor") == 0) { svg_info->element.minor= @@ -1555,13 +2041,29 @@ SVGStartElement(void *context,const xmlChar *name, { double angle; - + angle=GetUserSpaceCoordinateValue(svg_info,0,value,MagickFalse); - MVGPrintf(svg_info->file,"translate %g,%g\n",svg_info->bounds.x, - svg_info->bounds.y); - svg_info->bounds.x=0; - svg_info->bounds.y=0; - MVGPrintf(svg_info->file,"rotate %g\n",angle); + /* + When the current text position was managed in this code, and a "rotate" was encountered + (indicating that the text character was to be rotated), the code would emit to the MVG file: + + translate x y (where x, y indicate the current text position) + rotate angle (where angle indicates the rotation angle) + + Now that the current text position is being managed by DrawImage() in render.c, this code + cannot issue the "translate" because it can't know the current text position. To handle + this, "textr" (text rotation) has been implemented in DrawImage() to perform the appropriate + translation/rotation sequence. + */ + if ( IsTextOrTSpan ) + MVGPrintf(svg_info->file,"textr %g\n",angle); /* pre-translation will be handled in DrawImage() */ + else + { + MVGPrintf(svg_info->file,"translate %g,%g\n",svg_info->bounds.x,svg_info->bounds.y); + svg_info->bounds.x=0; + svg_info->bounds.y=0; + MVGPrintf(svg_info->file,"rotate %g\n",angle); + } break; } if (LocaleCompare(keyword,"rx") == 0) @@ -1634,7 +2136,7 @@ SVGStartElement(void *context,const xmlChar *name, if (LocaleCompare(keyword,"stroke-miterlimit") == 0) { double stroke_miterlimit; - if ((MagickAtoFChk(value,&stroke_miterlimit) != MagickPass) || + if ((MagickAtoFChk(value,&stroke_miterlimit) != MagickPass) || stroke_miterlimit < 1.0) { errno=0; @@ -1674,6 +2176,18 @@ SVGStartElement(void *context,const xmlChar *name, " %.1024s: %.1024s",keyword,value); switch (*keyword) { + case 'B': + case 'b': + { + if (LocaleCompare(keyword,"background") == 0) + { + /* only do this if background was specified inside 0)) - { - for (j=0; j < (number_tokens-1); j+=2) - { - keyword=(char *) tokens[j]; - value=(char *) tokens[j+1]; - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " %.1024s: %.1024s",keyword,value); - current=transform; - IdentityAffine(&affine); - switch (*keyword) - { - case 'M': - case 'm': - { - if (LocaleCompare(keyword,"matrix") == 0) - { - p=(char *) value; - (void) MagickGetToken(p,&p,token,MaxTextExtent); - affine.sx=MagickAtoF(value); - (void) MagickGetToken(p,&p,token,MaxTextExtent); - if (*token == ',') - (void) MagickGetToken(p,&p,token,MaxTextExtent); - affine.rx=MagickAtoF(token); - (void) MagickGetToken(p,&p,token,MaxTextExtent); - if (*token == ',') - (void) MagickGetToken(p,&p,token,MaxTextExtent); - affine.ry=MagickAtoF(token); - (void) MagickGetToken(p,&p,token,MaxTextExtent); - if (*token == ',') - (void) MagickGetToken(p,&p,token,MaxTextExtent); - affine.sy=MagickAtoF(token); - (void) MagickGetToken(p,&p,token,MaxTextExtent); - if (*token == ',') - (void) MagickGetToken(p,&p,token,MaxTextExtent); - affine.tx=MagickAtoF(token); - (void) MagickGetToken(p,&p,token,MaxTextExtent); - if (*token == ',') - (void) MagickGetToken(p,&p,token,MaxTextExtent); - affine.ty=MagickAtoF(token); - break; - } - break; - } - case 'R': - case 'r': - { - if (LocaleCompare(keyword,"rotate") == 0) - { - double - angle; - - angle=GetUserSpaceCoordinateValue(svg_info,0,value,MagickFalse); - affine.sx=cos(DegreesToRadians(fmod(angle,360.0))); - affine.rx=sin(DegreesToRadians(fmod(angle,360.0))); - affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0)))); - affine.sy=cos(DegreesToRadians(fmod(angle,360.0))); - break; - } - break; - } - case 'S': - case 's': - { - if (LocaleCompare(keyword,"scale") == 0) - { - for (p=(char *) value; *p != '\0'; p++) - if (isspace((int) (*p)) || (*p == ',')) - break; - affine.sx=GetUserSpaceCoordinateValue(svg_info,1,value,MagickFalse); - affine.sy=affine.sx; - if (*p != '\0') - affine.sy= - GetUserSpaceCoordinateValue(svg_info,-1,p+1,MagickFalse); - svg_info->scale[svg_info->n]=ExpandAffine(&affine); - break; - } - if (LocaleCompare(keyword,"skewX") == 0) - { - affine.sx=svg_info->affine.sx; - affine.ry=tan(DegreesToRadians(fmod( - GetUserSpaceCoordinateValue(svg_info,1,value,MagickFalse), - 360.0))); - affine.sy=svg_info->affine.sy; - break; - } - if (LocaleCompare(keyword,"skewY") == 0) - { - affine.sx=svg_info->affine.sx; - affine.rx=tan(DegreesToRadians(fmod( - GetUserSpaceCoordinateValue(svg_info,-1,value,MagickFalse), - 360.0))); - affine.sy=svg_info->affine.sy; - break; - } - break; - } - case 'T': - case 't': - { - if (LocaleCompare(keyword,"translate") == 0) - { - for (p=(char *) value; *p != '\0'; p++) - if (isspace((int) (*p)) || (*p == ',')) - break; - affine.tx=GetUserSpaceCoordinateValue(svg_info,1,value,MagickFalse); - affine.ty=affine.tx; - if (*p != '\0') - affine.ty= - GetUserSpaceCoordinateValue(svg_info,-1,p+1,MagickFalse); - break; - } - break; - } - default: - break; - } - transform.sx=current.sx*affine.sx+current.ry*affine.rx; - transform.rx=current.rx*affine.sx+current.sy*affine.rx; - transform.ry=current.sx*affine.ry+current.ry*affine.sy; - transform.sy=current.rx*affine.ry+current.sy*affine.sy; - transform.tx=current.sx*affine.tx+current.ry*affine.ty+ - current.tx; - transform.ty=current.rx*affine.tx+current.sy*affine.ty+ - current.ty; - } - MVGPrintf(svg_info->file,"affine %g %g %g %g %g %g\n", - transform.sx,transform.rx,transform.ry,transform.sy, - transform.tx,transform.ty); - } /* if ((tokens != (char **) NULL) && (number_tokens > 0)) */ - if (tokens != (char **) NULL) - { - for (j=0; tokens[j] != (char *) NULL; j++) - MagickFreeMemory(tokens[j]); - MagickFreeMemory(tokens); - } - break; - } - break; - } - case 'V': - case 'v': - { - if (LocaleCompare(keyword,"verts") == 0) - { - (void) CloneString(&svg_info->vertices,value); - break; - } - if (LocaleCompare(keyword,"viewBox") == 0) - { - p=(char *) value; - (void) MagickGetToken(p,&p,token,MaxTextExtent); - svg_info->view_box.x=MagickAtoF(token); - (void) MagickGetToken(p,&p,token,MaxTextExtent); - if (*token == ',') - (void) MagickGetToken(p,&p,token,MaxTextExtent); - svg_info->view_box.y=MagickAtoF(token); - (void) MagickGetToken(p,&p,token,MaxTextExtent); - if (*token == ',') - (void) MagickGetToken(p,&p,token,MaxTextExtent); - svg_info->view_box.width=MagickAtoF(token); - (void) MagickGetToken(p,&p,token,MaxTextExtent); - if (*token == ',') - (void) MagickGetToken(p,&p,token,MaxTextExtent); - svg_info->view_box.height=MagickAtoF(token); - if (svg_info->view_box.width < 0.0 || - svg_info->view_box.height < 0.0) + /* + The code that was here has been refactored into + function SVGProcessTransformString() + */ + SVGProcessTransformString(context,value); + break; + } + break; + } + case 'V': + case 'v': + { + if (LocaleCompare(keyword,"verts") == 0) + { + (void) CloneString(&svg_info->vertices,value); + break; + } + if (LocaleCompare(keyword,"viewBox") == 0) + { + p=(char *) value; + (void) MagickGetToken(p,&p,token,MaxTextExtent); + svg_info->view_box.x=MagickAtoF(token); + (void) MagickGetToken(p,&p,token,MaxTextExtent); + if (*token == ',') + (void) MagickGetToken(p,&p,token,MaxTextExtent); + svg_info->view_box.y=MagickAtoF(token); + (void) MagickGetToken(p,&p,token,MaxTextExtent); + if (*token == ',') + (void) MagickGetToken(p,&p,token,MaxTextExtent); + svg_info->view_box.width=MagickAtoF(token); + (void) MagickGetToken(p,&p,token,MaxTextExtent); + if (*token == ',') + (void) MagickGetToken(p,&p,token,MaxTextExtent); + svg_info->view_box.height=MagickAtoF(token); + if (svg_info->view_box.width < 0.0 || + svg_info->view_box.height < 0.0) { ThrowException(svg_info->exception,CorruptImageError, NegativeOrZeroImageSize, @@ -2137,11 +2515,26 @@ SVGStartElement(void *context,const xmlChar *name, if (LocaleCompare(keyword,"x") == 0) { svg_info->bounds.x=GetUserSpaceCoordinateValue(svg_info,1,value,MagickFalse); + /* update text current position for tspan (already did this if text) */ + if ( IsTSpan ) + MVGPrintf(svg_info->file,"textx %g\n",svg_info->bounds.x); break; } if (LocaleCompare(keyword,"xlink:href") == 0) { - (void) CloneString(&svg_info->url,value); + /* process "#identifier" as if it were "url(#identifier)" */ + if ( value[0] == '#' ) + { + /* reallocate the needed memory once */ + size_t NewSize = strlen(value) + 6; /* 6 == url() */ + MagickReallocMemory(char *,svg_info->url,NewSize); + memcpy(svg_info->url,"url(",4); + strcpy(svg_info->url+4,value); + svg_info->url[NewSize-2] = ')'; + svg_info->url[NewSize-1] = '\0'; + } + else + (void) CloneString(&svg_info->url,value); break; } if (LocaleCompare(keyword,"x1") == 0) @@ -2164,6 +2557,9 @@ SVGStartElement(void *context,const xmlChar *name, if (LocaleCompare(keyword,"y") == 0) { svg_info->bounds.y=GetUserSpaceCoordinateValue(svg_info,-1,value,MagickFalse); + /* update text current position for tspan (already did this if text) */ + if ( IsTSpan ) + MVGPrintf(svg_info->file,"texty %g\n",svg_info->bounds.y); break; } if (LocaleCompare(keyword,"y1") == 0) @@ -2197,7 +2593,7 @@ SVGStartElement(void *context,const xmlChar *name, double sx, sy; - + if ((svg_info->view_box.width == 0.0) || (svg_info->view_box.height == 0.0)) svg_info->view_box=svg_info->bounds; @@ -2211,10 +2607,10 @@ SVGStartElement(void *context,const xmlChar *name, { char tuple[MaxTextExtent]; - + GetColorTuple(&svg_info->image_info->background_color,8,True,True, tuple); - + MVGPrintf(svg_info->file,"push graphic-context\n"); MVGPrintf(svg_info->file,"fill %s\n", tuple); MVGPrintf(svg_info->file,"rectangle 0,0 %g,%g\n", @@ -2236,16 +2632,15 @@ SVGStartElement(void *context,const xmlChar *name, if (attributes != (const xmlChar **) NULL) { char - *geometry, - *p; - + *geometry; + RectangleInfo page; - + double sx, sy; - + if (svg_info->bounds.width < 0.0 || svg_info->bounds.height < 0.0) { ThrowException(svg_info->exception,CorruptImageError, @@ -2278,38 +2673,465 @@ SVGStartElement(void *context,const xmlChar *name, geometry=GetPageGeometry(svg_info->size); if (geometry != (char *) NULL) { - p=strchr(geometry,'>'); - if (p != (char *) NULL) - *p='\0'; + /* + A terminating '>' in a geometry string is interpreted to mean that + the dimensions of an image should only be changed if its width or + height exceeds the geometry specification. For an unapparent and + undocumented reason, a terminating '>', if present, was being nulled + out, making this feature unusable for SVG files (now fixed). + */ (void) GetMagickGeometry(geometry,&page.x,&page.y, &page.width,&page.height); MagickFreeMemory(geometry); } - if (svg_info->affine.sx != 1.0) - page.width=(unsigned long) - ceil(ExpandAffine(&svg_info->affine)*page.width-0.5); - if (svg_info->affine.sy != 0.0) - page.height=(unsigned long) - ceil(ExpandAffine(&svg_info->affine)*page.height-0.5); + /* NOTE: the scale factor returned by ExpandAffine() has already been applied + to page.width and page.height + */ (void) MVGPrintf(svg_info->file,"viewbox 0 0 %g %g\n", svg_info->view_box.width,svg_info->view_box.height); sx=(double) page.width/svg_info->view_box.width; sy=(double) page.height/svg_info->view_box.height; MVGPrintf(svg_info->file,"affine %g 0 0 %g %g %g\n",sx,sy, -sx*svg_info->view_box.x,-sy*svg_info->view_box.y); - svg_info->width=page.width; - svg_info->height=page.height; + /* only set the output width and height if this is the outermost */ + if ( svg_info->svgPushCount == 1 ) + {/*outermost */ + svg_info->width=page.width; + svg_info->height=page.height; + /* check if background color was specified using file,"push graphic-context\n"); + MVGPrintf(svg_info->file,"fill %s\n",svg_element_background_color); + MVGPrintf(svg_info->file,"rectangle 0,0 %g,%g\n",svg_info->view_box.width,svg_info->view_box.height); + MVGPrintf(svg_info->file,"pop graphic-context\n"); + } + }/*outermost */ } } #endif /* Error dispatch point */ svg_start_element_error:; - + (void) LogMagickEvent(CoderEvent,GetMagickModule()," )"); MagickFreeMemory(units); MagickFreeMemory(color); } +/* Process the "class" definitions inside */ +static +void ProcessStyleClassDefs ( + SVGInfo * svg_info + ) +{/*ProcessStyleClassDefs*/ + + /* + Style defs look like: + + .class1,.class2,.class3{kwd:val;kwd:val;} + + Class name (e.g., ".class1"} can show up multiple times + */ + + /* keyword/value pair for an element */ + typedef struct ElementValue + {/*ElementValue*/ + struct ElementValue * pNext; /* next in list */ + char * pKeyword; + char * pValue; + }/*ElementValue*/ + ElementValue; + + /* the keyword/value pair list associated with a class */ + typedef struct ClassDef + {/*ClassDef*/ + struct ClassDef * pNext; /* next in list */ + struct ClassDef * pActiveNext; /* next in active list */ + char * pName; /* class name */ + ElementValue ElementValueHead; /* list head for style element/value pairs */ + ElementValue * pElementValueLast; + }/*ClassDef*/ + ClassDef; + + ClassDef ClassDefHead; /* list head for classes */ + ClassDef * pClassDefLast = &ClassDefHead; /* tail ptr for class def list */ + ClassDef ClassDefActiveHead; /* list head for "active" class defs */ + ClassDef * pClassDefActiveLast = &ClassDefActiveHead; /* tail ptr for "active" class def list */ + ClassDef * pClassDef; + char * pCopyOfText; + char * pString; + char * cp,*cp2; + int c; + + memset(&ClassDefHead,0,sizeof(ClassDefHead)); + memset(&ClassDefActiveHead,0,sizeof(ClassDefActiveHead)); + + /* a macro to allocate an zero out a new struct instance, + and add it to the end of a linked list */ + #define ADD_NEW_STRUCT(pNew,pLast,TheTypeDef) \ + pNew = MagickAllocateMemory(TheTypeDef *,sizeof(TheTypeDef)); \ + memset(pNew,0,sizeof(TheTypeDef)); \ + pLast = pLast->pNext = pNew + + /* we will get a modifiable value of the string, and delimit + substrings by storing null characters */ + pCopyOfText = AcquireString(svg_info->text); + for ( pString = pCopyOfText; *pString; ) + {/*pString loop*/ + char * pClassNameList; + char * pStyleElementList; + + while ( (c = *pString) && isspace(c) ) pString++; /* skip white space */ + if ( !*pString ) break; /* found end of string; done */ + pClassNameList = pString; + + /* find the end of the comma-separated list of class names */ + while ( (c = *pString) && (c != '{') ) pString++; + if ( !*pString ) + { + /* malformed input: class name list not followed by '{' */ + MagickFreeMemory(pCopyOfText); + return; + } + *pString++ = '\0'; + pStyleElementList = pString; + + /* extract the class names */ + ClassDefActiveHead.pActiveNext = 0; + pClassDefActiveLast = &ClassDefActiveHead; /* initially, no active class defs */ + for ( cp = pClassNameList; *cp; ) + {/*extract class name loop*/ + + while ( (c = *cp) && (isspace(c) || (c ==',')) ) cp++; /* skip white space/commas */ + if ( *cp == '.' ) cp++; /* .classname, skip leading period */ + if ( *cp ) + {/*found class name*/ + + char * pClassName = cp; + while ( (c = *cp) && !(isspace(c) || (c == ',')) ) cp++; /* find white space/comma/null */ + if ( *cp ) + *cp++ = '\0'; /* terminate identifier string and increment */ + /* add uniquely to list */ + for ( pClassDef = ClassDefHead.pNext; + pClassDef && (strcmp(pClassName,pClassDef->pName) != 0); + pClassDef = pClassDef->pNext ); + if ( pClassDef == 0 ) + {/*new class name*/ + ADD_NEW_STRUCT(pClassDef,pClassDefLast,ClassDef); + pClassDef->pElementValueLast = &pClassDef->ElementValueHead; + pClassDef->pName = pClassName; + }/*new class name*/ + pClassDefActiveLast = pClassDefActiveLast->pActiveNext = pClassDef; /* add to active list */ + + }/*found class name*/ + + }/*extract class name loop*/ + + /* find the end of the style elements */ + while ( (c = *pString) && (c != '}') ) pString++; + if ( !*pString ) + { + /* malformed input: style elements not terminated by '{' */ + MagickFreeMemory(pCopyOfText); + return; + } + *pString++ = '\0'; /* advance past '}' for next loop pass */ + + /* get the style elements */ + for ( cp = pStyleElementList; *cp; ) + {/*extract style elements loop*/ + + /* looking for : */ + while ( (c = *cp) && isspace(c) ) cp++; /* skip white space */ + if ( *cp ) + {/*found style element*/ + + char * pStyleElement = cp; + while ( (c = *cp) && (c != ':') ) cp++; /* find colon/null */ + for ( cp2 = cp-1; isspace(*cp2); *cp2-- = '\0'); /* trim white space */ + if ( *cp ) + *cp++ = '\0'; /* terminate style element string and increment */ + + /* looking for ; */ + while ( (c = *cp) && isspace(c) ) cp++; /* skip white space */ + if ( *cp ) + {/*found style element value*/ + + char * pStyleValue = cp; + while ( (c = *cp) && (c != ';') ) cp++; /* find semi-colon/null */ + for ( cp2 = cp-1; isspace(*cp2); *cp2-- = '\0'); /* trim white space */ + if ( *cp ) + *cp++ = '\0'; /* terminate style value string and increment */ + + /* add style element/value pair to each active class def */ + for ( pClassDef = ClassDefActiveHead.pActiveNext; pClassDef; pClassDef = pClassDef->pActiveNext ) + { + ElementValue * pEV; + ADD_NEW_STRUCT(pEV,pClassDef->pElementValueLast,ElementValue); + pEV->pKeyword = pStyleElement; + pEV->pValue = pStyleValue; + } + + }/*found style element value*/ + + }/*found style element*/ + + }/*extract style elements loop*/ + + }/*pString loop*/ + + /* emit class definitions */ + for ( pClassDef = ClassDefHead.pNext; pClassDef; pClassDef = pClassDef->pNext ) + {/*pClassDef loop*/ + + ElementValue * pEV; + MVGPrintf(svg_info->file,"push class '%s'\n",pClassDef->pName); + /* NOTE: we allow class definitions that are empty */ + for ( pEV = pClassDef->ElementValueHead.pNext; pEV; pEV = pEV->pNext ) + {/*pEV loop*/ + + char * keyword = pEV->pKeyword; + char * value = pEV->pValue; + /* switch below was copied/pasted from elsewhere and modified */ + switch (*keyword) + {/*keyword*/ + + case 'C': + case 'c': + {/*Cc*/ + if (LocaleCompare(keyword,"clip-path") == 0) + { + MVGPrintf(svg_info->file,"clip-path '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"clip-rule") == 0) + { + MVGPrintf(svg_info->file,"clip-rule '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"clipPathUnits") == 0) + { + MVGPrintf(svg_info->file,"clip-units '%s'\n",value); + break; + } + break; + }/*Cc*/ + + case 'F': + case 'f': + {/*Ff*/ + if ( (LocaleCompare(keyword,"fill") == 0) || (LocaleCompare(keyword,"fillcolor") == 0) ) + { + MVGPrintf(svg_info->file,"fill '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"fill-rule") == 0) + { + MVGPrintf(svg_info->file,"fill-rule '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"fill-opacity") == 0) + { + MVGPrintf(svg_info->file,"fill-opacity '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"font-family") == 0) + { + /* + Deal with Adobe Illustrator 10.0 which double-quotes + font-family. Maybe we need a generalized solution for + this. + */ + size_t n; + if ( (value[0] == '\'') && (value[(n = (strlen(value)-1))] == '\'') ) + { + size_t i; + FILE * fp = svg_info->file; + MVGPrintf(fp,"font-family '"); + for(i = 1; i < n; i++) + fputc(value[i],fp); + MVGPrintf(fp,"'\n"); + } + else + MVGPrintf(svg_info->file,"font-family '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"font-stretch") == 0) + { + MVGPrintf(svg_info->file,"font-stretch '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"font-style") == 0) + { + MVGPrintf(svg_info->file,"font-style '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"font-size") == 0) + { + if (LocaleCompare(value,"medium") == 0) + svg_info->pointsize = 12; + else + svg_info->pointsize = GetUserSpaceCoordinateValue(svg_info,0,value,MagickTrue); + MVGPrintf(svg_info->file,"font-size %g\n",svg_info->pointsize); + break; + } + if (LocaleCompare(keyword,"font-weight") == 0) + { + MVGPrintf(svg_info->file,"font-weight '%s'\n",value); + break; + } + break; + }/*Ff*/ + + case 'O': + case 'o': + {/*Oo*/ + if (LocaleCompare(keyword,"offset") == 0) + { + MVGPrintf(svg_info->file,"offset %g\n",GetUserSpaceCoordinateValue(svg_info,1,value,MagickFalse)); + break; + } + if (LocaleCompare(keyword,"opacity") == 0) + { + MVGPrintf(svg_info->file,"opacity '%s'\n",value); + break; + } + break; + }/*Oo*/ + + case 'S': + case 's': + {/*Ss*/ + if (LocaleCompare(keyword,"stop-color") == 0) + { + (void) CloneString(&svg_info->stop_color,value); + break; + } + if (LocaleCompare(keyword,"stroke") == 0) + { + MVGPrintf(svg_info->file,"stroke '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"stroke-antialiasing") == 0) + { + MVGPrintf(svg_info->file,"stroke-antialias %d\n",LocaleCompare(value,"true") == 0); + break; + } + if (LocaleCompare(keyword,"stroke-dasharray") == 0) + { + MVGPrintf(svg_info->file,"stroke-dasharray %s\n",value); + break; + } + if (LocaleCompare(keyword,"stroke-dashoffset") == 0) + { + double dashoffset=GetUserSpaceCoordinateValue(svg_info,1,value,MagickFalse); + MVGPrintf(svg_info->file,"stroke-dashoffset %g\n",dashoffset); + break; + } + if (LocaleCompare(keyword,"stroke-linecap") == 0) + { + MVGPrintf(svg_info->file,"stroke-linecap '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"stroke-linejoin") == 0) + { + MVGPrintf(svg_info->file,"stroke-linejoin '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"stroke-miterlimit") == 0) + { + double stroke_miterlimit; + if ((MagickAtoFChk(value,&stroke_miterlimit) != MagickPass) || stroke_miterlimit < 1.0) + { + errno=0; + ThrowException(svg_info->exception,DrawError,InvalidPrimitiveArgument,value); + break; + } + MVGPrintf(svg_info->file,"stroke-miterlimit '%ld'\n",(long) stroke_miterlimit); + break; + } + if (LocaleCompare(keyword,"stroke-opacity") == 0) + { + MVGPrintf(svg_info->file,"stroke-opacity '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"stroke-width") == 0) + { + MVGPrintf(svg_info->file,"stroke-width %g\n",GetUserSpaceCoordinateValue(svg_info,1,value,MagickTrue)); + break; + } + break; + }/*Ss*/ + + case 'T': + case 't': + {/*Tt*/ + if (LocaleCompare(keyword,"text-align") == 0) + { + MVGPrintf(svg_info->file,"text-align '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"text-anchor") == 0) + { + MVGPrintf(svg_info->file,"text-anchor '%s'\n",value); + break; + } + if (LocaleCompare(keyword,"text-decoration") == 0) + { + if (LocaleCompare(value,"underline") == 0) + MVGPrintf(svg_info->file,"decorate underline\n"); + if (LocaleCompare(value,"line-through") == 0) + MVGPrintf(svg_info->file,"decorate line-through\n"); + if (LocaleCompare(value,"overline") == 0) + MVGPrintf(svg_info->file,"decorate overline\n"); + break; + } + if (LocaleCompare(keyword,"text-antialiasing") == 0) + { + MVGPrintf(svg_info->file,"text-antialias %d\n",LocaleCompare(value,"true") == 0); + break; + } + if (LocaleCompare(keyword,"transform") == 0) + {/*style="transform: ...*/ + SVGProcessTransformString((void *)svg_info,value); + break; + }/*style="transform: ...*/ + break; + }/*Tt*/ + + default: + break; + + }/*keyword*/ + + }/*pEV loop*/ + + MVGPrintf(svg_info->file,"pop class\n"); + + }/*pClassDef loop*/ + + /* clean up */ + { + ClassDef * pClassDef; + for(pClassDef = ClassDefHead.pNext; pClassDef; ) + { + ElementValue *pEV; + ClassDef * pClassDefTemp = pClassDef; + for(pEV = pClassDef->ElementValueHead.pNext; pEV; ) + { + ElementValue * pEVTemp = pEV; + pEV = pEV->pNext; + MagickFreeMemory(pEVTemp); + } + pClassDef = pClassDef->pNext; + MagickFreeMemory(pClassDefTemp); + } + } + MagickFreeMemory(pCopyOfText); + +#undef ADD_NEW_STRUCT +}/*ProcessStyleClassDefs*/ + static void SVGEndElement(void *context,const xmlChar *name) { @@ -2341,6 +3163,11 @@ SVGEndElement(void *context,const xmlChar *name) svg_info->element.cy,svg_info->element.cx,svg_info->element.cy+ svg_info->element.minor); MVGPrintf(svg_info->file,"pop graphic-context\n"); + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "pop id" if warranted */ + { + svg_info->idLevelInsideDefs = 0; + MVGPrintf(svg_info->file,"pop id\n"); + } break; } if (LocaleCompare((char *) name,"clipPath") == 0) @@ -2355,6 +3182,7 @@ SVGEndElement(void *context,const xmlChar *name) { if (LocaleCompare((char *) name,"defs") == 0) { + svg_info->defsPushCount--; MVGPrintf(svg_info->file,"pop defs\n"); break; } @@ -2362,7 +3190,7 @@ SVGEndElement(void *context,const xmlChar *name) { register char *p; - + Strip(svg_info->text); if (*svg_info->text == '\0') break; @@ -2386,13 +3214,34 @@ SVGEndElement(void *context,const xmlChar *name) { double angle; - + angle=svg_info->element.angle; MVGPrintf(svg_info->file,"ellipse %g,%g %g,%g 0,360\n", svg_info->element.cx,svg_info->element.cy, angle == 0.0 ? svg_info->element.major : svg_info->element.minor, angle == 0.0 ? svg_info->element.minor : svg_info->element.major); MVGPrintf(svg_info->file,"pop graphic-context\n"); + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "pop id" if warranted */ + { + svg_info->idLevelInsideDefs = 0; + MVGPrintf(svg_info->file,"pop id\n"); + } + break; + } + break; + } + case 'F': + case 'f': + { + /* + For now we are ignoring "foreignObject". However, we do a push/pop + graphic-context so that any settings (e.g., fill) are consumed and + discarded. Otherwise they might persist and "leak" into the graphic + elements that follow. + */ + if (LocaleCompare((char *) name,"foreignObject") == 0) + { + MVGPrintf(svg_info->file,"pop graphic-context\n"); break; } break; @@ -2403,6 +3252,11 @@ SVGEndElement(void *context,const xmlChar *name) if (LocaleCompare((char *) name,"g") == 0) { MVGPrintf(svg_info->file,"pop graphic-context\n"); + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "pop id" if warranted */ + { + svg_info->idLevelInsideDefs = 0; + MVGPrintf(svg_info->file,"pop id\n"); + } break; } break; @@ -2428,6 +3282,11 @@ SVGEndElement(void *context,const xmlChar *name) MVGPrintf(svg_info->file,"line %g,%g %g,%g\n",svg_info->segment.x1, svg_info->segment.y1,svg_info->segment.x2,svg_info->segment.y2); MVGPrintf(svg_info->file,"pop graphic-context\n"); + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "pop id" if warranted */ + { + svg_info->idLevelInsideDefs = 0; + MVGPrintf(svg_info->file,"pop id\n"); + } break; } if (LocaleCompare((char *) name,"linearGradient") == 0) @@ -2437,6 +3296,16 @@ SVGEndElement(void *context,const xmlChar *name) } break; } + case 'M': + case 'm': + { + if (LocaleCompare((char *) name,"mask") == 0) /* added mask */ + { + MVGPrintf(svg_info->file,"pop mask\n"); + break; + } + break; + } case 'P': case 'p': { @@ -2449,18 +3318,33 @@ SVGEndElement(void *context,const xmlChar *name) { MVGPrintf(svg_info->file,"path '%s'\n",svg_info->vertices); MVGPrintf(svg_info->file,"pop graphic-context\n"); + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "pop id" if warranted */ + { + svg_info->idLevelInsideDefs = 0; + MVGPrintf(svg_info->file,"pop id\n"); + } break; } if (LocaleCompare((char *) name,"polygon") == 0) { MVGPrintf(svg_info->file,"polygon %s\n",svg_info->vertices); MVGPrintf(svg_info->file,"pop graphic-context\n"); + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "pop id" if warranted */ + { + svg_info->idLevelInsideDefs = 0; + MVGPrintf(svg_info->file,"pop id\n"); + } break; } if (LocaleCompare((char *) name,"polyline") == 0) { MVGPrintf(svg_info->file,"polyline %s\n",svg_info->vertices); MVGPrintf(svg_info->file,"pop graphic-context\n"); + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "pop id" if warranted */ + { + svg_info->idLevelInsideDefs = 0; + MVGPrintf(svg_info->file,"pop id\n"); + } break; } break; @@ -2482,6 +3366,11 @@ SVGEndElement(void *context,const xmlChar *name) svg_info->bounds.x+svg_info->bounds.width, svg_info->bounds.y+svg_info->bounds.height); MVGPrintf(svg_info->file,"pop graphic-context\n"); + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "pop id" if warranted */ + { + svg_info->idLevelInsideDefs = 0; + MVGPrintf(svg_info->file,"pop id\n"); + } break; } if (svg_info->radius.x == 0.0) @@ -2495,6 +3384,11 @@ SVGEndElement(void *context,const xmlChar *name) svg_info->radius.x=0.0; svg_info->radius.y=0.0; MVGPrintf(svg_info->file,"pop graphic-context\n"); + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "pop id" if warranted */ + { + svg_info->idLevelInsideDefs = 0; + MVGPrintf(svg_info->file,"pop id\n"); + } break; } break; @@ -2508,8 +3402,16 @@ SVGEndElement(void *context,const xmlChar *name) svg_info->offset); break; } + /* element "style" inside */ + if (LocaleCompare((char *) name,"style") == 0) + { + /* the style definitions are in svg_info->text */ + ProcessStyleClassDefs(svg_info); + break; + } if (LocaleCompare((char *) name,"svg") == 0) { + svg_info->svgPushCount--; MVGPrintf(svg_info->file,"pop graphic-context\n"); break; } @@ -2527,12 +3429,16 @@ SVGEndElement(void *context,const xmlChar *name) *text; text=EscapeString(svg_info->text,'\''); - MVGPrintf(svg_info->file,"text %g,%g '%s'\n",svg_info->bounds.x, - svg_info->bounds.y,text); + MVGPrintf(svg_info->file,"textc '%s'\n",text); /* write text at current position */ MagickFreeMemory(text); *svg_info->text='\0'; } MVGPrintf(svg_info->file,"pop graphic-context\n"); + if ( svg_info->idLevelInsideDefs == svg_info->n ) /* emit a "pop id" if warranted */ + { + svg_info->idLevelInsideDefs = 0; + MVGPrintf(svg_info->file,"pop id\n"); + } break; } if (LocaleCompare((char *) name,"tspan") == 0) @@ -2540,26 +3446,18 @@ SVGEndElement(void *context,const xmlChar *name) Strip(svg_info->text); if (*svg_info->text != '\0') { - DrawInfo - *draw_info; - - TypeMetric - metrics; - char *text; text=EscapeString(svg_info->text,'\''); - MVGPrintf(svg_info->file,"text %g,%g '%s'\n",svg_info->bounds.x, - svg_info->bounds.y,text); + MVGPrintf(svg_info->file,"textc '%s'\n",text); /* write text at current position */ MagickFreeMemory(text); - draw_info=CloneDrawInfo(svg_info->image_info,(DrawInfo *) NULL); - draw_info->pointsize=svg_info->pointsize; - draw_info->text=AllocateString(svg_info->text); - (void) ConcatenateString(&draw_info->text," "); - (void) GetTypeMetrics(svg_info->image,draw_info,&metrics); - svg_info->bounds.x+=metrics.width; - DestroyDrawInfo(draw_info); + /* + The code that used to be here to compute the next text position has been eliminated. + The reason is that at this point in the code we may not know the font or font size + (they may be hidden in a "class" definition), so we can't really do that computation. + This functionality is now handled by DrawImage() in render.c. + */ *svg_info->text='\0'; } MVGPrintf(svg_info->file,"pop graphic-context\n"); @@ -2576,6 +3474,34 @@ SVGEndElement(void *context,const xmlChar *name) } break; } + case 'U': + case 'u': + { + if (LocaleCompare((char *) name,"use") == 0) + { + /* + If the "use" had a "transform" attribute it has already been output to the MVG file. + + According to the SVG spec for "use": + + In the generated content, the 'use' will be replaced by 'g', where all attributes + from the 'use' element except for 'x', 'y', 'width', 'height' and 'xlink:href' are + transferred to the generated 'g' element. An additional transformation translate(x,y) + is appended to the end (i.e., right-side) of the 'transform' attribute on the generated + 'g', where x and y represent the values of the 'x' and 'y' attributes on the 'use' + element. The referenced object and its contents are deep-cloned into the generated tree. + */ + if ( (svg_info->bounds.x != 0.0) || (svg_info->bounds.y != 0.0) ) + MVGPrintf(svg_info->file,"translate %g,%g\n",svg_info->bounds.x,svg_info->bounds.y); + + /* NOTE: not implementing "width" and "height" for now */ + + MVGPrintf(svg_info->file,"use '%s'\n",svg_info->url); + MVGPrintf(svg_info->file,"pop graphic-context\n"); + break; + } + break; + } default: break; } @@ -2693,6 +3619,9 @@ SVGComment(void *context,const xmlChar *value) } static void +SVGWarning(void *context,const char *format,...) MAGICK_ATTRIBUTE((__format__ (__printf__,2,3))); + +static void SVGWarning(void *context,const char *format,...) { char @@ -2722,6 +3651,9 @@ SVGWarning(void *context,const char *format,...) } static void +SVGError(void *context,const char *format,...) MAGICK_ATTRIBUTE((__format__ (__printf__,2,3))); + +static void SVGError(void *context,const char *format,...) { char @@ -2881,6 +3813,24 @@ ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception) assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AllocateImage(image_info); + /* + If there is a geometry string in image_info->size (e.g., gm convert + -size "50x50%" in.svg out.png), AllocateImage() sets image->columns + and image->rows to the width and height values from the size string. + However, this makes no sense if the size string was something like + "50x50%" (we'll get columns = rows = 50). So we set columns and + rows to 0 here, which is the same as if no size string was supplied + by the client. This also results in svg_info.bounds to be set to + 0,0 below (i.e., unknown), so that svg_info.bounds will be set using + the image size information from either the svg "canvas" width/height + or from the viewbox. Later, variable "page" is set from + svg_info->bounds. Then the geometry string in image_info->size gets + applied to the (now known) "page" width and height when + SvgStartElement() calls GetMagickGeometry(), and the intended result + is obtained. + */ + image->columns = 0; + image->rows = 0; status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == False) ThrowReaderException(FileOpenError,UnableToOpenFile,image); @@ -2916,6 +3866,9 @@ ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception) svg_info.scale[0]=ExpandAffine(&svg_info.affine); svg_info.bounds.width=image->columns; svg_info.bounds.height=image->rows; + svg_info.defsPushCount = 0; + svg_info.idLevelInsideDefs = 0; + svg_info.svgPushCount = 0; if (image_info->size != (char *) NULL) (void) CloneString(&svg_info.size,image_info->size); (void) LogMagickEvent(CoderEvent,GetMagickModule(),"begin SAX"); diff --git a/coders/tga.c b/coders/tga.c index 73062b2..8f839b6 100644 --- a/coders/tga.c +++ b/coders/tga.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2015 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -240,7 +240,7 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "ImageType=%s CMapType=%u CMapStart=%u CMapLength=%u CMapDepth=%u\n" - " XOffset=%u YOffset=%u Width=%u Height=%u PixelDepth=%u Attributes=0x%.2x", + " XOffset=%u YOffset=%u Width=%u Height=%u PixelDepth=%u Attributes=0x%.2x", ((tga_info.image_type == TGAColormap) ? "Colormapped" : (tga_info.image_type == TGARGB) ? "TrueColor" : (tga_info.image_type == TGAMonochrome) ? "Monochrome" : @@ -296,8 +296,15 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) (tga_info.image_type == TGARLEColormap) || (tga_info.image_type == TGARLEMonochrome)) { - (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Setting PseudoClass"); - image->storage_class=PseudoClass; + if ((tga_info.bits_per_pixel == 1) || (tga_info.bits_per_pixel == 8)) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Setting PseudoClass"); + image->storage_class=PseudoClass; + } + else + { + ThrowReaderException(CoderError,DataStorageTypeIsNotSupported,image); + } } if ((tga_info.image_type == TGARLEColormap) || @@ -335,13 +342,14 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) ((image->storage_class == DirectClass) ? "DirectClass" : "PseduoClass"), MagickBoolToString(image->matte), image->depth, MagickBoolToString(is_grayscale)); - + if (tga_info.id_length != 0) { /* TGA image comment. */ - assert((size_t) (tga_info.id_length+1) == commentsize); + if ((size_t) (tga_info.id_length+1) != commentsize) + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); if (ReadBlob(image,tga_info.id_length,commentbuffer) != tga_info.id_length) ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); commentbuffer[tga_info.id_length]='\0'; @@ -379,10 +387,10 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) packet; if (ReadBlob(image, 2, readbuffer) != 2) - ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); - readbufferpos = 0; - packet = ReadBlobByteFromBuffer(readbuffer, &readbufferpos); - packet |= (((unsigned int) ReadBlobByteFromBuffer(readbuffer, &readbufferpos)) << 8); + ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); + readbufferpos = 0; + packet = ReadBlobByteFromBuffer(readbuffer, &readbufferpos); + packet |= (((unsigned int) ReadBlobByteFromBuffer(readbuffer, &readbufferpos)) << 8); pixel.red=(packet >> 10) & 0x1f; pixel.red=ScaleCharToQuantum(ScaleColor5to8(pixel.red)); @@ -399,11 +407,11 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) 8 bits each of blue, green and red. */ if (ReadBlob(image, 3, readbuffer) != 3) - ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); - readbufferpos = 0; - pixel.blue=ScaleCharToQuantum(ReadBlobByteFromBuffer(readbuffer, &readbufferpos)); - pixel.green=ScaleCharToQuantum(ReadBlobByteFromBuffer(readbuffer, &readbufferpos)); - pixel.red=ScaleCharToQuantum(ReadBlobByteFromBuffer(readbuffer, &readbufferpos)); + ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); + readbufferpos = 0; + pixel.blue=ScaleCharToQuantum(ReadBlobByteFromBuffer(readbuffer, &readbufferpos)); + pixel.green=ScaleCharToQuantum(ReadBlobByteFromBuffer(readbuffer, &readbufferpos)); + pixel.red=ScaleCharToQuantum(ReadBlobByteFromBuffer(readbuffer, &readbufferpos)); break; } } @@ -494,13 +502,13 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) packet; if (ReadBlob(image, 2, readbuffer) != 2) - { - status=MagickFail; - break; - } - readbufferpos = 0; - packet = ReadBlobByteFromBuffer(readbuffer, &readbufferpos); - packet |= (((unsigned int) ReadBlobByteFromBuffer(readbuffer, &readbufferpos)) << 8); + { + status=MagickFail; + break; + } + readbufferpos = 0; + packet = ReadBlobByteFromBuffer(readbuffer, &readbufferpos); + packet |= (((unsigned int) ReadBlobByteFromBuffer(readbuffer, &readbufferpos)) << 8); pixel.red=(packet >> 10) & 0x1f; pixel.red=ScaleCharToQuantum(ScaleColor5to8(pixel.red)); @@ -515,7 +523,7 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) else pixel.opacity=TransparentOpacity; } - + if (image->storage_class == PseudoClass) { index=(IndexPacket) (packet & 0x7fff); @@ -528,10 +536,10 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) 8 bits each of blue green and red. */ if (ReadBlob(image, 3, readbuffer) != 3) - { - status=MagickFail; - break; - } + { + status=MagickFail; + break; + } readbufferpos = 0; pixel.blue=ScaleCharToQuantum(ReadBlobByteFromBuffer(readbuffer, &readbufferpos)); pixel.green=ScaleCharToQuantum(ReadBlobByteFromBuffer(readbuffer, &readbufferpos)); @@ -543,10 +551,10 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) 8 bits each of blue green and red. */ if (ReadBlob(image, 4, readbuffer) != 4) - { - status=MagickFail; - break; - } + { + status=MagickFail; + break; + } readbufferpos = 0; pixel.blue=ScaleCharToQuantum(ReadBlobByteFromBuffer(readbuffer, &readbufferpos)); pixel.green=ScaleCharToQuantum(ReadBlobByteFromBuffer(readbuffer, &readbufferpos)); @@ -588,7 +596,7 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception, LoadImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } if (EOFBlob(image)) @@ -606,18 +614,18 @@ static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception) status=MagickFalse; if (ReadBlob(image, 3, readbuffer) == 3) - { - readbufferpos = 0; - tga_info.id_length=(unsigned char)ReadBlobByteFromBuffer(readbuffer, &readbufferpos); - tga_info.colormap_type=(unsigned char)ReadBlobByteFromBuffer(readbuffer, &readbufferpos); - tga_info.image_type=(unsigned char)ReadBlobByteFromBuffer(readbuffer, &readbufferpos); - status=((tga_info.image_type == TGAColormap) || - (tga_info.image_type == TGARGB) || - (tga_info.image_type == TGAMonochrome) || - (tga_info.image_type == TGARLEColormap) || - (tga_info.image_type == TGARLERGB) || - (tga_info.image_type == TGARLEMonochrome)); - } + { + readbufferpos = 0; + tga_info.id_length=(unsigned char)ReadBlobByteFromBuffer(readbuffer, &readbufferpos); + tga_info.colormap_type=(unsigned char)ReadBlobByteFromBuffer(readbuffer, &readbufferpos); + tga_info.image_type=(unsigned char)ReadBlobByteFromBuffer(readbuffer, &readbufferpos); + status=((tga_info.image_type == TGAColormap) || + (tga_info.image_type == TGARGB) || + (tga_info.image_type == TGAMonochrome) || + (tga_info.image_type == TGARLEColormap) || + (tga_info.image_type == TGARLERGB) || + (tga_info.image_type == TGARLEMonochrome)); + } if (!EOFBlob(image) && (status == MagickTrue)) { /* @@ -827,6 +835,9 @@ static unsigned int WriteTGAImage(const ImageInfo *image_info,Image *image) unsigned long scene; + size_t + image_list_length; + /* Open output image file. */ @@ -834,6 +845,7 @@ static unsigned int WriteTGAImage(const ImageInfo *image_info,Image *image) assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); + image_list_length=GetImageListLength(image); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == MagickFalse) ThrowWriterException(FileOpenError,UnableToOpenFile,image); @@ -841,7 +853,7 @@ static unsigned int WriteTGAImage(const ImageInfo *image_info,Image *image) do { ImageCharacteristics - characteristics; + characteristics; write_grayscale=MagickFalse; @@ -895,10 +907,10 @@ static unsigned int WriteTGAImage(const ImageInfo *image_info,Image *image) targa_info.id_length=0; attribute=GetImageAttribute(image,"comment"); if (attribute != (const ImageAttribute *) NULL) - { - unsigned char id_length =(unsigned char) strlen(attribute->value); + { + unsigned char id_length =(unsigned char) strlen(attribute->value); targa_info.id_length=Min(id_length,255); - } + } targa_info.colormap_type=0; targa_info.colormap_index=0; targa_info.colormap_length=0; @@ -917,11 +929,11 @@ static unsigned int WriteTGAImage(const ImageInfo *image_info,Image *image) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Writing Grayscale raster ..."); targa_info.image_type=TargaMonochrome; - targa_info.bits_per_pixel=8; - targa_info.colormap_type=0; + targa_info.bits_per_pixel=8; + targa_info.colormap_type=0; targa_info.colormap_index=0; targa_info.colormap_length=0; - targa_info.colormap_size=0; + targa_info.colormap_size=0; } else if (image->storage_class == DirectClass) { @@ -1050,14 +1062,14 @@ static unsigned int WriteTGAImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } MagickFreeMemory(targa_pixels); if (image->next == (Image *) NULL) break; image=SyncNextImageInList(image); - if (!MagickMonitorFormatted(scene++,GetImageListLength(image), + if (!MagickMonitorFormatted(scene++,image_list_length, &image->exception,SaveImagesText, image->filename)) break; diff --git a/coders/tiff.c b/coders/tiff.c index affab1d..7bfeb5d 100644 --- a/coders/tiff.c +++ b/coders/tiff.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2016 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -65,6 +65,9 @@ # if !defined(COMPRESSION_ADOBE_DEFLATE) # define COMPRESSION_ADOBE_DEFLATE 8 # endif /* !defined(COMPRESSION_ADOBE_DEFLATE) */ +# if defined(COMPRESSION_ZSTD) && defined(HasZSTD) +# include "zstd.h" +# endif /* if defined(COMPRESSION_ZSTD) && defined(HasZSTD) */ /* JPEG headers are needed in order to obtain BITS_IN_JSAMPLE @@ -276,8 +279,8 @@ TIFFIgnoreTags(TIFF *tiff) *p, *tags; - const ImageInfo - *image_info; + Magick_TIFF_ClientData + *client_data; register ssize_t i; @@ -291,8 +294,10 @@ TIFFIgnoreTags(TIFF *tiff) if (TIFFGetReadProc(tiff) != TIFFReadBlob) return; - image_info=((Magick_TIFF_ClientData *)TIFFClientdata(tiff))->image_info; - tags=AccessDefinition(image_info,"tiff","ignore-tags"); + client_data=((Magick_TIFF_ClientData *) TIFFClientdata(tiff)); + if (client_data == (Magick_TIFF_ClientData *) NULL) + return; + tags=AccessDefinition(client_data->image_info,"tiff","ignore-tags"); if (tags == (const char *) NULL) return; count=0; @@ -303,9 +308,7 @@ TIFFIgnoreTags(TIFF *tiff) p++; { - /* Avoid warning about unused strtol return value on Linux */ - long ignored = strtol(p,&q,10); - (void) ignored; + (void) strtol(p,&q,10); } if (p == q) return; @@ -321,6 +324,12 @@ TIFFIgnoreTags(TIFF *tiff) i=0; p=tags; ignore=MagickAllocateArray(TIFFFieldInfo*,count,sizeof(*ignore)); + if (ignore == (TIFFFieldInfo*) NULL) + { + ThrowException(&client_data->image->exception,ResourceLimitError, + MemoryAllocationFailed,client_data->image->filename); + return; + } /* This also sets field_bit to 0 (FIELD_IGNORE) */ (void) memset(ignore,0,count*sizeof(*ignore)); while (*p != '\0') @@ -359,7 +368,7 @@ ExtensionTagsDefaultDirectory(TIFF *tif) * the default directory method, we call it now to * allow it to set up the rest of its own methods. */ - if (_ParentExtender) + if (_ParentExtender) (*_ParentExtender)(tif); TIFFIgnoreTags(tif); } @@ -373,7 +382,7 @@ void ExtensionTagsInitialize(void) { static int first_time=1; - + if (! first_time) return; /* Been there. Done that. */ first_time = 0; @@ -389,7 +398,7 @@ void ExtensionTagsInitialize(void) */ static MagickBool CompressionSupported(const CompressionType compression, - char *compression_name) + char *compression_name) { uint16 compress_tag; @@ -436,24 +445,24 @@ CompressionSupported(const CompressionType compression, { strlcpy(compression_name,"Group4 FAX",MaxTextExtent); #if defined(COMPRESSION_CCITTFAX4) - compress_tag=COMPRESSION_CCITTFAX4; + compress_tag=COMPRESSION_CCITTFAX4; status=MagickTrue; #endif break; } case JBIG1Compression: { - strlcpy(compression_name,"JBIG",MaxTextExtent); + strlcpy(compression_name,"JBIG",MaxTextExtent); #if defined(COMPRESSION_JBIG) compress_tag=COMPRESSION_JBIG; status=MagickTrue; #endif - break; + break; } case JBIG2Compression: { - strlcpy(compression_name,"JBIG2",MaxTextExtent); - break; + strlcpy(compression_name,"JBIG2",MaxTextExtent); + break; } case JPEGCompression: { @@ -501,6 +510,15 @@ CompressionSupported(const CompressionType compression, #endif break; } + case WebPCompression: + { + strlcpy(compression_name,"WebP",MaxTextExtent); +#if defined(COMPRESSION_WEBP) + compress_tag=COMPRESSION_WEBP; + status=MagickTrue; +#endif + break; + } case ZipCompression: { strlcpy(compression_name,"Adobe Deflate",MaxTextExtent); @@ -510,6 +528,15 @@ CompressionSupported(const CompressionType compression, #endif break; } + case ZSTDCompression: + { + strlcpy(compression_name,"Zstandard",MaxTextExtent); +#if defined(COMPRESSION_ZSTD) + compress_tag=COMPRESSION_ZSTD; + status=MagickTrue; +#endif + break; + } } if (MagickTrue == status) @@ -522,12 +549,12 @@ CompressionSupported(const CompressionType compression, working. Otherwise 0 will be returned. */ if (!TIFFIsCODECConfigured(compress_tag)) - status = MagickFalse; - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "TIFFIsCODECConfigured says support for %s " - "compression %s configured.", - compression_name, - (status == MagickTrue ? "is" : "is not")); + status = MagickFalse; + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "TIFFIsCODECConfigured says support for %s " + "compression %s configured.", + compression_name, + (status == MagickTrue ? "is" : "is not")); } #else switch (compress_tag) @@ -627,6 +654,21 @@ CompressionTagToString(unsigned int compress_tag) result="ThunderScan RLE"; break; #endif +#if defined(COMPRESSION_LZMA) + case COMPRESSION_LZMA: + result="LZMA"; + break; +#endif +#if defined(COMPRESSION_ZSTD) + case COMPRESSION_ZSTD: + result="Zstandard"; + break; +#endif +#if defined(COMPRESSION_WEBP) + case COMPRESSION_WEBP: + result="WebP"; + break; +#endif } return result; } @@ -636,7 +678,7 @@ PhotometricTagToString(unsigned int photometric) { const char *result = "Unknown"; - + switch (photometric) { case PHOTOMETRIC_CIELAB: @@ -676,53 +718,122 @@ PhotometricTagToString(unsigned int photometric) return result; } +/* + Locate and store Photoshop or IPTC profiles. + + Arguments: + + text - Pointer to octet buffer + length - Number of bytes or 32-bit words in buffer + image - Image to store into + type - TIFF tag (TIFFTAG_PHOTOSHOP or TIFFTAG_RICHTIFFIPTC) + + If the tag is TIFFTAG_RICHTIFFIPTC then it appears that the length + represents the number of 32-bit words. If the tag is + TIFFTAG_PHOTOSHOP then the length is in bytes, but the underlying + data is stored in units of 16-bit words. + */ +#define NEWSP_REMAINING(base_p,current_p,length) ((ssize_t) length-(current_p-base_p)) static unsigned int -ReadNewsProfile(char *text,long int length,Image *image,int type) +ReadNewsProfile(const unsigned char *text,const size_t length,Image *image,const int type) { - register unsigned char + register const unsigned char *p; - if (length <= 0) - return(False); +#if defined(GET_ONLY_IPTC_DATA) + static const char tag_header [] = "8BIM44"; +#else + static const char tag_header [] = "8BIM"; +#endif + + MagickBool found_header=MagickFalse; + + if ((length == 0) || ((ssize_t) length < 0)) + return MagickFail; + p=(unsigned char *) text; if (type == TIFFTAG_RICHTIFFIPTC) { /* - Handle IPTC tag. + Handle IPTC tag (length is number of 32-bit words). */ - length*=4; - return SetImageProfile(image,"IPTC",p,(size_t) length); + return SetImageProfile(image,"IPTC",p,(size_t) length*4U); } /* - Handle PHOTOSHOP tag. + Handle PHOTOSHOP tag (length is in bytes, but data is organized as + array of 16-bit values. */ - while (length > 0) - { -#if defined(GET_ONLY_IPTC_DATA) - if (LocaleNCompare((char *) p,"8BIM44",6) == 0) -#else - if (LocaleNCompare((char *) p,"8BIM",4) == 0) -#endif - break; - length-=2; - p+=2; - } - if (length <= 0) - return(False); + while (NEWSP_REMAINING(text,p,length) > (ssize_t) sizeof(tag_header)) + { + if (LocaleNCompare((char *) p,tag_header,sizeof(tag_header)-1) == 0) + { + found_header=MagickTrue; + break; + } + p+=2; + } + if (!found_header) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Failed to find %s header, ignoring profile.", + tag_header); + return MagickFail; + } #if defined(GET_ONLY_IPTC_DATA) /* Eat OSType, IPTC ID code, and Pascal string length bytes. */ - p+=6; - length=(*p++); - if (length) - p+=length; - if ((length & 0x01) == 0) - p++; /* align to an even byte boundary */ - length=(p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; - p+=4; + do + { + magick_uint32_t + hdr_length; + + p+=sizeof(tag_header)-1; + if (NEWSP_REMAINING(text,p,length) < 8) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Truncated profile: %" MAGICK_SIZE_T_F + "u bytes, %" MAGICK_SSIZE_T_F "u remaining" + ", ignoring profile.", + (MAGICK_SIZE_T) length, + (MAGICK_SSIZE_T) NEWSP_REMAINING(text,p,length)); + break; + } + hdr_length=(*p++); + p+=hdr_length; + if (NEWSP_REMAINING(text,p,length) < 8) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Truncated profile: %" MAGICK_SIZE_T_F + "u bytes, %" MAGICK_SSIZE_T_F "u remaining" + ", ignoring profile.", + (MAGICK_SIZE_T) length, + (MAGICK_SSIZE_T) NEWSP_REMAINING(text,p,length)); + break; + } + if ((hdr_length & 0x01) == 0) + p++; /* align to an even byte boundary */ + hdr_length=(p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + p+=4; + if (((ssize_t) hdr_length <= 0) || + ((ssize_t) hdr_length > NEWSP_REMAINING(text,p,length))) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Truncated profile: %" MAGICK_SIZE_T_F + "u bytes, %" MAGICK_SSIZE_T_F "u " + "remaining (need %u more bytes)" + ", ignoring profile.", + (MAGICK_SIZE_T) length, + (MAGICK_SSIZE_T) NEWSP_REMAINING(text,p,length), + hdr_length); + return MagickFail; + } + return SetImageProfile(image,"8BIM",p,hdr_length); + } while (0); + return MagickFail; +#else + return SetImageProfile(image,"8BIM",p,(size_t) NEWSP_REMAINING(text,p,length)); #endif - return SetImageProfile(image,"8BIM",p,(size_t) length); } /* @@ -775,7 +886,10 @@ TIFFCloseBlob(thandle_t image_handle) } /* Report errors. */ -static unsigned int +static void +TIFFErrors(const char *module,const char *format, + va_list warning) MAGICK_ATTRIBUTE((__format__ (__printf__,2,0))); +static void TIFFErrors(const char *module,const char *format, va_list warning) { @@ -791,7 +905,6 @@ TIFFErrors(const char *module,const char *format, (void) strlcat(message,".",MaxTextExtent); tiff_exception=(ExceptionInfo *) MagickTsdGetSpecific(tsd_key); ThrowException2(tiff_exception,CoderError,message,module); - return(True); } /* Memory map entire input file in read-only mode. */ @@ -810,8 +923,8 @@ TIFFMapBlob(thandle_t image_handle,tdata_t *base,toff_t *size) #if LOG_TIFF_BLOB_IO if (image->logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "TIFF mapped blob: base=0x%p size=%" MAGICK_OFF_F - "d",*base, (magick_off_t) *size); + "TIFF mapped blob: base=0x%p size=%" MAGICK_OFF_F + "d",*base, (magick_off_t) *size); #endif return 1; } @@ -835,8 +948,8 @@ TIFFReadBlob(thandle_t image_handle,tdata_t data,tsize_t size) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "TIFF read blob: data=0x%p size=%" MAGICK_SIZE_T_F "u, returns %" - MAGICK_SIZE_T_F "u", - data, (MAGICK_SIZE_T) size, + MAGICK_SIZE_T_F "u", + data, (MAGICK_SIZE_T) size, (MAGICK_SIZE_T) result); #endif /* LOG_TIFF_BLOB_IO */ @@ -858,13 +971,13 @@ TIFFSeekBlob(thandle_t image_handle,toff_t offset,int whence) if (image->logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "TIFF seek blob: offset=%" MAGICK_OFF_F - "u whence=%d (%s), returns %" MAGICK_OFF_F "d", + "u whence=%d (%s), returns %" MAGICK_OFF_F "d", (magick_off_t) offset, - whence, + whence, (whence == SEEK_SET ? "SET" : (whence == SEEK_CUR ? "CUR" : (whence == SEEK_END ? "END" : "unknown"))), - (magick_off_t) result); + (magick_off_t) result); #endif /* LOG_TIFF_BLOB_IO */ return result; } @@ -884,8 +997,8 @@ TIFFGetBlobSize(thandle_t image_handle) #if LOG_TIFF_BLOB_IO if (image->logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "TIFF get blob size returns %" MAGICK_OFF_F "d", - (magick_off_t) result); + "TIFF get blob size returns %" MAGICK_OFF_F "d", + (magick_off_t) result); #endif /* LOG_TIFF_BLOB_IO */ return result; @@ -903,8 +1016,8 @@ TIFFUnmapBlob(thandle_t image, if (image->logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "TIFF unmap blob: base=0x%p size=%" MAGICK_OFF_F "d", - base,(magick_off_t) size); + "TIFF unmap blob: base=0x%p size=%" MAGICK_OFF_F "d", + base,(magick_off_t) size); #else ARG_NOT_USED(image); ARG_NOT_USED(base); @@ -913,7 +1026,9 @@ TIFFUnmapBlob(thandle_t image, } /* Report warnings as a coder log message. */ -static unsigned int +static void +TIFFWarningsLogOnly(const char *module,const char *format,va_list warning) MAGICK_ATTRIBUTE((__format__ (__printf__,2,0))); +static void TIFFWarningsLogOnly(const char *module,const char *format,va_list warning) { /* ExceptionInfo */ @@ -931,11 +1046,12 @@ TIFFWarningsLogOnly(const char *module,const char *format,va_list warning) /* ThrowException2(tiff_exception,CoderWarning,message,module); */ (void) LogMagickEvent(CoderEvent,GetMagickModule(), "TIFF Warning: %s",message); - return(True); } /* Report warnings as exception in thread-specific ExceptionInfo */ -static unsigned int +static void +TIFFWarningsThrowException(const char *module,const char *format,va_list warning) MAGICK_ATTRIBUTE((__format__ (__printf__,2,0))); +static void TIFFWarningsThrowException(const char *module,const char *format,va_list warning) { ExceptionInfo @@ -953,7 +1069,6 @@ TIFFWarningsThrowException(const char *module,const char *format,va_list warning ThrowException2(tiff_exception,CoderWarning,message,module); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "TIFF Warning: %s",message); - return(True); } /* Write data at current offset */ @@ -971,10 +1086,10 @@ TIFFWriteBlob(thandle_t image_handle,tdata_t data,tsize_t size) #if LOG_TIFF_BLOB_IO if (image->logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "TIFF write blob: data=0x%p size=%" MAGICK_SIZE_T_F - "u, returns %" MAGICK_SIZE_T_F "u", - data, (MAGICK_SIZE_T) size, - (MAGICK_SIZE_T) result); + "TIFF write blob: data=0x%p size=%" MAGICK_SIZE_T_F + "u, returns %" MAGICK_SIZE_T_F "u", + data, (MAGICK_SIZE_T) size, + (MAGICK_SIZE_T) result); #endif /* LOG_TIFF_BLOB_IO */ return result; @@ -986,30 +1101,30 @@ TIFFWriteBlob(thandle_t image_handle,tdata_t data,tsize_t size) #if !defined(WORDS_BIGENDIAN) static void SwabDataToBigEndian(const uint16 bits_per_sample, tdata_t data, - const tsize_t size) + const tsize_t size) { if (bits_per_sample == 64U) { TIFFSwabArrayOfDouble((double*) data, - NumberOfObjectsInArray(size,sizeof(double))); + NumberOfObjectsInArray(size,sizeof(double))); } else if (bits_per_sample == 32U) { TIFFSwabArrayOfLong((uint32*) data, - NumberOfObjectsInArray(size,sizeof(uint32))); + NumberOfObjectsInArray(size,sizeof(uint32))); } #if defined(HAVE_TIFFSWABARRAYOFTRIPLES) /* New libtiff function to swap 24 bit values. Grumble ... */ else if (bits_per_sample == 24U) { TIFFSwabArrayOfTriples(data, - NumberOfObjectsInArray(size,3)); + NumberOfObjectsInArray(size,3)); } #endif else if (bits_per_sample == 16U) { TIFFSwabArrayOfShort((uint16*) data, - NumberOfObjectsInArray(size,sizeof(uint16))); + NumberOfObjectsInArray(size,sizeof(uint16))); } } #endif @@ -1020,30 +1135,30 @@ SwabDataToBigEndian(const uint16 bits_per_sample, tdata_t data, #if !defined(WORDS_BIGENDIAN) static void SwabDataToNativeEndian(const uint16 bits_per_sample, tdata_t data, - const tsize_t size) + const tsize_t size) { if (bits_per_sample == 64) { TIFFSwabArrayOfDouble((double*) data, - NumberOfObjectsInArray(size,sizeof(double))); + NumberOfObjectsInArray(size,sizeof(double))); } else if (bits_per_sample == 32) { TIFFSwabArrayOfLong((uint32*) data, - NumberOfObjectsInArray(size,sizeof(uint32))); + NumberOfObjectsInArray(size,sizeof(uint32))); } #if defined(HAVE_TIFFSWABARRAYOFTRIPLES) /* New libtiff function to swap 24 bit values. Grumble ... */ else if (bits_per_sample == 24U) { TIFFSwabArrayOfTriples(data, - NumberOfObjectsInArray(size,3)); + NumberOfObjectsInArray(size,3)); } #endif else if (bits_per_sample == 16) { TIFFSwabArrayOfShort((uint16*) data, - NumberOfObjectsInArray(size,sizeof(uint16))); + NumberOfObjectsInArray(size,sizeof(uint16))); } } #endif @@ -1085,7 +1200,7 @@ InitializeImageColormap(Image *image, TIFF *tiff) else image->colors=MaxColormapSize; } - + if (image->colors > 0) { (void) LogMagickEvent(CoderEvent,GetMagickModule(), @@ -1117,12 +1232,12 @@ InitializeImageColormap(Image *image, TIFF *tiff) { long range; - + uint16 *blue_colormap, *green_colormap, *red_colormap; - + (void) TIFFGetField(tiff,TIFFTAG_COLORMAP,&red_colormap, &green_colormap,&blue_colormap); range=256L; /* might be old style 8-bit colormap */ @@ -1278,22 +1393,28 @@ QuantumTransferMode(const Image *image, } case PHOTOMETRIC_LOGL: { - *quantum_type=CIEYQuantum; - *quantum_samples=1; - break; - } - case PHOTOMETRIC_LOGLUV: - { - if (samples_per_pixel == 1) + if (!image->matte) { - /* FIXME: this might not work. */ *quantum_type=CIEYQuantum; *quantum_samples=1; } - else + break; + } + case PHOTOMETRIC_LOGLUV: + { + if (!image->matte) { - *quantum_type=CIEXYZQuantum; - *quantum_samples=3; + if (samples_per_pixel == 1) + { + /* FIXME: this might not work. */ + *quantum_type=CIEYQuantum; + *quantum_samples=1; + } + else + { + *quantum_type=CIEXYZQuantum; + *quantum_samples=3; + } } break; } @@ -1439,7 +1560,10 @@ QuantumTransferMode(const Image *image, } } } - /* fprintf(stderr,"Quantum Type: %d Quantum Samples: %d\n",(int) *quantum_type,*quantum_samples); */ + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Quantum Type: %s, Quantum Samples: %d", + QuantumTypeToString(*quantum_type),*quantum_samples); /* FIXME: We do need to support YCbCr! */ if (*quantum_samples != 0) @@ -1461,6 +1585,10 @@ QuantumTransferMode(const Image *image, } } + if ((image->logging) && (*quantum_samples == 0)) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Reporting failure"); + return (*quantum_samples != 0 ? MagickPass : MagickFail); } @@ -1472,12 +1600,13 @@ QuantumTransferMode(const Image *image, */ static void CompactSamples( const unsigned long total_pixels, - const unsigned int bits_per_sample, - const unsigned int samples_per_pixel, - const unsigned int quantum_samples, - unsigned char *samples) + const unsigned int bits_per_sample, + const unsigned int samples_per_pixel, + const unsigned int quantum_samples, + unsigned char *samples) { - if (samples_per_pixel > quantum_samples) + if ((samples_per_pixel > quantum_samples) && + (bits_per_sample > 0) && bits_per_sample <= 32) { /* Compact scanline to only contain raster data. @@ -1604,7 +1733,7 @@ DisassociateAlphaRegion(Image *image) _attribute[Min(sizeof(_attribute)-1,count)]='\0'; \ (void) SetImageAttribute(image,key,_attribute); \ } while(0); - + typedef enum { @@ -1616,6 +1745,13 @@ typedef enum RGBAPuntMethod /* RGBA whole-image method (last resort) */ } TIFFMethod; +#define ThrowTIFFReaderException(code_,reason_,image_) \ +{ \ + if (tiff != (TIFF *) NULL) \ + TIFFClose(tiff); \ + ThrowReaderException(code_,reason_,image_); \ +} + static Image * ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) { @@ -1646,7 +1782,11 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) i; TIFF - *tiff; + *tiff = (TIFF *) NULL; + + magick_off_t + file_size, + max_compress_ratio=1000; /* Maximum compression ratio */ uint16 compress_tag, @@ -1703,6 +1843,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFail) ThrowReaderException(FileOpenError,UnableToOpenFile,image); + file_size = GetBlobSize(image); (void) MagickTsdSetSpecific(tsd_key,(void *) exception); (void) TIFFSetErrorHandler((TIFFErrorHandler) TIFFErrors); (void) TIFFSetWarningHandler((TIFFErrorHandler) (CheckThrowWarnings(image_info) ? @@ -1711,8 +1852,8 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) client_data.image=image; client_data.image_info=image_info; tiff=TIFFClientOpen(image->filename,"rb",(thandle_t) &client_data,TIFFReadBlob, - TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob, - TIFFGetBlobSize,TIFFMapBlob,TIFFUnmapBlob); + TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob, + TIFFGetBlobSize,TIFFMapBlob,TIFFUnmapBlob); if (tiff == (TIFF *) NULL) ThrowReaderException(FileOpenError,UnableToOpenFile,image); @@ -1726,9 +1867,8 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) status=TIFFReadDirectory(tiff); if (status == False) { - TIFFClose(tiff); - ThrowReaderException(CorruptImageError,UnableToReadSubImageData, - image); + ThrowTIFFReaderException(CorruptImageError,UnableToReadSubImageData, + image); } } do @@ -1757,15 +1897,14 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&fill_order) == 1); if (status == 0) { - TIFFClose(tiff); /* Promote TIFF warnings to errors for these critical tags. */ if ((exception->severity > WarningException) && (exception->severity < ErrorException)) exception->severity += (ErrorException - WarningException); - ThrowReaderException(CorruptImageError,ImproperImageHeader, - image); + ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader, + image); } if (TIFFGetField(tiff,TIFFTAG_ORIENTATION,&orientation) == 1) image->orientation=(OrientationType) orientation; @@ -1798,7 +1937,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) { double value; - + if (TIFFGetField(tiff,TIFFTAG_SMINSAMPLEVALUE,&value) == 1) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Special min sample value: %g", value); @@ -1827,14 +1966,13 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) #if 1 image->colorspace=LABColorspace; #else - TIFFClose(tiff); - ThrowReaderException(CoderError,UnableToReadCIELABImages,image); + ThrowTIFFReaderException(CoderError,UnableToReadCIELABImages,image); #endif } if (photometric == PHOTOMETRIC_SEPARATED) image->colorspace=CMYKColorspace; if (planar_config == PLANARCONFIG_SEPARATE) - image->interlace=PlaneInterlace; + image->interlace=PlaneInterlace; (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_RESOLUTIONUNIT,&units); x_resolution=image->x_resolution; y_resolution=image->y_resolution; @@ -1892,7 +2030,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Photoshop embedded profile with length %lu bytes", (unsigned long) length); - (void) ReadNewsProfile(text,(long) length,image,TIFFTAG_PHOTOSHOP); + (void) ReadNewsProfile((unsigned char *) text,(long) length,image,TIFFTAG_PHOTOSHOP); } #elif defined(TIFFTAG_RICHTIFFIPTC) /* IPTC TAG from RichTIFF specifications */ @@ -1902,7 +2040,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) TIFFSwabArrayOfLong((uint32 *) text,length); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "IPTC Newsphoto embedded profile with length %u bytes",length); - ReadNewsProfile(text,length,image,TIFFTAG_RICHTIFFIPTC); + ReadNewsProfile((unsigned char *) text,length,image,TIFFTAG_RICHTIFFIPTC); } #endif /* @@ -1920,22 +2058,54 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) #endif } /* - Allocate memory for the image and pixel buffer. + Map from TIFF compression tags to GraphicsMagick equivalents + as well as estimate a maximum compression ratio (for + validating scanline/strip/tile allocation requests). */ switch (compress_tag) { - case COMPRESSION_NONE: image->compression=NoCompression; break; - case COMPRESSION_CCITTFAX3: image->compression=FaxCompression; break; - case COMPRESSION_CCITTFAX4: image->compression=Group4Compression; break; - case COMPRESSION_JPEG: image->compression=JPEGCompression; break; - case COMPRESSION_OJPEG: image->compression=JPEGCompression; break; - case COMPRESSION_LZW: image->compression=LZWCompression; break; + case COMPRESSION_NONE: + image->compression=NoCompression; + break; + case COMPRESSION_CCITTFAX3: + image->compression=FaxCompression; + break; + case COMPRESSION_CCITTFAX4: + image->compression=Group4Compression; + break; + case COMPRESSION_JPEG: + image->compression=JPEGCompression; + break; + case COMPRESSION_OJPEG: + image->compression=JPEGCompression; + break; + case COMPRESSION_LZW: + image->compression=LZWCompression; + break; #if defined(COMPRESSION_LZMA) - case COMPRESSION_LZMA: image->compression=LZMACompression; break; + case COMPRESSION_LZMA: + image->compression=LZMACompression; + break; #endif /* defined(COMPRESSION_LZMA) */ - case COMPRESSION_DEFLATE: image->compression=ZipCompression; break; - case COMPRESSION_ADOBE_DEFLATE: image->compression=ZipCompression; break; - default: image->compression=RLECompression; break; + case COMPRESSION_DEFLATE: + image->compression=ZipCompression; + break; + case COMPRESSION_ADOBE_DEFLATE: + image->compression=ZipCompression; + break; +#if defined(COMPRESSION_ZSTD) + case COMPRESSION_ZSTD: + image->compression=ZSTDCompression; + break; +#endif /* defined(COMPRESSION_ZSTD) */ +#if defined(COMPRESSION_WEBP) + case COMPRESSION_WEBP: + image->compression=WebPCompression; + break; +#endif /* if defined(COMPRESSION_WEBP) */ + default: + image->compression=NoCompression; + break; } image->columns=width; image->rows=height; @@ -1963,14 +2133,15 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) else if (sample_info[0] == EXTRASAMPLE_ASSOCALPHA) alpha_type=AssociatedAlpha; } - for (sample_index=0 ; sample_index < extra_samples; sample_index++) - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Extra sample %u contains %s alpha",sample_index+1, - ((sample_info[sample_index] == EXTRASAMPLE_ASSOCALPHA) ? "ASSOCIATED" : - (sample_info[sample_index] == EXTRASAMPLE_UNASSALPHA) ? "UNASSOCIATED" : - "UNSPECIFIED")); - } + if (image->logging) + for (sample_index=0 ; sample_index < extra_samples; sample_index++) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Extra sample %u contains %s alpha",sample_index+1, + ((sample_info[sample_index] == EXTRASAMPLE_ASSOCALPHA) ? "ASSOCIATED" : + (sample_info[sample_index] == EXTRASAMPLE_UNASSALPHA) ? "UNASSOCIATED" : + "UNSPECIFIED")); + } } /* Handle RGBA images which are improperly marked. @@ -2031,11 +2202,11 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (units == RESUNIT_CENTIMETER) image->units=PixelsPerCentimeterResolution; { - uint16 - pagenumber; + uint16 + pagenumber; - pagenumber=(unsigned short) image->scene; - if (TIFFGetFieldDefaulted(tiff,TIFFTAG_PAGENUMBER,&pagenumber,&pages) == 1) + pagenumber=(unsigned short) image->scene; + if (TIFFGetFieldDefaulted(tiff,TIFFTAG_PAGENUMBER,&pagenumber,&pages) == 1) image->scene=pagenumber; } @@ -2074,10 +2245,10 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) */ if (TIFFGetField(tiff,TIFFTAG_OPIIMAGEID,&count,&text) == 1) CopySizedFieldToAttribute("imageid",count,text); - + if (TIFFGetField(tiff,33423,&count,&text) == 1) CopySizedFieldToAttribute("kodak-33423",count,text); - + if (TIFFGetField(tiff,36867,&count,&text) == 1) CopySizedFieldToAttribute("kodak-36867",count,text); @@ -2087,8 +2258,8 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) ((image_info->type == PaletteType) || (image_info->type == PaletteMatteType)) && (MaxColormapSize > MaxValueGivenBits(bits_per_sample)) - ) - ) + ) + ) { /* Palette image @@ -2099,8 +2270,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) } else { - TIFFClose(tiff); - ThrowReaderException(CoderError,ColormapTooLarge,image); + ThrowTIFFReaderException(CoderError,ColormapTooLarge,image); } } @@ -2119,8 +2289,28 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (CheckImagePixelLimits(image, exception) != MagickPass) { - TIFFClose(tiff); - ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); + ThrowTIFFReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); + } + + /* + Check if the bits-per-sample value is supported by the + implementation before proceeding. + + Currently we support a range of 1-32, and 64 bits if the + samples are float. + */ + if (!((sample_format == SAMPLEFORMAT_IEEEFP && bits_per_sample == 64) || + ((bits_per_sample > 0) && (bits_per_sample <= 32)))) + { + ThrowTIFFReaderException(CoderError,UnsupportedBitsPerSample,image); + } + + /* + Check for excessive samples per pixel or excessive extra samples. + */ + if ((samples_per_pixel > 8U) || (extra_samples > 8U)) + { + ThrowTIFFReaderException(CoderError,UnsupportedSamplesPerPixel,image); } /* @@ -2135,7 +2325,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) if ((samples_per_pixel > 1) && (compress_tag == COMPRESSION_JPEG) && - (photometric == PHOTOMETRIC_YCBCR)) + (photometric == PHOTOMETRIC_YCBCR)) { /* Following hack avoids the error message "Application transferred too many scanlines. (JPEGLib)." caused by @@ -2145,7 +2335,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Resetting photometric from %s to %s for JPEG RGB", PhotometricTagToString(photometric), - PhotometricTagToString(PHOTOMETRIC_RGB)); + PhotometricTagToString(PHOTOMETRIC_RGB)); (void) TIFFSetField( tiff, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB ); photometric=PHOTOMETRIC_RGB; } @@ -2190,8 +2380,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) /* QuantumTransferMode reported an error */ - TIFFClose(tiff); - ThrowReaderException(CorruptImageError,ImproperImageHeader,image); + ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image); } } @@ -2251,10 +2440,26 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) "Using scanline %s read method with %u bits per sample", PhotometricTagToString(photometric),bits_per_sample); /* + Prepare for separate/contiguous retrieval. + */ + max_sample=1; + if (planar_config == PLANARCONFIG_SEPARATE) + { + if (QuantumTransferMode(image,photometric,compress_tag, + sample_format,samples_per_pixel, + PLANARCONFIG_CONTIG,0, + &quantum_type,&quantum_samples, + exception) + != MagickPass) + ThrowTIFFReaderException(CorruptImageError, + ImproperImageHeader,image); + max_sample=quantum_samples; + } + /* Allocate memory for one scanline. */ scanline_size=TIFFScanlineSize(tiff); - if (0 == scanline_size) + if (scanline_size <= 0) { status=MagickFail; break; @@ -2266,44 +2471,43 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Allocating scanline buffer of %lu bytes", - (unsigned long) scanline_size); + "Request to allocate scanline buffer of %" + MAGICK_SIZE_T_F "u bytes", + (MAGICK_SIZE_T) scanline_size); + + /* + Rationalize memory request based on file size + */ + if (scanline_size > file_size*max_compress_ratio) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Unreasonable allocation size " + "(ratio of alloc to file size %g)", + (double) scanline_size/file_size); + ThrowTIFFReaderException(CorruptImageError,InsufficientImageDataInFile, + image); + } scanline=MagickAllocateMemory(unsigned char *,(size_t) scanline_size); if (scanline == (unsigned char *) NULL) { - TIFFClose(tiff); - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, - image); + ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed, + image); } - /* - Prepare for separate/contiguous retrieval. - */ - max_sample=1; - if (planar_config == PLANARCONFIG_SEPARATE) + memset(scanline,0,(size_t) scanline_size); + for (sample=0; sample < max_sample; sample++) { - if (QuantumTransferMode(image,photometric,compress_tag, - sample_format,samples_per_pixel, - PLANARCONFIG_CONTIG,0, - &quantum_type,&quantum_samples, - exception) - == MagickPass) - max_sample=quantum_samples; - } - for (sample=0; sample < max_sample; sample++) - { - for (y=0; y < image->rows; y++) - { - if (sample == 0) - q=SetImagePixels(image,0,y,image->columns,1); - else - q=GetImagePixels(image,0,y,image->columns,1); - if (q == (PixelPacket *) NULL) - { - CopyException(exception,&image->exception); - status=MagickFail; - break; - } + for (y=0; y < image->rows; y++) + { + if (sample == 0) + q=SetImagePixelsEx(image,0,y,image->columns,1,exception); + else + q=GetImagePixelsEx(image,0,y,image->columns,1,exception); + if (q == (PixelPacket *) NULL) + { + status=MagickFail; + break; + } /* Obtain a scanline */ @@ -2327,7 +2531,6 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) exception) == MagickFail) { - CopyException(exception,&image->exception); status=MagickFail; break; } @@ -2348,29 +2551,28 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) status=MagickFail; break; } - /* - Disassociate alpha from pixels if necessary. - */ - if ((image->matte) && (alpha_type == AssociatedAlpha) && - (sample == (max_sample-1))) - DisassociateAlphaRegion(image); - /* - Save our updates. - */ - if (!SyncImagePixels(image)) - { - CopyException(exception,&image->exception); - status=MagickFail; - break; - } - if (image->previous == (Image *) NULL) - if (QuantumTick(y+sample*image->rows,image->rows*max_sample)) - if (!MagickMonitorFormatted(y+sample*image->rows, - image->rows*max_sample,exception, - LoadImageText,image->filename, - image->columns,image->rows)) - break; - } + /* + Disassociate alpha from pixels if necessary. + */ + if ((image->matte) && (alpha_type == AssociatedAlpha) && + (sample == (max_sample-1))) + DisassociateAlphaRegion(image); + /* + Save our updates. + */ + if (!SyncImagePixelsEx(image,exception)) + { + status=MagickFail; + break; + } + if (image->previous == (Image *) NULL) + if (QuantumTick(y+sample*image->rows,image->rows*max_sample)) + if (!MagickMonitorFormatted(y+sample*image->rows, + image->rows*max_sample,exception, + LoadImageText,image->filename, + image->columns,image->rows)) + break; + } } MagickFreeMemory(scanline); break; @@ -2404,18 +2606,43 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) QuantumType quantum_type; + ImportPixelAreaInfo + import_info; + if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using stripped read method with %u bits per sample", bits_per_sample); + /* + Prepare for separate/contiguous retrieval. + */ + max_sample=1; + if (planar_config == PLANARCONFIG_SEPARATE) + { + if (QuantumTransferMode(image,photometric,compress_tag, + sample_format, + samples_per_pixel,PLANARCONFIG_CONTIG, + 0,&quantum_type,&quantum_samples, + exception) + != MagickPass) + ThrowTIFFReaderException(CorruptImageError, + ImproperImageHeader,image); + max_sample=quantum_samples; + } + /* pixels_per_strip=rows_per_strip*image->columns; */ p=0; strip_size=0; strip_id=0; - /* + /* Allocate memory for one strip. */ strip_size_max=TIFFStripSize(tiff); + if (strip_size_max <= 0) + { + status=MagickFail; + break; + } /* Scale up to size of 32-bit word. */ @@ -2424,33 +2651,32 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Maximum strip size %" MAGICK_SIZE_T_F "u", (MAGICK_SSIZE_T) strip_size_max); - if (0 == strip_size_max) + if (strip_size_max <= 0) { status=MagickFail; break; } - strip=MagickAllocateMemory(unsigned char *,(size_t) strip_size_max); - if (strip == (unsigned char *) NULL) - { - TIFFClose(tiff); - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, - image); - } /* - Prepare for separate/contiguous retrieval. + Rationalize memory request based on file size */ - max_sample=1; - if (planar_config == PLANARCONFIG_SEPARATE) + if (strip_size_max > file_size*max_compress_ratio) { - if (QuantumTransferMode(image,photometric,compress_tag, - sample_format, - samples_per_pixel,PLANARCONFIG_CONTIG, - 0,&quantum_type,&quantum_samples, - exception) - == MagickPass) - max_sample=quantum_samples; + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Unreasonable allocation size " + "(ratio of alloc to file size %g)", + (double) strip_size_max/file_size); + ThrowTIFFReaderException(CorruptImageError,InsufficientImageDataInFile, + image); } + + strip=MagickAllocateMemory(unsigned char *,(size_t) strip_size_max); + if (strip == (unsigned char *) NULL) + { + ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed, + image); + } + memset(strip,0,(size_t) strip_size_max); /* Compute per-row stride. */ @@ -2471,7 +2697,6 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) exception) == MagickFail) { - CopyException(exception,&image->exception); status=MagickFail; break; } @@ -2481,12 +2706,11 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) Access Magick pixels. */ if (sample == 0) - q=SetImagePixels(image,0,y,image->columns,1); + q=SetImagePixelsEx(image,0,y,image->columns,1,exception); else - q=GetImagePixels(image,0,y,image->columns,1); + q=GetImagePixelsEx(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { - CopyException(exception,&image->exception); status=MagickFail; break; } @@ -2522,7 +2746,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) Import strip row into image. */ if (ImportImagePixelArea(image,quantum_type,bits_per_sample,p, - &import_options,0) == MagickFail) + &import_options,&import_info) == MagickFail) { CopyException(exception,&image->exception); status=MagickFail; @@ -2537,9 +2761,8 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) /* Save our updates. */ - if (!SyncImagePixels(image)) + if (!SyncImagePixelsEx(image,exception)) { - CopyException(exception,&image->exception); status=MagickFail; break; } @@ -2553,7 +2776,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (QuantumTick(y+image->rows*sample,image->rows*max_sample)) if (!MagickMonitorFormatted(y+image->rows*sample,image->rows*max_sample,exception, LoadImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) { status=MagickFail; break; @@ -2590,198 +2813,218 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) QuantumType quantum_type; - unsigned long + size_t tile_total_pixels; - + if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using tiled %s read method with %u bits per sample", PhotometricTagToString(photometric), bits_per_sample); /* + Prepare for separate/contiguous retrieval. + */ + max_sample=1; + if (planar_config == PLANARCONFIG_SEPARATE) + { + if (QuantumTransferMode(image,photometric,compress_tag, + sample_format,samples_per_pixel, + PLANARCONFIG_CONTIG,0,&quantum_type, + &quantum_samples, + exception) + != MagickPass) + ThrowTIFFReaderException(CorruptImageError, + ImproperImageHeader,image); + max_sample=quantum_samples; + } + /* Obtain tile geometry */ if(!(TIFFGetField(tiff,TIFFTAG_TILEWIDTH,&tile_columns) == 1) || !(TIFFGetField(tiff,TIFFTAG_TILELENGTH,&tile_rows) == 1)) { - TIFFClose(tiff); - ThrowReaderException(CoderError,ImageIsNotTiled,image); + ThrowTIFFReaderException(CoderError,ImageIsNotTiled,image); } /* Obtain the maximum number of bytes required to contain a tile. */ tile_size_max=TIFFTileSize(tiff); + if (tile_size_max <= 0) + { + ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed, + image); + } /* Scale up to size of 32-bit word. */ tile_size_max=RoundUpToAlignment(tile_size_max,sizeof(magick_int32_t)); if (0 == tile_size_max) { - status=MagickFail; - break; + ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed, + image); } /* Compute the total number of pixels in one tile */ - tile_total_pixels=tile_columns*tile_rows; + tile_total_pixels=MagickArraySize(tile_columns,tile_rows); if (logging) { (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "TIFF tile geometry %ux%u, %lu pixels", + "TIFF tile geometry %ux%u, " + "%" MAGICK_SIZE_T_F "u pixels" + " (%" MAGICK_SIZE_T_F "u bytes max)", (unsigned int)tile_columns, (unsigned int)tile_rows, - tile_total_pixels); + (MAGICK_SIZE_T) tile_total_pixels, + (MAGICK_SIZE_T) tile_size_max); } + /* - Allocate tile buffer + Rationalize memory request based on file size */ - tile=MagickAllocateMemory(unsigned char *, (size_t) tile_size_max); - if (tile == (unsigned char *) NULL) + if (tile_size_max > file_size*max_compress_ratio) { - TIFFClose(tiff); - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, - image); + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Unreasonable tile allocation size " + "(ratio of alloc to file size %g)", + (double) tile_size_max/file_size); + ThrowTIFFReaderException(CorruptImageError,InsufficientImageDataInFile, + image); } + /* - Prepare for separate/contiguous retrieval. + Allocate tile buffer */ - max_sample=1; - if (planar_config == PLANARCONFIG_SEPARATE) + tile=MagickAllocateMemory(unsigned char *, (size_t) tile_size_max); + if (tile == (unsigned char *) NULL) { - if (QuantumTransferMode(image,photometric,compress_tag, - sample_format,samples_per_pixel, - PLANARCONFIG_CONTIG,0,&quantum_type, - &quantum_samples, - exception) - == MagickPass) - max_sample=quantum_samples; + ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed, + image); } + memset(tile,0,(size_t) tile_size_max); /* Compute per-row stride. */ stride=TIFFTileRowSize(tiff); - /* - Process each plane. - */ - for (sample=0; sample < max_sample; sample++) - { - /* - Determine quantum parse method. - */ - if (QuantumTransferMode(image,photometric,compress_tag, + /* + Process each plane. + */ + for (sample=0; sample < max_sample; sample++) + { + /* + Determine quantum parse method. + */ + if (QuantumTransferMode(image,photometric,compress_tag, sample_format,samples_per_pixel, planar_config,sample,&quantum_type, &quantum_samples,exception) - == MagickFail) - { - CopyException(exception,&image->exception); - status=MagickFail; - break; - } - for (y=0; y < image->rows; y+=tile_rows) - { - for (x=0; x < image->columns; x+=tile_columns) - { - long - tile_set_columns, - tile_set_rows; - - unsigned char - *p; - - register long - yy; - - /* - Compute image region corresponding to tile. - */ - if (x+tile_columns > image->columns) - tile_set_columns=(tile_columns-(x+tile_columns-image->columns)); - else - tile_set_columns=tile_columns; - if (y+tile_rows > image->rows) - tile_set_rows=(tile_rows-(y+tile_rows-image->rows)); - else - tile_set_rows=tile_rows; - - /* - Read a tile. - */ - if ((tile_size=TIFFReadTile(tiff,tile,x,y,0,sample)) == -1) - { - status=MagickFail; - break; - } + == MagickFail) + { + status=MagickFail; + break; + } + for (y=0; y < image->rows; y+=tile_rows) + { + for (x=0; x < image->columns; x+=tile_columns) + { + long + tile_set_columns, + tile_set_rows; + + unsigned char + *p; + + register long + yy; + + /* + Compute image region corresponding to tile. + */ + if (x+tile_columns > image->columns) + tile_set_columns=(tile_columns-(x+tile_columns-image->columns)); + else + tile_set_columns=tile_columns; + if (y+tile_rows > image->rows) + tile_set_rows=(tile_rows-(y+tile_rows-image->rows)); + else + tile_set_rows=tile_rows; + + /* + Read a tile. + */ + if ((tile_size=TIFFReadTile(tiff,tile,x,y,0,sample)) == -1) + { + status=MagickFail; + break; + } #if !defined(WORDS_BIGENDIAN) - if (24 == bits_per_sample) - SwabDataToBigEndian(bits_per_sample,tile,tile_size); + if (24 == bits_per_sample) + SwabDataToBigEndian(bits_per_sample,tile,tile_size); #endif - p=tile; - for (yy=y; yy < (long) y+tile_set_rows; yy++) - { - /* - Obtain pixel region corresponding to tile row. - */ - if (sample == 0) - q=SetImagePixels(image,x,yy,tile_set_columns,1); - else - q=GetImagePixels(image,x,yy,tile_set_columns,1); - if (q == (PixelPacket *) NULL) - { - CopyException(exception,&image->exception); - status=MagickFail; - break; - } - /* - Compact tile row to only contain raster data. - */ - if ((samples_per_pixel > quantum_samples) && - (planar_config == PLANARCONFIG_CONTIG)) - CompactSamples(tile_set_columns, bits_per_sample, - samples_per_pixel, quantum_samples, p); - /* - Import tile row - */ - if (ImportImagePixelArea(image,quantum_type, - bits_per_sample,p, - &import_options,0) - == MagickFail) - { - CopyException(exception,&image->exception); - status=MagickFail; - break; - } - /* - Disassociate alpha from pixels if necessary. - */ - if ((image->matte) && (alpha_type == AssociatedAlpha) - && (sample == (max_sample-1))) - DisassociateAlphaRegion(image); - /* - Save our updates. - */ - if (!SyncImagePixels(image)) - { - CopyException(exception,&image->exception); - status=MagickFail; - break; - } - p += stride; - } - if (status == MagickFail) - break; + p=tile; + for (yy=y; yy < (long) y+tile_set_rows; yy++) + { + /* + Obtain pixel region corresponding to tile row. + */ + if (sample == 0) + q=SetImagePixelsEx(image,x,yy,tile_set_columns,1,exception); + else + q=GetImagePixelsEx(image,x,yy,tile_set_columns,1,exception); + if (q == (PixelPacket *) NULL) + { + status=MagickFail; + break; + } + /* + Compact tile row to only contain raster data. + */ + if ((samples_per_pixel > quantum_samples) && + (planar_config == PLANARCONFIG_CONTIG)) + CompactSamples(tile_set_columns, bits_per_sample, + samples_per_pixel, quantum_samples, p); + /* + Import tile row + */ + if (ImportImagePixelArea(image,quantum_type, + bits_per_sample,p, + &import_options,0) + == MagickFail) + { + CopyException(exception,&image->exception); + status=MagickFail; + break; + } + /* + Disassociate alpha from pixels if necessary. + */ + if ((image->matte) && (alpha_type == AssociatedAlpha) + && (sample == (max_sample-1))) + DisassociateAlphaRegion(image); + /* + Save our updates. + */ + if (!SyncImagePixelsEx(image,exception)) + { + status=MagickFail; + break; + } + p += stride; + } + if (status == MagickFail) + break; } if (status == MagickFail) break; - + if (image->previous == (Image *) NULL) if (QuantumTick((y+sample*image->rows)/tile_rows, - (image->rows*max_sample)/tile_rows)) + (image->rows*max_sample)/tile_rows)) if (!MagickMonitorFormatted((y+sample*image->rows)/tile_rows, - (image->rows*max_sample)/tile_rows, - exception, + (image->rows*max_sample)/tile_rows, + exception, LoadImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) { status=MagickFail; break; @@ -2815,17 +3058,29 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) number_pixels=MagickArraySize(image->columns,rows_per_strip); if (0 == number_pixels) { - TIFFClose(tiff); - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, - image); + ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed, + image); + } + /* + Rationalize memory request based on file size + */ + if ((magick_off_t) (number_pixels*sizeof(uint32)) > + file_size*max_compress_ratio) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Unreasonable allocation size " + "(ratio of alloc to file size %g)", + (double) (number_pixels*sizeof(uint32))/file_size); + ThrowTIFFReaderException(CorruptImageError,InsufficientImageDataInFile, + image); } strip_pixels=MagickAllocateArray(uint32 *,number_pixels,sizeof(uint32)); if (strip_pixels == (uint32 *) NULL) { - TIFFClose(tiff); - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, - image); + ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed, + image); } + memset(strip_pixels,0,(size_t) number_pixels*sizeof(uint32)); if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Allocated %" MAGICK_SIZE_T_F "u bytes for RGBA strip", @@ -2837,10 +3092,9 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) p=0; for (y=0; y < image->rows; y++) { - q=SetImagePixels(image,0,y,image->columns,1); + q=SetImagePixelsEx(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { - CopyException(exception,&image->exception); status=MagickFail; break; } @@ -2869,10 +3123,9 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) Disassociate alpha from pixels if necessary. */ if ((image->matte) && (alpha_type == AssociatedAlpha)) - DisassociateAlphaRegion(image); - if (!SyncImagePixels(image)) + DisassociateAlphaRegion(image); + if (!SyncImagePixelsEx(image,exception)) { - CopyException(exception,&image->exception); status=MagickFail; break; } @@ -2880,7 +3133,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception, LoadImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) { status=MagickFail; break; @@ -2896,15 +3149,18 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) */ register uint32 *p; - + uint32 *tile_pixels, tile_columns, tile_rows; - + + tsize_t + tile_size_max; + size_t tile_total_pixels; - + if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using RGB tiled read method with %u bits per sample", @@ -2915,8 +3171,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (!(TIFFGetField(tiff,TIFFTAG_TILEWIDTH,&tile_columns) == 1) || !(TIFFGetField(tiff,TIFFTAG_TILELENGTH,&tile_rows) == 1)) { - TIFFClose(tiff); - ThrowReaderException(CoderError,ImageIsNotTiled,image); + ThrowTIFFReaderException(CoderError,ImageIsNotTiled,image); } tile_total_pixels=MagickArraySize(tile_columns,tile_rows); if (logging) @@ -2929,15 +3184,35 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) (MAGICK_SIZE_T) tile_total_pixels); } /* + Obtain the maximum number of bytes required to contain a tile. + */ + tile_size_max=TIFFTileSize(tiff); + if (tile_size_max <= 0) + { + ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed, + image); + } + /* + Rationalize memory request based on file size + */ + if (tile_size_max > file_size*max_compress_ratio) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Unreasonable tile allocation size " + "(ratio of alloc to file size %g)", + (double) tile_size_max/file_size); + ThrowTIFFReaderException(CorruptImageError,InsufficientImageDataInFile, + image); + } + /* Allocate tile buffer */ tile_pixels=MagickAllocateArray(uint32*,MagickArraySize(tile_columns,tile_rows), sizeof (uint32)); if (tile_pixels == (uint32 *) NULL) { - TIFFClose(tiff); - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, - image); + ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed, + image); } for (y=0; y < image->rows; y+=tile_rows) { @@ -2959,10 +3234,9 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) /* Obtain a row of pixels */ - strip=SetImagePixels(image,0,y,image->columns,tile_rows_remaining); + strip=SetImagePixelsEx(image,0,y,image->columns,tile_rows_remaining,exception); if (strip == (PixelPacket *) NULL) { - CopyException(exception,&image->exception); status=MagickFail; break; } @@ -3027,10 +3301,9 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) Disassociate alpha from pixels if necessary. */ if ((image->matte) && (alpha_type == AssociatedAlpha)) - DisassociateAlphaRegion(image); - if (!SyncImagePixels(image)) + DisassociateAlphaRegion(image); + if (!SyncImagePixelsEx(image,exception)) { - CopyException(exception,&image->exception); status=MagickFail; break; } @@ -3038,7 +3311,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception, LoadImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) { status=MagickFail; break; @@ -3066,41 +3339,60 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) /* Convert TIFF image to DirectClass MIFF image. */ - number_pixels=(size_t) image->columns*image->rows; - if ((image->columns == 0) || - (number_pixels/image->columns != image->rows)) + number_pixels=MagickArraySize(image->columns,image->rows); + if (number_pixels == 0) { - TIFFClose(tiff); - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, - image); + ThrowException(exception,ResourceLimitError,MemoryAllocationFailed, + image->filename); + status=MagickFail; + break; } - pixels=MagickAllocateArray(uint32 *, - number_pixels+6*image->columns, - sizeof(uint32)); + + /* + TIFFReadRGBAImage reads a strip- or tile-based image + into memory, storing the result in the user supplied + raster. The raster is assumed to be an array of width + times height 32-bit entries, where width must be less + than or equal to the width of the image (height may be + any non-zero size). If the raster dimensions are smaller + than the image, the image data is cropped to the raster + bounds. If the raster height is greater than that of + the image, then the image data are placed in the lower + part of the raster. (Note that the raster is assumed to + be organized such that the pixel at location (x,y) is + raster[y*width+x]; with the raster origin in the + lower-left hand corner.) + + Please note that this allocation used to be + (number_pixels+6*image->columns)*sizeof(uint32) for + unknown reasons. + */ + pixels=MagickAllocateArray(uint32 *,number_pixels,sizeof(uint32)); if (pixels == (uint32 *) NULL) { - TIFFClose(tiff); - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, - image); + ThrowException(exception,ResourceLimitError,MemoryAllocationFailed, + image->filename); + status=MagickFail; + break; + } if (!TIFFReadRGBAImage(tiff,(uint32) image->columns, (uint32) image->rows, - pixels+image->columns,0)) + pixels,0)) { MagickFreeMemory(pixels); - TIFFClose(tiff); - return ((Image *) NULL); + status=MagickFail; + break; } /* Convert image to DirectClass pixel packets. */ - p=pixels+number_pixels+image->columns-1; + p=pixels+number_pixels-1; for (y=0; y < image->rows; y++) { - q=SetImagePixels(image,0,y,image->columns,1); + q=SetImagePixelsEx(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { - CopyException(exception,&image->exception); status=MagickFail; break; } @@ -3129,9 +3421,8 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) */ if ((image->matte) && (alpha_type == AssociatedAlpha)) DisassociateAlphaRegion(image); - if (!SyncImagePixels(image)) + if (!SyncImagePixelsEx(image,exception)) { - CopyException(exception,&image->exception); status=MagickFail; break; } @@ -3139,7 +3430,7 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception, LoadImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) { status=MagickFail; break; @@ -3185,10 +3476,10 @@ ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception) status=MagickMonitorFormatted(image->scene-1,image->scene, &image->exception, LoadImageText,image->filename, - image->columns,image->rows); + image->columns,image->rows); } } - + if (status == MagickFail) break; @@ -3518,7 +3809,7 @@ WriteGROUP4RAWImage(const ImageInfo *image_info,Image *image) TIFFClose(tiff); (void) LiberateTemporaryFile(temporary_filename); ThrowWriterException(ResourceLimitError,MemoryAllocationFailed, - image); + image); } /* Open blob for output @@ -3536,13 +3827,13 @@ WriteGROUP4RAWImage(const ImageInfo *image_info,Image *image) Compress runlength encoded to 2D Huffman pixels. */ (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Output 2D Huffman pixels."); + "Output 2D Huffman pixels."); for (i=0; i < TIFFNumberOfStrips(tiff); i++) { count=TIFFReadRawStrip(tiff,(uint32) i,strip,strip_size); (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Writing strip %u (%lu bytes) to blob ...", - i,(unsigned long) count); + "Writing strip %u (%lu bytes) to blob ...", + i,(unsigned long) count); if ((toff_t) WriteBlob(image,count,strip) != count) status=MagickFail; } @@ -3568,7 +3859,7 @@ WriteGROUP4RAWImage(const ImageInfo *image_info,Image *image) % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% WritePTIFImage() writes an image in the pyrimid-encoded Tagged image file +% WritePTIFImage() writes an image in the pyramid-encoded Tagged image file % format. % % The format of the WritePTIFImage method is: @@ -3602,6 +3893,12 @@ WritePTIFImage(const ImageInfo *image_info,Image *image) unsigned int status; + const char + *def; + + RectangleInfo + min_geometry; + /* Create pyramid-encoded TIFF image. */ @@ -3609,28 +3906,53 @@ WritePTIFImage(const ImageInfo *image_info,Image *image) assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); + if (!(((def=AccessDefinition(image_info,"ptif","minimum-geometry")) != NULL) && + (GetGeometry(def,&min_geometry.x,&min_geometry.y,&min_geometry.width, + &min_geometry.height) & (WidthValue|HeightValue)))) + { + /* + Minimum default subresolution frame is 32x32 + */ + min_geometry.height=32; + min_geometry.width=32; + } + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "PTIF minimum pyramid dimensions: %lux%lu", + min_geometry.width, min_geometry.height); filter=TriangleFilter; if (image->is_monochrome) filter=PointFilter; pyramid_image=CloneImage(image,0,0,True,&image->exception); if (pyramid_image == (Image *) NULL) ThrowWriterException2(FileOpenError,image->exception.reason,image); + DestroyBlob(pyramid_image); + pyramid_image->blob=ReferenceBlob(image->blob); (void) SetImageAttribute(pyramid_image,"subfiletype","NONE"); - do + while(1) { + if ((pyramid_image->columns/2 < min_geometry.width) || + (pyramid_image->rows/2 < min_geometry.height)) + break; + pyramid_image->next=ResizeImage(image,pyramid_image->columns/2, pyramid_image->rows/2,filter, 1.0,&image->exception); if (pyramid_image->next == (Image *) NULL) - ThrowWriterException2(FileOpenError,image->exception.reason,image); + { + DestroyImageList(pyramid_image); + ThrowWriterException2(FileOpenError,image->exception.reason,image); + } + DestroyBlob(pyramid_image->next); + pyramid_image->next->blob=ReferenceBlob(image->blob); if ((!image->is_monochrome) && (image->storage_class == PseudoClass)) (void) MapImage(pyramid_image->next,image,False); - pyramid_image->next->x_resolution=pyramid_image->x_resolution/2; - pyramid_image->next->y_resolution=pyramid_image->y_resolution/2; + pyramid_image->next->x_resolution=pyramid_image->x_resolution/2.0; + pyramid_image->next->y_resolution=pyramid_image->y_resolution/2.0; (void) SetImageAttribute(pyramid_image->next,"subfiletype","REDUCEDIMAGE"); pyramid_image->next->previous=pyramid_image; pyramid_image=pyramid_image->next; - } while ((pyramid_image->columns > 64) && (pyramid_image->rows > 64)); + }; while (pyramid_image->previous != (Image *) NULL) pyramid_image=pyramid_image->previous; /* @@ -3683,9 +4005,9 @@ WritePTIFImage(const ImageInfo *image_info,Image *image) static void WriteNewsProfile(TIFF *tiff, - int profile_tag, - const unsigned char *profile_data, - const size_t profile_length) + int profile_tag, + const unsigned char *profile_data, + const size_t profile_length) { unsigned char *profile=0; @@ -3756,9 +4078,13 @@ WriteNewsProfile(TIFF *tiff, MagickFreeMemory(profile); } -#if !defined(TIFFDefaultStripSize) -#define TIFFDefaultStripSize(tiff,request) ((8*1024)/TIFFScanlineSize(tiff)) -#endif +#define ThrowTIFFWriterException(code_,reason_,image_) \ +{ \ + if (tiff != (TIFF *) NULL) \ + TIFFClose(tiff); \ + ThrowWriterException(code_,reason_,image_); \ +} + static MagickPassFail WriteTIFFImage(const ImageInfo *image_info,Image *image) { @@ -3777,7 +4103,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) i; TIFF - *tiff; + *tiff = (TIFF *) NULL; uint16 bits_per_sample, @@ -3823,6 +4149,9 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) depth, scene; + size_t + image_list_length; + /* Open TIFF file. */ @@ -3830,6 +4159,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); + image_list_length=GetImageListLength(image); logging=IsEventLogging(); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == MagickFail) @@ -3897,7 +4227,8 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) TIFFUnmapBlob); if (tiff == (TIFF *) NULL) { - /* CloseBlob(image); */ + if (GetBlobIsOpen(image)) + CloseBlob(image); return(MagickFail); } scene=0; @@ -3950,7 +4281,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "%s compression not supported. " - "Compression request removed", + "Compression request removed", compression_name); } } @@ -3984,7 +4315,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) case JBIG1Compression: { compress_tag=COMPRESSION_JBIG; - fill_order=FILLORDER_LSB2MSB; + fill_order=FILLORDER_LSB2MSB; break; } #endif /* defined(COMPRESSION_JBIG) */ @@ -4015,6 +4346,20 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) compress_tag=COMPRESSION_ADOBE_DEFLATE; break; } +#if defined(COMPRESSION_ZSTD) + case ZSTDCompression: + { + compress_tag=COMPRESSION_ZSTD; + break; + } +#endif /* defined(COMPRESSION_ZSTD) */ +#if defined(COMPRESSION_WEBP) + case WebPCompression: + { + compress_tag=COMPRESSION_WEBP; + break; + } +#endif /* defined(COMPRESSION_WEBP) */ default: { compress_tag=COMPRESSION_NONE; @@ -4045,7 +4390,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Image characteristics: cmyk=%c, gray=%c, mono=%c," - " opaque=%c, palette=%c", + " opaque=%c, palette=%c", (characteristics.cmyk ? 'y' : 'n'), (characteristics.grayscale ? 'y' : 'n'), (characteristics.monochrome ? 'y' : 'n'), @@ -4070,7 +4415,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) { const char * compress_type; - + compress_type=CompressionTagToString(compress_tag); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Disabled image matte channel since " @@ -4130,13 +4475,13 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) MINISWHITE. CMYK takes precedence over JPEG compression. */ if ((compress_tag == COMPRESSION_JPEG) && - (photometric == PHOTOMETRIC_PALETTE)) + (photometric == PHOTOMETRIC_PALETTE)) { photometric=PHOTOMETRIC_RGB; if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using RGB photometric due to request for" - " JPEG compression."); + " JPEG compression."); } else if (compress_tag == COMPRESSION_CCITTFAX3) { @@ -4144,7 +4489,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using MINISWHITE photometric due to request" - " for Group3 FAX compression."); + " for Group3 FAX compression."); } else if (compress_tag == COMPRESSION_CCITTFAX4) { @@ -4152,7 +4497,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using MINISWHITE photometric due to request" - " for Group4 FAX compression."); + " for Group4 FAX compression."); } #if defined(COMPRESSION_JBIG) else if (compress_tag == COMPRESSION_JBIG) @@ -4161,9 +4506,19 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using MINISWHITE photometric due to request" - " for JBIG compression."); + " for JBIG compression."); } #endif /* defined(COMPRESSION_JBIG) */ +#if defined(COMPRESSION_WEBP) + else if (compress_tag == COMPRESSION_WEBP) + { + photometric=PHOTOMETRIC_RGB; + if (logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Using RGB photometric due to request for" + " WebP compression."); + } +#endif /* defined(COMPRESSION_WEBP) */ /* Allow user to override the photometric. @@ -4237,15 +4592,15 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) */ if ((compress_tag == COMPRESSION_JPEG) && ((photometric != PHOTOMETRIC_MINISWHITE) && - (photometric != PHOTOMETRIC_MINISBLACK) && - (photometric != PHOTOMETRIC_RGB) && + (photometric != PHOTOMETRIC_MINISBLACK) && + (photometric != PHOTOMETRIC_RGB) && (photometric != PHOTOMETRIC_YCBCR))) { compress_tag=COMPRESSION_NONE; if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Ignoring request for JPEG compression due " - "to incompatible photometric."); + "to incompatible photometric."); } else if ((compress_tag == COMPRESSION_CCITTFAX3) && (photometric != PHOTOMETRIC_MINISWHITE)) @@ -4255,7 +4610,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Ignoring request for Group3 FAX compression" - " due to incompatible photometric."); + " due to incompatible photometric."); } else if ((compress_tag == COMPRESSION_CCITTFAX4) && (photometric != PHOTOMETRIC_MINISWHITE)) @@ -4265,7 +4620,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Ignoring request for Group4 FAX compression" - " due to incompatible photometric."); + " due to incompatible photometric."); } #if defined(COMPRESSION_JBIG) else if ((compress_tag == COMPRESSION_JBIG) && @@ -4276,7 +4631,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Ignoring request for JBIG compression" - " due to incompatible photometric."); + " due to incompatible photometric."); } #endif /* defined(COMPRESSION_JBIG) */ @@ -4355,7 +4710,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) libtiff or libtiff can be extended? FIXME - */ + */ #if defined(BITS_IN_JSAMPLE) depth=BITS_IN_JSAMPLE; bits_per_sample=BITS_IN_JSAMPLE; @@ -4415,7 +4770,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) break; } } - + (void) TIFFSetField(tiff,TIFFTAG_EXTRASAMPLES,extra_samples, &sample_info); } @@ -4479,12 +4834,12 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) /* Clamp maximum unsigned bits per sample to 32 bits */ if ((bits_per_sample < 1) || ((bits_per_sample > 32) && (bits_per_sample != 64))) - bits_per_sample=old_value; + bits_per_sample=old_value; } if ((logging) && (old_value != bits_per_sample)) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "User override (bits-per-sample): %u bits " - "per sample (was %u)", + "per sample (was %u)", (unsigned int) bits_per_sample, old_value); } @@ -4499,7 +4854,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "User override (samples-per-pixel): %u " - "samples per pixel (was %u)", + "samples per pixel (was %u)", (unsigned int) samples_per_pixel, old_value); } } @@ -4509,35 +4864,35 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) */ planar_config=PLANARCONFIG_CONTIG; if (samples_per_pixel > 1) - { - switch (image->interlace) - { - case UndefinedInterlace: - break; - case NoInterlace: - case LineInterlace: - case PartitionInterlace: - planar_config=PLANARCONFIG_CONTIG; - break; - case PlaneInterlace: - planar_config=PLANARCONFIG_SEPARATE; - break; - } - - switch (image_info->interlace) - { - case UndefinedInterlace: - break; - case NoInterlace: - case LineInterlace: - case PartitionInterlace: - planar_config=PLANARCONFIG_CONTIG; - break; - case PlaneInterlace: - planar_config=PLANARCONFIG_SEPARATE; - break; - } - } + { + switch (image->interlace) + { + case UndefinedInterlace: + break; + case NoInterlace: + case LineInterlace: + case PartitionInterlace: + planar_config=PLANARCONFIG_CONTIG; + break; + case PlaneInterlace: + planar_config=PLANARCONFIG_SEPARATE; + break; + } + + switch (image_info->interlace) + { + case UndefinedInterlace: + break; + case NoInterlace: + case LineInterlace: + case PartitionInterlace: + planar_config=PLANARCONFIG_CONTIG; + break; + case PlaneInterlace: + planar_config=PLANARCONFIG_SEPARATE; + break; + } + } /* YCbCr encoding compresses much better than RGB. Use YCbCr @@ -4557,7 +4912,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using %s photometric, %u samples per pixel, " - "%u bits per sample, format %s", + "%u bits per sample, format %s", PhotometricTagToString(photometric), (unsigned int) samples_per_pixel, (unsigned int) bits_per_sample, @@ -4584,10 +4939,10 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,sample_format); (void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,planar_config); if (logging) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "%s image planes", - (planar_config == PLANARCONFIG_SEPARATE ? - "Separate" : "Contiguous")); + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "%s image planes", + (planar_config == PLANARCONFIG_SEPARATE ? + "Separate" : "Contiguous")); (void) TIFFSetField(tiff,TIFFTAG_COMPRESSION,compress_tag); /* @@ -4620,16 +4975,26 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) /* RowsPerStrip must be multiple of 16 for JPEG. - RowsPerStrip is required to be a multiple of 8 times the - largest vertical sampling factor. If YCbCr subsampling - is 2,2 then RowsPerStrip must be a multiple of 16. + RowsPerStrip is required to be a multiple of 8 times the + largest vertical sampling factor. If YCbCr subsampling + is 2,2 then RowsPerStrip must be a multiple of 16. */ - rows_per_strip=(((rows_per_strip < 16 ? 16 : rows_per_strip)+1)/16)*16; + rows_per_strip=(((rows_per_strip < 16 ? 16 : rows_per_strip)+1)/16)*16; + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "JPEG Quality: %u", (unsigned) image_info->quality); (void) TIFFSetField(tiff,TIFFTAG_JPEGQUALITY,image_info->quality); if (IsRGBColorspace(image->colorspace)) - (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RGB); + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "TIFFTAG_JPEGCOLORMODE: JPEGCOLORMODE_RGB"); + (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RGB); + } if (bits_per_sample == 12) - (void) TIFFSetField(tiff,TIFFTAG_JPEGTABLESMODE,JPEGTABLESMODE_QUANT); + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "TIFFTAG_JPEGTABLESMODE: JPEGTABLESMODE_QUANT"); + (void) TIFFSetField(tiff,TIFFTAG_JPEGTABLESMODE,JPEGTABLESMODE_QUANT); + } break; } case COMPRESSION_ADOBE_DEFLATE: @@ -4652,7 +5017,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (((photometric == PHOTOMETRIC_RGB) || (photometric == PHOTOMETRIC_MINISBLACK)) && ((bits_per_sample == 8) || (bits_per_sample == 16))) - predictor=PREDICTOR_HORIZONTAL; + predictor=PREDICTOR_HORIZONTAL; { /* Zip quality has a useful range of 1-9. @@ -4662,6 +5027,9 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) zip_quality=1; if (zip_quality > 9) zip_quality=9; + + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "TIFFTAG_ZIPQUALITY: %u", zip_quality); (void) TIFFSetField(tiff,TIFFTAG_ZIPQUALITY,zip_quality); } break; @@ -4675,25 +5043,25 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) Group3Options = 4,5. LONG. Data may be one- or two-dimensional, but EOLs must be byte-aligned. Uncompressed data is not allowed. - + bit 0 = 0 for 1-Dimensional, 1 for 2-Dimensional - + bit 1 = must be 0 (uncompressed data not allowed) bit 2 = 1 for byte-aligned EOLs */ - uint32 - group_three_options = 4; - - const char * - value; - - if ((value=AccessDefinition(image_info,"tiff","group-three-options"))) - { - group_three_options=(uint32) strtol(value,(char **)NULL, 10); - } - (void) TIFFSetField(tiff,TIFFTAG_GROUP3OPTIONS,group_three_options); + uint32 + group_three_options = 4; + + const char * + value; + + if ((value=AccessDefinition(image_info,"tiff","group-three-options"))) + { + group_three_options=(uint32) strtol(value,(char **)NULL, 10); + } + (void) TIFFSetField(tiff,TIFFTAG_GROUP3OPTIONS,group_three_options); /* It is recommended (but not required) to output FAX as @@ -4724,67 +5092,70 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) #if defined(COMPRESSION_LZMA) case COMPRESSION_LZMA: { - unsigned int - lzma_preset; - - const char * - lzma_preset_str; - - /* - Lzma preset has a useful range of 1-9. - - We default to 1 since testing does not show much benefit - from use of larger values. However, we allow the - power-user who wants to experiment to change the preset - value via syntax like '-define tiff:lzmapreset=7'. This - ability is intentionally not documented other than here. - */ - - lzma_preset=1; - if ((lzma_preset_str=AccessDefinition(image_info,"tiff","lzmapreset"))) - lzma_preset=(unsigned short) MagickAtoI(lzma_preset_str); - - if (lzma_preset < 1) - lzma_preset=1; - if (lzma_preset > 9) - lzma_preset=9; - (void) TIFFSetField(tiff,TIFFTAG_LZMAPRESET,lzma_preset); - if (logging) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "LZMA PRESET set to %u", lzma_preset); - - { - /* - Provide a default rows-per-strip which is suitably - tailored for the compression level. - */ - - /* - Strip memory target for various compression preset levels. - Values are arbitrary. LZMA is a memory and CPU pig. - */ - static const unsigned int - lzma_memory_mb[] = - { /* Level Compress Decompress */ - 1U, /* 1 2 MB 1 MB */ - 4U, /* 2 12 MB 2 MB */ - 4U, /* 3 12 MB 1 MB */ - 4U, /* 4 16 MB 2 MB */ - 6U, /* 5 26 MB 3 MB */ - 10U, /* 6 45 MB 5 MB */ - 18U, /* 7 83 MB 9 MB */ - 34U, /* 8 159 MB 17 MB */ - 66U /* 9 311 MB 33 MB */ - }; - - rows_per_strip = (uint32) (((lzma_memory_mb[lzma_preset-1]*1024U*1024U))/ - ((((unsigned long) bits_per_sample*samples_per_pixel)/ - 8U)*image->rows)); - if (rows_per_strip < 1) - rows_per_strip=1U; - if (rows_per_strip > image->rows) - rows_per_strip=image->rows; - } + unsigned int + lzma_preset; + + const char * + lzma_preset_str; + + /* + Lzma preset has a useful range of 1-9. + + We default to 1 since testing does not show much benefit + from use of larger values. However, we allow the + power-user who wants to experiment to change the preset + value via syntax like '-define tiff:lzmapreset=7'. This + ability is intentionally not documented other than here. + */ + + lzma_preset=1; + if ((lzma_preset_str=AccessDefinition(image_info,"tiff","lzmapreset"))) + lzma_preset=(unsigned short) MagickAtoI(lzma_preset_str); + + if (lzma_preset < 1) + lzma_preset=1; + if (lzma_preset > 9) + lzma_preset=9; + (void) TIFFSetField(tiff,TIFFTAG_LZMAPRESET,lzma_preset); + if (logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "LZMA PRESET set to %u", lzma_preset); + + { + /* + Provide a default rows-per-strip which is suitably + tailored for the compression level. + */ + + /* + Strip memory target for various compression preset levels. + Values are arbitrary. LZMA is a memory and CPU pig. + */ + static const unsigned int + lzma_memory_mb[] = + { /* Level Compress Decompress */ + 1U, /* 1 2 MB 1 MB */ + 4U, /* 2 12 MB 2 MB */ + 4U, /* 3 12 MB 1 MB */ + 4U, /* 4 16 MB 2 MB */ + 6U, /* 5 26 MB 3 MB */ + 10U, /* 6 45 MB 5 MB */ + 18U, /* 7 83 MB 9 MB */ + 34U, /* 8 159 MB 17 MB */ + 66U /* 9 311 MB 33 MB */ + }; + + rows_per_strip = + (uint32) ceil((((double) lzma_memory_mb[lzma_preset-1]* + 1024.0*1024.0*8.0))/ + (((double) bits_per_sample*samples_per_pixel + *image->columns)))/8.0; + + if (rows_per_strip < 1) + rows_per_strip=1U; + if (rows_per_strip > image->rows) + rows_per_strip=image->rows; + } /* Use horizontal differencing (type 2) for images which are @@ -4794,13 +5165,13 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (((photometric == PHOTOMETRIC_RGB) || (photometric == PHOTOMETRIC_MINISBLACK)) && ((bits_per_sample == 8) || (bits_per_sample == 16))) - predictor=PREDICTOR_HORIZONTAL; + predictor=PREDICTOR_HORIZONTAL; break; } #endif /* COMPRESSION_LZMA */ #if defined(COMPRESSION_JBIG) - case COMPRESSION_JBIG: - { + case COMPRESSION_JBIG: + { /* It is recommended (but not required) to output FAX as one strip. We will limit strip size to 16 megapixels by @@ -4811,8 +5182,8 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) rows_per_strip=1; if (rows_per_strip > image->rows) rows_per_strip=(uint32) image->rows; - break; - } + break; + } #endif /* COMPRESSION_JBIG */ case COMPRESSION_LZW: { @@ -4824,9 +5195,104 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (((photometric == PHOTOMETRIC_RGB) || (photometric == PHOTOMETRIC_MINISBLACK)) && ((bits_per_sample == 8) || (bits_per_sample == 16))) - predictor=PREDICTOR_HORIZONTAL; + predictor=PREDICTOR_HORIZONTAL; + break; + } +#if defined(COMPRESSION_ZSTD) + case COMPRESSION_ZSTD: + { + /* + Larger strips compress better with diminishing returns + (enlarge if necessary).. + */ + unsigned int + proposed_rows_per_strip; + + proposed_rows_per_strip = (uint32) (512*1024) / Max(scanline_size,1); + if (proposed_rows_per_strip > rows_per_strip) + rows_per_strip=proposed_rows_per_strip; + /* + Use horizontal differencing (type 2) for images which are + likely to be continuous tone. The TIFF spec says that this + usually leads to better compression. + */ + if (((photometric == PHOTOMETRIC_RGB) || + (photometric == PHOTOMETRIC_MINISBLACK)) && + ((bits_per_sample == 8) || (bits_per_sample == 16))) + predictor=PREDICTOR_HORIZONTAL; + { + /* + Zstd level has a useful range of 1-19 (or even 22). + + Libtiff uses a default level of 9. + + Default for ImageInfo 'quality' is 75, which is translated to 9. + + Use -define tiff:zstd-compress-level= to specify a value. + */ + const char *value; + int compress_level = (image_info->quality*9)/75; +#if defined(HasZSTD) + int max_compression = ZSTD_maxCLevel(); +#else + int max_compression = 19; +#endif + if ((value=AccessDefinition(image_info,"tiff","zstd-compress-level"))) + compress_level=MagickAtoI(value); + if (compress_level < 1) + compress_level=1; + if (compress_level > max_compression) + compress_level=max_compression; + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "TIFFTAG_ZSTD_LEVEL: %u", compress_level); + (void) TIFFSetField(tiff,TIFFTAG_ZSTD_LEVEL,compress_level); + } + break; + } +#endif /* defined(COMPRESSION_ZSTD) */ +#if defined(COMPRESSION_WEBP) + case COMPRESSION_WEBP: + { + /* + Larger strips compress better with diminishing returns + (enlarge if necessary).. + */ + unsigned int + proposed_rows_per_strip; + + proposed_rows_per_strip = (uint32) (1024*1024) / Max(scanline_size,1); + if (proposed_rows_per_strip > rows_per_strip) + rows_per_strip=proposed_rows_per_strip; + + /* TIFFTAG_WEBP_LEVEL */ + if (image_info->quality != DefaultCompressionQuality) + { + int quality = (int) image_info->quality; + if (quality < 1) + quality=1; + else if (quality > 100) + quality=100; + + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "TIFFTAG_WEBP_LEVEL: %d", quality); + (void) TIFFSetField(tiff,TIFFTAG_WEBP_LEVEL,quality); + } + + /* TIFFTAG_WEBP_LOSSLESS */ + { + const char *value; + if (((value=AccessDefinition(image_info,"tiff","webp-lossless")) != NULL) || + ((value=AccessDefinition(image_info,"webp","lossless")) != NULL)) + { + int lossless=(LocaleCompare(value,"TRUE") == 0 ? 1 : 0); + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "TIFFTAG_WEBP_LOSSLESS: %d", lossless); + (void) TIFFSetField(tiff,TIFFTAG_WEBP_LOSSLESS,lossless); + } + } break; } +#endif /* defined(COMPRESSION_WEBP) */ default: { break; @@ -4834,24 +5300,24 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) } /* - Allow the user to specify the predictor (at their own peril) + Allow the user to specify the predictor (at their own peril) */ { - const char * + const char * value; - - if ((value=AccessDefinition(image_info,"tiff","predictor"))) - predictor=(unsigned short) MagickAtoI(value); + + if ((value=AccessDefinition(image_info,"tiff","predictor"))) + predictor=(unsigned short) MagickAtoI(value); } if (predictor != 0) - { - if (logging) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Requesting predictor %u", - (unsigned int) predictor); - (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,predictor); - } + { + if (logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Requesting predictor %u", + (unsigned int) predictor); + (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,predictor); + } /* Allow the user to override rows-per-strip settings. @@ -4865,13 +5331,13 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) { unsigned int old_value; - + old_value=rows_per_strip; rows_per_strip=MagickAtoI(value); if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "User override (rows_per_strip): %u rows" - " per strip (was %u)", + " per strip (was %u)", (unsigned int) rows_per_strip, old_value); } if ((value=AccessDefinition(image_info,"tiff","strip-per-page"))) @@ -4879,27 +5345,27 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (LocaleCompare("TRUE",value) == 0) { rows_per_strip=(uint32) image->rows; - + if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "User requested a single strip per " - "page (strip-per-page)"); + "page (strip-per-page)"); } } } if (COMPRESSION_JPEG == compress_tag) - { - /* - RowsPerStrip must be multiple of 16 for JPEG. - */ - rows_per_strip=(((rows_per_strip < 16 ? 16 : rows_per_strip)+1)/16)*16; - } + { + /* + RowsPerStrip must be multiple of 16 for JPEG. + */ + rows_per_strip=(((rows_per_strip < 16 ? 16 : rows_per_strip)+1)/16)*16; + } if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using %s compression", - CompressionTagToString(compress_tag)); + CompressionTagToString(compress_tag)); if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Image depth %lu bits",depth); @@ -4981,7 +5447,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) profile_data); } #endif /* defined(TIFFTAG_XMLPACKET) */ - + #if defined(TIFFTAG_ICCPROFILE) /* ICC color profile. @@ -4995,7 +5461,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) profile_data); } #endif /* defined(ICC_SUPPORT) */ - + /* IPTC NewsPhoto profile. */ @@ -5008,14 +5474,14 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) profile_tag=TIFFTAG_PHOTOSHOP; (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Photoshop embedded profile with length %lu" - " bytes", + " bytes", (unsigned long) profile_length); #else /* IPTC TAG from RichTIFF specifications */ profile_tag=TIFFTAG_RICHTIFFIPTC; (void) LogMagickEvent(CoderEvent,GetMagickModule(), "IPTC Newsphoto embedded profile with length" - " %lu bytes", + " %lu bytes", (unsigned long) profile_length); #endif /* defined(PHOTOSHOP_SUPPORT) */ @@ -5054,7 +5520,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) pages; page=(uint16) scene; - pages=GetImageListLength(image); + pages=(uint16) image_list_length; if (image_info->adjoin && pages > 1) { @@ -5092,7 +5558,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) attribute=GetImageAttribute(image,"make"); if (attribute != (const ImageAttribute *) NULL) (void) TIFFSetField(tiff,TIFFTAG_MAKE,attribute->value); - + attribute=GetImageAttribute(image,"model"); if (attribute != (const ImageAttribute *) NULL) (void) TIFFSetField(tiff,TIFFTAG_MODEL,attribute->value); @@ -5118,8 +5584,8 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) #if 0 /* - This tag is not supported by libtiff so the tag extension - mechanism would need to be used to add support for it. + This tag is not supported by libtiff so the tag extension + mechanism would need to be used to add support for it. */ attribute=GetImageAttribute(image,"imageid"); if (attribute != (const ImageAttribute *) NULL) @@ -5145,8 +5611,13 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if ((blue == (unsigned short *) NULL) || (green == (unsigned short *) NULL) || (red == (unsigned short *) NULL)) - ThrowWriterException(ResourceLimitError,MemoryAllocationFailed, - image); + { + MagickFreeMemory(blue); + MagickFreeMemory(green); + MagickFreeMemory(red); + ThrowTIFFWriterException(ResourceLimitError,MemoryAllocationFailed, + image); + } (void) memset(red,0,65536L*sizeof(unsigned short)); (void) memset(green,0,65536L*sizeof(unsigned short)); (void) memset(blue,0,65536L*sizeof(unsigned short)); @@ -5222,7 +5693,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) QuantumType quantum_type; - + /* Allocate memory for one scanline. */ @@ -5231,13 +5702,9 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using scanline %s write method with %u " - "bits per sample (%lu bytes/scanline)", + "bits per sample (%lu bytes/scanline)", PhotometricTagToString(photometric), - bits_per_sample, (unsigned long) scanline_size); - - scanline=MagickAllocateMemory(unsigned char *,(size_t) scanline_size); - if (scanline == (unsigned char *) NULL) - ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image); + bits_per_sample, (unsigned long) scanline_size); /* Prepare for separate/contiguous retrieval. */ @@ -5251,6 +5718,10 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) == MagickPass) max_sample=quantum_samples; } + + scanline=MagickAllocateMemory(unsigned char *,(size_t) scanline_size); + if (scanline == (unsigned char *) NULL) + ThrowTIFFWriterException(ResourceLimitError,MemoryAllocationFailed,image); /* For each plane */ @@ -5309,15 +5780,15 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) } if (image->previous == (Image *) NULL) - if (QuantumTick(y+sample*image->rows,image->rows*max_sample)) - if (!MagickMonitorFormatted(y+sample*image->rows, - image->rows*max_sample,&image->exception, - SaveImageText,image->filename, - image->columns,image->rows)) - { - status=MagickFail; - break; - } + if (QuantumTick(y+sample*image->rows,image->rows*max_sample)) + if (!MagickMonitorFormatted(y+sample*image->rows, + image->rows*max_sample,&image->exception, + SaveImageText,image->filename, + image->columns,image->rows)) + { + status=MagickFail; + break; + } } if (status == MagickFail) @@ -5353,13 +5824,13 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) unsigned long tile_total_pixels; - + if (logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Using tiled %s write method with %u bits " - "per sample", + "per sample", PhotometricTagToString(photometric), - bits_per_sample); + bits_per_sample); /* Determine tile size @@ -5370,17 +5841,17 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) tile_columns=0; tile_rows=0; - + /* Enable tiled output (with default size, or specified separately) -define tiff:tile - + Use an exact tile size in rows & columns -define tiff:tile-geometry=128x128 - + Use a specific tile width (pixels) -define tiff:tile-width=128 - + Use a specific tile height (pixels) -define tiff:tile-height=128 */ @@ -5404,7 +5875,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) { tile_rows=MagickAtoL(value); } - + TIFFDefaultTileSize(tiff,&tile_columns,&tile_rows); } @@ -5433,7 +5904,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) */ tile=MagickAllocateMemory(unsigned char *, (size_t) tile_size_max); if (tile == (unsigned char *) NULL) - ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image); + ThrowTIFFWriterException(ResourceLimitError,MemoryAllocationFailed,image); /* Prepare for separate/contiguous retrieval. */ @@ -5452,52 +5923,52 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) */ stride=TIFFTileRowSize(tiff); - /* - Process each plane. - */ - for (sample=0; sample < max_sample; sample++) - { - /* - Determine quantum parse method. - */ - if (QuantumTransferMode(image,photometric,compress_tag, + /* + Process each plane. + */ + for (sample=0; sample < max_sample; sample++) + { + /* + Determine quantum parse method. + */ + if (QuantumTransferMode(image,photometric,compress_tag, sample_format,samples_per_pixel, planar_config,sample,&quantum_type, &quantum_samples,&image->exception) == MagickFail) - { - status=MagickFail; - break; - } - for (y=0; y < image->rows; y+=tile_rows) - { - for (x=0; x < image->columns; x+=tile_columns) - { - const PixelPacket - *p; - - long - tile_set_columns, - tile_set_rows; - - unsigned char - *q; - - register long - yy; - - /* - Compute image region corresponding to tile. - */ - if (x+tile_columns > image->columns) - tile_set_columns=(tile_columns-(x+tile_columns-image->columns)); - else - tile_set_columns=tile_columns; - if (y+tile_rows > image->rows) - tile_set_rows=(tile_rows-(y+tile_rows-image->rows)); - else - tile_set_rows=tile_rows; - + { + status=MagickFail; + break; + } + for (y=0; y < image->rows; y+=tile_rows) + { + for (x=0; x < image->columns; x+=tile_columns) + { + const PixelPacket + *p; + + long + tile_set_columns, + tile_set_rows; + + unsigned char + *q; + + register long + yy; + + /* + Compute image region corresponding to tile. + */ + if (x+tile_columns > image->columns) + tile_set_columns=(tile_columns-(x+tile_columns-image->columns)); + else + tile_set_columns=tile_columns; + if (y+tile_rows > image->rows) + tile_set_rows=(tile_rows-(y+tile_rows-image->rows)); + else + tile_set_rows=tile_rows; + q=tile; for (yy=y; yy < (long) y+tile_set_rows; yy++) { @@ -5508,7 +5979,7 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) p=GetImagePixels(image,x,yy,tile_set_columns,1); else p=AcquireImagePixels(image,x,yy,tile_set_columns, - 1,&image->exception); + 1,&image->exception); if (p == (const PixelPacket *) NULL) { status=MagickFail; @@ -5550,26 +6021,26 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) { status=MagickFail; } - if (status == MagickFail) - break; - } /* for x */ - /* - Progress indicator. - */ - if (image->previous == (Image *) NULL) - if (QuantumTick((y+sample*image->rows)/tile_rows, - (image->rows*max_sample)/tile_rows)) - if (!MagickMonitorFormatted((y+sample*image->rows)/tile_rows, - (image->rows*max_sample)/tile_rows, - &image->exception, - SaveImageText,image->filename, - image->columns,image->rows)) - status=MagickFail; - - if (status == MagickFail) - break; - } /* for y */ - } /* for sample */ + if (status == MagickFail) + break; + } /* for x */ + /* + Progress indicator. + */ + if (image->previous == (Image *) NULL) + if (QuantumTick((y+sample*image->rows)/tile_rows, + (image->rows*max_sample)/tile_rows)) + if (!MagickMonitorFormatted((y+sample*image->rows)/tile_rows, + (image->rows*max_sample)/tile_rows, + &image->exception, + SaveImageText,image->filename, + image->columns,image->rows)) + status=MagickFail; + + if (status == MagickFail) + break; + } /* for y */ + } /* for sample */ MagickFreeMemory(tile); break; } @@ -5577,16 +6048,16 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) if (image_info->verbose > 1) TIFFPrintDirectory(tiff,stdout,MagickFalse); if(!TIFFWriteDirectory(tiff)) - { - status=MagickFail; - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "TIFFWriteDirectory returns failed status!"); - } + { + status=MagickFail; + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "TIFFWriteDirectory returns failed status!"); + } if (image->next == (Image *) NULL) break; image=SyncNextImageInList(image); if ((status &= MagickMonitorFormatted(scene++, - GetImageListLength(image), + image_list_length, &image->exception, SaveImagesText, image->filename)) == MagickFail) @@ -5601,10 +6072,10 @@ WriteTIFFImage(const ImageInfo *image_info,Image *image) /* Handle write failure. */ - + if (unlink(filename) != -1) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Removed broken output file \"%s\"",filename); + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Removed broken output file \"%s\"",filename); return (MagickFail); } diff --git a/coders/tile.c b/coders/tile.c index 0553aff..ad127c0 100644 --- a/coders/tile.c +++ b/coders/tile.c @@ -86,7 +86,7 @@ static Image *ReadTILEImage(const ImageInfo *image_info, RectangleInfo geometry; - + /* Initialize Image structure. @@ -100,6 +100,7 @@ static Image *ReadTILEImage(const ImageInfo *image_info, clone_info->blob=(void *) NULL; clone_info->length=0; *clone_info->magick='\0'; + MagickFreeMemory(clone_info->size); tile_image=ReadImage(clone_info,exception); DestroyImageInfo(clone_info); if (tile_image == (Image *) NULL) diff --git a/coders/tim.c b/coders/tim.c index d48721c..a250f2d 100644 --- a/coders/tim.c +++ b/coders/tim.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2015 GraphicsMagick Group +% Copyright (C) 2003-2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -38,6 +38,8 @@ #include "magick/studio.h" #include "magick/blob.h" #include "magick/colormap.h" +#include "magick/enum_strings.h" +#include "magick/log.h" #include "magick/magick.h" #include "magick/monitor.h" #include "magick/pixel_cache.h" @@ -114,13 +116,13 @@ static Image *ReadTIMImage(const ImageInfo *image_info,ExceptionInfo *exception) *p; unsigned char - *tim_data, *tim_pixels; unsigned short word; unsigned int + index, status; size_t @@ -148,260 +150,332 @@ static Image *ReadTIMImage(const ImageInfo *image_info,ExceptionInfo *exception) */ tim_info.id=ReadBlobLSBLong(image); do - { - /* - Verify TIM identifier. - */ - if (tim_info.id != 0x00000010) - ThrowReaderException(CorruptImageError,ImproperImageHeader,image); - tim_info.flag=ReadBlobLSBLong(image); - has_clut=!!(tim_info.flag & (1 << 3)); - pixel_mode=tim_info.flag & 0x07; - switch ((int) pixel_mode) { - case 0: bits_per_pixel=4; break; - case 1: bits_per_pixel=8; break; - case 2: bits_per_pixel=16; break; - case 3: bits_per_pixel=24; break; - default: bits_per_pixel=4; break; - } - image->depth=8; - if (has_clut) - { - unsigned char - *tim_colormap; - - /* - Read TIM raster colormap. - */ - (void)ReadBlobLSBLong(image); - (void)ReadBlobLSBShort(image); - (void)ReadBlobLSBShort(image); - /* width= */ (void)ReadBlobLSBShort(image); - /* height= */ (void)ReadBlobLSBShort(image); - if (!AllocateImageColormap(image,pixel_mode == 1 ? 256 : 16)) - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, - image); - tim_colormap=MagickAllocateMemory(unsigned char *,image->colors*2); - if (tim_colormap == (unsigned char *) NULL) - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, - image); - (void) ReadBlob(image,2*image->colors,(char *) tim_colormap); - p=tim_colormap; - for (i=0; i < (long) image->colors; i++) + /* + Verify TIM identifier. + */ + if (tim_info.id != 0x00000010) + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); + tim_info.flag=ReadBlobLSBLong(image); + has_clut=!!(tim_info.flag & (1 << 3)); + pixel_mode=tim_info.flag & 0x07; + switch ((int) pixel_mode) { - word=(*p++); - word|=(unsigned short) (*p++ << 8U); - image->colormap[i].blue=ScaleCharToQuantum(ScaleColor5to8((word >> 10U) & 0x1fU)); - image->colormap[i].green=ScaleCharToQuantum(ScaleColor5to8((word >> 5U) & 0x1fU)); - image->colormap[i].red=ScaleCharToQuantum(ScaleColor5to8(word & 0x1fU)); + case 0: bits_per_pixel=4; break; + case 1: bits_per_pixel=8; break; + case 2: bits_per_pixel=16; break; + case 3: bits_per_pixel=24; break; + default: bits_per_pixel=4; break; } - MagickFreeMemory(tim_colormap); - } - - /* - Read image data. - */ - (void) ReadBlobLSBLong(image); - (void) ReadBlobLSBShort(image); - (void) ReadBlobLSBShort(image); - if (EOFBlob(image)) - ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); - width=ReadBlobLSBShort(image); - height=ReadBlobLSBShort(image); - image_size=MagickArraySize(2,MagickArraySize(width,height)); - bytes_per_line=MagickArraySize(width,2); - width=(unsigned long)(MagickArraySize(width,16))/bits_per_pixel; - /* - Initialize image structure. - */ - image->columns=width; - image->rows=height; - - if (image_info->ping && (image_info->subrange != 0)) - if (image->scene >= (image_info->subimage+image_info->subrange-1)) - break; - - if (CheckImagePixelLimits(image, exception) != MagickPass) - ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); - - tim_data=MagickAllocateMemory(unsigned char *,image_size); - if (tim_data == (unsigned char *) NULL) - ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); - (void) ReadBlob(image,image_size,(char *) tim_data); - tim_pixels=tim_data; - - /* - Convert TIM raster image to pixel packets. - */ - switch (bits_per_pixel) - { - case 4: - { - /* - Convert PseudoColor scanline. - */ - for (y=(long) image->rows-1; y >= 0; y--) + image->depth=8; + if (has_clut) { - q=SetImagePixelsEx(image,0,y,image->columns,1,exception); - if (q == (PixelPacket *) NULL) - break; - indexes=AccessMutableIndexes(image); - p=tim_pixels+y*bytes_per_line; - for (x=0; x < ((long) image->columns-1); x+=2) - { - indexes[x]=(*p) & 0xf; - indexes[x+1]=(*p >> 4) & 0xf; - p++; - } - if ((image->columns % 2) != 0) + unsigned char + *tim_colormap; + + /* + Read TIM raster colormap. + */ + (void)ReadBlobLSBLong(image); + (void)ReadBlobLSBShort(image); + (void)ReadBlobLSBShort(image); + /* width= */ (void)ReadBlobLSBShort(image); + /* height= */ (void)ReadBlobLSBShort(image); + if (!AllocateImageColormap(image,pixel_mode == 1 ? 256 : 16)) + ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, + image); + tim_colormap=MagickAllocateMemory(unsigned char *,image->colors*2); + if (tim_colormap == (unsigned char *) NULL) + ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, + image); + if (ReadBlob(image,2*image->colors,(char *) tim_colormap) != 2*image->colors) { - indexes[x]=(*p >> 4) & 0xf; - p++; + MagickFreeMemory(tim_colormap); + ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); } - if (!SyncImagePixelsEx(image,exception)) - break; - if (QuantumTick(y,image->rows)) + p=tim_colormap; + for (i=0; i < (long) image->colors; i++) { - status=MagickMonitorFormatted(image->rows-y-1,image->rows, - exception,LoadImageText, - image->filename, - image->columns,image->rows); - if (status == False) - break; + word=(*p++); + word|=(unsigned short) (*p++ << 8U); + image->colormap[i].blue=ScaleCharToQuantum(ScaleColor5to8((word >> 10U) & 0x1fU)); + image->colormap[i].green=ScaleCharToQuantum(ScaleColor5to8((word >> 5U) & 0x1fU)); + image->colormap[i].red=ScaleCharToQuantum(ScaleColor5to8(word & 0x1fU)); + image->colormap[i].opacity=OpaqueOpacity; } + MagickFreeMemory(tim_colormap); + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "PSX-TIM read CLUT with %u entries", + image->colors); } - break; - } - case 8: - { - /* - Convert PseudoColor scanline. - */ - for (y=(long) image->rows-1; y >= 0; y--) + if ((bits_per_pixel == 4) || (bits_per_pixel == 8)) { - q=SetImagePixelsEx(image,0,y,image->columns,1,exception); - if (q == (PixelPacket *) NULL) - break; - indexes=AccessMutableIndexes(image); - p=tim_pixels+y*bytes_per_line; - for (x=0; x < (long) image->columns; x++) - indexes[x]=(*p++); - if (!SyncImagePixelsEx(image,exception)) - break; - if (QuantumTick(y,image->rows)) + if (image->storage_class != PseudoClass) { - status=MagickMonitorFormatted(image->rows-y-1,image->rows, - exception,LoadImageText, - image->filename, - image->columns,image->rows); - if (status == False) - break; + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "PSX-TIM %u bits/sample requires a CLUT!", + bits_per_pixel); + errno=0; + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); } } - break; - } - case 16: - { - /* - Convert DirectColor scanline. - */ - for (y=(long) image->rows-1; y >= 0; y--) + else { - p=tim_pixels+y*bytes_per_line; - q=SetImagePixelsEx(image,0,y,image->columns,1,exception); - if (q == (PixelPacket *) NULL) - break; - for (x=0; x < (long) image->columns; x++) - { - word=(*p++); - word|=(*p++ << 8); - q->blue=ScaleCharToQuantum(ScaleColor5to8((word >> 10) & 0x1f)); - q->green=ScaleCharToQuantum(ScaleColor5to8((word >> 5) & 0x1f)); - q->red=ScaleCharToQuantum(ScaleColor5to8(word & 0x1f)); - q++; - } - if (!SyncImagePixelsEx(image,exception)) - break; - if (QuantumTick(y,image->rows)) + if (image->storage_class == PseudoClass) { - status=MagickMonitorFormatted(image->rows-y-1,image->rows, - exception,LoadImageText, - image->filename, - image->columns,image->rows); - if (status == False) - break; + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "PSX-TIM %u bits/sample does not use" + " a CLUT, ignoring it", + bits_per_pixel); + image->storage_class=DirectClass; } } - break; - } - case 24: - { - /* - Convert DirectColor scanline. - */ - for (y=(long) image->rows-1; y >= 0; y--) + + /* + Read image data. + */ + (void) ReadBlobLSBLong(image); + (void) ReadBlobLSBShort(image); + (void) ReadBlobLSBShort(image); + width=ReadBlobLSBShort(image); + height=ReadBlobLSBShort(image); + if (EOFBlob(image)) + ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); + image_size=MagickArraySize(2,MagickArraySize(width,height)); + bytes_per_line=MagickArraySize(width,2); + width=(unsigned long)(MagickArraySize(width,16))/bits_per_pixel; + /* + Initialize image structure. + */ + image->columns=width; + image->rows=height; + + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "TIM[%lu] %lux%lu %d bits/pixel %s", + image->scene, + image->columns, image->rows, + bits_per_pixel, + ClassTypeToString(image->storage_class)); + + if (image_info->ping) + if ((image_info->subrange == 0) || + ((image_info->subrange != 0) && + (image->scene >= (image_info->subimage+image_info->subrange-1)))) + break; + + if (CheckImagePixelLimits(image, exception) != MagickPass) + ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); + + tim_pixels=MagickAllocateMemory(unsigned char *,image_size); + if (tim_pixels == (unsigned char *) NULL) + ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); + if (ReadBlob(image,image_size,(char *) tim_pixels) != image_size) { - p=tim_pixels+y*bytes_per_line; - q=SetImagePixelsEx(image,0,y,image->columns,1,exception); - if (q == (PixelPacket *) NULL) + MagickFreeMemory(tim_pixels); + ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); + } + + /* + Convert TIM raster image to pixel packets. + */ + switch (bits_per_pixel) + { + case 4: + { + /* + Convert PseudoColor scanline. + */ + for (y=(long) image->rows-1; y >= 0; y--) + { + q=SetImagePixelsEx(image,0,y,image->columns,1,exception); + if (q == (PixelPacket *) NULL) + break; + indexes=AccessMutableIndexes(image); + if (indexes == (IndexPacket *) NULL) + break; + p=tim_pixels+y*bytes_per_line; + for (x=0; x < ((long) image->columns-1); x+=2) + { + index=(*p) & 0xf; + VerifyColormapIndex(image,index); + indexes[x]=index; + index=(*p >> 4) & 0xf; + VerifyColormapIndex(image,index); + indexes[x+1]=index; + p++; + } + if ((image->columns % 2) != 0) + { + index=(*p >> 4) & 0xf; + VerifyColormapIndex(image,index); + indexes[x]=(*p >> 4) & 0xf; + p++; + } + if (!SyncImagePixelsEx(image,exception)) + break; + if (QuantumTick(y,image->rows)) + { + status=MagickMonitorFormatted(image->rows-y-1,image->rows, + exception,LoadImageText, + image->filename, + image->columns,image->rows); + if (status == False) + break; + } + } break; - for (x=0; x < (long) image->columns; x++) + } + case 8: { - q->red=ScaleCharToQuantum(*p++); - q->green=ScaleCharToQuantum(*p++); - q->blue=ScaleCharToQuantum(*p++); - q++; + /* + Convert PseudoColor scanline. + */ + for (y=(long) image->rows-1; y >= 0; y--) + { + q=SetImagePixelsEx(image,0,y,image->columns,1,exception); + if (q == (PixelPacket *) NULL) + break; + indexes=AccessMutableIndexes(image); + if (indexes == (IndexPacket *) NULL) + break; + p=tim_pixels+y*bytes_per_line; + for (x=0; x < (long) image->columns; x++) + { + index=(*p++); + VerifyColormapIndex(image,index); + indexes[x]=index; + } + if (!SyncImagePixelsEx(image,exception)) + break; + if (QuantumTick(y,image->rows)) + { + status=MagickMonitorFormatted(image->rows-y-1,image->rows, + exception,LoadImageText, + image->filename, + image->columns,image->rows); + if (status == False) + break; + } + } + break; } - if (!SyncImagePixelsEx(image,exception)) + case 16: + { + /* + Convert DirectColor scanline. + */ + for (y=(long) image->rows-1; y >= 0; y--) + { + PixelPacket *t; + p=tim_pixels+y*bytes_per_line; + q=SetImagePixelsEx(image,0,y,image->columns,1,exception); + if (q == (PixelPacket *) NULL) + break; + t=q; + for (x=0; x < (long) image->columns; x++) + { + word=(*p++); + word|=(*p++ << 8); + q->blue=ScaleCharToQuantum(ScaleColor5to8((word >> 10) & 0x1f)); + q->green=ScaleCharToQuantum(ScaleColor5to8((word >> 5) & 0x1f)); + q->red=ScaleCharToQuantum(ScaleColor5to8(word & 0x1f)); + q->opacity=OpaqueOpacity; + q++; + } + memset(t,0,image->columns*sizeof(PixelPacket)); + if (!SyncImagePixelsEx(image,exception)) + break; + if (QuantumTick(y,image->rows)) + { + status=MagickMonitorFormatted(image->rows-y-1,image->rows, + exception,LoadImageText, + image->filename, + image->columns,image->rows); + if (status == False) + break; + } + } break; - if (QuantumTick(y,image->rows)) - { - status=MagickMonitorFormatted(image->rows-y-1,image->rows, - exception,LoadImageText, - image->filename, - image->columns,image->rows); - if (status == False) - break; - } - } - break; - } - default: - ThrowReaderException(CorruptImageError,ImproperImageHeader,image) - } - if (image->storage_class == PseudoClass) - (void) SyncImage(image); - MagickFreeMemory(tim_pixels); - if (EOFBlob(image)) - { - ThrowException(exception,CorruptImageError,UnexpectedEndOfFile, - image->filename); - break; - } - /* - Proceed to next image. - */ - tim_info.id=ReadBlobLSBLong(image); - if (tim_info.id == 0x00000010) - { - /* - Allocate next image structure. - */ - AllocateNextImage(image_info,image); - if (image->next == (Image *) NULL) + } + case 24: + { + /* + Convert DirectColor scanline. + */ + for (y=(long) image->rows-1; y >= 0; y--) + { + p=tim_pixels+y*bytes_per_line; + q=SetImagePixelsEx(image,0,y,image->columns,1,exception); + if (q == (PixelPacket *) NULL) + break; + for (x=0; x < (long) image->columns; x++) + { + q->red=ScaleCharToQuantum(*p++); + q->green=ScaleCharToQuantum(*p++); + q->blue=ScaleCharToQuantum(*p++); + q->opacity=OpaqueOpacity; + q++; + } + if (!SyncImagePixelsEx(image,exception)) + break; + if (QuantumTick(y,image->rows)) + { + status=MagickMonitorFormatted(image->rows-y-1,image->rows, + exception,LoadImageText, + image->filename, + image->columns,image->rows); + if (status == False) + break; + } + } + break; + } + default: { - DestroyImageList(image); - return((Image *) NULL); + MagickFreeMemory(tim_pixels); + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); } - image=SyncNextImageInList(image); - status=MagickMonitorFormatted(TellBlob(image),GetBlobSize(image), - exception,LoadImagesText, - image->filename); - if (status == False) + } + if (image->storage_class == PseudoClass) + (void) SyncImage(image); + MagickFreeMemory(tim_pixels); + if (EOFBlob(image)) + { + ThrowException(exception,CorruptImageError,UnexpectedEndOfFile, + image->filename); + break; + } + /* + Proceed to next image. + */ + if (image_info->subrange != 0) + if (image->scene >= (image_info->subimage+image_info->subrange-1)) break; - } - } while (tim_info.id == 0x00000010); + + tim_info.id=ReadBlobLSBLong(image); + if (tim_info.id == 0x00000010) + { + /* + Allocate next image structure. + */ + AllocateNextImage(image_info,image); + if (image->next == (Image *) NULL) + { + DestroyImageList(image); + return((Image *) NULL); + } + image=SyncNextImageInList(image); + status=MagickMonitorFormatted(TellBlob(image),GetBlobSize(image), + exception,LoadImagesText, + image->filename); + if (status == False) + break; + } + } while (tim_info.id == 0x00000010); while (image->previous != (Image *) NULL) image=image->previous; CloseBlob(image); diff --git a/coders/topol.c b/coders/topol.c index efc06fa..a52fa19 100644 --- a/coders/topol.c +++ b/coders/topol.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2015 GraphicsMagick Group +% Copyright (C) 2003-2018 GraphicsMagick Group % % This program is covered by multiple licenses, which are described in % Copyright.txt. You should have received a copy of Copyright.txt with this @@ -20,7 +20,7 @@ % % % Software Design % % Jaroslav Fojtik % -% June 2003 % +% 2003 - 2018 % % % % % % % @@ -48,34 +48,34 @@ typedef struct char Name[20]; magick_uint16_t Rows; magick_uint16_t Cols; - magick_uint16_t FileType; /* 0-binary, 1-8 bitu, 2-8 bits+PAL, 3-4 bits, - 4-4 bits+PAL, 5-24 bits, 6-16 bits, 7-32 - bits */ + magick_uint16_t FileType; /* 0-binary, 1-8 bitu, 2-8 bits+PAL, 3-4 bits, + 4-4 bits+PAL, 5-24 bits, 6-16 bits, 7-32 + bits */ magick_uint32_t Zoom; magick_uint16_t Version; - magick_uint16_t Komprese; /* 0 - uncompressed (from release 1) */ + magick_uint16_t Komprese; /* 0 - uncompressed (from release 1) */ magick_uint16_t Stav; double xRasMin; double yRasMin; double xRasMax; double yRasMax; - double Scale; /* from release 2 */ - magick_uint16_t TileWidth; /* tile width in pixels */ - magick_uint16_t TileHeight; /* tile height in pixels */ - magick_uint32_t TileOffsets; /* offset to array of longints that contains - adresses of tiles in the raster (adreses - are counted from 0) */ + double Scale; /* from release 2 */ + magick_uint16_t TileWidth; /* tile width in pixels */ + magick_uint16_t TileHeight; /* tile height in pixels */ + magick_uint32_t TileOffsets; /* offset to array of longints that contains + adresses of tiles in the raster (adreses + are counted from 0) */ magick_uint32_t TileByteCounts;/* offset to array of words, that contain amount of bytes stored in - tiles. The tile size might vary depending on - the value TileCompression */ + tiles. The tile size might vary depending on + the value TileCompression */ magick_uint8_t TileCompression;/* 0 - uncompressed, 1 - variant TIFF - Packbits, 2 - CCITT G3 */ + Packbits, 2 - CCITT G3 */ magick_uint8_t Dummy[423]; } RasHeader; /* -typedef struct The palette record inside TopoL +typedef struct The palette record inside TopoL { BYTE Flag; BYTE Red; @@ -83,7 +83,7 @@ typedef struct The palette record inside TopoL BYTE Blue; } paletteRAS;*/ -static void InsertRow(int depth, unsigned char *p, long y, Image * image, unsigned Xoffset, unsigned columns, ImportPixelAreaOptions *import_options) +static int InsertRow(int depth, unsigned char *p, long y, Image * image, unsigned Xoffset, unsigned columns, ImportPixelAreaOptions *import_options) { int bit; @@ -102,13 +102,12 @@ static void InsertRow(int depth, unsigned char *p, long y, Image * image, unsign switch (depth) { - case 1: /* Convert bitmap scanline. */ + case 1: /* Convert bitmap scanline. */ { - q = SetImagePixels(image, Xoffset, y, columns, 1); - if (q == (PixelPacket *) NULL) - break; - indexes = AccessMutableIndexes(image); - for (x = 0; x < ((long)columns - 7); x += 8) + q = SetImagePixels(image, Xoffset, y, columns, 1); + if(q == (PixelPacket *) NULL) return -1; + indexes = AccessMutableIndexes(image); + for (x = 0; x < ((long)columns - 7); x += 8) { for (bit = 0; bit < 8; bit++) { @@ -118,7 +117,7 @@ static void InsertRow(int depth, unsigned char *p, long y, Image * image, unsign } p++; } - if ((columns % 8) != 0) + if ((columns % 8) != 0) { for (bit = 0; bit < (long)(columns % 8); bit++) { @@ -128,20 +127,19 @@ static void InsertRow(int depth, unsigned char *p, long y, Image * image, unsign } p++; } - if (!SyncImagePixels(image)) - break; - /* if (image->previous == (Image *) NULL) - if (QuantumTick(y,image->rows)) - ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); */ - break; + if (!SyncImagePixels(image)) + break; + /* if (image->previous == (Image *) NULL) + if (QuantumTick(y,image->rows)) + ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); */ + break; } - case 2: /* Convert PseudoColor scanline. */ + case 2: /* Convert PseudoColor scanline. */ { - q = SetImagePixels(image, Xoffset, y, columns, 1); - if (q == (PixelPacket *) NULL) - break; - indexes = AccessMutableIndexes(image); - for (x = 0; x < ((long)columns - 1); x += 2) + q = SetImagePixels(image, Xoffset, y, columns, 1); + if(q == (PixelPacket *) NULL) return -1; + indexes = AccessMutableIndexes(image); + for (x = 0; x < ((long)columns - 1); x += 2) { index = (IndexPacket) ((*p >> 6) & 0x3); VerifyColormapIndex(image, index); @@ -161,7 +159,7 @@ static void InsertRow(int depth, unsigned char *p, long y, Image * image, unsign *q++ = image->colormap[index]; p++; } - if ((columns % 4) != 0) + if ((columns % 4) != 0) { index = (IndexPacket) ((*p >> 6) & 0x3); VerifyColormapIndex(image, index); @@ -183,55 +181,53 @@ static void InsertRow(int depth, unsigned char *p, long y, Image * image, unsign } p++; } - if (!SyncImagePixels(image)) - break; - /* if (image->previous == (Image *) NULL) + if (!SyncImagePixels(image)) + break; + /* if (image->previous == (Image *) NULL) if (QuantumTick(y,image->rows)) ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); */ - break; + break; } - case 4: /* Convert PseudoColor scanline. */ + case 4: /* Convert PseudoColor scanline. */ { - q = SetImagePixels(image, Xoffset, y, columns, 1); - if (q == (PixelPacket *) NULL) - break; - indexes = AccessMutableIndexes(image); - for (x = 0; x < ((long)columns - 1); x += 2) + q = SetImagePixels(image, Xoffset, y, columns, 1); + if(q == (PixelPacket *) NULL) return -1; + indexes = AccessMutableIndexes(image); + for (x = 0; x < ((long)columns - 1); x += 2) { - index = (IndexPacket) ((*p >> 4) & 0xF); /* Lo nibble */ + index = (IndexPacket) ((*p >> 4) & 0xF); /* Lo nibble */ VerifyColormapIndex(image, index); indexes[x] = index; *q++ = image->colormap[index]; - index = (IndexPacket) ((*p) & 0xF); /* Hi nibble */ + index = (IndexPacket) ((*p) & 0xF); /* Hi nibble */ VerifyColormapIndex(image, index); indexes[x + 1] = index; *q++ = image->colormap[index]; p++; } - if((columns % 2) != 0) + if((columns % 2) != 0) { - index = (IndexPacket) ((*p >> 4) & 0xF); /* padding nibble */ + index = (IndexPacket) ((*p >> 4) & 0xF); /* padding nibble */ VerifyColormapIndex(image, index); indexes[x] = index; *q++ = image->colormap[index]; p++; } - if (!SyncImagePixels(image)) - break; - /* if (image->previous == (Image *) NULL) + if (!SyncImagePixels(image)) + break; + /* if (image->previous == (Image *) NULL) if (QuantumTick(y,image->rows)) ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); */ - break; + break; } - case 8: /* Convert PseudoColor scanline. */ + case 8: /* Convert PseudoColor scanline. */ { - q = SetImagePixels(image, Xoffset, y, columns, 1); - if (q == (PixelPacket *) NULL) - break; - indexes = AccessMutableIndexes(image); + q = SetImagePixels(image, Xoffset, y, columns, 1); + if(q == (PixelPacket *) NULL) return -1; + indexes = AccessMutableIndexes(image); - for (x = 0; x < (long)columns; x++) + for (x = 0; x < (long)columns; x++) { index = (IndexPacket) (*p); VerifyColormapIndex(image, index); @@ -239,52 +235,51 @@ static void InsertRow(int depth, unsigned char *p, long y, Image * image, unsign *q++ = image->colormap[index]; p++; } - if (!SyncImagePixels(image)) - break; - /* if (image->previous == (Image *) NULL) + if (!SyncImagePixels(image)) + break; + /* if (image->previous == (Image *) NULL) if (QuantumTick(y,image->rows)) ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); */ } break; - case 16: /* Convert 16 bit Gray scanline. */ + case 16: /* Convert 16 bit Gray scanline. */ q = SetImagePixels(image, Xoffset, y, columns, 1); - if (q == (PixelPacket *) NULL) - break; + if(q == (PixelPacket *) NULL) return -1; (void)ImportImagePixelArea(image,GrayQuantum,16,p,import_options,0); if(!SyncImagePixels(image)) break; break; - case 24: /* Convert RGB scanline. */ + case 24: /* Convert RGB scanline. */ q = SetImagePixels(image, Xoffset, y, columns, 1); - if (q == (PixelPacket *) NULL) - break; + if(q == (PixelPacket *) NULL) return -1; (void)ImportImagePixelArea(image,RGBQuantum,8,p,import_options,0); if(!SyncImagePixels(image)) break; break; - case 32: /* Convert 32 bit Gray scanline. */ + case 32: /* Convert 32 bit Gray scanline. */ q = SetImagePixels(image, Xoffset, y, columns, 1); - if (q == (PixelPacket *) NULL) - break; + if(q == (PixelPacket *) NULL) return -1; (void)ImportImagePixelArea(image,GrayQuantum,32,p,import_options,0); if(!SyncImagePixels(image)) break; break; - + } + + return 0; } /* This function reads one block of unsigned longS */ -static void ReadBlobDwordLSB(Image *image, size_t len, magick_uint32_t *data) +static int ReadBlobDwordLSB(Image *image, size_t len, magick_uint32_t *data) { - while (len >= 4) - { - *data++ = ReadBlobLSBLong(image); - len -= 4; - } - if (len > 0) - (void) SeekBlob(image, len, SEEK_CUR); + if(ReadBlob(image, len, data) != len) return -1; + +#if defined(WORDS_BIGENDIAN) + MagickSwabArrayOfUInt32(data, len/4); +#endif + + return 0; } /* @@ -319,12 +314,13 @@ static void ReadBlobDwordLSB(Image *image, size_t len, magick_uint32_t *data) % */ -#define ThrowPDBReaderException(code_,reason_,image_) \ +#define ThrowTOPOLReaderException(code_,reason_,image_) \ { \ if (clone_info) \ DestroyImageInfo(clone_info); \ if (palette) \ DestroyImage(palette); \ + MagickFreeMemory(BImgBuff); \ ThrowReaderException(code_,reason_,image_); \ } @@ -332,10 +328,10 @@ static Image *ReadTOPOLImage(const ImageInfo * image_info, ExceptionInfo * excep { Image *image, - *palette; + *palette = (Image *) NULL; ImageInfo - *clone_info; + *clone_info = (ImageInfo *) NULL; RasHeader Header; @@ -343,8 +339,8 @@ static Image *ReadTOPOLImage(const ImageInfo * image_info, ExceptionInfo * excep int logging; int - depth, - status; + depth, + status; long i, @@ -368,7 +364,7 @@ static Image *ReadTOPOLImage(const ImageInfo * image_info, ExceptionInfo * excep assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); - logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter"); + logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter"); image = AllocateImage(image_info); status = OpenBlob(image_info, image, ReadBinaryBlobMode, exception); @@ -384,11 +380,14 @@ static Image *ReadTOPOLImage(const ImageInfo * image_info, ExceptionInfo * excep */ (void) memset(&Header, 0, sizeof(Header)); (void) ReadBlob(image, 20, &Header.Name); + Header.Rows = ReadBlobLSBShort(image); Header.Cols = ReadBlobLSBShort(image); Header.FileType = ReadBlobLSBShort(image); Header.Zoom = ReadBlobLSBLong(image); Header.Version = ReadBlobLSBShort(image); + if (EOFBlob(image)) + ThrowTOPOLReaderException(CorruptImageError,UnexpectedEndOfFile,image); if (Header.Version >= 1) { Header.Komprese = ReadBlobLSBShort(image); @@ -397,7 +396,7 @@ static Image *ReadTOPOLImage(const ImageInfo * image_info, ExceptionInfo * excep Header.yRasMin = ReadBlobLSBDouble(image); Header.xRasMax = ReadBlobLSBDouble(image); Header.yRasMax = ReadBlobLSBDouble(image); - if (Header.Version >= 2) /* from release 2 */ + if (Header.Version >= 2) /* from release 2 */ { Header.Scale = ReadBlobLSBDouble(image); Header.TileWidth = ReadBlobLSBShort(image); @@ -407,19 +406,26 @@ static Image *ReadTOPOLImage(const ImageInfo * image_info, ExceptionInfo * excep Header.TileCompression = ReadBlobByte(image); /* BYTE Dummy[423]; */ } + if (EOFBlob(image)) + ThrowTOPOLReaderException(CorruptImageError,UnexpectedEndOfFile,image); } for (i = 0; i < (long) sizeof(Header.Name); i++) { if (Header.Name[i] < ' ') -TOPOL_KO: ThrowPDBReaderException(CorruptImageError,ImproperImageHeader, image); +TOPOL_KO: ThrowTOPOLReaderException(CorruptImageError,ImproperImageHeader, image); } if (Header.Komprese != 0 || (Header.Version >= 2 && Header.TileCompression != 0)) - ThrowPDBReaderException(CorruptImageError, UnrecognizedImageCompression, image); - if (Header.Rows == 0 || Header.Cols == 0) - goto TOPOL_KO; + ThrowTOPOLReaderException(CorruptImageError, UnrecognizedImageCompression, image); + if (((Header.Rows == 0 || Header.Cols == 0)) || + ((Header.Version >= 2) && + (Header.TileWidth == 0 || + Header.TileHeight == 0 || + Header.TileOffsets == 0 || + Header.TileByteCounts == 0))) + ThrowTOPOLReaderException(CorruptImageError,ImproperImageHeader, image); if (Header.Version > 2) - ThrowPDBReaderException(CorruptImageError, InvalidFileFormatVersion, image); /* unknown version */ + ThrowTOPOLReaderException(CorruptImageError, InvalidFileFormatVersion, image); /* unknown version */ switch(Header.FileType) { @@ -445,11 +451,11 @@ TOPOL_KO: ThrowPDBReaderException(CorruptImageError,ImproperImageHe case 6: image->colors = 0; depth = 16; - break; /* ????????? 16 bits */ + break; /* ????????? 16 bits */ case 7: image->colors = 0; depth = 32; - break; /* ????????? 32 bits */ + break; /* ????????? 32 bits */ default: goto TOPOL_KO; } @@ -457,6 +463,11 @@ TOPOL_KO: ThrowPDBReaderException(CorruptImageError,ImproperImageHe image->columns = Header.Cols; image->rows = Header.Rows; + i = GetBlobSize(image); + if(i>0) + if(((magick_uint64_t)8*Header.Cols*(magick_uint64_t)Header.Rows) / image->depth > (magick_uint64_t)GetBlobSize(image)) + goto TOPOL_KO; /* Check for forged image that overflows file size. */ + /* If ping is true, then only set image size and colors without reading any image data. */ if (image_info->ping) goto DONE_READING; @@ -464,19 +475,19 @@ TOPOL_KO: ThrowPDBReaderException(CorruptImageError,ImproperImageHe j = image->colors; if(j<=0 || j>256) j=256; for(i=0; i=5) goto NoMEZ; - + + if(Header.FileType>=5) goto NoMEZ; + if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoMEZ; - + i=(long) strlen(clone_info->filename); j=i; while(--i>0) { - if(clone_info->filename[i]=='.') + if(clone_info->filename[i]=='.') { break; } @@ -486,31 +497,34 @@ TOPOL_KO: ThrowPDBReaderException(CorruptImageError,ImproperImageHe break; } } - - (void) strcpy(clone_info->filename+i,".MEZ"); + + if (i <= 0) + goto NoPalette; + + (void) strlcpy(clone_info->filename+i,".MEZ",sizeof(clone_info->filename)-i); if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) { - (void) strcpy(clone_info->filename+i,".mez"); + (void) strlcpy(clone_info->filename+i,".mez",sizeof(clone_info->filename)-i); if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) { DestroyImageInfo(clone_info); clone_info=NULL; - goto NoMEZ; + goto NoMEZ; } } if( (palette=AllocateImage(clone_info))==NULL ) goto NoMEZ; status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception); - if (status == False) goto NoMEZ; + if (status == False) goto NoMEZ; ldblk=(long) GetBlobSize(palette); if ( ldblk > (long) sizeof(MEZ)) ldblk=sizeof(MEZ); - (void) ReadBlob(palette, ldblk, MEZ); - -NoMEZ: /*Clean up palette and clone_info*/ + (void) ReadBlob(palette, ldblk, MEZ); + +NoMEZ: /*Clean up palette and clone_info*/ if (palette != NULL) {DestroyImage(palette);palette=NULL;} - if (clone_info != NULL) + if (clone_info != NULL) { DestroyImageInfo(clone_info); clone_info=NULL; @@ -519,31 +533,34 @@ NoMEZ: /*Clean up palette and clone_info*/ /* ----- Do something with palette ----- */ if(Header.FileType==5) goto NoPalette; if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette; - + i=(long) strlen(clone_info->filename); j=i; while(--i>0) { - if(clone_info->filename[i]=='.') + if(clone_info->filename[i]=='.') { break; } if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' || - clone_info->filename[i]==':' ) + clone_info->filename[i]==':' ) { i=j; break; } } - - (void) strcpy(clone_info->filename+i,".PAL"); - if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) + + if (i <= 0) + goto NoPalette; + + (void) strlcpy(clone_info->filename+i,".PAL",sizeof(clone_info->filename)-i); + if ((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) { - (void) strcpy(clone_info->filename+i,".pal"); - if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) + (void) strlcpy(clone_info->filename+i,".pal",sizeof(clone_info->filename)-i); + if ((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) { clone_info->filename[i]=0; - if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) + if ((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) { DestroyImageInfo(clone_info); clone_info=NULL; @@ -556,31 +573,31 @@ NoMEZ: /*Clean up palette and clone_info*/ status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception); if (status == False) { - ErasePalette: + ErasePalette: DestroyImage(palette); palette=NULL; goto NoPalette; } - - + + if(palette!=NULL) { - ldblk=ReadBlobByte(palette); /*size of palette*/ + ldblk=ReadBlobByte(palette); /*size of palette*/ if(ldblk==EOF) goto ErasePalette; - image->colors=ldblk+1; + image->colors=ldblk+1; if (!AllocateImageColormap(image, image->colors)) goto NoMemory; - + for(i=0;i<=ldblk;i++) - { - j = ReadBlobByte(palette); /* Flag */ - if(j==EOF) break; /* unexpected end of file */ + { + j = ReadBlobByte(palette); /* Flag */ + if(j==EOF) break; /* unexpected end of file */ if(j<=ldblk) { - if(j==MEZ[i]) - j = i; /* MEZ[i]; ignore MEZ!!! proper palete element after reindexing */ + if(j==MEZ[i]) + j = i; /* MEZ[i]; ignore MEZ!!! proper palete element after reindexing */ else - j = MEZ[i]; /* ?? I do not know, big mess ?? */ - if(j>=(long) image->colors) j=image->colors-1; + j = MEZ[i]; /* ?? I do not know, big mess ?? */ + if(j>=(long) image->colors) j=image->colors-1; image->colormap[j].red = ScaleCharToQuantum(ReadBlobByte(palette)); image->colormap[j].green = ScaleCharToQuantum(ReadBlobByte(palette)); image->colormap[j].blue = ScaleCharToQuantum(ReadBlobByte(palette)); @@ -589,7 +606,7 @@ NoMEZ: /*Clean up palette and clone_info*/ { (void) SeekBlob(palette, 3, SEEK_CUR); (void) fprintf(stderr,"TopoL: Wrong index inside palette %d!",(int)j); - } + } } } @@ -601,12 +618,12 @@ NoPalette: if (!AllocateImageColormap(image, image->colors)) { NoMemory: - ThrowPDBReaderException(ResourceLimitError, MemoryAllocationFailed, image); + ThrowTOPOLReaderException(ResourceLimitError, MemoryAllocationFailed, image); } for(i = 0; i < (long) image->colors; i++) { - j = MEZ[i]; + j = MEZ[i]; image->colormap[i].red = ScaleCharToQuantum(j); image->colormap[i].green = ScaleCharToQuantum(j); image->colormap[i].blue = ScaleCharToQuantum(j); @@ -614,19 +631,19 @@ NoPalette: } } - /* ----- Load TopoL raster ----- */ + /* ----- Load TopoL raster ----- */ switch(Header.Version) { case 0: case 1: ldblk = (long) ((depth * image->columns + 7) / 8); - BImgBuff = MagickAllocateMemory(unsigned char *,(size_t) ldblk); /*Ldblk was set in the check phase */ + BImgBuff = MagickAllocateMemory(unsigned char *,(size_t) ldblk); /*Ldblk was set in the check phase */ if (BImgBuff == NULL) - ThrowPDBReaderException(ResourceLimitError, MemoryAllocationFailed, image); + ThrowTOPOLReaderException(ResourceLimitError, MemoryAllocationFailed, image); (void) SeekBlob(image, 512 /*sizeof(Header)*/, SEEK_SET); for (i = 0; i < (int) Header.Rows; i++) { - (void)ReadBlob(image, ldblk, (char *)BImgBuff); + (void)ReadBlob(image, ldblk, (char *)BImgBuff); InsertRow(depth, BImgBuff, i, image, 0, image->columns, &import_options); } break; @@ -639,44 +656,71 @@ NoPalette: unsigned TilesDown = (Header.Rows+Header.TileHeight-1) / Header.TileHeight; if(Header.TileCompression!=0) - { - ThrowPDBReaderException(CorruptImageError, UnrecognizedImageCompression, image); - break; - } + { + ThrowTOPOLReaderException(CorruptImageError, UnrecognizedImageCompression, image); + break; + } ldblk = (long)((depth * Header.TileWidth + 7) / 8); - BImgBuff = MagickAllocateMemory(unsigned char *,(size_t) ldblk); /*Ldblk was set in the check phase */ + BImgBuff = MagickAllocateMemory(unsigned char *,(size_t) ldblk); /*Ldblk was set in the check phase */ + if (BImgBuff == NULL) + ThrowTOPOLReaderException(ResourceLimitError, MemoryAllocationFailed, image); /* dlazdice.create(Header.TileWidth,Header.TileHeight,p.Planes); */ - Offsets = MagickAllocateMemory(magick_uint32_t *,(size_t)TilesAcross*TilesDown*sizeof(magick_uint32_t)); + Offsets = MagickAllocateArray(magick_uint32_t *, + MagickArraySize((size_t)TilesAcross,(size_t)TilesDown), + sizeof(magick_uint32_t)); if(Offsets==NULL) - ThrowPDBReaderException(ResourceLimitError, MemoryAllocationFailed, image); + ThrowTOPOLReaderException(ResourceLimitError, MemoryAllocationFailed, image); (void)SeekBlob(image, Header.TileOffsets, SEEK_SET); - ReadBlobDwordLSB(image, TilesAcross*TilesDown*4, (magick_uint32_t *)Offsets); + if(ReadBlobDwordLSB(image, TilesAcross*TilesDown*4, (magick_uint32_t *)Offsets) < 0) + { + MagickFreeMemory(Offsets); + ThrowTOPOLReaderException(CorruptImageError,InsufficientImageDataInFile, image); + } for(TilY=0;TilYcolumns - TilX*Header.TileWidth; - - if(ldblk>Header.TileWidth) ldblk = Header.TileWidth; - SkipBlk = ((long)depth * (Header.TileWidth-ldblk)+7) / 8; - ldblk = ((long)depth * ldblk+7) / 8; - - (void)SeekBlob(image, Offsets[(TilY/Header.TileHeight)*TilesAcross+TilX], SEEK_SET); - j = TilX * (ldblk+SkipBlk); - for(i=0;icolumns - TilX*Header.TileWidth; + + if(ldblk>Header.TileWidth) ldblk = Header.TileWidth; + SkipBlk = ((long)depth * (Header.TileWidth-ldblk)+7) / 8; + ldblk = ((long)depth * ldblk+7) / 8; + + j = TilX * (ldblk+SkipBlk); + for(i=0;i=image->rows) break; /* Do not read padding tile data, abort the current tile. */ + + if(ReadBlob(image, ldblk, (char *)BImgBuff) != (size_t) ldblk) + { + MagickFreeMemory(Offsets); + ThrowTOPOLReaderException(CorruptImageError,InsufficientImageDataInFile, image); + break; + } if(SkipBlk>0) SeekBlob(image, SkipBlk, SEEK_CUR); - InsertRow(depth, BImgBuff, i+TilY, image, TilX, - (image->columnscolumns:Header.TileWidth, &import_options); - } - } + if(InsertRow(depth, BImgBuff, i+TilY, image, TilX, + (image->columnscolumns:Header.TileWidth, &import_options)) + { + MagickFreeMemory(Offsets); + ThrowTOPOLReaderException(CorruptImageError,TooMuchImageDataInFile, image); + break; + } + } + } - if(Offsets) {MagickFreeMemory(Offsets);Offsets=NULL;} + MagickFreeMemory(Offsets); break; } } @@ -684,14 +728,13 @@ NoPalette: /* Finish: */ DONE_READING: - if (BImgBuff != NULL) - MagickFreeMemory(BImgBuff); + MagickFreeMemory(BImgBuff); if (palette != NULL) DestroyImage(palette); if (clone_info != NULL) DestroyImageInfo(clone_info); /* if (EOFBlob(image)) - ThrowPDBReaderException(CorruptImageError,UnexpectedEndOfFile,image); */ + ThrowTOPOLReaderException(CorruptImageError,UnexpectedEndOfFile,image); */ CloseBlob(image); if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return"); diff --git a/coders/txt.c b/coders/txt.c index 75bf7e8..6432325 100644 --- a/coders/txt.c +++ b/coders/txt.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2016 GraphicsMagick Group +% Copyright (C) 2003-2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -32,7 +32,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Patterns accepted: -% 0,0: 129,129,129,255 +% 0,0: 129,129,129,255 % 0,0: 129,129,129 % 0,0: (129,129,129) #818181 % 0,0: (3411594072,2774050136,1883729991) #CB58CB58A558A55870477047 @@ -108,6 +108,9 @@ static long ReadInt(Image *image, int *pch) long n; + unsigned int + digits; + n=0; if (pch) ch=*pch; @@ -118,15 +121,17 @@ static long ReadInt(Image *image, int *pch) { ch = ReadBlobByte(image); if (ch == EOF) - return (0); + return (0); } - while (isdigit(ch)) + digits=0; + while ((digits < 10) && isdigit(ch)) { n=10*n+(ch-'0'); ch = ReadBlobByte(image); if (ch == EOF) - return (n); + return (n); + digits++; } if (pch) @@ -343,56 +348,60 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) } while (0); unsigned - x, - y; + x, + y; unsigned - x_min, - x_max, - y_curr; + x_min, + x_max, + y_curr; int - ch; + ch; unsigned long - max, - i; + max, + i; char - NumOfPlanes; + NumOfPlanes; unsigned char - *BImgBuff=0; + *BImgBuff=0; magick_uint16_t - *WImgBuff; + *WImgBuff; magick_uint32_t - *DImgBuff; + *DImgBuff; magick_uint32_t - R, - G, - B, - A; + R, + G, + B, + A; - const PixelPacket - *q; + PixelPacket + *q; ExtendedSignedIntegralType NextImagePos = 0; ImportPixelAreaOptions - import_options; + import_options; if (logging) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "File RAW TXT type: %d", (int) txt_subformat); + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "File RAW TXT type: %d", (int) txt_subformat); do { (void) SeekBlob(image,NextImagePos,SEEK_SET); if(NextImagePos!=0) { + if (image_info->subrange != 0) + if (image->scene >= (image_info->subimage+image_info->subrange-1)) + break; + /* Allocate next image structure. */ AllocateNextImage(image_info,image); if(image->next == (Image *)NULL) break; @@ -415,8 +424,8 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) case TXT_GM16B_HEX: case TXT_GM16B_HEX_Q: max=65535; - break; - case TXT_GM32B_HEX: + break; + case TXT_GM32B_HEX: case TXT_GM32B_HEX_Q: max=65536; break; @@ -450,7 +459,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) ch=0; if (x == 0 && y == 0) - while (!EOFBlob(image)) /* auto detect sizes and num of planes */ + while (!EOFBlob(image)) /* auto detect sizes and num of planes */ { while (!(ch >= '0' && ch <= '9')) { @@ -458,7 +467,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) ch = ReadBlobByte(image); if (ch == EOF) goto EndReading; - if (ch == '#') + if (ch == '#') { readln(image,&ch); continue; @@ -467,17 +476,17 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { - TXT_FAIL: /* not a text data */ + TXT_FAIL: /* not a text data */ ThrowNOTXTReaderException(CoderError,ImageTypeNotSupported,image); } } /* x,y: (R,G,B) */ - x_min = ReadInt(image,&ch); /* x */ + x_min = ReadInt(image,&ch); /* x */ if (x_min > x) x = x_min; while (ch != ',') - { + { ch = ReadBlobByte(image); if (ch==EOF) break; @@ -485,11 +494,11 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) goto TXT_FAIL; } ch=0; - i=ReadInt(image,&ch); /* y */ + i=ReadInt(image,&ch); /* y */ /* Check for next image start. */ - if(x_min==0 && i==0 && x>0 && y>0) - goto EndReading; + if(x_min==0 && i==0 && x>0 && y>0) + goto EndReading; if (i > y) y=i; @@ -512,12 +521,12 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) break; } ch=0; - R = ReadInt(image,&ch); /* R */ + R = ReadInt(image,&ch); /* R */ if (R > max) max=R; while (ch != ',') - { + { ch = ReadBlobByte(image); if (ch == 10 || ch == 13) goto TXT_FAIL; @@ -525,7 +534,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) break; } ch=0; - G = ReadInt(image,&ch); /* G */ + G = ReadInt(image,&ch); /* G */ if (G > max) max=G; @@ -538,7 +547,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) break; } ch=0; - B = ReadInt(image,&ch); /* B */ + B = ReadInt(image,&ch); /* B */ if (B > max) max=B; @@ -553,7 +562,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) break; } ch=0; - A = ReadInt(image,&ch); /* A */ + A = ReadInt(image,&ch); /* A */ if (A > max) max=A; } @@ -587,26 +596,66 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), - "Image detected [%u * %u]: %d", x, y, NumOfPlanes); + "Image detected[%lu] [%u * %u]: %d", image->scene, x, y, NumOfPlanes); image->depth = Min(QuantumDepth,NumOfPlanes); ImportPixelAreaOptionsInit(&import_options); import_options.endian = NativeEndian; - + + image->columns = x+1; + image->rows = y+1; + if (logging) + (void)LogMagickEvent(CoderEvent,GetMagickModule(), + "Image Geometry: %lux%lu", image->columns, image->rows); + + if (CheckImagePixelLimits(image, exception) != MagickPass) + ThrowNOTXTReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); + + /* + Validate that file size is sufficient for claimed image properties + */ + if (BlobIsSeekable(image)) + { + magick_off_t + file_size; + + if ((file_size=GetBlobSize(image)) != 0) + { + double + ratio; + + double + packet_size=40.0; /* Max characters in a row */ + + double + number_pixels=image->columns*image->rows; + + ratio = (((double) number_pixels*packet_size)/file_size); + + if (ratio > 2.0) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Unreasonable file size " + "(ratio of pixels to file size %g)", + ratio); + ThrowReaderException(CorruptImageError,InsufficientImageDataInFile, + image); + } + } + } + + /* Assure that all image pixels are initialized to black */ + SetImage(image,OpaqueOpacity); + BImgBuff = MagickAllocateArray(unsigned char *, (size_t)(x+1), ( ((image->matte) ? 4 : 3) * NumOfPlanes/8)); WImgBuff = (magick_uint16_t *)BImgBuff; - DImgBuff = (magick_uint32_t *)BImgBuff; - if (BImgBuff == NULL) + DImgBuff = (magick_uint32_t *)BImgBuff; + if (BImgBuff == NULL) ThrowNOTXTReaderException(ResourceLimitError,MemoryAllocationFailed,image); - - image->columns = x+1; - image->rows = y+1; - if (CheckImagePixelLimits(image, exception) != MagickPass) - ThrowNOTXTReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); (void) SeekBlob(image,NextImagePos,SEEK_SET); NextImagePos = 0; @@ -623,23 +672,29 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) if (EOFBlob(image)) goto FINISH; ch = ReadBlobByte(image); - if (ch == '#') + if (ch == '#') { readln(image,&ch); continue; } + if (ch == 0 || ch > 128 || /* Duplicate image check for data with fixed geometry previous check is skipped. */ + (ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z')) + { /* not a text data */ + ThrowNOTXTReaderException(CoderError,ImageTypeNotSupported,image); + } } - - x = ReadInt(image,&ch); /* x */ + + x = ReadInt(image,&ch); /* x */ while (ch != ',') { - ch = ReadBlobByte(image); + ch = ReadBlobByte(image); if (ch == EOF) break; } ch = 0; - y = ReadInt(image,&ch); /* y */ + y = ReadInt(image,&ch); /* y */ /* New image detected. */ if(x==0 && y==0 && y_curr>0 && x_max>0) @@ -661,7 +716,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) break; } ch=0; - R = ReadInt(image,&ch); /* R */ + R = ReadInt(image,&ch); /* R */ while (ch != ',') { @@ -670,7 +725,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) break; } ch=0; - G = ReadInt(image,&ch); /* G */ + G = ReadInt(image,&ch); /* G */ while (ch != ',') { @@ -679,18 +734,18 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) break; } ch=0; - B = ReadInt(image,&ch); /* B */ + B = ReadInt(image,&ch); /* B */ if (image->matte) { while (ch != ',') { - ch = ReadBlobByte(image); + ch = ReadBlobByte(image); if (ch == EOF) break; } ch=0; - A = ReadInt(image,&ch); /* A */ + A = ReadInt(image,&ch); /* A */ if (A > max) max=A; } @@ -750,7 +805,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) DImgBuff[2+4*x] = B; DImgBuff[3+4*x] = 4294967295U-A; break; - } + } } else { @@ -771,7 +826,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) DImgBuff[1+3*x] = G; DImgBuff[2+3*x] = B; break; - } + } } if (x_min > x_max) { @@ -792,10 +847,10 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) FINISH: if (x_min <= x_max) { - q = SetImagePixels(image,x_min,y_curr,x_max-x_min+1,1); + q = SetImagePixels(image,x_min,y_curr,x_max-x_min+1,1); if (q != (PixelPacket *)NULL) { - if (image->matte) + if (image->matte) (void)ImportImagePixelArea(image, RGBAQuantum, NumOfPlanes, BImgBuff + 4*x_min*(NumOfPlanes/8), &import_options, 0); @@ -814,7 +869,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) } /* Note that DImgBuff and WImgBuff point to BImgBuff */ MagickFreeMemory(BImgBuff); - } while(!EOFBlob(image) && NextImagePos>0); + } while(!EOFBlob(image) && NextImagePos>0); goto FINISH_TXT; } @@ -844,10 +899,10 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) DrawInfo *draw_info = (DrawInfo *) NULL; - + RectangleInfo page; - + TypeMetric metrics; @@ -858,14 +913,14 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) dy_resolution=72.0; if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0)) { - char - density[MaxTextExtent]; - - (void) strlcpy(density,PSDensityGeometry,sizeof(density)); - count=GetMagickDimension(density,&image->x_resolution, - &image->y_resolution,NULL,NULL); - if (count != 2) - image->y_resolution=image->x_resolution; + char + density[MaxTextExtent]; + + (void) strlcpy(density,PSDensityGeometry,sizeof(density)); + count=GetMagickDimension(density,&image->x_resolution, + &image->y_resolution,NULL,NULL); + if (count != 2) + image->y_resolution=image->x_resolution; } SetGeometry(image,&page); page.width=612; @@ -873,11 +928,11 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) (void) GetGeometry("612x792+43+43",&page.x,&page.y,&page.width,&page.height); if (image_info->page != (char *) NULL) (void) GetGeometry(image_info->page,&page.x,&page.y,&page.width, - &page.height); + &page.height); if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), - "Page Geometry: %lux%lu%+ld%+ld", - page.width,page.height,page.x,page.y); + "Page Geometry: %lux%lu%+ld%+ld", + page.width,page.height,page.x,page.y); /* Initialize Image structure. */ @@ -892,15 +947,15 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) texture=(Image *) NULL; if (image_info->texture != (char *) NULL) { - ImageInfo - *clone_info; - - clone_info=CloneImageInfo(image_info); - clone_info->blob=(void *) NULL; - clone_info->length=0; - (void) strlcpy(clone_info->filename,image_info->texture,MaxTextExtent); - texture=ReadImage(clone_info,exception); - DestroyImageInfo(clone_info); + ImageInfo + *clone_info; + + clone_info=CloneImageInfo(image_info); + clone_info->blob=(void *) NULL; + clone_info->length=0; + (void) strlcpy(clone_info->filename,image_info->texture,MaxTextExtent); + texture=ReadImage(clone_info,exception); + DestroyImageInfo(clone_info); } /* Annotate the text image. @@ -921,91 +976,91 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) } if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), - "Type metrics: ascent=%g descent=%g" - " height=%g max_advance=%g", - metrics.ascent,metrics.descent, - metrics.height,metrics.max_advance); + "Type metrics: ascent=%g descent=%g" + " height=%g max_advance=%g", + metrics.ascent,metrics.descent, + metrics.height,metrics.max_advance); pixels_per_line=(long) (metrics.ascent-metrics.descent); margins=2*page.y; lines_per_page=((image->rows+1)-margins)/pixels_per_line+1; if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), - "Pixels per line: %ld", - pixels_per_line); + "Pixels per line: %ld", + pixels_per_line); if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), - "Lines per page: %ld", - lines_per_page); + "Lines per page: %ld", + lines_per_page); (void) strlcpy(filename,image_info->filename,MaxTextExtent); - if (draw_info->text != '\0') - *draw_info->text='\0'; + if (draw_info->text != NULL) + *draw_info->text='\0'; page_num=1; line_num=0; while (p != (char *) NULL) { - /* - Annotate image with text. - - Text lines are concatenated so that a full page is - rendered at a time via AnnotateImage(). - */ - (void) ConcatenateString(&draw_info->text,text); - (void) ConcatenateString(&draw_info->text,"\\n"); - line_num++; - - if (image->previous == (Image *) NULL) - if (QuantumTick(line_num,lines_per_page)) - if (!MagickMonitorFormatted(line_num,lines_per_page,&image->exception, - LoadImageText,image->filename, - image->columns,image->rows)) - break; - - p=ReadBlobString(image,text); - if ((line_num < lines_per_page) && (p != (char *) NULL)) - continue; - if (texture != (Image *) NULL) - { - MonitorHandler - handler; - - handler=SetMonitorHandler((MonitorHandler) NULL); - (void) TextureImage(image,texture); - (void) SetMonitorHandler(handler); - } - (void) AnnotateImage(image,draw_info); - if (p == (char *) NULL) - break; - - if (logging) - (void)LogMagickEvent(CoderEvent,GetMagickModule(), - "page %ld scene %ld ",page_num, image->scene); - - if ((image_info->subimage != 0) || (image_info->subrange != 0)) - if (image->scene >= (image_info->subimage+image_info->subrange-1)) - break; - - /* - Page is full-- allocate next image structure. - */ - *draw_info->text='\0'; - page_num++; - line_num=0; - AllocateNextImage(image_info,image); - if (image->next == (Image *) NULL) - { + /* + Annotate image with text. + + Text lines are concatenated so that a full page is + rendered at a time via AnnotateImage(). + */ + (void) ConcatenateString(&draw_info->text,text); + (void) ConcatenateString(&draw_info->text,"\\n"); + line_num++; + + if (image->previous == (Image *) NULL) + if (QuantumTick(line_num,lines_per_page)) + if (!MagickMonitorFormatted(line_num,lines_per_page,&image->exception, + LoadImageText,image->filename, + image->columns,image->rows)) + break; + + p=ReadBlobString(image,text); + if ((line_num < lines_per_page) && (p != (char *) NULL)) + continue; + if (texture != (Image *) NULL) + { + MonitorHandler + handler; + + handler=SetMonitorHandler((MonitorHandler) NULL); + (void) TextureImage(image,texture); + (void) SetMonitorHandler(handler); + } + (void) AnnotateImage(image,draw_info); + if (p == (char *) NULL) + break; + + if (logging) + (void)LogMagickEvent(CoderEvent,GetMagickModule(), + "page %ld scene %ld ",page_num, image->scene); + + if ((image_info->subimage != 0) || (image_info->subrange != 0)) + if (image->scene >= (image_info->subimage+image_info->subrange-1)) + break; + + /* + Page is full-- allocate next image structure. + */ + *draw_info->text='\0'; + page_num++; + line_num=0; + AllocateNextImage(image_info,image); + if (image->next == (Image *) NULL) + { DestroyDrawInfo(draw_info); - DestroyImageList(image); - return ((Image *) NULL); - } - image->next->columns=image->columns; - image->next->rows=image->rows; - image=SyncNextImageInList(image); - (void) strlcpy(image->filename,filename,MaxTextExtent); - (void) SetImage(image,OpaqueOpacity); - if (!MagickMonitorFormatted(TellBlob(image),GetBlobSize(image),exception, - LoadImagesText,image->filename)) - break; + DestroyImageList(image); + return ((Image *) NULL); + } + image->next->columns=image->columns; + image->next->rows=image->rows; + image=SyncNextImageInList(image); + (void) strlcpy(image->filename,filename,MaxTextExtent); + (void) SetImage(image,OpaqueOpacity); + if (!MagickMonitorFormatted(TellBlob(image),GetBlobSize(image),exception, + LoadImagesText,image->filename)) + break; } if (texture != (Image *) NULL) @@ -1026,9 +1081,9 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) FINISH_TXT: CloseBlob(image); { - Image *p; + Image *p; long scene=0; - + /* Rewind list, removing any empty images while rewinding. */ @@ -1045,7 +1100,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) p=p->previous; } } - + /* Fix scene numbers */ @@ -1053,7 +1108,7 @@ static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) p->scene=scene++; } - if(logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return"); + if(logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return"); return (image); } @@ -1171,6 +1226,9 @@ static unsigned int WriteTXTImage(const ImageInfo *image_info,Image *image) register long x; + size_t + image_list_length; + unsigned int status; @@ -1188,18 +1246,19 @@ static unsigned int WriteTXTImage(const ImageInfo *image_info,Image *image) if (status == False) ThrowWriterException(FileOpenError,UnableToOpenFile,image); scene=0; + image_list_length=GetImageListLength(image); do { unsigned int - depth; - + depth; + (void) TransformColorspace(image,RGBColorspace); if (image->depth <= 8) - depth=8; + depth=8; else if (image->depth <= 16) - depth=16; + depth=16; else - depth=32; + depth=32; if ((AccessDefinition(image_info,"txt","with-im-header"))) { @@ -1211,39 +1270,40 @@ static unsigned int WriteTXTImage(const ImageInfo *image_info,Image *image) "# ImageMagick pixel enumeration: %.20g,%.20g,%.20g,rgb%c\n", (double) image->columns, (double) image->rows, (double) depth, a); - (void) WriteBlobString(image,buffer); + (void) WriteBlobString(image,buffer); } /* - Convert MIFF to TXT raster pixels. + Convert MIFF to TXT raster pixels. */ for (y=0; y < (long) image->rows; y++) - { - p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); - if (p == (const PixelPacket *) NULL) - break; - for (x=0; x < (long) image->columns; x++) - { - FormatString(buffer,"%ld,%ld: ",x,y); - (void) WriteBlobString(image,buffer); - GetColorTuple(p,depth,image->matte,MagickFalse,tuple); - (void) strlcat(tuple," ",sizeof(tuple)); - (void) WriteBlobString(image,tuple); - /* (void) QueryColorname(image,p,SVGCompliance,tuple,&image->exception); */ - GetColorTuple(p,depth,image->matte,MagickTrue,tuple); - (void) WriteBlobString(image,tuple); - (void) WriteBlobString(image,"\n"); - p++; - } - } + { + p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); + if (p == (const PixelPacket *) NULL) + break; + for (x=0; x < (long) image->columns; x++) + { + FormatString(buffer,"%ld,%ld: ",x,y); + (void) WriteBlobString(image,buffer); + GetColorTuple(p,depth,image->matte,MagickFalse,tuple); + (void) strlcat(tuple," ",sizeof(tuple)); + (void) WriteBlobString(image,tuple); + /* (void) QueryColorname(image,p,SVGCompliance,tuple,&image->exception); */ + GetColorTuple(p,depth,image->matte,MagickTrue,tuple); + (void) WriteBlobString(image,tuple); + (void) WriteBlobString(image,"\n"); + p++; + } + } if (image->next == (Image *) NULL) - break; + break; image=SyncNextImageInList(image); - status=MagickMonitorFormatted(scene++,GetImageListLength(image), - &image->exception,SaveImagesText, - image->filename); + status=MagickMonitorFormatted(scene,image_list_length, + &image->exception,SaveImagesText, + image->filename); if (status == False) - break; + break; + scene++; } while (image_info->adjoin); if (image_info->adjoin) while (image->previous != (Image *) NULL) diff --git a/coders/uil.c b/coders/uil.c index 9a58143..e13ab87 100644 --- a/coders/uil.c +++ b/coders/uil.c @@ -83,6 +83,7 @@ ModuleExport void RegisterUILImage(void) entry->adjoin=False; entry->description="X-Motif UIL table"; entry->module="UIL"; + entry->coder_class=UnstableCoderClass; (void) RegisterMagickInfo(entry); } @@ -231,6 +232,7 @@ static unsigned int WriteUILImage(const ImageInfo *image_info,Image *image) colors=image->colors; if (transparent) { + i=0; colors++; for (y=0; y < (long) image->rows; y++) { @@ -265,7 +267,7 @@ static unsigned int WriteUILImage(const ImageInfo *image_info,Image *image) GetPathComponent(image->filename,BasePath,basename); FormatString(buffer,"value\n %.1024s_ct : color_table(\n",basename); (void) WriteBlobString(image,buffer); - for (i=0; i < (long) colors; i++) + for (i=0; i < (long) image->colors; i++) { /* Define UIL color. @@ -333,7 +335,7 @@ static unsigned int WriteUILImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } CloseBlob(image); diff --git a/coders/url.c b/coders/url.c index 0effa56..5d7562e 100644 --- a/coders/url.c +++ b/coders/url.c @@ -140,13 +140,13 @@ static Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception) else if (LocaleCompare(image_info->magick,"file") == 0) access_mode=URLGetFileConfirmAccessMode; - + /* Attempt to re-compose original URL */ (void) strlcpy(filename,image_info->magick,MaxTextExtent); LocaleLower(filename); (void) strlcat(filename,":",MaxTextExtent); (void) strlcat(filename,image_info->filename,MaxTextExtent); - + if (MagickConfirmAccess(access_mode,filename,exception) == MagickFail) return image; diff --git a/coders/uyvy.c b/coders/uyvy.c index 4f003bf..c248599 100644 --- a/coders/uyvy.c +++ b/coders/uyvy.c @@ -166,7 +166,7 @@ static Image *ReadUYVYImage(const ImageInfo *image_info, if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText, image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } image->colorspace=YCbCrColorspace; @@ -354,7 +354,7 @@ static unsigned int WriteUYVYImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } /* diff --git a/coders/vicar.c b/coders/vicar.c index 3e2c90d..ff92c6c 100644 --- a/coders/vicar.c +++ b/coders/vicar.c @@ -293,7 +293,7 @@ static Image *ReadVICARImage(const ImageInfo *image_info, if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText, image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } MagickFreeMemory(scanline); @@ -454,7 +454,7 @@ static unsigned int WriteVICARImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } MagickFreeMemory(scanline); diff --git a/coders/viff.c b/coders/viff.c index 086414d..a1e3da8 100644 --- a/coders/viff.c +++ b/coders/viff.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2016 GraphicsMagick Group +% Copyright (C) 2003-2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -330,7 +330,6 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, size_t alloc_size, - blob_size, max_packets, number_pixels; @@ -419,6 +418,8 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, image->columns=viff_info.rows; image->rows=viff_info.columns; image->depth=viff_info.x_pixel_size <= 8 ? 8 : QuantumDepth; + if (CheckImagePixelLimits(image, exception) != MagickPass) + ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); /* Verify that we can read this VIFF image. */ @@ -501,6 +502,9 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, viff_colormap_size=MagickArraySize(MagickArraySize(bytes_per_pixel, image->colors), viff_info.map_rows); + if (BlobIsSeekable(image) && + (GetBlobSize(image)-TellBlob(image) < (magick_off_t) viff_colormap_size)) + ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); viff_colormap=MagickAllocateMemory(unsigned char *,viff_colormap_size); if (viff_colormap == (unsigned char *) NULL) ThrowReaderException(ResourceLimitError,MemoryAllocationFailed, @@ -510,7 +514,10 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, */ if (ReadBlob(image,viff_colormap_size,(char *) viff_colormap) != viff_colormap_size) - ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); + { + MagickFreeMemory(viff_colormap); + ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); + } lsb_first=1; if (*(char *) &lsb_first && @@ -575,8 +582,16 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, if (image_info->ping && (image_info->subrange != 0)) if (image->scene >= (image_info->subimage+image_info->subrange-1)) break; - if (CheckImagePixelLimits(image, exception) != MagickPass) - ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); + + if (viff_info.data_storage_type == VFF_TYP_BIT) + { + /* + Allocate bi-level colormap + */ + if (AllocateImageColormap(image,2) == MagickFail) + ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); + image->colorspace=GRAYColorspace; + } /* Allocate VIFF pixels. */ @@ -621,8 +636,8 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, (MAGICK_SIZE_T) viff_info.number_data_bands); } alloc_size=MagickArraySize(bytes_per_pixel,max_packets); - blob_size=GetBlobSize(image); - if ((blob_size != 0) && (alloc_size > blob_size)) + if (BlobIsSeekable(image) && + (GetBlobSize(image)-TellBlob(image) < (magick_off_t) alloc_size)) ThrowReaderException(CorruptImageError,InsufficientImageDataInFile,image); viff_pixels=MagickAllocateArray(unsigned char *, MagickArraySize(bytes_per_pixel, @@ -630,7 +645,12 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, sizeof(Quantum)); if (viff_pixels == (unsigned char *) NULL) ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); - (void) ReadBlob(image,bytes_per_pixel*max_packets,(char *) viff_pixels); + if (ReadBlob(image,bytes_per_pixel*max_packets,(char *) viff_pixels) + != bytes_per_pixel*max_packets) + { + MagickFreeMemory(viff_pixels); + ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); + } lsb_first=1; if (*(char *) &lsb_first && ((viff_info.machine_dependency != VFF_DEP_DECORDER) && @@ -736,7 +756,6 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, /* Convert bitmap scanline. */ - (void) SetImageType(image,BilevelType); polarity=PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2); if (image->colors >= 2) polarity=PixelIntensityToQuantum(&image->colormap[0]) > @@ -773,7 +792,7 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception, LoadImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } } @@ -797,7 +816,7 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception, LoadImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } else @@ -839,7 +858,7 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception, LoadImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } } @@ -859,7 +878,7 @@ static Image *ReadVIFFImage(const ImageInfo *image_info, if (image->scene >= (image_info->subimage+image_info->subrange-1)) break; count=ReadBlob(image,1,(char *) &viff_info.identifier); - if ((count != 0) && (viff_info.identifier == 0xab)) + if ((count == 1) && (viff_info.identifier == 0xab)) { /* Allocate next image structure. @@ -1031,6 +1050,9 @@ static unsigned int WriteVIFFImage(const ImageInfo *image_info,Image *image) ViffInfo viff_info; + size_t + image_list_length; + /* Open output image file. */ @@ -1038,6 +1060,7 @@ static unsigned int WriteVIFFImage(const ImageInfo *image_info,Image *image) assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); + image_list_length=GetImageListLength(image); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == False) ThrowWriterException(FileOpenError,UnableToOpenFile,image); @@ -1208,7 +1231,7 @@ static unsigned int WriteVIFFImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } } @@ -1251,7 +1274,7 @@ static unsigned int WriteVIFFImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } } @@ -1303,7 +1326,7 @@ static unsigned int WriteVIFFImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } } @@ -1326,8 +1349,8 @@ static unsigned int WriteVIFFImage(const ImageInfo *image_info,Image *image) if (image->previous == (Image *) NULL) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, - SaveImageText,image->filename, - image->columns,image->rows)) + SaveImageText,image->filename, + image->columns,image->rows)) break; } } @@ -1336,7 +1359,7 @@ static unsigned int WriteVIFFImage(const ImageInfo *image_info,Image *image) if (image->next == (Image *) NULL) break; image=SyncNextImageInList(image); - status=MagickMonitorFormatted(scene++,GetImageListLength(image), + status=MagickMonitorFormatted(scene++,image_list_length, &image->exception,SaveImagesText, image->filename); if (status == False) diff --git a/coders/wbmp.c b/coders/wbmp.c index e6d616d..9cd5bff 100644 --- a/coders/wbmp.c +++ b/coders/wbmp.c @@ -144,16 +144,16 @@ static Image *ReadWBMPImage(const ImageInfo *image_info, status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == False) ThrowReaderException(FileOpenError,UnableToOpenFile,image); - if (!ReadBlob(image,2,(char *) &header)) + if (ReadBlob(image,2,(char *) &header) != 2) ThrowReaderException(CorruptImageError,ImproperImageHeader,image); if (header != 0U) ThrowReaderException(CoderError,OnlyLevelZerofilesSupported,image); /* Initialize image structure. */ - if (WBMPReadInteger(image,&image->columns) == False) + if (WBMPReadInteger(image,&image->columns) == False) ThrowReaderException(CorruptImageError,CorruptImage,image); - if (WBMPReadInteger(image,&image->rows) == False) + if (WBMPReadInteger(image,&image->rows) == False) ThrowReaderException(CorruptImageError,CorruptImage,image); if ((image->columns == 0) || (image->rows == 0)) ThrowReaderException(CorruptImageError,ImproperImageHeader,image); @@ -199,7 +199,7 @@ static Image *ReadWBMPImage(const ImageInfo *image_info, if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText, image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } (void) SyncImage(image); @@ -404,7 +404,7 @@ static unsigned int WriteWBMPImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } CloseBlob(image); diff --git a/coders/webp.c b/coders/webp.c index 284a714..7ff34b4 100644 --- a/coders/webp.c +++ b/coders/webp.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2013 - 2014 GraphicsMagick Group +% Copyright (C) 2013 - 2017 GraphicsMagick Group % % This program is covered by multiple licenses, which are described in % Copyright.txt. You should have received a copy of Copyright.txt with this @@ -44,6 +44,8 @@ #include "magick/magick.h" #include "magick/monitor.h" #include "magick/pixel_cache.h" +#include "magick/profile.h" +#include "magick/tsd.h" #include "magick/utility.h" /* @@ -64,13 +66,19 @@ static unsigned int WriteWEBPImage(const ImageInfo *,Image *); Release versions vs ABI versions (found in src/webp/encode.h) 0.1.3 - 0x0002 - 0.1.99 - 0x0100 + 0.1.99 - 0x0100 <-- earliest version we support 0.2.0 - 0x0200 0.2.1 - 0x0200 0.3.0 - 0x0201 0.4.0 - 0x0202 0.4.1 - 0x0202 0.4.2 - 0x0202 + 0.4.3 - 0x0202 + 0.4.4 - 0x0202 + 0.5.0 - 0x0209 + 0.5.1 - 0x0209 + 0.5.2 - 0x0209 + 0.6.0 - 0x020e */ /* @@ -89,6 +97,20 @@ static unsigned int WriteWEBPImage(const ImageInfo *,Image *); # define SUPPORT_CONFIG_THREAD_LEVEL # define SUPPORT_CONFIG_LOW_MEMORY #endif +#if WEBP_ENCODER_ABI_VERSION >= 0x0202 /* >= 0.4.0 */ +#endif +#if WEBP_ENCODER_ABI_VERSION >= 0x0209 /* >= 0.5.0 */ +# define SUPPORT_WEBP_MUX +#include +#endif +#if WEBP_ENCODER_ABI_VERSION >= 0x020e /* >= 0.6.0 */ +#endif + +/* + Global declarations. +*/ +static MagickTsdKey_t tsd_key = (MagickTsdKey_t) 0; + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -200,9 +222,9 @@ static Image *ReadWEBPImage(const ImageInfo *image_info, case VP8_STATUS_SUSPENDED: /* Incremental decoder object may be left in SUSPENDED state - if the picture is only partially decoded, pending - additional input. We are not doing incremental decoding - at this time. + if the picture is only partially decoded, pending + additional input. We are not doing incremental decoding + at this time. */ break; case VP8_STATUS_USER_ABORT: @@ -242,8 +264,8 @@ static Image *ReadWEBPImage(const ImageInfo *image_info, &stream_features.height); else pixels=(unsigned char *) WebPDecodeRGB(stream,length, - &stream_features.width, - &stream_features.height); + &stream_features.width, + &stream_features.height); if (pixels == (unsigned char *) NULL) { MagickFreeMemory(stream); @@ -270,9 +292,40 @@ static Image *ReadWEBPImage(const ImageInfo *image_info, q++; } - if(!SyncImagePixels(image)) + if (!SyncImagePixels(image)) break; } + +#if defined(SUPPORT_WEBP_MUX) + /* Read features out of the WebP container */ + { + uint32_t webp_flags=0; + WebPData flag_data; + WebPData content={stream,length}; + + WebPMux *mux=WebPMuxCreate(&content,0); + (void) memset(&flag_data,0,sizeof(flag_data)); + WebPMuxGetFeatures(mux,&webp_flags); + + if (webp_flags & ICCP_FLAG) { + WebPMuxGetChunk(mux,"ICCP",&flag_data); + AppendImageProfile(image,"ICC",flag_data.bytes,flag_data.size); + } + + if (webp_flags & EXIF_FLAG) { + WebPMuxGetChunk(mux,"EXIF",&flag_data); + AppendImageProfile(image,"EXIF",flag_data.bytes,flag_data.size); + } + + if (webp_flags & XMP_FLAG) { + WebPMuxGetChunk(mux,"XMP",&flag_data); + AppendImageProfile(image,"XMP",flag_data.bytes,flag_data.size); + } + + WebPMuxDelete(mux); + } +#endif /* defined(SUPPORT_WEBP_MUX) */ + /* Free scale resource. */ @@ -329,6 +382,12 @@ ModuleExport void RegisterWEBPImage(void) *version='\0'; /* + Initialize thread specific data key. + */ + if (tsd_key == (MagickTsdKey_t) 0) + (void) MagickTsdKeyCreate(&tsd_key); + + /* Obtain the encoder's version number from the library, packed in hexadecimal using 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. @@ -381,6 +440,15 @@ ModuleExport void RegisterWEBPImage(void) ModuleExport void UnregisterWEBPImage(void) { (void) UnregisterMagickInfo("WEBP"); + + /* + Destroy thread specific data key. + */ + if (tsd_key != (MagickTsdKey_t) 0) + { + (void) MagickTsdKeyDelete(tsd_key); + tsd_key = (MagickTsdKey_t) 0; + } } #if defined(HasWEBP) @@ -409,8 +477,10 @@ ModuleExport void UnregisterWEBPImage(void) % */ -/* - Called to write data to blob +#if !defined(SUPPORT_WEBP_MUX) + /* + Called to write data to blob ("Should return true if writing was + successful") */ static int WriterCallback(const unsigned char *stream,size_t length, const WebPPicture *const picture) @@ -419,11 +489,17 @@ static int WriterCallback(const unsigned char *stream,size_t length, *image; image=(Image *) picture->custom_ptr; - return (length != 0 ? (int) WriteBlob(image,length,stream) : 1); + assert(image != (Image *) NULL); + assert(image->signature == MagickSignature); + return (length != 0U ? (WriteBlob(image,length,stream) == length) : + MagickTrue); } +#endif /* !defined(SUPPORT_WEBP_MUX) */ /* - Called to provide progress indication + Called to provide progress indication ("It can return false to + request an abort of the encoding process, or true otherwise if + everything is OK.") */ #if defined(SUPPORT_PROGRESS) static int ProgressCallback(int percent, const WebPPicture* picture) @@ -431,12 +507,24 @@ static int ProgressCallback(int percent, const WebPPicture* picture) Image *image; + /* + When the WebPMemoryWriter is used, it commandeers custom_ptr + and the ProgressCallback no longer has access to image. + + We use thread specific data instead. + */ + (void) picture; + image=(Image *) MagickTsdGetSpecific(tsd_key); +#if 0 image=(Image *) picture->custom_ptr; +#endif + assert(image != (Image *) NULL); + assert(image->signature == MagickSignature); return MagickMonitorFormatted(percent, 101, &image->exception, SaveImageText, image->filename, image->columns, image->rows); } -#endif +#endif /* defined(SUPPORT_PROGRESS) */ static unsigned int WriteWEBPImage(const ImageInfo *image_info,Image *image) { @@ -473,6 +561,11 @@ static unsigned int WriteWEBPImage(const ImageInfo *image_info,Image *image) WebPPicture picture; +#if defined(SUPPORT_WEBP_MUX) + WebPMemoryWriter + writer; +#endif /* defined(SUPPORT_WEBP_MUX) */ + WebPAuxStats statistics; @@ -501,8 +594,16 @@ static unsigned int WriteWEBPImage(const ImageInfo *image_info,Image *image) (void) TransformColorspace(image,RGBColorspace); image->storage_class=DirectClass; + (void) MagickTsdSetSpecific(tsd_key,(void *) image); + +#if !defined(SUPPORT_WEBP_MUX) picture.writer=WriterCallback; picture.custom_ptr=(void *) image; +#else + WebPMemoryWriterInit(&writer); + picture.writer=WebPMemoryWrite; + picture.custom_ptr=&writer; +#endif #if defined(SUPPORT_PROGRESS) picture.progress_hook=ProgressCallback; #endif @@ -589,7 +690,7 @@ static unsigned int WriteWEBPImage(const ImageInfo *image_info,Image *image) for (y = 0; y < image->rows; y++) { magick_uint32_t *s = picture.argb + y * picture.argb_stride; - p=GetImagePixelsEx(image,0,y,image->columns,1,&image->exception); + p=GetImagePixelsEx(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; for (x = 0; x < image->columns; x++) @@ -707,7 +808,98 @@ static unsigned int WriteWEBPImage(const ImageInfo *image_info,Image *image) } /* if (! webp_status) */ } /* if (webp_status) */ +#if defined(SUPPORT_WEBP_MUX) + /* Write profiles */ + if (image->profiles) + { + size_t idx; + + /* Mapping of GraphicsMagick->libwebp feature/profile names */ + char data_features[][3][6]={{"ICC", "ICCP"},{"EXIF", "EXIF"},{"XMP", "XMP"}}; + + /* Prepare the WebP muxer */ + WebPMuxError mux_error; + WebPMux *mux=WebPMuxNew(); + WebPData encoded_image={writer.mem,writer.size}; + + WebPMuxSetImage(mux,&encoded_image,1); + + /* Iterate over all available features and try to push them into the WebP container */ + for (idx=0;idxr); stroke_color.green = ScaleCharToQuantum(rgb->g); stroke_color.blue = ScaleCharToQuantum(rgb->b); stroke_color.opacity = OpaqueOpacity; - + DrawSetStrokeColor(WmfDrawContext,&stroke_color); } @@ -333,7 +333,7 @@ static void ipa_rop_draw(wmfAPI * API, wmfROP_Draw_t * rop_draw) { /* wmfBrush */ /* *brush = WMF_DC_BRUSH(rop_draw->dc); */ - + /* wmfBMP */ /* *brush_bmp = WMF_BRUSH_BITMAP(brush); */ @@ -348,12 +348,12 @@ static void ipa_rop_draw(wmfAPI * API, wmfROP_Draw_t * rop_draw) /* struct _wmfROP_Draw_t { wmfDC* dc; - + wmfD_Coord TL; wmfD_Coord BR; - + U32 ROP; - + double pixel_width; double pixel_height; }; @@ -540,7 +540,7 @@ static void ipa_bmp_read(wmfAPI * API, wmfBMP_Read_t * bmp_read) { { char size[MaxTextExtent]; - + FormatString(size,"%ux%u",bmp_read->width,bmp_read->height); (void) CloneString(&image_info->size,size); } @@ -667,7 +667,7 @@ static void ipa_device_begin(wmfAPI * API) ImageInfo *image_info; - + ExceptionInfo exception; @@ -1226,7 +1226,7 @@ static void ipa_functions(wmfAPI *API) static void ipa_draw_text(wmfAPI * API, wmfDrawText_t * draw_text) { - double + double angle = 0, /* text rotation angle */ pointsize = 0; /* pointsize to output font with desired height */ @@ -1320,7 +1320,7 @@ static void ipa_draw_text(wmfAPI * API, wmfDrawText_t * draw_text) { Image *image = ddata->image; - + DrawInfo *draw_info; @@ -1336,7 +1336,7 @@ static void ipa_draw_text(wmfAPI * API, wmfDrawText_t * draw_text) { double text_width = metrics.width * (ddata->scale_y / ddata->scale_x); - + #if defined(HasWMFlite) point.x -= text_width / 2; #else @@ -1564,7 +1564,7 @@ static void util_set_brush(wmfAPI * API, wmfDC * dc, const BrushApply brush_appl DrawPushDefs(WmfDrawContext); draw_pattern_push(API, ddata->pattern_id, 8, 8); DrawPushGraphicContext(WmfDrawContext); - + if (WMF_DC_OPAQUE(dc)) { if( brush_apply == BrushApplyStroke ) @@ -1577,12 +1577,12 @@ static void util_set_brush(wmfAPI * API, wmfDC * dc, const BrushApply brush_appl DrawSetStrokeAntialias(WmfDrawContext, False); DrawSetStrokeWidth(WmfDrawContext, 1); - + draw_color_stroke_rgb(API,WMF_BRUSH_COLOR(brush)); - + switch ((unsigned int) WMF_BRUSH_HATCH(brush)) { - + case HS_HORIZONTAL: /* ----- */ { DrawLine(WmfDrawContext, 0, 3, 7,3); @@ -1657,7 +1657,7 @@ static void util_set_brush(wmfAPI * API, wmfDC * dc, const BrushApply brush_appl if (brush_bmp && brush_bmp->data != 0) { - CompositeOperator + CompositeOperator mode; const Image @@ -1972,7 +1972,7 @@ static double util_pointsize( wmfAPI* API, wmfFont* font, char* str, double font draw_info->pointsize = pointsize; if (GetTypeMetrics(image, draw_info, &metrics) != False) pointsize *= (font_height / metrics.height); - + } @@ -2130,7 +2130,7 @@ static const wmfFontMap WMFFontMap[] = { /* Mapping between base name and Ghostscript family name */ static const wmfMapping SubFontMap[] = { - { "Arial", "Helvetica", (FT_Encoding) 0 }, + { "Arial", "Helvetica", (FT_Encoding) 0 }, { "Courier", "Courier", (FT_Encoding) 0 }, { "Fixed", "Courier", (FT_Encoding) 0 }, { "Helvetica", "Helvetica", (FT_Encoding) 0 }, @@ -2209,7 +2209,7 @@ static void lite_font_map( wmfAPI* API, wmfFont* font) weight; /* printf("Considering font %s\n", type_info->description); */ - + if( WMF_FONT_ITALIC(font) && !(strstr(type_info->description,"Italic") || strstr(type_info->description,"Oblique")) ) continue; @@ -2296,7 +2296,7 @@ static void lite_font_map( wmfAPI* API, wmfFont* font) printf("WMF_FONT_PSNAME = \"%s\"\n", WMF_FONT_PSNAME(font)); fflush(stdout); #endif - + } /* Initialize API font structures */ @@ -2402,7 +2402,7 @@ static Image *ReadWMFImage(const ImageInfo * image_info, ExceptionInfo * excepti } ThrowReaderException(FileOpenError,UnableToOpenFile,image); } - + /* * Create WMF API * @@ -2571,7 +2571,7 @@ static Image *ReadWMFImage(const ImageInfo * image_info, ExceptionInfo * excepti { (void) LogMagickEvent(CoderEvent,GetMagickModule()," Placeable metafile: %s", (API)->File->placeable ? "Yes" : "No"); - + (void) LogMagickEvent(CoderEvent,GetMagickModule()," Size in metafile units: %.4gx%.4g", wmf_width, wmf_height); (void) LogMagickEvent(CoderEvent,GetMagickModule()," Metafile units/inch: %.4g", @@ -2601,7 +2601,7 @@ static Image *ReadWMFImage(const ImageInfo * image_info, ExceptionInfo * excepti wmfPen default_pen; wmfBrush default_brush; wmfFont default_font; - + wmfDC* dc; /* current dc */ }; @@ -2694,7 +2694,7 @@ static Image *ReadWMFImage(const ImageInfo * image_info, ExceptionInfo * excepti if (logging) { (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Playing WMF failed with wmf_error_code %d", wmf_error_code); + " Playing WMF failed with wmf_error_code %d", wmf_error_code); (void) LogMagickEvent(CoderEvent,GetMagickModule(),"leave ReadWMFImage()"); } ipa_device_close(API); @@ -2719,8 +2719,8 @@ static Image *ReadWMFImage(const ImageInfo * image_info, ExceptionInfo * excepti if(image->exception.severity != UndefinedException) ThrowException2(exception, CoderWarning, - ddata->image->exception.reason, - ddata->image->exception.description); + image->exception.reason, + image->exception.description); if(logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(),"leave ReadWMFImage()"); @@ -2761,7 +2761,7 @@ ModuleExport void RegisterWMFImage(void) *entry; static const char - *WMFNote = + *WMFNote = { "Use density to adjust scale (default 72DPI). Use background or\n" "texture to apply a background color or texture under the image." diff --git a/coders/wpg.c b/coders/wpg.c index b4b83ca..ef67f09 100644 --- a/coders/wpg.c +++ b/coders/wpg.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2016 GraphicsMagick Group +% Copyright (C) 2003-2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % % This program is covered by multiple licenses, which are described in @@ -21,7 +21,7 @@ % % % Software Design % % Jaroslav Fojtik % -% June 2000 - 2016 % +% June 2000 - 2018 % % Rework for GraphicsMagick % % Bob Friesenhahn % % Feb-May 2003 % @@ -39,6 +39,7 @@ #include "magick/blob.h" #include "magick/colormap.h" #include "magick/constitute.h" +#include "magick/log.h" #include "magick/magic.h" #include "magick/magick.h" #include "magick/pixel_cache.h" @@ -57,137 +58,144 @@ typedef struct /* Default palette for WPG level 1 */ const RGB_Record WPG1_Palette[256]={ -{ 0, 0, 0}, { 0, 0,168}, -{ 0,168, 0}, { 0,168,168}, -{168, 0, 0}, {168, 0,168}, -{168, 84, 0}, {168,168,168}, -{ 84, 84, 84}, { 84, 84,252}, -{ 84,252, 84}, { 84,252,252}, -{252, 84, 84}, {252, 84,252}, -{252,252, 84}, {252,252,252}, /*16*/ -{ 0, 0, 0}, { 20, 20, 20}, -{ 32, 32, 32}, { 44, 44, 44}, -{ 56, 56, 56}, { 68, 68, 68}, -{ 80, 80, 80}, { 96, 96, 96}, -{112,112,112}, {128,128,128}, -{144,144,144}, {160,160,160}, -{180,180,180}, {200,200,200}, -{224,224,224}, {252,252,252}, /*32*/ -{ 0, 0,252}, { 64, 0,252}, -{124, 0,252}, {188, 0,252}, -{252, 0,252}, {252, 0,188}, -{252, 0,124}, {252, 0, 64}, -{252, 0, 0}, {252, 64, 0}, -{252,124, 0}, {252,188, 0}, -{252,252, 0}, {188,252, 0}, -{124,252, 0}, { 64,252, 0}, /*48*/ -{ 0,252, 0}, { 0,252, 64}, -{ 0,252,124}, { 0,252,188}, -{ 0,252,252}, { 0,188,252}, -{ 0,124,252}, { 0, 64,252}, -{124,124,252}, {156,124,252}, -{188,124,252}, {220,124,252}, -{252,124,252}, {252,124,220}, -{252,124,188}, {252,124,156}, /*64*/ -{252,124,124}, {252,156,124}, -{252,188,124}, {252,220,124}, -{252,252,124}, {220,252,124}, -{188,252,124}, {156,252,124}, -{124,252,124}, {124,252,156}, -{124,252,188}, {124,252,220}, -{124,252,252}, {124,220,252}, -{124,188,252}, {124,156,252}, /*80*/ -{180,180,252}, {196,180,252}, -{216,180,252}, {232,180,252}, -{252,180,252}, {252,180,232}, -{252,180,216}, {252,180,196}, -{252,180,180}, {252,196,180}, -{252,216,180}, {252,232,180}, -{252,252,180}, {232,252,180}, -{216,252,180}, {196,252,180}, /*96*/ -{180,220,180}, {180,252,196}, -{180,252,216}, {180,252,232}, -{180,252,252}, {180,232,252}, -{180,216,252}, {180,196,252}, -{0,0,112}, {28,0,112}, -{56,0,112}, {84,0,112}, -{112,0,112}, {112,0,84}, -{112,0,56}, {112,0,28}, /*112*/ -{112,0,0}, {112,28,0}, -{112,56,0}, {112,84,0}, -{112,112,0}, {84,112,0}, -{56,112,0}, {28,112,0}, -{0,112,0}, {0,112,28}, -{0,112,56}, {0,112,84}, -{0,112,112}, {0,84,112}, -{0,56,112}, {0,28,112}, /*128*/ -{56,56,112}, {68,56,112}, -{84,56,112}, {96,56,112}, -{112,56,112}, {112,56,96}, -{112,56,84}, {112,56,68}, -{112,56,56}, {112,68,56}, -{112,84,56}, {112,96,56}, -{112,112,56}, {96,112,56}, -{84,112,56}, {68,112,56}, /*144*/ -{56,112,56}, {56,112,69}, -{56,112,84}, {56,112,96}, -{56,112,112}, {56,96,112}, -{56,84,112}, {56,68,112}, -{80,80,112}, {88,80,112}, -{96,80,112}, {104,80,112}, -{112,80,112}, {112,80,104}, -{112,80,96}, {112,80,88}, /*160*/ -{112,80,80}, {112,88,80}, -{112,96,80}, {112,104,80}, -{112,112,80}, {104,112,80}, -{96,112,80}, {88,112,80}, -{80,112,80}, {80,112,88}, -{80,112,96}, {80,112,104}, -{80,112,112}, {80,114,112}, -{80,96,112}, {80,88,112}, /*176*/ -{0,0,64}, {16,0,64}, -{32,0,64}, {48,0,64}, -{64,0,64}, {64,0,48}, -{64,0,32}, {64,0,16}, -{64,0,0}, {64,16,0}, -{64,32,0}, {64,48,0}, -{64,64,0}, {48,64,0}, -{32,64,0}, {16,64,0}, /*192*/ -{0,64,0}, {0,64,16}, -{0,64,32}, {0,64,48}, -{0,64,64}, {0,48,64}, -{0,32,64}, {0,16,64}, -{32,32,64}, {40,32,64}, -{48,32,64}, {56,32,64}, -{64,32,64}, {64,32,56}, -{64,32,48}, {64,32,40}, /*208*/ -{64,32,32}, {64,40,32}, -{64,48,32}, {64,56,32}, -{64,64,32}, {56,64,32}, -{48,64,32}, {40,64,32}, -{32,64,32}, {32,64,40}, -{32,64,48}, {32,64,56}, -{32,64,64}, {32,56,64}, -{32,48,64}, {32,40,64}, /*224*/ -{44,44,64}, {48,44,64}, -{52,44,64}, {60,44,64}, -{64,44,64}, {64,44,60}, -{64,44,52}, {64,44,48}, -{64,44,44}, {64,48,44}, -{64,52,44}, {64,60,44}, -{64,64,44}, {60,64,44}, -{52,64,44}, {48,64,44}, /*240*/ -{44,64,44}, {44,64,48}, -{44,64,52}, {44,64,60}, -{44,64,64}, {44,60,64}, -{44,55,64}, {44,48,64}, -{0,0,0}, {0,0,0}, -{0,0,0}, {0,0,0}, -{0,0,0}, {0,0,0}, -{0,0,0}, {0,0,0} /*256*/ +{ 0, 0, 0}, { 0, 0,168}, +{ 0,168, 0}, { 0,168,168}, +{168, 0, 0}, {168, 0,168}, +{168, 84, 0}, {168,168,168}, +{ 84, 84, 84}, { 84, 84,252}, +{ 84,252, 84}, { 84,252,252}, +{252, 84, 84}, {252, 84,252}, +{252,252, 84}, {252,252,252}, /*16*/ +{ 0, 0, 0}, { 20, 20, 20}, +{ 32, 32, 32}, { 44, 44, 44}, +{ 56, 56, 56}, { 68, 68, 68}, +{ 80, 80, 80}, { 96, 96, 96}, +{112,112,112}, {128,128,128}, +{144,144,144}, {160,160,160}, +{180,180,180}, {200,200,200}, +{224,224,224}, {252,252,252}, /*32*/ +{ 0, 0,252}, { 64, 0,252}, +{124, 0,252}, {188, 0,252}, +{252, 0,252}, {252, 0,188}, +{252, 0,124}, {252, 0, 64}, +{252, 0, 0}, {252, 64, 0}, +{252,124, 0}, {252,188, 0}, +{252,252, 0}, {188,252, 0}, +{124,252, 0}, { 64,252, 0}, /*48*/ +{ 0,252, 0}, { 0,252, 64}, +{ 0,252,124}, { 0,252,188}, +{ 0,252,252}, { 0,188,252}, +{ 0,124,252}, { 0, 64,252}, +{124,124,252}, {156,124,252}, +{188,124,252}, {220,124,252}, +{252,124,252}, {252,124,220}, +{252,124,188}, {252,124,156}, /*64*/ +{252,124,124}, {252,156,124}, +{252,188,124}, {252,220,124}, +{252,252,124}, {220,252,124}, +{188,252,124}, {156,252,124}, +{124,252,124}, {124,252,156}, +{124,252,188}, {124,252,220}, +{124,252,252}, {124,220,252}, +{124,188,252}, {124,156,252}, /*80*/ +{180,180,252}, {196,180,252}, +{216,180,252}, {232,180,252}, +{252,180,252}, {252,180,232}, +{252,180,216}, {252,180,196}, +{252,180,180}, {252,196,180}, +{252,216,180}, {252,232,180}, +{252,252,180}, {232,252,180}, +{216,252,180}, {196,252,180}, /*96*/ +{180,220,180}, {180,252,196}, +{180,252,216}, {180,252,232}, +{180,252,252}, {180,232,252}, +{180,216,252}, {180,196,252}, +{0,0,112}, {28,0,112}, +{56,0,112}, {84,0,112}, +{112,0,112}, {112,0,84}, +{112,0,56}, {112,0,28}, /*112*/ +{112,0,0}, {112,28,0}, +{112,56,0}, {112,84,0}, +{112,112,0}, {84,112,0}, +{56,112,0}, {28,112,0}, +{0,112,0}, {0,112,28}, +{0,112,56}, {0,112,84}, +{0,112,112}, {0,84,112}, +{0,56,112}, {0,28,112}, /*128*/ +{56,56,112}, {68,56,112}, +{84,56,112}, {96,56,112}, +{112,56,112}, {112,56,96}, +{112,56,84}, {112,56,68}, +{112,56,56}, {112,68,56}, +{112,84,56}, {112,96,56}, +{112,112,56}, {96,112,56}, +{84,112,56}, {68,112,56}, /*144*/ +{56,112,56}, {56,112,69}, +{56,112,84}, {56,112,96}, +{56,112,112}, {56,96,112}, +{56,84,112}, {56,68,112}, +{80,80,112}, {88,80,112}, +{96,80,112}, {104,80,112}, +{112,80,112}, {112,80,104}, +{112,80,96}, {112,80,88}, /*160*/ +{112,80,80}, {112,88,80}, +{112,96,80}, {112,104,80}, +{112,112,80}, {104,112,80}, +{96,112,80}, {88,112,80}, +{80,112,80}, {80,112,88}, +{80,112,96}, {80,112,104}, +{80,112,112}, {80,114,112}, +{80,96,112}, {80,88,112}, /*176*/ +{0,0,64}, {16,0,64}, +{32,0,64}, {48,0,64}, +{64,0,64}, {64,0,48}, +{64,0,32}, {64,0,16}, +{64,0,0}, {64,16,0}, +{64,32,0}, {64,48,0}, +{64,64,0}, {48,64,0}, +{32,64,0}, {16,64,0}, /*192*/ +{0,64,0}, {0,64,16}, +{0,64,32}, {0,64,48}, +{0,64,64}, {0,48,64}, +{0,32,64}, {0,16,64}, +{32,32,64}, {40,32,64}, +{48,32,64}, {56,32,64}, +{64,32,64}, {64,32,56}, +{64,32,48}, {64,32,40}, /*208*/ +{64,32,32}, {64,40,32}, +{64,48,32}, {64,56,32}, +{64,64,32}, {56,64,32}, +{48,64,32}, {40,64,32}, +{32,64,32}, {32,64,40}, +{32,64,48}, {32,64,56}, +{32,64,64}, {32,56,64}, +{32,48,64}, {32,40,64}, /*224*/ +{44,44,64}, {48,44,64}, +{52,44,64}, {60,44,64}, +{64,44,64}, {64,44,60}, +{64,44,52}, {64,44,48}, +{64,44,44}, {64,48,44}, +{64,52,44}, {64,60,44}, +{64,64,44}, {60,64,44}, +{52,64,44}, {48,64,44}, /*240*/ +{44,64,44}, {44,64,48}, +{44,64,52}, {44,64,60}, +{44,64,64}, {44,60,64}, +{44,55,64}, {44,48,64}, +{0,0,0}, {0,0,0}, +{0,0,0}, {0,0,0}, +{0,0,0}, {0,0,0}, +{0,0,0}, {0,0,0} /*256*/ }; +static int ApproveFormatForWPG(const char *Format) +{ + if(!strcmp(Format,"PFB")) return 0; + return 1; +} + + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -228,33 +236,32 @@ static unsigned int IsWPG(const unsigned char *magick,const size_t length) } -static void Rd_WP_DWORD(Image *image,unsigned long *d) +static int Rd_WP_DWORD(Image *image, unsigned long *d) { - unsigned char - b; + unsigned char b; - b=ReadBlobByte(image); - *d=b; + b = ReadBlobByte(image); + *d = b; if (b < 0xFFU) - return; - b=ReadBlobByte(image); - *d=(unsigned long) b; - b=ReadBlobByte(image); + return 1; + b = ReadBlobByte(image); + *d = (unsigned long) b; + b = ReadBlobByte(image); *d+=(unsigned long) b*256l; if (*d < 0x8000) - return; + return 3; *d=(*d & 0x7FFF) << 16; + b = ReadBlobByte(image); + *d += (unsigned long) b; b=ReadBlobByte(image); - *d+=(unsigned long) b; - b=ReadBlobByte(image); - *d+=(unsigned long) b*256l; - return; + *d += (unsigned long) b*256l; + return 5; } -static MagickPassFail InsertRow(unsigned char *p,long y, Image *image, int bpp) +static MagickPassFail InsertRow(unsigned char *p,unsigned long y, Image *image, int bpp) { - long + unsigned long x; register PixelPacket *q; @@ -262,15 +269,19 @@ static MagickPassFail InsertRow(unsigned char *p,long y, Image *image, int bpp) IndexPacket index; IndexPacket *indexes; + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Insert row %ld of %lu...", y, image->rows); q = SetImagePixels(image,0,y,image->columns,1); - if(q == (PixelPacket *) NULL) return MagickFail; + if(q == (PixelPacket *) NULL) + return MagickFail; switch (bpp) { case 1: /* Convert bitmap scanline. WP seems to ignore palette even if it is present. */ RetVal = ImportImagePixelArea(image,GrayQuantum,bpp,p,NULL,0); - break; + break; case 4: /* Convert PseudoColor scanline. */ case 8: /* Convert PseudoColor scanline. */ @@ -280,8 +291,16 @@ static MagickPassFail InsertRow(unsigned char *p,long y, Image *image, int bpp) case 2: /* Convert PseudoColor scanline. */ { indexes=AccessMutableIndexes(image); + if ((image->storage_class != PseudoClass) || + (indexes == (IndexPacket *) NULL)) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Image has no colormap, skipping..."); + return MagickFail; + } x = 0; - while(x < (long)image->columns-3) + while(x+3 < image->columns) { index = (IndexPacket)((*p >> 6) & 0x3); VerifyColormapIndex(image,index); @@ -300,20 +319,20 @@ static MagickPassFail InsertRow(unsigned char *p,long y, Image *image, int bpp) indexes[x++]=index; *q++ = image->colormap[index]; p++; - } - if(x < (long) image->columns) + } + if(x < image->columns) { index = (IndexPacket) ((*p >> 6) & 0x3); VerifyColormapIndex(image,index); indexes[x++] = index; *q++=image->colormap[index]; - if(x < (long) image->columns) + if(x < image->columns) { index = (IndexPacket) ((*p >> 4) & 0x3); VerifyColormapIndex(image,index); indexes[x++] = index; *q++=image->colormap[index]; - if(x < (long) image->columns) + if(x < image->columns) { index = (IndexPacket)((*p >> 2) & 0x3); VerifyColormapIndex(image,index); @@ -322,29 +341,36 @@ static MagickPassFail InsertRow(unsigned char *p,long y, Image *image, int bpp) } } /* p++; */ - } + } RetVal = MagickPass; break; } - - case 24: /* Convert DirectColor scanline. */ + + case 24: /* Convert DirectColor scanline. */ RetVal = ImportImagePixelArea(image,RGBQuantum,8,p,NULL,0); break; default: + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Unsupported bits per pixel %u",bpp); + return MagickFail; /* emit some error here */ } if(RetVal==MagickFail) - (void) LogMagickEvent(CoderEvent,GetMagickModule(),"ImportImagePixelArea failed for row: %ld, bpp: %d", y, bpp); + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(),"ImportImagePixelArea failed for row: %lu, bpp: %d", y, bpp); + return MagickFail; + } - if (!SyncImagePixels(image)) + if(!SyncImagePixels(image)) { - (void) LogMagickEvent(CoderEvent,GetMagickModule(),"SyncImagePixels failed for row: %ld, bpp: %d", y, bpp); - RetVal = MagickFail; + (void) LogMagickEvent(CoderEvent,GetMagickModule(),"SyncImagePixels failed for row: %ld, bpp: %d", y, bpp); + return MagickFail; } - + return RetVal; } @@ -356,19 +382,42 @@ return RetVal; x++; \ if((long) x>=ldblk) \ { \ - (void)InsertRow(BImgBuff,(long) y,image,bpp); \ + if(InsertRow(BImgBuff,y,image,bpp)==MagickFail) RetVal=-6; \ x=0; \ y++; \ + if(y>=image->rows) break; \ } \ } -/* WPG1 raster reader. */ + +/** Call this function to ensure that all data matrix is filled with something. This function + * is used only to error recovery. */ +static void ZeroFillMissingData(unsigned char *BImgBuff,unsigned long x, unsigned long y, Image *image, + int bpp, long ldblk) +{ + while(y < image->rows) + { + if((long) xcolumns+7)/8); + ldblk = (long)((bpp*image->columns+7)/8); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Raster allocation size: %ld byte%s", ldblk, (ldblk > 1 ? "s" : "")); @@ -389,11 +438,12 @@ static int UnpackWPGRaster(Image *image,int bpp) if(BImgBuff==NULL) return(-2); (void) memset(BImgBuff,0,(size_t) ldblk); - while(y<(long) image->rows) + while(yrows) { i = ReadBlobByte(image); - if(i==EOF) - { + if(i==EOF) + { + ZeroFillMissingData(BImgBuff,x,y,image,bpp,ldblk); MagickFreeMemory(BImgBuff); return(-5); } @@ -422,29 +472,47 @@ static int UnpackWPGRaster(Image *image,int bpp) } } else { /* repeat previous line runcount* */ - RunCount=ReadBlobByte(image); - if(x) { /* attempt to duplicate row from x position: */ - /* I do not know what to do here */ + i = ReadBlobByte(image); + if(i==EOF) + { + ZeroFillMissingData(BImgBuff,x,y,image,bpp,ldblk); + MagickFreeMemory(BImgBuff); + return -7; + } + RunCount = i; + if(x!=0) { /* attempt to duplicate row from x position: */ + /* I do not know what to do here */ + if (InsertRow(BImgBuff,y,image,bpp) == MagickPass) /* May be line flush can fix a situation. */ + { + x=0; + y++; + ZeroFillMissingData(BImgBuff,x,y,image,bpp,ldblk); + } MagickFreeMemory(BImgBuff); return(-3); } - for(i=0;i < (int) RunCount;i++) - { - x=0; - y++; /* Here I need to duplicate previous row RUNCOUNT* */ - if(y<2) continue; - if(y>(long) image->rows) + for(i=0; i<(int)RunCount; i++) + { /* Here I need to duplicate previous row RUNCOUNT* */ + /* when x=0; y points to a new empty line. For y=0 zero line will be populated. */ + if(y>=image->rows) { + ZeroFillMissingData(BImgBuff,x,y,image,bpp,ldblk); MagickFreeMemory(BImgBuff); return(-4); } - (void) InsertRow(BImgBuff,y-1,image,bpp); + if(InsertRow(BImgBuff,y,image,bpp)==MagickFail) + { + ZeroFillMissingData(BImgBuff,x,y,image,bpp,ldblk); + MagickFreeMemory(BImgBuff); + return(-6); + } + y++; } } } } MagickFreeMemory(BImgBuff); - return(0); + return(RetVal); } @@ -458,7 +526,7 @@ static int UnpackWPGRaster(Image *image,int bpp) x++; \ if((long) x >= ldblk) \ { \ - (void)InsertRow(BImgBuff,(long) y,image,bpp); \ + if(InsertRow(BImgBuff,(long) y,image,bpp)==MagickFail) RetVal=-6; \ x=0; \ y++; \ XorMe = 0; \ @@ -483,7 +551,7 @@ static int UnpackWPG2Raster(Image *image, int bpp) unsigned char bbuf, - *BImgBuff = (unsigned char *) NULL, /* Buffer for a current line. */ + *BImgBuff = (unsigned char *) NULL, /* Buffer for a current line. */ *UpImgBuff = (unsigned char *) NULL, /* Buffer for previous line. */ *tmpImgBuff = (unsigned char *) NULL, RunCount, @@ -501,6 +569,7 @@ static int UnpackWPG2Raster(Image *image, int bpp) int XorMe = 0; int c; + int RetVal = 0; x=0; y=0; @@ -542,9 +611,9 @@ static int UnpackWPG2Raster(Image *image, int bpp) } break; case 0x7E: - if(y==0) /* XOR */ - (void)fprintf(stderr,"\nWPG token XOR on the first line is not supported, please report!"); - XorMe=!XorMe; /* or XorMe=1 ?? */ + if(y==0) /* XOR */ + (void)fprintf(stderr,"\nWPG token XOR on the first line is not supported, please report!"); + XorMe=!XorMe; /* or XorMe=1 ?? */ break; case 0x7F: if ((c = ReadBlobByte(image)) == EOF) /* BLK */ @@ -564,8 +633,8 @@ static int UnpackWPG2Raster(Image *image, int bpp) FreeUnpackWPG2RasterAllocs(BImgBuff,UpImgBuff); return(-4); } - RunCount=c; - for(i=0; i<= RunCount;i++) + RunCount=c; + for(i=0; i<= RunCount;i++) for(bbuf=0; bbuf < SampleSize; bbuf++) InsertByte6(SampleBuffer[bbuf]); break; @@ -587,15 +656,18 @@ static int UnpackWPG2Raster(Image *image, int bpp) { /* duplicate the previous row RunCount x */ for(i=0;i<=RunCount;i++) - { - (void) InsertRow(UpImgBuff,(long) (image->rows >= y ? y : image->rows-1), - image,bpp); + { + if(InsertRow(UpImgBuff,(long)((image->rows>y) ? y : image->rows-1),image,bpp) == MagickFail) + { + FreeUnpackWPG2RasterAllocs(BImgBuff,UpImgBuff); + return(-4); + } y++; - } + } } break; case 0xFF: - if ((c = ReadBlobByte(image)) == EOF) /* WHT */ + if ((c = ReadBlobByte(image)) == EOF) /* WHT */ { FreeUnpackWPG2RasterAllocs(BImgBuff,UpImgBuff); return(-4); @@ -609,15 +681,15 @@ static int UnpackWPG2Raster(Image *image, int bpp) default: RunCount=bbuf & 0x7F; - if(bbuf & 0x80) /* REP */ - { + if(bbuf & 0x80) /* REP */ + { for(i=0; i < SampleSize; i++) SampleBuffer[i]=ReadBlobByte(image); for(i=0;i<=RunCount;i++) for(bbuf=0;bbuf=0) (*CTM)[0][2] = (float)x+(float)DenX/0x10000; else (*CTM)[0][2] = (float)x-(float)DenX/0x10000; - x=ReadBlobLSBLong(image); DenX=ReadBlobLSBShort(image); /*Ty*/ - (*CTM)[1][2]=(float)x + ((x>=0)?1:-1)*(float)DenX/0x10000; + x=ReadBlobLSBLong(image); DenX=ReadBlobLSBShort(image); /*Ty*/ + (*CTM)[1][2]=(float)x + ((x>=0)?1:-1)*(float)DenX/0x10000; if(x>=0) (*CTM)[1][2] = (float)x+(float)DenX/0x10000; else (*CTM)[1][2] = (float)x-(float)DenX/0x10000; - } + } if(Flags & TPR) - { - x=ReadBlobLSBShort(image); DenX=ReadBlobLSBShort(image); /*Px*/ - (*CTM)[2][0] = x + (float)DenX/0x10000;; - x=ReadBlobLSBShort(image); DenX=ReadBlobLSBShort(image); /*Py*/ - (*CTM)[2][1] = x + (float)DenX/0x10000; - } + { + x=ReadBlobLSBShort(image); DenX=ReadBlobLSBShort(image); /*Px*/ + (*CTM)[2][0] = x + (float)DenX/0x10000;; + x=ReadBlobLSBShort(image); DenX=ReadBlobLSBShort(image); /*Py*/ + (*CTM)[2][1] = x + (float)DenX/0x10000; + } return(Flags); } @@ -713,13 +785,13 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info, Image *image2; - + unsigned char magick[2*MaxTextExtent]; size_t magick_size; - + if ((clone_info=CloneImageInfo(image_info)) == NULL) return(image); @@ -727,7 +799,7 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info, clone_info->length=0; /* Obtain temporary file */ - ps_file=AcquireTemporaryFileStream(postscript_file,BinaryFileIOMode); + ps_file = AcquireTemporaryFileStream(postscript_file,BinaryFileIOMode); if (!ps_file) { (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Gannot create file stream for PS image"); @@ -735,46 +807,106 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info, } /* Copy postscript to temporary file */ - (void) SeekBlob(image,PS_Offset,SEEK_SET); - magick_size=ReadBlob(image, sizeof(magick), magick); - - (void) SeekBlob(image,PS_Offset,SEEK_SET); + if(SeekBlob(image,PS_Offset,SEEK_SET) != PS_Offset) goto BAD_SEEK; + magick_size = ReadBlob(image, sizeof(magick), magick); + + if(SeekBlob(image,PS_Offset,SEEK_SET) != PS_Offset) + { +BAD_SEEK: + (void) fclose(ps_file); + ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,image->filename); + goto FINISH_UNL; + } + while(PS_Size-- > 0) { - (void) fputc(ReadBlobByte(image),ps_file); + int c; + if ((c = ReadBlobByte(image)) == EOF) + { + (void) fclose(ps_file); + ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,image->filename); + goto FINISH_UNL; + } + (void) fputc(c,ps_file); } (void) fclose(ps_file); - + /* Detect file format - Check magic.mgk configuration file. */ if (GetMagickFileFormat(magick,magick_size,clone_info->magick, - MaxTextExtent,exception) == MagickFail) + MaxTextExtent,exception) == MagickFail) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Failed to identify embedded file type!"); + ThrowException(exception,CorruptImageError,UnableToReadImageHeader,image->filename); + goto FINISH_UNL; + } + + if(!ApproveFormatForWPG(clone_info->magick)) + { + (void) LogMagickEvent(CoderEvent, GetMagickModule(), + "Format \"%s\" cannot be embedded inside WPG.", clone_info->magick); + ThrowException(exception,CorruptImageError,UnableToReadImageHeader,image->filename); goto FINISH_UNL; - - /* Read nested image */ - /*FormatString(clone_info->filename,"%s:%.1024s",magic_info->name,postscript_file);*/ - FormatString(clone_info->filename,"%.1024s",postscript_file); - image2=ReadImage(clone_info,exception); + } + + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Reading embedded \"%s\" content...", clone_info->magick); + + /* Read nested image, forcing read as Postscript format */ + FormatString(clone_info->filename,"%s:%.1024s",clone_info->magick,postscript_file); + image2 = ReadImage(clone_info,exception); if (!image2) goto FINISH_UNL; + if(exception->severity>=ErrorException) /* When exception is raised, destroy image2 read. */ + { + CloseBlob(image2); + DestroyImageList(image2); + goto FINISH_UNL; + } /* Replace current image with new image while copying base image attributes. */ - (void) strlcpy(image2->filename,image->filename,MaxTextExtent); - (void) strlcpy(image2->magick_filename,image->magick_filename,MaxTextExtent); - (void) strlcpy(image2->magick,image->magick,MaxTextExtent); - image2->depth=image->depth; - DestroyBlob(image2); - image2->blob=ReferenceBlob(image->blob); - - if ((image->rows == 0) || (image->columns == 0)) + { + Image *p; + p = image2; + do + { + (void) strlcpy(p->filename,image->filename,MaxTextExtent); + (void) strlcpy(p->magick_filename,image->magick_filename,MaxTextExtent); + (void) strlcpy(p->magick,image->magick,MaxTextExtent); + /*image2->depth=image->depth;*/ /* !!!! The image2 depth should not be modified here. Image2 is completely different. */ + DestroyBlob(p); + + if(p->rows==0 || p->columns==0) + { + DeleteImageFromList(&p); + if(p==NULL) + { + image2 = NULL; + goto FINISH_UNL; /* Nothing to add, skip. */ + } + } + else + { + p->blob = ReferenceBlob(image->blob); + p = p->next; + } + } while(p!=NULL); + } + + if((image->rows==0 || image->columns==0) && (image->previous!=NULL || image->next!=NULL)) + { DeleteImageFromList(&image); + } - AppendImageToList(&image,image2); + AppendImageToList(&image,image2); /* This should append list 'image2' to the list 'image', image2 accepts NULL. */ + while(image->next != NULL) + image = image->next; /* Rewind the cursor to the end. */ - FINISH_UNL: + FINISH_UNL: (void) LiberateTemporaryFile(postscript_file); FINISH: DestroyImageInfo(clone_info); @@ -819,7 +951,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info, typedef struct { unsigned long FileId; - ExtendedSignedIntegralType DataOffset; + ExtendedSignedIntegralType DataOffset; /* magick_uint32_t */ unsigned int ProductType; unsigned int FileType; unsigned char MajorVersion; @@ -844,8 +976,8 @@ static Image *ReadWPGImage(const ImageInfo *image_info, typedef struct { - unsigned HorizontalUnits; - unsigned VerticalUnits; + unsigned HorizontalUnits; + unsigned VerticalUnits; unsigned char PosSizePrecision; } WPG2Start; @@ -936,6 +1068,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info, unsigned char *BImgBuff; BlobInfo *TmpBlob; + magick_off_t FilePos, filesize; tCTM CTM; /*current transform matrix*/ @@ -947,7 +1080,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info, assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); - logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter"); + logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter"); image=AllocateImage(image_info); image->depth=8; @@ -978,34 +1111,60 @@ static Image *ReadWPGImage(const ImageInfo *image_info, if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), "File type: %d", Header.FileType); + /* Determine file size. */ + filesize = GetBlobSize(image); /* zero is returned if the size cannot be determined. */ + if(filesize>0 && BlobIsSeekable(image)) + { + if(filesize > (magick_off_t)0xFFFFFFFF) + filesize = (magick_off_t)0xFFFFFFFF; /* More than 4GiB are not supported in MAT! */ + } + else + { + filesize = (magick_off_t)0xFFFFFFFF; + if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), + "Blob is not seekable, WPG reader could fail."); + ThrowReaderException(CorruptImageError,AnErrorHasOccurredReadingFromFile,image); + } + switch(Header.FileType) { case 1: /* WPG level 1 */ BitmapHeader2.RotAngle = 0; - + FilePos = Header.DataOffset; while(!EOFBlob(image)) /* object parser loop */ { - (void) SeekBlob(image,Header.DataOffset,SEEK_SET); - if(EOFBlob(image)) + if(SeekBlob(image,FilePos,SEEK_SET) != FilePos) break; - Rec.RecType=(i=ReadBlobByte(image)); - if(i==EOF) - break; - Rd_WP_DWORD(image,&Rec.RecordLength); - if(EOFBlob(image)) - break; + Rec.RecType = (i=ReadBlobByte(image)); + if(i==EOF) break; + FilePos += 1; - Header.DataOffset=TellBlob(image)+Rec.RecordLength; + FilePos += Rd_WP_DWORD(image,&Rec.RecordLength); + if((magick_off_t)Rec.RecordLength > filesize) + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); + if(EOFBlob(image)) break; + + FilePos += (magick_off_t)Rec.RecordLength; + if(FilePos>filesize || FilePoscolormap[i].red= - ScaleCharToQuantum(ReadBlobByte(image)); - image->colormap[i].green= - ScaleCharToQuantum(ReadBlobByte(image)); - image->colormap[i].blue= - ScaleCharToQuantum(ReadBlobByte(image)); + image->colormap[i].red=ScaleCharToQuantum(ReadBlobByte(image)); + image->colormap[i].green=ScaleCharToQuantum(ReadBlobByte(image)); + image->colormap[i].blue=ScaleCharToQuantum(ReadBlobByte(image)); + image->colormap[i].opacity = OpaqueOpacity; } break; - + case 0x11: /* Start PS l1 */ if(Rec.RecordLength > 8) image=ExtractPostscript(image,image_info, TellBlob(image)+8, /* skip PS header in the wpg */ (long) Rec.RecordLength-8,exception); - break; + break; case 0x14: /* bitmap type 2 */ BitmapHeader2.RotAngle=ReadBlobLSBShort(image); @@ -1057,6 +1214,8 @@ static Image *ReadWPGImage(const ImageInfo *image_info, BitmapHeader2.UpRightY=ReadBlobLSBShort(image); BitmapHeader2.Width=ReadBlobLSBShort(image); BitmapHeader2.Heigth=ReadBlobLSBShort(image); + if ((BitmapHeader2.Width == 0) || (BitmapHeader2.Heigth == 0)) + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); BitmapHeader2.Depth=ReadBlobLSBShort(image); BitmapHeader2.HorzRes=ReadBlobLSBShort(image); BitmapHeader2.VertRes=ReadBlobLSBShort(image); @@ -1077,8 +1236,11 @@ static Image *ReadWPGImage(const ImageInfo *image_info, image->rows=BitmapHeader2.Heigth; bpp=BitmapHeader2.Depth; - UnpackRaster: - if ((image->colors == 0) && (bpp != 24)) + UnpackRaster: + if(bpp>24) + {ThrowReaderException(CoderError,ColorTypeNotSupported,image)} + + if ((image->storage_class != PseudoClass) && (bpp != 24)) { image->colors=1 << bpp; if (!AllocateImageColormap(image,image->colors)) @@ -1090,10 +1252,11 @@ static Image *ReadWPGImage(const ImageInfo *image_info, image->storage_class = PseudoClass; /* printf("Load default colormap \n"); */ for (i=0; (i < (int) image->colors) && (i < 256); i++) - { + { image->colormap[i].red=ScaleCharToQuantum(WPG1_Palette[i].Red); image->colormap[i].green=ScaleCharToQuantum(WPG1_Palette[i].Green); image->colormap[i].blue=ScaleCharToQuantum(WPG1_Palette[i].Blue); + image->colormap[i].opacity = OpaqueOpacity; } } else @@ -1103,31 +1266,36 @@ static Image *ReadWPGImage(const ImageInfo *image_info, MagickReallocMemory(PixelPacket *,image->colormap, (size_t) (1U<colormap[0].red==0 && - image->colormap[0].green==0 && - image->colormap[0].blue==0 && - image->colormap[1].red==0 && - image->colormap[1].green==0 && - image->colormap[1].blue==0) + if(image->colors<=0) + { + image->colormap[0].red = + image->colormap[0].green = + image->colormap[0].blue = 0; + image->colormap[0].opacity = OpaqueOpacity; + } + if(image->colors<=1 || /* Realloc has been enforced and value [1] remains uninitialised, or .. */ + (image->colormap[0].red==0 && image->colormap[0].green==0 && image->colormap[0].blue==0 && + image->colormap[1].red==0 && image->colormap[1].green==0 && image->colormap[1].blue==0)) { /* fix crippled monochrome palette */ image->colormap[1].red = image->colormap[1].green = image->colormap[1].blue = MaxRGB; + image->colormap[1].opacity = OpaqueOpacity; } - } + } if(!image_info->ping) - if(UnpackWPGRaster(image,bpp) < 0) - { /* The raster cannot be unpacked */ + if(UnpackWPGRaster(image,bpp) < 0) + { /* The raster cannot be unpacked */ DecompressionFailed: ThrowReaderException(CoderError,UnableToDecompressImage,image) } if(Rec.RecType==0x14 && BitmapHeader2.RotAngle!=0 && !image_info->ping) - { + { /* flop command */ if(BitmapHeader2.RotAngle & 0x8000) { @@ -1152,8 +1320,8 @@ static Image *ReadWPGImage(const ImageInfo *image_info, ReplaceImageInList(&image,rotated_image); } } - - /* rotate command */ + + /* rotate command */ if(BitmapHeader2.RotAngle & 0x0FFF) { rotated_image = RotateImage(image, @@ -1166,7 +1334,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info, image->blob = TmpBlob; ReplaceImageInList(&image,rotated_image); } - } + } } /* Allocate next image structure. */ @@ -1194,7 +1362,8 @@ static Image *ReadWPGImage(const ImageInfo *image_info, StartWPG.PosSizePrecision = 0; while(!EOFBlob(image)) /* object parser loop */ { - (void) SeekBlob(image,Header.DataOffset,SEEK_SET); + if(SeekBlob(image,Header.DataOffset,SEEK_SET) != Header.DataOffset) + break; if(EOFBlob(image)) break; @@ -1216,7 +1385,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info, switch(Rec2.RecType) { - case 1: + case 1: StartWPG.HorizontalUnits=ReadBlobLSBShort(image); StartWPG.VerticalUnits=ReadBlobLSBShort(image); StartWPG.PosSizePrecision=ReadBlobByte(image); @@ -1225,10 +1394,18 @@ static Image *ReadWPGImage(const ImageInfo *image_info, WPG_Palette.StartIndex=ReadBlobLSBShort(image); WPG_Palette.NumOfEntries=ReadBlobLSBShort(image); - /* Sanity check for amount of palette entries. */ - if( (WPG_Palette.NumOfEntries-WPG_Palette.StartIndex) > (Rec2.RecordLength-2-2) / 3) - ThrowReaderException(CorruptImageError,InvalidColormapIndex,image); - + /* Sanity check for amount of palette entries. */ + if (WPG_Palette.NumOfEntries == 0) + ThrowReaderException(CorruptImageError,UnrecognizedNumberOfColors,image); + + if (WPG_Palette.NumOfEntries > MaxMap+1) + ThrowReaderException(CorruptImageError,ColormapExceedsColorsLimit,image); + + if ( (WPG_Palette.StartIndex > WPG_Palette.NumOfEntries) || + (((WPG_Palette.NumOfEntries-WPG_Palette.StartIndex) > + ((Rec2.RecordLength-2-2) / 3))) ) + ThrowReaderException(CorruptImageError,InvalidColormapIndex,image); + image->colors=WPG_Palette.NumOfEntries; if (!AllocateImageColormap(image,image->colors)) ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); @@ -1239,12 +1416,15 @@ static Image *ReadWPGImage(const ImageInfo *image_info, image->colormap[i].red=ScaleCharToQuantum(ReadBlobByte(image)); image->colormap[i].green=ScaleCharToQuantum(ReadBlobByte(image)); image->colormap[i].blue=ScaleCharToQuantum(ReadBlobByte(image)); + image->colormap[i].opacity = OpaqueOpacity; (void) ReadBlobByte(image); /*Opacity??*/ } break; case 0x0E: Bitmap2Header1.Width=ReadBlobLSBShort(image); Bitmap2Header1.Heigth=ReadBlobLSBShort(image); + if ((Bitmap2Header1.Width == 0) || (Bitmap2Header1.Heigth == 0)) + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); Bitmap2Header1.Depth=ReadBlobByte(image); Bitmap2Header1.Compression=ReadBlobByte(image); @@ -1252,7 +1432,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info, continue; /*Unknown compression method */ switch(Bitmap2Header1.Depth) { - case 1: bpp=1; + case 1: bpp=1; break; case 2: bpp=2; break; @@ -1266,7 +1446,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info, continue; /*Ignore raster with unknown depth*/ } image->columns=Bitmap2Header1.Width; - image->rows=Bitmap2Header1.Heigth; + image->rows=Bitmap2Header1.Heigth; if ((image->colors == 0) && (bpp != 24)) { @@ -1295,12 +1475,20 @@ static Image *ReadWPGImage(const ImageInfo *image_info, for(i=0; i< (long) image->rows; i++) { - (void) ReadBlob(image,ldblk,(char *) BImgBuff); - (void) InsertRow(BImgBuff,i,image,bpp); + if (ReadBlob(image,ldblk,(char *) BImgBuff) != (size_t) ldblk) + { + MagickFreeMemory(BImgBuff); + ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,image->filename); + goto DecompressionFailed; + } + if(InsertRow(BImgBuff,i,image,bpp) == MagickFail) + { + if(BImgBuff) MagickFreeMemory(BImgBuff); + goto DecompressionFailed; + } } - if(BImgBuff) - MagickFreeMemory(BImgBuff); + if(BImgBuff) MagickFreeMemory(BImgBuff); break; } case 1: /*RLE for WPG2 */ @@ -1308,13 +1496,13 @@ static Image *ReadWPGImage(const ImageInfo *image_info, if( UnpackWPG2Raster(image,bpp) < 0) goto DecompressionFailed; break; - } + } } if(CTM[0][0]<0 && !image_info->ping) - { /*?? RotAngle=360-RotAngle;*/ - rotated_image = FlopImage(image, exception); + { /*?? RotAngle=360-RotAngle;*/ + rotated_image = FlopImage(image, exception); if (rotated_image != (Image *) NULL) { TmpBlob = rotated_image->blob; @@ -1322,15 +1510,15 @@ static Image *ReadWPGImage(const ImageInfo *image_info, image->blob = TmpBlob; ReplaceImageInList(&image,rotated_image); } - /* Try to change CTM according to Flip - I am not sure, must be checked. + /* Try to change CTM according to Flip - I am not sure, must be checked. Tx(0,0)=-1; Tx(1,0)=0; Tx(2,0)=0; Tx(0,1)= 0; Tx(1,1)=1; Tx(2,1)=0; Tx(0,2)=(WPG._2Rect.X_ur+WPG._2Rect.X_ll); - Tx(1,2)=0; Tx(2,2)=1; */ + Tx(1,2)=0; Tx(2,2)=1; */ } if(CTM[1][1]<0 && !image_info->ping) - { /*?? RotAngle=360-RotAngle;*/ - rotated_image = FlipImage(image, exception); + { /*?? RotAngle=360-RotAngle;*/ + rotated_image = FlipImage(image, exception); if (rotated_image != (Image *) NULL) { TmpBlob = rotated_image->blob; @@ -1343,9 +1531,9 @@ static Image *ReadWPGImage(const ImageInfo *image_info, Tx(0,0)= 1; Tx(1,0)= 0; Tx(2,0)=0; Tx(0,1)= 0; Tx(1,1)=-1; Tx(2,1)=0; Tx(0,2)= 0; Tx(1,2)=(WPG._2Rect.Y_ur+WPG._2Rect.Y_ll); - Tx(2,2)=1; */ - } - + Tx(2,2)=1; */ + } + /* Allocate next image structure. */ AllocateNextImage(image_info,image); @@ -1358,14 +1546,14 @@ static Image *ReadWPGImage(const ImageInfo *image_info, break; case 0x12: /* Postscript WPG2*/ - i=ReadBlobLSBShort(image); + i=ReadBlobLSBShort(image); if(Rec2.RecordLength > (unsigned int) i) image=ExtractPostscript(image,image_info, - TellBlob(image)+i, /*skip PS header in the wpg2*/ + TellBlob(image)+i, /*skip PS header in the wpg2*/ (long) (Rec2.RecordLength-i-2),exception); break; - case 0x1B: /*bitmap rectangle*/ + case 0x1B: /*bitmap rectangle*/ (void) LoadWPG2Flags(image,StartWPG.PosSizePrecision,NULL,&CTM); /* WPG2Flags */ break; } @@ -1385,10 +1573,10 @@ static Image *ReadWPGImage(const ImageInfo *image_info, { Image *p; - + long scene=0; - + /* Rewind list, removing any empty images while rewinding. */ @@ -1405,7 +1593,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info, p=p->previous; } } - + /* Fix scene numbers */ @@ -1413,10 +1601,10 @@ static Image *ReadWPGImage(const ImageInfo *image_info, p->scene=scene++; } - if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return"); + if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return"); if(image==NULL) ThrowReaderException(CorruptImageError,ImageFileDoesNotContainAnyImageData,image); - return(image); + return(image); } /* diff --git a/coders/xbm.c b/coders/xbm.c index b33e05e..b5cdf0b 100644 --- a/coders/xbm.c +++ b/coders/xbm.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 -2012 GraphicsMagick Group +% Copyright (C) 2003-2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -119,16 +119,23 @@ static unsigned int IsXBM(const unsigned char *magick,const size_t length) % */ -static int XBMInteger(Image *image,short int *hex_digits) +static int XBMInteger(Image *image,const unsigned int max_digits, short int *hex_digits) { + unsigned int + digits; + int c, - flag, value; + /* + Read hex value in form 0xhh or 0xhhhh from text which may look + like ", 0x7f". FIXME: This implementation is non-validating. + */ + value=0; - flag=0; - for ( ; ; ) + digits=0U; + for ( digits=0U; digits <= max_digits+1; ) { c=ReadBlobByte(image); if (c == EOF) @@ -140,12 +147,15 @@ static int XBMInteger(Image *image,short int *hex_digits) if (isxdigit(c)) { value=(value << 4)+hex_digits[c]; - flag++; + digits++; continue; } - if ((hex_digits[c]) < 0 && flag) + if ((hex_digits[c]) < 0 && digits) break; } + /* The '0' in '0x' is currently counted as a digit */ + if (digits > max_digits+1) + value=(-1); return(value); } @@ -158,18 +168,20 @@ static Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception) Image *image; - int - bit; - - long - y; - register IndexPacket *indexes; - register long - i, - x; + register size_t + bytes_per_line, + i; + + unsigned long + x, + y; + + long + columns_signed, + rows_signed; register PixelPacket *q; @@ -177,22 +189,24 @@ static Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception) register unsigned char *p; - short int - hex_digits[256]; - unsigned char *data; unsigned int - status; - - unsigned long + bit, byte, - bytes_per_line, padding, - value, version; + int + value; + + short int + hex_digits[256]; + + MagickPassFail + status; + /* Open image file. */ @@ -207,16 +221,26 @@ static Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception) /* Read X bitmap header. */ + (void) memset(buffer,0,sizeof(buffer)); + name[0]='\0'; + columns_signed=0; + rows_signed=0; while (ReadBlobString(image,buffer) != (char *) NULL) - if (sscanf(buffer,"#define %s %lu",name,&image->columns) == 2) + if (sscanf(buffer,"#define %s %ld",name,&columns_signed) == 2) if ((strlen(name) >= 6) && (LocaleCompare(name+strlen(name)-6,"_width") == 0)) break; while (ReadBlobString(image,buffer) != (char *) NULL) - if (sscanf(buffer,"#define %s %lu",name,&image->rows) == 2) + if (sscanf(buffer,"#define %s %ld",name,&rows_signed) == 2) if ((strlen(name) >= 7) && (LocaleCompare(name+strlen(name)-7,"_height") == 0)) break; + if (EOFBlob(image)) + ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); + if ((columns_signed <= 0) || (rows_signed <= 0)) + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); + image->columns=(unsigned long) columns_signed; + image->rows=(unsigned long) rows_signed; image->depth=8; image->storage_class=PseudoClass; image->colors=2; @@ -244,8 +268,9 @@ static Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception) if (LocaleCompare("bits[]",(char *) p) == 0) break; } - if ((image->columns == 0) || (image->rows == 0) || EOFBlob(image)) - ThrowReaderException(CorruptImageError,ImproperImageHeader,image); + if (EOFBlob(image)) + ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); + /* Initialize image structure. */ @@ -265,6 +290,8 @@ static Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception) CloseBlob(image); return(image); } + if (CheckImagePixelLimits(image, exception) != MagickPass) + ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); /* Allocate temporary storage for X bitmap image */ @@ -278,6 +305,8 @@ static Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception) /* Initialize hex values. */ + for (i = 0; i < sizeof(hex_digits)/sizeof(hex_digits[0]); i++) + hex_digits[i]=(-1); hex_digits['0']=0; hex_digits['1']=1; hex_digits['2']=2; @@ -311,47 +340,57 @@ static Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception) */ p=data; if (version == 10) - for (i=0; i < (long) (bytes_per_line*image->rows); (i+=2)) + for (i=0; i < (bytes_per_line*image->rows); (i+=2)) { - value=XBMInteger(image,hex_digits); + value=XBMInteger(image,4,hex_digits); + if (value < 0) + { + MagickFreeMemory(data); + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); + } *p++=(unsigned char) value; if (!padding || ((i+2) % bytes_per_line)) *p++=(unsigned char) (value >> 8); } else - for (i=0; i < (long) (bytes_per_line*image->rows); i++) + for (i=0; i < (bytes_per_line*image->rows); i++) { - value=XBMInteger(image,hex_digits); + value=XBMInteger(image,2,hex_digits); + if (value < 0) + { + MagickFreeMemory(data); + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); + } *p++=(unsigned char) value; } /* Convert X bitmap image to pixel packets. */ p=data; - for (y=0; y < (long) image->rows; y++) + for (y=0; y < image->rows; y++) { q=SetImagePixels(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; indexes=AccessMutableIndexes(image); - bit=0; - byte=0; - for (x=0; x < (long) image->columns; x++) + bit=0U; + byte=0U; + for (x=0; x < image->columns; x++) { - if (bit == 0) + if (bit == 0U) byte=(*p++); indexes[x]=byte & 0x01 ? 0x01 : 0x00; bit++; - byte>>=1; - if (bit == 8) - bit=0; + byte>>=1U; + if (bit == 8U) + bit=0U; } if (!SyncImagePixels(image)) break; if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,exception, LoadImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } MagickFreeMemory(data); @@ -570,7 +609,7 @@ static unsigned int WriteXBMImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } (void) strcpy(buffer,"};\n"); diff --git a/coders/xcf.c b/coders/xcf.c index a4bd5b5..71260bf 100644 --- a/coders/xcf.c +++ b/coders/xcf.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2016 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % % This program is covered by multiple licenses, which are described in @@ -102,7 +102,7 @@ typedef struct { compression; /* not really part of the doc, but makes it easy to pass around! */ - ExceptionInfo + ExceptionInfo *exception; /* File size */ @@ -307,7 +307,7 @@ static char *ReadBlobStringWithLongSize(Image *image,char *string,size_t max) } -static MagickPassFail load_tile (Image* image, Image* tile_image, XCFDocInfo* inDocInfo, +static MagickPassFail load_tile (Image* image, Image* tile_image, XCFDocInfo* inDocInfo, XCFLayerInfo* inLayerInfo, size_t data_length) { size_t @@ -365,9 +365,7 @@ static MagickPassFail load_tile (Image* image, Image* tile_image, XCFDocInfo* in if (nmemb_read_successfully != data_length) { MagickFreeMemory(xcfodata); - ThrowException(&image->exception,CorruptImageError,UnexpectedEndOfFile, - NULL); - return MagickFail; + ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); } q=SetImagePixels(tile_image,0,0,tile_image->columns,tile_image->rows); @@ -398,7 +396,7 @@ static MagickPassFail load_tile (Image* image, Image* tile_image, XCFDocInfo* in q->green = ScaleCharToQuantum(xcfdata->green); q->blue = ScaleCharToQuantum(xcfdata->blue); q->opacity = (Quantum) (xcfdata->opacity==0U ? TransparentOpacity : - ScaleCharToQuantum(255U-inLayerInfo->opacity)); + ScaleCharToQuantum(255U-inLayerInfo->opacity)); xcfdata++; q++; } @@ -411,7 +409,7 @@ static MagickPassFail load_tile (Image* image, Image* tile_image, XCFDocInfo* in static MagickPassFail load_tile_rle (Image* image, Image* tile_image, - XCFDocInfo* inDocInfo, + XCFDocInfo* inDocInfo, XCFLayerInfo* inLayerInfo, size_t data_length) { @@ -458,13 +456,11 @@ static MagickPassFail load_tile_rle (Image* image, (unsigned long) nmemb_read_successfully, (unsigned long) data_length); MagickFreeMemory(xcfodata); - ThrowException(&image->exception,CorruptImageError,UnexpectedEndOfFile, - NULL); - return MagickFail; + ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); } xcfdatalimit = &xcfodata[nmemb_read_successfully - 1]; - + for (i = 0; i < bpp; i++) { q=SetImagePixels(tile_image,0,0,tile_image->columns,tile_image->rows); @@ -482,9 +478,9 @@ static MagickPassFail load_tile_rle (Image* image, { goto bogus_rle; } - + val = *xcfdata++; - + length = val; if (length >= 128) @@ -497,24 +493,24 @@ static MagickPassFail load_tile_rle (Image* image, { goto bogus_rle; } - + length = ((*xcfdata << 8) + xcfdata[1]) & 0xFFFF; xcfdata += 2; } - + count += length; size -= length; - + if (size < 0) { goto bogus_rle; } - + if (&xcfdata[length-1] > xcfdatalimit) { goto bogus_rle; } - + while (length-- > 0) { data = *xcfdata++; @@ -522,7 +518,7 @@ static MagickPassFail load_tile_rle (Image* image, { case 0: { - q->red = ScaleCharToQuantum(data); + q->red = ScaleCharToQuantum(data); if ( inDocInfo->image_type == GIMP_GRAY ) { q->green = ScaleCharToQuantum(data); @@ -550,7 +546,7 @@ static MagickPassFail load_tile_rle (Image* image, case 3: { q->opacity = (Quantum) (data==0 ? TransparentOpacity : - ScaleCharToQuantum(255-inLayerInfo->opacity)); + ScaleCharToQuantum(255-inLayerInfo->opacity)); break; } } @@ -566,26 +562,26 @@ static MagickPassFail load_tile_rle (Image* image, { goto bogus_rle; } - + length = ((*xcfdata << 8) + xcfdata[1]) & 0xFFFF; xcfdata += 2; } - + count += length; size -= length; if (size < 0) { - goto bogus_rle; + goto bogus_rle; } - + if (xcfdata > xcfdatalimit) { goto bogus_rle; } - + val = *xcfdata++; - + for (j = 0; j < length; j++) { data = val; @@ -593,7 +589,7 @@ static MagickPassFail load_tile_rle (Image* image, { case 0: { - q->red = ScaleCharToQuantum(data); + q->red = ScaleCharToQuantum(data); if ( inDocInfo->image_type == GIMP_GRAY ) { q->green = ScaleCharToQuantum(data); @@ -621,7 +617,7 @@ static MagickPassFail load_tile_rle (Image* image, case 3: { q->opacity = (Quantum) (data==0 ? TransparentOpacity : - ScaleCharToQuantum(255-inLayerInfo->opacity)); + ScaleCharToQuantum(255-inLayerInfo->opacity)); break; } } @@ -630,7 +626,7 @@ static MagickPassFail load_tile_rle (Image* image, } } if (SyncImagePixelsEx(tile_image,&tile_image->exception) == MagickFail) - break; + break; } MagickFreeMemory(xcfodata); return MagickPass; @@ -682,9 +678,9 @@ static MagickPassFail load_level (Image* image, MagickPassFail status = MagickPass; - ExceptionInfo + ExceptionInfo *exception = inDocInfo->exception; - + /* start reading the data */ width = ReadBlobMSBLong(image); /* width */ height = ReadBlobMSBLong(image); /* height */ @@ -694,6 +690,10 @@ static MagickPassFail load_level (Image* image, * and we can simply return. */ offset = ReadBlobMSBLong(image); + + if (EOFBlob(image)) + ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); + if (offset == 0) return MagickPass; @@ -749,6 +749,8 @@ static MagickPassFail load_level (Image* image, amount of data needed for this tile */ offset2 = ReadBlobMSBLong(image); + if (EOFBlob(image)) + ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); if (offset2 >= inDocInfo->file_size) { if (image->logging) @@ -757,12 +759,22 @@ static MagickPassFail load_level (Image* image, (long) offset2, (unsigned long) inDocInfo->file_size); ThrowBinaryException(CorruptImageError,CorruptImage,image->filename); } - + + /* verify that seek position is in file */ + if ((magick_off_t) offset >= GetBlobSize(image)) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Tile offset %" MAGICK_OFF_F "d is outside file bounds", + (magick_off_t) offset); + ThrowBinaryException(CorruptImageError,InsufficientImageDataInFile,image->filename); + } + /* seek to the tile offset */ if (SeekBlob(image, offset, SEEK_SET) != offset) ThrowBinaryException(CorruptImageError,InsufficientImageDataInFile,image->filename); - /* allocate the image for the tile + /* allocate the image for the tile NOTE: the last tile in a row or column may not be a full tile! */ tile_image_width=(size_t) (destLeft == (int) ntile_cols-1 ? @@ -774,6 +786,9 @@ static MagickPassFail load_level (Image* image, tile_image=CloneImage(inLayerInfo->image, tile_image_width, tile_image_height,True,exception); + if (tile_image == (Image *) NULL) + return MagickFail; + /* Compute the tile data size. */ @@ -825,7 +840,10 @@ static MagickPassFail load_level (Image* image, "Final tile data size: %lu", (unsigned long) tile_data_size); if (offset2 <= offset) - ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); + { + DestroyImage(tile_image); + ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); + } } } @@ -841,9 +859,11 @@ static MagickPassFail load_level (Image* image, tile_data_size); break; case COMPRESS_ZLIB: + DestroyImage(tile_image); ThrowBinaryException(CoderError,ZipCompressionNotSupported, image->filename); case COMPRESS_FRACTAL: + DestroyImage(tile_image); ThrowBinaryException(CoderError,FractalCompressionNotSupported, image->filename); } @@ -916,9 +936,9 @@ static MagickPassFail load_level (Image* image, destTop++; } - if (MagickPass != status) + if (MagickPass != status) return status; - + /* restore the saved position so we'll be ready to * read the next offset. */ @@ -926,11 +946,13 @@ static MagickPassFail load_level (Image* image, /* read in the offset of the next tile */ offset = ReadBlobMSBLong(image); + if (EOFBlob(image)) + ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); if (offset != 0) if (!MagickMonitorFormatted(offset,inDocInfo->file_size, &image->exception,LoadImageText, image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } @@ -943,7 +965,7 @@ static MagickPassFail load_level (Image* image, (void) MagickMonitorFormatted(inDocInfo->file_size, inDocInfo->file_size+1,&image->exception, LoadImageText,image->filename, - image->columns,image->rows); + image->columns,image->rows); } return MagickPass; @@ -973,22 +995,36 @@ static MagickPassFail load_hierarchy (Image *image, XCFDocInfo* inDocInfo, XCFLa */ offset = ReadBlobMSBLong(image); /* top level */ + if (EOFBlob(image)) + ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); + if (image->logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "load_hierarchy: dimensions %lux%lu, bpp=%lu, offset=%lu", + "load_hierarchy: dimensions %lux%lu, bpp=%lu," + " offset=%" MAGICK_OFF_F "d", width,height,(unsigned long) inDocInfo->bpp, - (unsigned long) offset); + (magick_off_t) offset); + + /* verify that seek position is in file */ + if ((magick_off_t) offset >= GetBlobSize(image)) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Heirarchy offset %" MAGICK_OFF_F "d is outside file bounds", + (magick_off_t) offset); + ThrowBinaryException(CorruptImageError,InsufficientImageDataInFile,image->filename); + } /* discard offsets for layers below first, if any. */ - do + do { junk = ReadBlobMSBLong(image); } while ((junk != 0) && (!EOFBlob(image))); if (EOFBlob(image)) - return MagickFail; + ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); /* save the current position as it is where the * next level offset is stored. @@ -996,15 +1032,25 @@ static MagickPassFail load_hierarchy (Image *image, XCFDocInfo* inDocInfo, XCFLa saved_pos = TellBlob(image); if (saved_pos < 0) ThrowBinaryException(BlobError,UnableToObtainOffset,image->filename); - + + /* verify that seek position is in file */ + if ((magick_off_t) offset >= GetBlobSize(image)) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Level offset %" MAGICK_OFF_F "d is outside file bounds", + (magick_off_t) offset); + ThrowBinaryException(CorruptImageError,InsufficientImageDataInFile,image->filename); + } + /* seek to the level offset */ if (SeekBlob(image, offset, SEEK_SET) != offset) ThrowBinaryException(CorruptImageError,InsufficientImageDataInFile,image->filename); - + /* read in the level */ if (load_level (image, inDocInfo, inLayer) == MagickFail) return MagickFail; - + /* restore the saved position so we'll be ready to * read the next offset. */ @@ -1025,12 +1071,16 @@ static MagickPassFail ReadOneLayer( Image* image, XCFDocInfo* inDocInfo, XCFLaye foundPropEnd = 0; unsigned long - hierarchy_offset, + hierarchy_offset, layer_mask_offset; + magick_off_t start_offset; + + start_offset = TellBlob(image); + /* clear the block! */ (void) memset( outLayer, 0, sizeof( XCFLayerInfo ) ); - + /* read in the layer width, height, type and name */ outLayer->width = ReadBlobMSBLong(image); outLayer->height = ReadBlobMSBLong(image); @@ -1038,6 +1088,9 @@ static MagickPassFail ReadOneLayer( Image* image, XCFDocInfo* inDocInfo, XCFLaye (void) ReadBlobStringWithLongSize(image, outLayer->name, sizeof(outLayer->name)); + if (EOFBlob(image)) + ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); + if (image->logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Loading layer \"%s\", dimensions %lux%lu, type %lu", @@ -1046,8 +1099,8 @@ static MagickPassFail ReadOneLayer( Image* image, XCFDocInfo* inDocInfo, XCFLaye (unsigned long) outLayer->height, (unsigned long) outLayer->type); - if (EOFBlob(image)) - ThrowBinaryException(CorruptImageError,InsufficientImageDataInFile,image->filename); + if ((outLayer->width == 0) || (outLayer->height == 0)) + ThrowBinaryException(CorruptImageError,ImproperImageHeader,image->filename); /* allocate the image for this layer */ outLayer->image=CloneImage(image,outLayer->width, outLayer->height,True, @@ -1055,9 +1108,6 @@ static MagickPassFail ReadOneLayer( Image* image, XCFDocInfo* inDocInfo, XCFLaye if (outLayer->image == (Image *) NULL) return MagickFail; - if (CheckImagePixelLimits(outLayer->image, &image->exception) != MagickPass) - ThrowBinaryException(ResourceLimitError,ImagePixelLimitExceeded,image->filename); - /* read the layer properties! */ foundPropEnd = 0; while ( !foundPropEnd && !EOFBlob(image) ) @@ -1148,6 +1198,8 @@ static MagickPassFail ReadOneLayer( Image* image, XCFDocInfo* inDocInfo, XCFLaye break; } } + if (EOFBlob(image)) + ThrowBinaryException(CorruptImageError,UnexpectedEndOfFile,image->filename); if (!foundPropEnd) return MagickFail; @@ -1161,22 +1213,69 @@ static MagickPassFail ReadOneLayer( Image* image, XCFDocInfo* inDocInfo, XCFLaye if ( outLayer->visible == False ) { /* BOGUS: should really be separate member var! */ - outLayer->image->compose = NoCompositeOp; + outLayer->image->compose = NoCompositeOp; } /* read the hierarchy and layer mask offsets */ hierarchy_offset = ReadBlobMSBLong(image); layer_mask_offset = ReadBlobMSBLong(image); + /* verify that seek position is in file */ + if ((magick_off_t) hierarchy_offset >= GetBlobSize(image)) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Hierarchy offset %" MAGICK_OFF_F "d is outside file bounds", + (magick_off_t) hierarchy_offset); + ThrowBinaryException(CorruptImageError,InsufficientImageDataInFile,image->filename); + } + /* + Verify that seek position is not too small. + Seek position provides ample opportunity for abuse. + */ + if ((magick_off_t) hierarchy_offset <= start_offset) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Hierarchy offset %" MAGICK_OFF_F "d is unreasonable", + (magick_off_t) hierarchy_offset); + ThrowBinaryException(CorruptImageError,ImproperImageHeader,image->filename); + } + /* read in the hierarchy */ if (SeekBlob(image, hierarchy_offset, SEEK_SET) != (magick_off_t) hierarchy_offset) ThrowBinaryException(CorruptImageError,InsufficientImageDataInFile,image->filename); + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Hierarchy offset %" MAGICK_OFF_F "d", + (magick_off_t) hierarchy_offset); if (load_hierarchy (image, inDocInfo, outLayer) == MagickFail) return MagickFail; /* read in the layer mask */ if (layer_mask_offset != 0) { + /* verify that seek position is in file */ + if ((magick_off_t) layer_mask_offset >= GetBlobSize(image)) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Layer mask offset %" MAGICK_OFF_F "d is outside file bounds", + (magick_off_t) layer_mask_offset); + ThrowBinaryException(CorruptImageError,InsufficientImageDataInFile,image->filename); + } + /* + Verify that seek position is not too small. + Seek position provides ample opportunity for abuse. + */ + if ((magick_off_t) layer_mask_offset <= start_offset) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Layer mask offset %" MAGICK_OFF_F "d is unreasonable", + (magick_off_t) hierarchy_offset); + ThrowBinaryException(CorruptImageError,ImproperImageHeader,image->filename); + } if (SeekBlob(image, layer_mask_offset, SEEK_SET) != (magick_off_t) layer_mask_offset) ThrowBinaryException(CorruptImageError,InsufficientImageDataInFile,image->filename); @@ -1296,7 +1395,7 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (status == MagickFail) ThrowReaderException(FileOpenError,UnableToOpenFile,image); count=ReadBlob(image,14,(char *) magick); - if ((count == 0) || + if ((count != 14) || (LocaleNCompare((char *) magick,"gimp xcf",8) != 0)) ThrowReaderException(CorruptImageError,ImproperImageHeader,image); /* clear the docinfo stuff */ @@ -1324,7 +1423,7 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) if ((image->columns == 0) || (image->rows == 0)) ThrowReaderException(CorruptImageError,NegativeOrZeroImageSize,image); - + /* setup some things about the image...*/ image->compression=NoCompression; image->depth = 8; @@ -1344,11 +1443,23 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) { ThrowReaderException(CorruptImageError,ImageTypeNotSupported,image); } + + if (CheckImagePixelLimits(image, exception) != MagickPass) + ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); + /* - SetImage can be very expensive and it is not clear that this one is - actually needed so comment it out for now. + SetImage can be very expensive but we do it here because it is + expected that the canvas is initialized to opaque-black and + operations may be done using uninitialized pixels if we don't + initialize here. */ - /* (void) SetImage(image,OpaqueOpacity); */ /* until we know otherwise...*/ + SetRedSample(&image->background_color,0); + SetGreenSample(&image->background_color,0); + SetBlueSample(&image->background_color,0); + SetOpacitySample(&image->background_color,OpaqueOpacity); + if (SetImage(image,OpaqueOpacity) != MagickPass) + ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); /* ??? */ + image->matte=True; /* XCF always has a matte! */ /* read properties */ @@ -1369,31 +1480,31 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (ReadBlobByte(image) == EOF) ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); /* - if (info->file_version == 0) + if (info->file_version == 0) { gint i; g_message (_("XCF warning: version 0 of XCF file format\n" "did not save indexed colormaps correctly.\n" "Substituting grayscale map.")); - info->cp += + info->cp += xcf_read_int32 (info->fp, (guint32*) &gimage->num_cols, 1); gimage->cmap = g_new (guchar, gimage->num_cols*3); xcf_seek_pos (info, info->cp + gimage->num_cols); - for (i = 0; inum_cols; i++) + for (i = 0; inum_cols; i++) { gimage->cmap[i*3+0] = i; gimage->cmap[i*3+1] = i; gimage->cmap[i*3+2] = i; } } - else + else { - info->cp += + info->cp += xcf_read_int32 (info->fp, (guint32*) &gimage->num_cols, 1); gimage->cmap = g_new (guchar, gimage->num_cols*3); - info->cp += - xcf_read_int8 (info->fp, + info->cp += + xcf_read_int8 (info->fp, (guint8*) gimage->cmap, gimage->num_cols*3); } */ @@ -1441,7 +1552,7 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) } */ - + /* BOGUS: we don't write these yet because we aren't reading them properly yet :( */ /* image->x_resolution = xres; */ @@ -1551,7 +1662,7 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) *layer_info; unsigned long - number_layers = 0, + number_layers = 0, num_layers = 0; long @@ -1563,24 +1674,63 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) MagickBool foundAllLayers = MagickFalse; + magick_off_t + oldPos; + + magick_uint32_t + previous_offset; + + if (CheckImagePixelLimits(image, exception) != MagickPass) + ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); + /* BIG HACK because XCF doesn't include the layer count, and we want to know it in advance in order to allocate memory, we have to scan the layer offset list, and then reposition the read pointer */ - magick_off_t oldPos = TellBlob(image); + oldPos = TellBlob(image); if (oldPos < 0) ThrowReaderException(BlobError,UnableToObtainOffset,image); + + previous_offset = 0; do { - long - offset = (long) ReadBlobMSBLong(image); + magick_uint32_t + offset = ReadBlobMSBLong(image); + + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Layer Offset[%lu] = %" MAGICK_UINT32_F "u", + number_layers, offset); + + if (offset >= doc_info.file_size) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Layer Offset %" MAGICK_UINT32_F "u" + " is outside of file bounds", + offset); + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); + } + /* + Are layer offsets assured to be ascending? + */ + if ((offset != 0) && (offset <= previous_offset)) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Layer Offset %" MAGICK_UINT32_F "u" + " is not ascending", + offset); + ThrowReaderException(CorruptImageError,ImproperImageHeader,image); + } if ( offset == 0 ) foundAllLayers = MagickTrue; else number_layers++; + previous_offset=offset; } while ( !foundAllLayers ); if (SeekBlob(image, oldPos, SEEK_SET) != oldPos) /* restore the position! */ @@ -1595,8 +1745,8 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (image->logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "XCF number_layers=%lu first_layer=%ld last_layer=%ld", - number_layers, first_layer, last_layer); + "XCF number_layers=%lu first_layer=%ld last_layer=%ld", + number_layers, first_layer, last_layer); /* XCF has layers backwards, so this gets a bit complicated */ T = last_layer; @@ -1606,8 +1756,8 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) if (image->logging) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "XCF reading layers %ld to %ld inclusive", first_layer, - last_layer); + "XCF reading layers %ld to %ld inclusive", first_layer, + last_layer); /* allocate our array of layer info blocks */ layer_info=MagickAllocateArray(XCFLayerInfo *, @@ -1646,24 +1796,35 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) } if ( first_layer <= current_layer && current_layer <= last_layer ) - { - /* seek to the layer offset */ - if (SeekBlob(image, offset, SEEK_SET) != offset) + { + /* verify that seek position is in file */ + if ((magick_off_t) offset >= GetBlobSize(image)) + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Layer offset %" MAGICK_OFF_F "d is outside file bounds", + (magick_off_t) offset); + DestroyLayerInfo(number_layers,layer_info); + ThrowReaderException(CorruptImageError,InsufficientImageDataInFile,image); + } + + /* seek to the layer offset */ + if (SeekBlob(image, offset, SEEK_SET) != offset) { /* FIXME: CID 64064: leaks layer_info */ DestroyLayerInfo(number_layers,layer_info); ThrowReaderException(CorruptImageError,InsufficientImageDataInFile,image); } - /* read in the layer */ - layer_ok = ReadOneLayer( image, &doc_info, &layer_info[current_layer-first_layer] ); - if (!layer_ok) - { + /* read in the layer */ + layer_ok = ReadOneLayer( image, &doc_info, &layer_info[current_layer-first_layer] ); + if (!layer_ok) + { #if 0 - int - j; + int + j; - for (j=0; j <= (current_layer-first_layer); j++) + for (j=0; j <= (current_layer-first_layer); j++) { if (layer_info[j].image) { @@ -1671,86 +1832,111 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) layer_info[j].image = (Image *) NULL; } } - MagickFreeMemory(layer_info); + MagickFreeMemory(layer_info); #endif DestroyLayerInfo(number_layers,layer_info); - CopyException(exception,&image->exception); - CloseBlob(image); - DestroyImageList(image); - return (Image *) NULL; - } - /* restore the saved position so we'll be ready to - * read the next offset. - */ - if (SeekBlob(image, saved_pos, SEEK_SET) != saved_pos) + CopyException(exception,&image->exception); + CloseBlob(image); + DestroyImageList(image); + return (Image *) NULL; + } + /* restore the saved position so we'll be ready to + * read the next offset. + */ + if (SeekBlob(image, saved_pos, SEEK_SET) != saved_pos) { /* FIXME: CID 64064: leaks layer_info */ DestroyLayerInfo(number_layers,layer_info); ThrowReaderException(BlobError,UnableToSeekToOffset,image); } - } + } current_layer++; } if ( number_layers == 1 ) - { - /* composite the layer data onto the main image & then dispose the layer */ - (void) CompositeImage(image, OverCompositeOp, layer_info[0].image, - layer_info[0].offset_x, layer_info[0].offset_y ); - DestroyImage( layer_info[0].image ); + { + /* composite the layer data onto the main image & then dispose the layer */ + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Composite Layer[0]: %lux%lu%+d%+d", + layer_info[0].image->columns, + layer_info[0].image->rows, + layer_info[0].offset_x, + layer_info[0].offset_y); + (void) CompositeImage(image, OverCompositeOp, layer_info[0].image, + layer_info[0].offset_x, layer_info[0].offset_y ); + DestroyImage( layer_info[0].image ); layer_info[0].image = (Image *) NULL; - } + } else - { + { #if 0 - { - /* NOTE: XCF layers are REVERSED from composite order! */ - long - j; - - for (j=number_layers-1; j>=0; j--) { - /* BOGUS: need to consider layer blending modes!! */ - if ( layer_info[j].visible ) { /* only visible ones, please! */ - CompositeImage(image, OverCompositeOp, layer_info[j].image, - layer_info[j].offset_x, layer_info[j].offset_y ); - DestroyImage( layer_info[j].image ); - layer_info[j].image = (Image *) NULL; - } - } - } + { + /* NOTE: XCF layers are REVERSED from composite order! */ + long + j; + + for (j=number_layers-1; j>=0; j--) + { + /* BOGUS: need to consider layer blending modes!! */ + if ( layer_info[j].visible ) /* only visible ones, please! */ + { + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Composite Layer[%lu]: %lux%lu%+d%+d", + j, + layer_info[j].image->columns, + layer_info[j].image->rows, + layer_info[j].offset_x, + layer_info[j].offset_y); + CompositeImage(image, OverCompositeOp, layer_info[j].image, + layer_info[j].offset_x, layer_info[j].offset_y ); + DestroyImage( layer_info[j].image ); + layer_info[j].image = (Image *) NULL; + } + } + } #else - { - /* NOTE: XCF layers are REVERSED from composite order! */ - long - j; - - /* first we copy the last layer on top of the main image */ - (void) CompositeImage(image, CopyCompositeOp, layer_info[number_layers-1].image, - layer_info[number_layers-1].offset_x, - layer_info[number_layers-1].offset_y ); - DestroyImage( layer_info[number_layers-1].image ); + { + /* NOTE: XCF layers are REVERSED from composite order! */ + long + j; + + /* first we copy the last layer on top of the main image */ + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Composite Layer[%lu]: %lux%lu%+d%+d", + number_layers-1, + layer_info[number_layers-1].image->columns, + layer_info[number_layers-1].image->rows, + layer_info[number_layers-1].offset_x, + layer_info[number_layers-1].offset_y); + (void) CompositeImage(image, CopyCompositeOp, layer_info[number_layers-1].image, + layer_info[number_layers-1].offset_x, + layer_info[number_layers-1].offset_y ); + DestroyImage( layer_info[number_layers-1].image ); layer_info[number_layers-1].image = (Image *) NULL; - /* now reverse the order of the layers as they are put - into subimages - */ - image->next=layer_info[number_layers-2].image; - layer_info[number_layers-2].image->previous=image; - for (j=(long) number_layers-2; j >= 0; j--) - { - if (j > 0) - layer_info[j].image->next=layer_info[j-1].image; - if (j < ((long) number_layers-1)) - layer_info[j].image->previous=layer_info[j+1].image; - layer_info[j].image->page.x = layer_info[j].offset_x; - layer_info[j].image->page.y = layer_info[j].offset_y; - layer_info[j].image->page.width = layer_info[j].width; - layer_info[j].image->page.height = layer_info[j].height; - } - } + /* now reverse the order of the layers as they are put + into subimages + */ + image->next=layer_info[number_layers-2].image; + layer_info[number_layers-2].image->previous=image; + for (j=(long) number_layers-2; j >= 0; j--) + { + if (j > 0) + layer_info[j].image->next=layer_info[j-1].image; + if (j < ((long) number_layers-1)) + layer_info[j].image->previous=layer_info[j+1].image; + layer_info[j].image->page.x = layer_info[j].offset_x; + layer_info[j].image->page.y = layer_info[j].offset_y; + layer_info[j].image->page.width = layer_info[j].width; + layer_info[j].image->page.height = layer_info[j].height; + } + } #endif - } + } MagickFreeMemory(layer_info); diff --git a/coders/xpm.c b/coders/xpm.c index 418daa1..b2c6b46 100644 --- a/coders/xpm.c +++ b/coders/xpm.c @@ -127,6 +127,60 @@ static unsigned int IsXPM(const unsigned char *magick,const size_t length) % */ +static char **StringToListMod(char *text) +{ + char + **textlist; + + register char + *p; + + register size_t + i; + + size_t + lines; + + if (text == (char *) NULL) + return((char **) NULL); + + /* + Convert string to an ASCII list, modifying the input string. + */ + lines=1; + for (p=text; *p != '\0'; p++) + if (*p == '\n') + lines++; + textlist=MagickAllocateMemory(char **,(lines+1)*sizeof(char *)); + if (textlist == (char **) NULL) + MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, + UnableToConvertText); + i=0; + textlist[i]=text; + for (p=text; *p != '\0'; p++) + { + if (*p == '\r') + { + *p='\0'; + continue; + } + if (*p == '\n') + { + *p='\0'; + if (*(p+1) != '\0') + { + i++; + textlist[i]=p+1; + } + } + } + i++; + textlist[i]=(char *) NULL; + return(textlist); +} + +static char *ParseColor(char *data) MAGICK_FUNC_PURE; + static char *ParseColor(char *data) { #define NumberTargets 6 @@ -172,9 +226,6 @@ do { \ for (i=0; i < (long) image->colors; i++) \ MagickFreeMemory(keys[i]); \ MagickFreeMemory(keys); \ - if (textlist) \ - for (i=0; textlist[i] != (char *) NULL; i++) \ - MagickFreeMemory(textlist[i]); \ MagickFreeMemory(textlist); \ MagickFreeMemory(xpm_buffer); \ ThrowReaderException(code_,reason_,image_); \ @@ -315,21 +366,37 @@ static Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception) ThrowXPMReaderException(CorruptImageError,CorruptImage,image); } } - textlist=StringToList(xpm_buffer); - MagickFreeMemory(xpm_buffer); + /* + Scan for non-white space binary control codes and reject file if + they are present. + */ + for (p=xpm_buffer; *p != '\0'; p++) + if (((unsigned char) *p < 32) && !isspace((int)(unsigned char) (*p))) + break; + if (*p != '\0') + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Binary control codes error"); + ThrowXPMReaderException(CorruptImageError,CorruptImage,image); + } + textlist=StringToListMod(xpm_buffer); if (textlist == (char **) NULL) ThrowXPMReaderException(ResourceLimitError,MemoryAllocationFailed,image); #if 0 if (image->logging) { + for (i=0; textlist[i] != (char *) NULL; i++) + { }; + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "TextList has %lu entries", i); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "TextList"); for (i=0; textlist[i] != (char *) NULL; i++) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " %lu: %s", i, textlist[i]); + " %lu: \"%s\"", i, textlist[i]); } #endif - + /* Initialize image structure. */ @@ -455,9 +522,8 @@ static Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception) for (i=0; i < (long) image->colors; i++) MagickFreeMemory(keys[i]); MagickFreeMemory(keys); - for (i=0; textlist[i] != (char *) NULL; i++) - MagickFreeMemory(textlist[i]); MagickFreeMemory(textlist); + MagickFreeMemory(xpm_buffer); CloseBlob(image); return(image); } @@ -829,7 +895,7 @@ static unsigned int WritePICONImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,picon->rows)) if (!MagickMonitorFormatted(y,picon->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } DestroyImage(picon); @@ -1059,7 +1125,7 @@ static unsigned int WriteXPMImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } (void) WriteBlobString(image,"};\n"); diff --git a/coders/xwd.c b/coders/xwd.c index 5490efa..b24e2a0 100644 --- a/coders/xwd.c +++ b/coders/xwd.c @@ -889,7 +889,7 @@ static unsigned int WriteXWDImage(const ImageInfo *image_info,Image *image) { for (x=(long) image->columns; x > 0; x--) { - + *q++=ScaleQuantumToChar(p->red); *q++=ScaleQuantumToChar(p->green); *q++=ScaleQuantumToChar(p->blue); @@ -903,7 +903,7 @@ static unsigned int WriteXWDImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } MagickFreeMemory(pixels); diff --git a/coders/yuv.c b/coders/yuv.c index d0aa863..9c5ac55 100644 --- a/coders/yuv.c +++ b/coders/yuv.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2015 GraphicsMagick Group +% Copyright (C) 2003-2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -84,6 +84,8 @@ static unsigned int #define ThrowYUVReaderException(code_,reason_,image_) \ { \ MagickFreeMemory(scanline); \ + DestroyImage(chroma_image); \ + DestroyImage(resize_image); \ ThrowReaderException(code_,reason_,image_); \ } @@ -274,7 +276,7 @@ static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception) if (image->previous == (Image *) NULL) if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText, image->filename, - image->columns,image->rows)) + image->columns,image->rows)) { status=MagickFail; break; @@ -355,6 +357,7 @@ static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception) resize_image=ResizeImage(chroma_image,image->columns,image->rows, TriangleFilter,1.0,exception); DestroyImage(chroma_image); + chroma_image=(Image *) NULL; if (resize_image == (Image *) NULL) ThrowYUVReaderException(ResourceLimitError,MemoryAllocationFailed,image); for (y=0; y < (long) image->rows; y++) @@ -381,6 +384,7 @@ static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception) } } DestroyImage(resize_image); + resize_image=(Image *) NULL; if (status == MagickFail) break; image->colorspace=YCbCrColorspace; @@ -412,6 +416,7 @@ static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception) if (image->next == (Image *) NULL) { DestroyImageList(image); + MagickFreeMemory(scanline); return((Image *) NULL); } image=SyncNextImageInList(image); @@ -550,10 +555,14 @@ static unsigned int WriteYUVImage(const ImageInfo *image_info,Image *image) height, width; + size_t + image_list_length; + assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); + image_list_length=GetImageListLength(image); interlace=image_info->interlace; horizontal_factor=2; vertical_factor=2; @@ -648,7 +657,7 @@ static unsigned int WriteYUVImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } DestroyImage(yuv_image); @@ -673,7 +682,7 @@ static unsigned int WriteYUVImage(const ImageInfo *image_info,Image *image) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, - image->columns,image->rows)) + image->columns,image->rows)) break; } DestroyImage(yuv_image); @@ -732,7 +741,7 @@ static unsigned int WriteYUVImage(const ImageInfo *image_info,Image *image) if (image->next == (Image *) NULL) break; image=SyncNextImageInList(image); - status=MagickMonitorFormatted(scene++,GetImageListLength(image), + status=MagickMonitorFormatted(scene++,image_list_length, &image->exception,SaveImagesText, image->filename); if (status == False) diff --git a/common.shi.in b/common.shi.in index 5d1dd21..eb3b108 100644 --- a/common.shi.in +++ b/common.shi.in @@ -1,5 +1,5 @@ # -*- shell-script -*- -# Copyright (C) 2012 GraphicsMagick Group +# Copyright (C) 2012-2017 GraphicsMagick Group # Definitions of optional features and configuration values for this build. # Intended for use by test scripts. MAGICK_FEATURES='@MAGICK_FEATURES@' @@ -13,6 +13,7 @@ LD_LIBRARY_PATH="@abs_top_builddir@/magick/.libs:${LD_LIBRARY_PATH}" MAGICK_CODER_MODULE_PATH='@abs_top_builddir@/coders' MAGICK_CONFIGURE_PATH='@abs_top_builddir@/config:@abs_top_srcdir@/config' MAGICK_FILTER_MODULE_PATH='@abs_top_builddir@/filters' +MAGICK_CODER_STABILITY='BROKEN' PATH="@abs_top_builddir@/utilities:${PATH}" set +a diff --git a/config/compile b/config/compile index a85b723..99e5052 100755 --- a/config/compile +++ b/config/compile @@ -1,9 +1,9 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2012-10-14.11; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ scriptversion=2012-10-14.11; # UTC # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -255,7 +255,8 @@ EOF echo "compile $scriptversion" exit $? ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac @@ -339,9 +340,9 @@ exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/config/config.guess b/config/config.guess index 6c32c86..256083a 100755 --- a/config/config.guess +++ b/config/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2014 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2014-11-04' +timestamp='2018-03-08' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2014-11-04' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -27,7 +27,7 @@ timestamp='2014-11-04' # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . @@ -39,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -107,9 +107,9 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; + ,,) echo "int x;" > "$dummy.c" ; for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; @@ -132,14 +132,14 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "${UNAME_SYSTEM}" in +case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu - eval $set_cc_for_build - cat <<-EOF > $dummy.c + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc @@ -149,13 +149,20 @@ Linux|GNU|GNU/*) LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi ;; esac # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -168,21 +175,31 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -197,44 +214,67 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in os=netbsd ;; esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "$machine-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -251,63 +291,54 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos + echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos + echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -319,7 +350,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} + echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos @@ -346,38 +377,38 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} + echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" + eval "$set_cc_for_build" + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in @@ -386,25 +417,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} + echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -415,44 +446,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} + echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} + echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} + echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} + echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} + echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} + echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} + echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} + echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -461,23 +492,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} + echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -503,17 +534,17 @@ EOF AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) @@ -530,7 +561,7 @@ EOF echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id @@ -542,14 +573,14 @@ EOF if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -560,7 +591,7 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else @@ -574,7 +605,7 @@ EOF exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc @@ -583,18 +614,18 @@ EOF IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -609,28 +640,28 @@ EOF echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include @@ -663,13 +694,13 @@ EOF exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ "$HP_ARCH" = hppa2.0w ] then - eval $set_cc_for_build + eval "$set_cc_for_build" # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -680,23 +711,23 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -721,11 +752,11 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -734,7 +765,7 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -742,9 +773,9 @@ EOF exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -769,127 +800,109 @@ EOF echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} + echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in + case "$UNAME_PROCESSOR" in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin + echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 + echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 + echo "$UNAME_MACHINE"-pc-mingw32 exit ;; *:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 + echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) - case ${UNAME_MACHINE} in + case "$UNAME_MACHINE" in x86) - echo i586-pc-interix${UNAME_RELEASE} + echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} + echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) - echo ia64-unknown-interix${UNAME_RELEASE} + echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin + echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix + echo "$UNAME_MACHINE"-pc-minix exit ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -902,58 +915,64 @@ EOF EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el @@ -967,64 +986,70 @@ EOF #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; openrisc*:Linux:*:*) - echo or1k-unknown-linux-${LIBC} + echo or1k-unknown-linux-"$LIBC" exit ;; or32:Linux:*:* | or1k*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} + echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} + echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} + echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} + echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} + echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. @@ -1038,34 +1063,34 @@ EOF # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx + echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable + echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} + echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp + echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) @@ -1075,12 +1100,12 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1090,9 +1115,9 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) @@ -1100,7 +1125,7 @@ EOF # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that + # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; @@ -1112,9 +1137,9 @@ EOF exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1134,9 +1159,9 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; @@ -1145,28 +1170,28 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} + echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} + echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} + echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} + echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} + echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1177,7 +1202,7 @@ EOF *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi @@ -1197,23 +1222,23 @@ EOF exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos + echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} + echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. @@ -1232,46 +1257,56 @@ EOF echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} + echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} + echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} + echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} + echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} + echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} + echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build + eval "$set_cc_for_build" if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi - if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub @@ -1282,27 +1317,33 @@ EOF # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1311,18 +1352,18 @@ EOF echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi - echo ${UNAME_MACHINE}-unknown-plan9 + echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1343,14 +1384,14 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in + case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1359,34 +1400,48 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos + echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros + echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs exit ;; esac +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp @@ -1405,16 +1460,16 @@ hostinfo = `(hostinfo) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/config/config.sub b/config/config.sub index 7ffe373..9ccf09a 100755 --- a/config/config.sub +++ b/config/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2014 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2014-12-03' +timestamp='2018-03-08' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2014-12-03' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -33,7 +33,7 @@ timestamp='2014-12-03' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -53,12 +53,11 @@ timestamp='2014-12-03' me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -68,7 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -95,7 +94,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -113,24 +112,24 @@ esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac @@ -179,44 +178,44 @@ case $os in ;; -sco6) os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 @@ -228,10 +227,7 @@ case $os in os=-lynxos ;; -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos @@ -255,15 +251,16 @@ case $basic_machine in | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ + | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ @@ -299,13 +296,14 @@ case $basic_machine in | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ - | pdp10 | pdp11 | pj | pjl \ + | pdp10 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -314,7 +312,7 @@ case $basic_machine in | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ - | we32k \ + | wasm32 \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown @@ -335,7 +333,7 @@ case $basic_machine in basic_machine=$basic_machine-unknown os=-none ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) ;; ms1) basic_machine=mt-unknown @@ -364,7 +362,7 @@ case $basic_machine in ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. @@ -376,17 +374,18 @@ case $basic_machine in | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ @@ -427,13 +426,15 @@ case $basic_machine in | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ + | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ @@ -442,6 +443,7 @@ case $basic_machine in | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -455,7 +457,7 @@ case $basic_machine in # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) - basic_machine=i386-unknown + basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) @@ -489,7 +491,7 @@ case $basic_machine in basic_machine=x86_64-pc ;; amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl @@ -518,6 +520,9 @@ case $basic_machine in basic_machine=i386-pc os=-aros ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -531,7 +536,7 @@ case $basic_machine in os=-linux ;; blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) @@ -539,13 +544,13 @@ case $basic_machine in os=-cnk ;; c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray @@ -634,10 +639,18 @@ case $basic_machine in basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -727,9 +740,6 @@ case $basic_machine in hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; - hppa-next) - os=-nextstep3 - ;; hppaosf) basic_machine=hppa1.1-hp os=-osf @@ -742,26 +752,26 @@ case $basic_machine in basic_machine=i370-ibm ;; i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; - i386-vsta | vsta) + vsta) basic_machine=i386-unknown os=-vsta ;; @@ -780,19 +790,16 @@ case $basic_machine in os=-sysv ;; leon-*|leon[3-9]-*) - basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; - m88k-omron*) - basic_machine=m88k-omron - ;; magnum | m3230) basic_machine=mips-mips os=-sysv @@ -824,10 +831,10 @@ case $basic_machine in os=-mint ;; mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` ;; mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k @@ -846,7 +853,7 @@ case $basic_machine in os=-msdos ;; ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc @@ -888,7 +895,7 @@ case $basic_machine in basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -933,6 +940,12 @@ case $basic_machine in nsr-tandem) basic_machine=nsr-tandem ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -965,7 +978,7 @@ case $basic_machine in os=-linux ;; parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; pbd) @@ -981,7 +994,7 @@ case $basic_machine in basic_machine=i386-pc ;; pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc @@ -996,16 +1009,16 @@ case $basic_machine in basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould @@ -1015,23 +1028,23 @@ case $basic_machine in ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm @@ -1085,17 +1098,10 @@ case $basic_machine in sequent) basic_machine=i386-sequent ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; sh5el) basic_machine=sh5le-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) + simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -1114,7 +1120,7 @@ case $basic_machine in os=-sysv4 ;; strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun @@ -1236,6 +1242,9 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; + x64) + basic_machine=x86_64-pc + ;; xbox) basic_machine=i686-pc os=-mingw32 @@ -1244,20 +1253,12 @@ case $basic_machine in basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; none) basic_machine=none-none os=-none @@ -1286,10 +1287,6 @@ case $basic_machine in vax) basic_machine=vax-dec ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; pdp11) basic_machine=pdp11-dec ;; @@ -1299,9 +1296,6 @@ case $basic_machine in sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; cydra) basic_machine=cydra-cydrome ;; @@ -1321,7 +1315,7 @@ case $basic_machine in # Make sure to match an already-canonicalized machine name. ;; *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac @@ -1329,10 +1323,10 @@ esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; @@ -1343,8 +1337,8 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux @@ -1355,45 +1349,48 @@ case $os in -solaris) os=-solaris2 ;; - -svr4*) - os=-sysv4 - ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* | -hcos* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1410,12 +1407,12 @@ case $os in -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + os=`echo "$os" | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc @@ -1424,10 +1421,10 @@ case $os in os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition @@ -1438,12 +1435,6 @@ case $os in -wince*) os=-wince ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; -utek*) os=-bsd ;; @@ -1468,7 +1459,7 @@ case $os in -nova*) os=-rtmk-nova ;; - -ns2 ) + -ns2) os=-nextstep2 ;; -nsk*) @@ -1490,7 +1481,7 @@ case $os in -oss*) os=-sysv3 ;; - -svr4) + -svr4*) os=-sysv4 ;; -svr3) @@ -1505,32 +1496,38 @@ case $os in -ose*) os=-ose ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; - -aros*) - os=-aros - ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; -nacl*) ;; + -ios) + ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1620,12 +1617,12 @@ case $basic_machine in sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; - *-haiku) - os=-haiku - ;; *-ibm) os=-aix ;; @@ -1665,7 +1662,7 @@ case $basic_machine in m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1680,9 +1677,6 @@ case $basic_machine in i370-*) os=-mvs ;; - *-next) - os=-nextstep3 - ;; *-gould) os=-sysv ;; @@ -1792,15 +1786,15 @@ case $basic_machine in vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$basic_machine$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/config/delegates.mgk.in b/config/delegates.mgk.in index b8040cd..295cbcb 100644 --- a/config/delegates.mgk.in +++ b/config/delegates.mgk.in @@ -98,6 +98,15 @@ + + + + + + + + + diff --git a/config/depcomp b/config/depcomp index fc98710..65cbf70 100755 --- a/config/depcomp +++ b/config/depcomp @@ -1,9 +1,9 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2013-05-30.07; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ scriptversion=2013-05-30.07; # UTC # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -783,9 +783,9 @@ exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/config/install-sh b/config/install-sh index 0b0fdcb..8175c64 100755 --- a/config/install-sh +++ b/config/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2013-12-25.23; # UTC +scriptversion=2018-03-11.20; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -271,15 +271,18 @@ do fi dst=$dst_arg - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. + # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst - dst=$dstdir/`basename "$src"` + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac dstdir_status=0 else dstdir=`dirname "$dst"` @@ -288,6 +291,11 @@ do fi fi + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + obsolete_mkdir_used=false if test $dstdir_status != 0; then @@ -324,34 +332,43 @@ do # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) + # Note that $RANDOM variable is not portable (e.g. dash); Use it + # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p' feature. if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi - rmdir "$tmpdir/d" "$tmpdir" + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac;; @@ -427,8 +444,8 @@ do else # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 @@ -493,9 +510,9 @@ do done # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/config/missing b/config/missing index f62bbae..625aeb1 100755 --- a/config/missing +++ b/config/missing @@ -1,9 +1,9 @@ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. -scriptversion=2013-10-28.13; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ scriptversion=2013-10-28.13; # UTC # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -101,9 +101,9 @@ else exit $st fi -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software program_details () { @@ -207,9 +207,9 @@ give_advice "$1" | sed -e '1s/^/WARNING: /' \ exit $st # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/config/tap-driver.sh b/config/tap-driver.sh index 4254e2b..2516e9c 100755 --- a/config/tap-driver.sh +++ b/config/tap-driver.sh @@ -1,5 +1,5 @@ #! /bin/sh -# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# Copyright (C) 2011-2018 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -12,7 +12,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -132,7 +132,7 @@ fi # last `echo $?' statement), and would thus die reporting an internal # error. # For more information, see the Autoconf manual and the threads: - # + # # trap : 1 3 2 13 15 if test $merge -gt 0; then @@ -643,9 +643,9 @@ test $? -eq 0 || fatal "I/O or internal error" # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/config/test-driver b/config/test-driver index 8e575b0..b8521a4 100755 --- a/config/test-driver +++ b/config/test-driver @@ -1,9 +1,9 @@ #! /bin/sh # test-driver - basic testsuite driver script. -scriptversion=2013-07-13.22; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# Copyright (C) 2011-2018 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ scriptversion=2013-07-13.22; # UTC # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -140,9 +140,9 @@ echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/configure b/configure index effa4f1..46b7c6d 100755 --- a/configure +++ b/configure @@ -638,6 +638,7 @@ MAGICK_API_LDFLAGS MAGICK_API_PC_CPPFLAGS MAGICK_API_CPPFLAGS MAGICK_API_CFLAGS +MAGICK_EXTRA_DEP_LIBS MAGICK_DEP_LIBS MAGICK_FEATURES DELEGATES @@ -720,6 +721,8 @@ LIB_XML_DEPS LIB_XML HasXML_FALSE HasXML_TRUE +XML_LIBS +XML_CFLAGS xml2_config LIB_WEBP HasWEBP_FALSE @@ -733,10 +736,12 @@ HasTIFF_TRUE LIB_TTF HasTTF_FALSE HasTTF_TRUE +FT_LIBS +FT_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG freetype_config -LIB_GS -HasGS_FALSE -HasGS_TRUE LIB_JP2 HasJP2_FALSE HasJP2_TRUE @@ -765,6 +770,9 @@ X_LIBS X_PRE_LIBS X_CFLAGS XMKMF +LIB_ZSTD +HasZSTD_FALSE +HasZSTD_TRUE LIB_LZMA HasLZMA_FALSE HasLZMA_TRUE @@ -1039,7 +1047,6 @@ with_perl_options with_bzlib with_dps with_fpx -with_gslib with_jbig with_webp with_jpeg @@ -1057,6 +1064,7 @@ with_gs_font_dir with_windows_font_dir with_xml with_zlib +with_zstd with_libstdc with_x ' @@ -1074,7 +1082,14 @@ CXX CXXFLAGS CCC CXXCPP -XMKMF' +XMKMF +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +FT_CFLAGS +FT_LIBS +XML_CFLAGS +XML_LIBS' # Initialize some variables set by options. @@ -1751,7 +1766,6 @@ Optional Packages: --without-bzlib disable BZLIB support --without-dps disable Display Postscript support --with-fpx enable FlashPIX support - --with-gslib enable Ghostscript library support (not recommended) --without-jbig disable JBIG support --without-webp disable WEBP support --without-jpeg disable JPEG support @@ -1770,6 +1784,7 @@ Optional Packages: directory containing MS-Windows fonts --without-xml disable XML support --without-zlib disable ZLIB support + --without-zstd disable Zstd support --with-libstdc=DIR use libstdc++ in DIR (for GNU C++) --with-x use the X Window System --without-png disable PNG support @@ -1789,6 +1804,15 @@ Some influential environment variables: CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor XMKMF Path to xmkmf, Makefile generator for X Window System + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + FT_CFLAGS C compiler flags for FT, overriding pkg-config + FT_LIBS linker flags for FT, overriding pkg-config + XML_CFLAGS C compiler flags for XML, overriding pkg-config + XML_LIBS linker flags for XML, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -8011,6 +8035,21 @@ fi # +# Decide if setjmp/longjmp is thread safe based on host OS +# +case "${host_os}" in + solaris2* ) + # Documented not to be MT safe + + ;; + *) + +$as_echo "#define SETJMP_IS_THREAD_SAFE 1" >>confdefs.h + + ;; +esac + +# # Configure libtool # @@ -19589,19 +19628,6 @@ if test "$with_fpx" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-fpx=$with_fpx " fi -# Enable Ghostscript library support. - -# Check whether --with-gslib was given. -if test "${with_gslib+set}" = set; then : - withval=$with_gslib; with_gslib=$withval -else - with_gslib='no' -fi - -if test "$with_gslib" != 'yes' ; then - DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-gslib=$with_gslib " -fi - # Disable JBIG. # Check whether --with-jbig was given. @@ -19682,10 +19708,10 @@ fi # # Disable MPEG. # AC_ARG_WITH(mpeg2, -# AS_HELP_STRING([--without-mpeg2], +# AS_HELP_STRING([--without-mpeg2], # [disable MPEG support]), -# [with_mpeg2=$withval], -# [with_mpeg2='yes']) +# [with_mpeg2=$withval], +# [with_mpeg2='yes']) # Disable PNG. @@ -19841,6 +19867,19 @@ if test "$with_zlib" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-zlib=$with_zlib " fi +# Disable Zstd (zstd library) + +# Check whether --with-zstd was given. +if test "${with_zstd+set}" = set; then : + withval=$with_zstd; with_zstd=$withval +else + with_zstd='yes' +fi + +if test "$with_zstd" != 'yes' ; then + DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-zstd=$with_zstd " +fi + # # Specify path to shared libstdc++ if not in normal location # @@ -22977,7 +23016,7 @@ else # Look for the header file in a standard set of common directories. # Check X11 before X11Rn because it is often a symlink to the current release. for ac_dir in \ - /lib/usr/lib/X11 \ + /lib/usr/lib/X11 \ /usr/X11/lib \ /usr/X11R4/lib \ /usr/X11R5/lib \ @@ -23014,7 +23053,7 @@ else if test -f "$ac_dir/X11/rgb.txt" then gm_cv_x_configure="$ac_dir/X11/" - break + break elif test -f "$ac_dir/rgb.txt" then gm_cv_x_configure="$ac_dir/" @@ -23829,8 +23868,10 @@ then $as_echo_n "checking for ZLIB support ... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } + failed=0 passed=0 + # PKG_CHECK_MODULES([ZLIB], [zlib], [], []) ac_fn_c_check_header_mongrel "$LINENO" "zconf.h" "ac_cv_header_zconf_h" "$ac_includes_default" if test "x$ac_cv_header_zconf_h" = xyes; then : passed=`expr $passed + 1` @@ -24297,6 +24338,7 @@ then $as_echo_n "checking for LZMA support ... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } + # PKG_CHECK_MODULES([LZMA], [liblzma], [], []) failed=0 passed=0 ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" @@ -24384,6 +24426,104 @@ fi # +# Check for Zstd +# +have_zstd='no' +LIB_ZSTD='' +if test "$with_zstd" != 'no' +then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Zstd support " >&5 +$as_echo_n "checking for Zstd support ... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 +$as_echo "" >&6; } + failed=0 + passed=0 + # PKG_CHECK_MODULES([ZSTD], [libzstd], [], []) + ac_fn_c_check_header_mongrel "$LINENO" "zstd.h" "ac_cv_header_zstd_h" "$ac_includes_default" +if test "x$ac_cv_header_zstd_h" = xyes; then : + passed=`expr $passed + 1` +else + failed=`expr $failed + 1` +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZSTD_createDStream in -lzstd" >&5 +$as_echo_n "checking for ZSTD_createDStream in -lzstd... " >&6; } +if ${ac_cv_lib_zstd_ZSTD_createDStream+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lzstd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ZSTD_createDStream (); +int +main () +{ +return ZSTD_createDStream (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_zstd_ZSTD_createDStream=yes +else + ac_cv_lib_zstd_ZSTD_createDStream=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_zstd_ZSTD_createDStream" >&5 +$as_echo "$ac_cv_lib_zstd_ZSTD_createDStream" >&6; } +if test "x$ac_cv_lib_zstd_ZSTD_createDStream" = xyes; then : + passed=`expr $passed + 1` +else + failed=`expr $failed + 1` +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Zstd package is complete" >&5 +$as_echo_n "checking if Zstd package is complete... " >&6; } + if test $passed -gt 0 + then + if test $failed -gt 0 + then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 +$as_echo "no -- some components failed test" >&6; } + have_zstd='no (failed tests)' + else + LIB_ZSTD='-lzstd' + LIBS="$LIB_ZSTD $LIBS" + +$as_echo "#define HasZSTD 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_zstd='yes' + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi +fi + if test "$have_zstd" = 'yes'; then + HasZSTD_TRUE= + HasZSTD_FALSE='#' +else + HasZSTD_TRUE='#' + HasZSTD_FALSE= +fi + + + +# # Find the X11 include and library directories. # LIB_X11='' @@ -25489,19 +25629,19 @@ $as_echo_n "checking if DPS package is complete... " >&6; } then if test $failed -gt 0 then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } have_dps='no (failed tests)' - CPPFLAGS="$O_CPPFLAGS" + CPPFLAGS="$O_CPPFLAGS" else - LIB_DPS="-ldpstk -ldps ${LIBDPS_XT}" - LIBS="$LIB_DPS $LIBS" + LIB_DPS="-ldpstk -ldps ${LIBDPS_XT}" + LIBS="$LIB_DPS $LIBS" $as_echo "#define HasDPS 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - have_dps='yes' + have_dps='yes' fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 @@ -25601,16 +25741,16 @@ $as_echo_n "checking if FlashPIX package is complete... " >&6; } then if test $failed -gt 0 then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } - have_fpx='no (failed tests)' + have_fpx='no (failed tests)' else - LIB_FPX='-lfpx' - # LIBS="$LIB_FPX $LIBS" + LIB_FPX='-lfpx' + # LIBS="$LIB_FPX $LIBS" $as_echo "#define HasFPX 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_fpx='yes' PERLMAINCC="$CXX" @@ -25645,6 +25785,8 @@ $as_echo "" >&6; } passed=0 have_lcms_header='no' + # PKG_CHECK_MODULES([LCMS2], [lcms2], [], []) + # Check for ac_fn_c_check_header_mongrel "$LINENO" "lcms2.h" "ac_cv_header_lcms2_h" "$ac_includes_default" if test "x$ac_cv_header_lcms2_h" = xyes; then : @@ -25781,6 +25923,7 @@ else with_png='yes' fi + # PKG_CHECK_MODULES([PNG], [libpng], [], []) if test "$with_png" != 'yes'; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-png=$with_png " @@ -25811,9 +25954,9 @@ fi pnglib="png1${var}" fi if test "$have_png" = 'no' - then + then - # Test for compatible LIBPNG library + # Test for compatible LIBPNG library failed=0 passed=0 if test "$with_png" = 'yes' -o "$with_png" = "libpng1${var}" ; then @@ -26129,18 +26272,18 @@ fi $as_echo_n "checking if ${pnglib} package is complete... " >&6; } if test $passed -gt 0 ; then if test $failed -gt 0 ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } - have_png='no (failed tests)' + have_png='no (failed tests)' else - LIB_PNG="-l${pnglib}" - LIBS="$LIB_PNG $LIBS" + LIB_PNG="-l${pnglib}" + LIBS="$LIB_PNG $LIBS" $as_echo "#define HasPNG 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - have_png='yes' + have_png='yes' fi fi fi @@ -26176,6 +26319,9 @@ $as_echo_n "checking for JPEG support ... " >&6; } $as_echo "" >&6; } failed=0 passed=0 + + # PKG_CHECK_MODULES([JPEG], [libturbojpeg, libjpeg], [], []) + ac_fn_c_check_header_mongrel "$LINENO" "jconfig.h" "ac_cv_header_jconfig_h" "$ac_includes_default" if test "x$ac_cv_header_jconfig_h" = xyes; then : passed=`expr $passed + 1` @@ -26299,16 +26445,16 @@ $as_echo_n "checking if JPEG package is complete... " >&6; } then if test $failed -gt 0 then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } have_jpeg='no (failed tests)' else - LIB_JPEG='-ljpeg' - LIBS="$LIB_JPEG $LIBS" + LIB_JPEG='-ljpeg' + LIBS="$LIB_JPEG $LIBS" $as_echo "#define HasJPEG 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_jpeg='yes' fi @@ -26396,18 +26542,18 @@ $as_echo_n "checking if JPEG version 2 support package is complete... " >&6; } then if test $failed -gt 0 then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } - have_jp2='no (failed tests)' + have_jp2='no (failed tests)' else - LIB_JP2='-ljasper' - LIBS="$LIB_JP2 $LIBS" + LIB_JP2='-ljasper' + LIBS="$LIB_JP2 $LIBS" $as_echo "#define HasJP2 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - have_jp2='yes' + have_jp2='yes' fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 @@ -26424,104 +26570,6 @@ fi -# -# Check for Ghostscript library -# -# Test for iapi.h & test for gsapi_new_instance in -lgs -have_gslib='no' -LIB_GS='' -if test "$with_gslib" != 'no' -then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ghostscript library support " >&5 -$as_echo_n "checking for Ghostscript library support ... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 -$as_echo "" >&6; } - failed=0 - passed=0 - ac_fn_c_check_header_mongrel "$LINENO" "ghostscript/iapi.h" "ac_cv_header_ghostscript_iapi_h" "$ac_includes_default" -if test "x$ac_cv_header_ghostscript_iapi_h" = xyes; then : - passed=`expr $passed + 1` -else - failed=`expr $failed + 1` -fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gsapi_new_instance in -lgs" >&5 -$as_echo_n "checking for gsapi_new_instance in -lgs... " >&6; } -if ${ac_cv_lib_gs_gsapi_new_instance+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lgs $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char gsapi_new_instance (); -int -main () -{ -return gsapi_new_instance (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_gs_gsapi_new_instance=yes -else - ac_cv_lib_gs_gsapi_new_instance=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gs_gsapi_new_instance" >&5 -$as_echo "$ac_cv_lib_gs_gsapi_new_instance" >&6; } -if test "x$ac_cv_lib_gs_gsapi_new_instance" = xyes; then : - passed=`expr $passed + 1` -else - failed=`expr $failed + 1` -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Ghostscript library package is complete" >&5 -$as_echo_n "checking if Ghostscript library package is complete... " >&6; } - if test $passed -gt 0 - then - if test $failed -gt 0 - then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 -$as_echo "no -- some components failed test" >&6; } - have_gslib='no (failed tests)' - else - LIB_GS='-lgs' - LIBS="$LIB_GS $LIBS" - -$as_echo "#define HasGS 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - have_gslib='yes' - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi -fi - if test "$have_gslib" = 'yes'; then - HasGS_TRUE= - HasGS_FALSE='#' -else - HasGS_TRUE='#' - HasGS_FALSE= -fi - - - # # # # Check for MPEG2 library # # @@ -26540,14 +26588,14 @@ fi # then # if test $failed -gt 0 # then -# AC_MSG_RESULT(no -- some components failed test) -# have_mpeg2='no (failed tests)' +# AC_MSG_RESULT(no -- some components failed test) +# have_mpeg2='no (failed tests)' # else -# LIB_MPEG2='-lmpeg2' -# LIBS="$LIB_MPEG2 $LIBS" -# AC_DEFINE(HasMPEG2,1,Define if you have MPEG2 library) -# AC_MSG_RESULT(yes) -# have_mpeg2='yes' +# LIB_MPEG2='-lmpeg2' +# LIBS="$LIB_MPEG2 $LIBS" +# AC_DEFINE(HasMPEG2,1,Define if you have MPEG2 library) +# AC_MSG_RESULT(yes) +# have_mpeg2='yes' # fi # else # AC_MSG_RESULT(no) @@ -26572,21 +26620,20 @@ $as_echo "" >&6; } OLD_LDFLAGS="$LDFLAGS" OLD_CPPFLAGS="$CPPFLAGS" + # https://autotools.io/pkgconfig/pkg_check_modules.html + # PKG_CHECK_MODULES(prefix, list-of-modules, action-if-found, action-if-not-found) + # % pkg-config --libs freetype2 + # -lfreetype + # % pkg-config --cflags freetype2 + # -I/usr/include/freetype2 -I/usr/include/libpng12 + # + # % grep FT_ config.status + # S["FT_LIBS"]="-R/usr/lib -lfreetype " + # S["FT_CFLAGS"]="-I/usr/include/freetype2 + freetype_cflags='' + freeype_libs='' freetype_config='' - # Allow the user to specify the location of freetype. - if test "$with_ttf" != 'yes' - then - if test -x "${with_ttf}/bin/freetype-config" - then - freetype_config="${with_ttf}/bin/freetype-config" - elif test -x "${with_ttf}" - then - freetype_config=${with_ttf} - fi - fi - if test -z "$freetype_config" - then - # Extract the first word of "freetype-config", so it can be a program name with args. + # Extract the first word of "freetype-config", so it can be a program name with args. set dummy freetype-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } @@ -26625,10 +26672,205 @@ else $as_echo "no" >&6; } fi - fi - if test -n "$freetype_config" - then - freetype_cflags=`${freetype_config} --cflags` + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype2" >&5 +$as_echo_n "checking for freetype2... " >&6; } + +if test -n "$FT_CFLAGS"; then + pkg_cv_FT_CFLAGS="$FT_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"freetype2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "freetype2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_FT_CFLAGS=`$PKG_CONFIG --cflags "freetype2" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$FT_LIBS"; then + pkg_cv_FT_LIBS="$FT_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"freetype2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "freetype2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_FT_LIBS=`$PKG_CONFIG --libs "freetype2" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + FT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "freetype2" 2>&1` + else + FT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "freetype2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$FT_PKG_ERRORS" >&5 + + if test -n "$freetype_config" + then + freetype_cflags=`${freetype_config} --cflags` + freeype_libs=`${freetype_config} --libs` + fi +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test -n "$freetype_config" + then + freetype_cflags=`${freetype_config} --cflags` + freeype_libs=`${freetype_config} --libs` + fi +else + FT_CFLAGS=$pkg_cv_FT_CFLAGS + FT_LIBS=$pkg_cv_FT_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + freetype_cflags=$FT_CFLAGS; freeype_libs=$FT_LIBS +fi # freetype-config --cflags may output values such as # -I/usr/local/include/freetype2 -I/usr/local/include # Take only the first -I option since non-Freetype include @@ -26657,7 +26899,6 @@ fi # Freetype. In the future we may need to do something different # if the FreeType library was to depend on some weird library # that we don't normally test for. - freeype_libs=`${freetype_config} --libs` for flag in $freeype_libs do case $flag in @@ -26680,7 +26921,6 @@ fi ;; esac done - fi as_ac_Lib=`$as_echo "ac_cv_lib_$LIB_TTF_BASE''_FT_Init_FreeType" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FT_Init_FreeType in -l$LIB_TTF_BASE" >&5 @@ -26761,9 +27001,9 @@ fi fi if test "$have_freetype_h" = 'yes' then - passed=`expr $passed + 1` + passed=`expr $passed + 1` else - failed=`expr $failed + 1` + failed=`expr $failed + 1` CPPFLAGS="$OLD_CPPFLAGS" fi @@ -26771,14 +27011,14 @@ fi $as_echo_n "checking if FreeType package is complete... " >&6; } if test $passed -gt 0 then - if test $failed -gt 0 - then + if test $failed -gt 0 + then LIB_TTF='' - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } - have_ttf='no (failed tests)' - else - LIBS="$LIB_TTF $LIBS" + have_ttf='no (failed tests)' + else + LIBS="$LIB_TTF $LIBS" $as_echo "#define HasTTF 1" >>confdefs.h @@ -26788,12 +27028,12 @@ $as_echo "#define HasTTF 1" >>confdefs.h $as_echo "#define HAVE_FT2BUILD_H 1" >>confdefs.h fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - have_ttf='yes' - fi + have_ttf='yes' + fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi @@ -26820,6 +27060,7 @@ $as_echo_n "checking for TIFF support ... " >&6; } $as_echo "" >&6; } failed=0 passed=0 + # PKG_CHECK_MODULES([TIFF], [libtiff-4], [], []) ac_fn_c_check_header_mongrel "$LINENO" "tiff.h" "ac_cv_header_tiff_h" "$ac_includes_default" if test "x$ac_cv_header_tiff_h" = xyes; then : passed=`expr $passed + 1` @@ -27052,19 +27293,19 @@ $as_echo_n "checking if TIFF package is complete... " >&6; } then if test $failed -gt 0 then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } - have_tiff='no (failed tests)' + have_tiff='no (failed tests)' else - LIB_TIFF='-ltiff' - LIBS="$LIB_TIFF $LIBS" + LIB_TIFF='-ltiff' + LIBS="$LIB_TIFF $LIBS" $as_echo "#define HasTIFF 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - have_tiff='yes' - for ac_header in tiffconf.h + have_tiff='yes' + for ac_header in tiffconf.h do : ac_fn_c_check_header_mongrel "$LINENO" "tiffconf.h" "ac_cv_header_tiffconf_h" "$ac_includes_default" if test "x$ac_cv_header_tiffconf_h" = xyes; then : @@ -27178,16 +27419,16 @@ $as_echo_n "checking if JBIG package is complete... " >&6; } then if test $failed -gt 0 then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } have_jbig='no (failed tests)' else - LIB_JBIG='-ljbig' - LIBS="$LIB_JBIG $LIBS" + LIB_JBIG='-ljbig' + LIBS="$LIB_JBIG $LIBS" $as_echo "#define HasJBIG 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_jbig='yes' fi @@ -27219,6 +27460,7 @@ $as_echo_n "checking for WEBP support ... " >&6; } $as_echo "" >&6; } failed=0 passed=0 + # PKG_CHECK_MODULES([WEBP], [libwebp], [], []) ac_fn_c_check_header_mongrel "$LINENO" "webp/decode.h" "ac_cv_header_webp_decode_h" "$ac_includes_default" if test "x$ac_cv_header_webp_decode_h" = xyes; then : passed=`expr $passed + 1` @@ -27227,6 +27469,14 @@ else fi + ac_fn_c_check_header_mongrel "$LINENO" "webp/encode.h" "ac_cv_header_webp_encode_h" "$ac_includes_default" +if test "x$ac_cv_header_webp_encode_h" = xyes; then : + passed=`expr $passed + 1` +else + failed=`expr $failed + 1` +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WebPDecodeRGB in -lwebp" >&5 $as_echo_n "checking for WebPDecodeRGB in -lwebp... " >&6; } if ${ac_cv_lib_webp_WebPDecodeRGB+:} false; then : @@ -27264,30 +27514,69 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_webp_WebPDecodeRGB" >&5 $as_echo "$ac_cv_lib_webp_WebPDecodeRGB" >&6; } if test "x$ac_cv_lib_webp_WebPDecodeRGB" = xyes; then : - passed=`expr $passed + 1` + passed=`expr $passed + 1`; LIB_WEBP='-lwebp' else failed=`expr $failed + 1` fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WebPMuxSetImage in -lwebpmux" >&5 +$as_echo_n "checking for WebPMuxSetImage in -lwebpmux... " >&6; } +if ${ac_cv_lib_webpmux_WebPMuxSetImage+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lwebpmux -lwebp $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char WebPMuxSetImage (); +int +main () +{ +return WebPMuxSetImage (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_webpmux_WebPMuxSetImage=yes +else + ac_cv_lib_webpmux_WebPMuxSetImage=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_webpmux_WebPMuxSetImage" >&5 +$as_echo "$ac_cv_lib_webpmux_WebPMuxSetImage" >&6; } +if test "x$ac_cv_lib_webpmux_WebPMuxSetImage" = xyes; then : + LIB_WEBP="$LIB_WEBP -lwebpmux" +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if WEBP package is complete" >&5 $as_echo_n "checking if WEBP package is complete... " >&6; } if test $passed -gt 0 then - if test $failed -gt 0 - then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + if test $failed -gt 0 + then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } - have_webp='no (failed tests)' - else - LIB_WEBP='-lwebp' - LIBS="$LIB_WEBP $LIBS" + have_webp='no (failed tests)' + else + LIBS="$LIB_WEBP $LIBS" $as_echo "#define HasWEBP 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - have_webp='yes' - fi + have_webp='yes' + fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -27319,6 +27608,8 @@ $as_echo_n "checking for XML support ... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } xml2_config='' + xml2_cflags='' + xml2_libs='' # Extract the first word of "xml2-config", so it can be a program name with args. set dummy xml2-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -27358,17 +27649,106 @@ else $as_echo "no" >&6; } fi - if test -n "$xml2_config" - then - # Sample output from xml2-config --cflags: - # -I/usr/include/libxml2 - # -I/usr/local/include/libxml2 -I/usr/local/include - xml2_cflags=`"$xml2_config" --cflags` - for flag in $xml2_cflags - do - case $flag in - -I*) - # Add flag to CPPFLAGS if not already present + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libxml-2.0" >&5 +$as_echo_n "checking for libxml-2.0... " >&6; } + +if test -n "$XML_CFLAGS"; then + pkg_cv_XML_CFLAGS="$XML_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_XML_CFLAGS=`$PKG_CONFIG --cflags "libxml-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$XML_LIBS"; then + pkg_cv_XML_LIBS="$XML_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_XML_LIBS=`$PKG_CONFIG --libs "libxml-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + XML_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libxml-2.0" 2>&1` + else + XML_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libxml-2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$XML_PKG_ERRORS" >&5 + + if test -n "$xml2_config" + then + # Sample output from xml2-config --cflags: + # -I/usr/include/libxml2 + # -I/usr/local/include/libxml2 -I/usr/local/include + xml2_cflags=`"$xml2_config" --cflags` + # Sample output from xml2-config --libs: + # -lxml2 + # -L/usr/lib -R/usr/lib -lxml2 -lz -lpthread -lm -lsocket -lnsl + #-L/usr/local/lib -lxml2 -lz -L/usr/local/lib -liconv -lm + xml2_libs=`$xml2_config --libs` + fi + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test -n "$xml2_config" + then + # Sample output from xml2-config --cflags: + # -I/usr/include/libxml2 + # -I/usr/local/include/libxml2 -I/usr/local/include + xml2_cflags=`"$xml2_config" --cflags` + # Sample output from xml2-config --libs: + # -lxml2 + # -L/usr/lib -R/usr/lib -lxml2 -lz -lpthread -lm -lsocket -lnsl + #-L/usr/local/lib -lxml2 -lz -L/usr/local/lib -liconv -lm + xml2_libs=`$xml2_config --libs` + fi + +else + XML_CFLAGS=$pkg_cv_XML_CFLAGS + XML_LIBS=$pkg_cv_XML_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + xml2_cflags=$XML_CFLAGS; xml2_libs=$XML_LIBS +fi + for flag in $xml2_cflags + do + case $flag in + -I*) + # Add flag to CPPFLAGS if not already present add=yes; for test_flag in $CPPFLAGS do @@ -27386,15 +27766,10 @@ fi ;; *) ;; - esac - done - # Sample output from xml2-config --libs: - # -lxml2 - # -L/usr/lib -R/usr/lib -lxml2 -lz -lpthread -lm -lsocket -lnsl - #-L/usr/local/lib -lxml2 -lz -L/usr/local/lib -liconv -lm - xml2_libs=`$xml2_config --libs` - for flag in $xml2_libs - do + esac + done + for flag in $xml2_libs + do case $flag in -L*) # Add flag to LDFLAGS if not already present @@ -27416,9 +27791,9 @@ fi *) ;; esac - done - for flag in $xml2_libs - do + done + for flag in $xml2_libs + do case $flag in -l*) # The first library listed is assumed to be the @@ -27434,8 +27809,7 @@ fi *) ;; esac - done - fi + done if test "x$LIB_XML2_BASE" = "x" then LIB_XML2_BASE=xml2 @@ -27593,13 +27967,13 @@ $as_echo_n "checking if XML package is complete ... " >&6; } then if test $failed -gt 0 then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } have_xml='no (failed tests)' LDFLAGS="$OLD_LDFLAGS" CPPFLAGS="$OLD_CPPFLAGS" else - LIB_XML="-l$LIB_XML2_BASE" + LIB_XML="-l$LIB_XML2_BASE" # Add lib to LIBS if not already present for test_lib in $LIB_XML $LIB_XML_DEPS do @@ -27620,7 +27994,7 @@ $as_echo "no -- some components failed test" >&6; } $as_echo "#define HasXML 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_xml='yes' fi @@ -27723,7 +28097,7 @@ $as_echo "#define HasWMFlite 1" >>confdefs.h LIBS="$LIB_WMF $LIBS" have_wmf='yes' else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- some components failed test" >&5 $as_echo "no -- some components failed test" >&6; } have_wmf='no (failed tests)' have_wmflite='no (failed tests)' @@ -29369,7 +29743,7 @@ if test "$with_perl" != 'no' then if test "$with_perl" != 'yes' then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl" >&5 $as_echo_n "checking for perl... " >&6; } if ${ac_cv_path_PERL+:} false; then : $as_echo_n "(cached) " >&6 @@ -29378,10 +29752,10 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_PERL" >&5 $as_echo "$ac_cv_path_PERL" >&6; }; - PERL=$ac_cv_path_PERL - have_perl="$ac_cv_path_PERL" + PERL=$ac_cv_path_PERL + have_perl="$ac_cv_path_PERL" else - for ac_prog in perl perl5 + for ac_prog in perl perl5 do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -29425,9 +29799,9 @@ fi test -n "$PERL" && break done - if test "$ac_cv_path_PERL" + if test "$ac_cv_path_PERL" then - have_perl="$ac_cv_path_PERL" + have_perl="$ac_cv_path_PERL" fi fi fi @@ -29712,13 +30086,16 @@ fi # The build_modules variable is set to 'yes' if coders and filters are # to be built as modules. This requires libltdl ($LIB_LTDL). +# Removed $LIB_OMP and $LIB_THREAD if test "$build_modules" != 'no' then - MAGICK_DEP_LIBS="$LIBS_USER $LIB_LCMS $LIB_TTF $LIB_GS $LIB_XEXT $LIB_IPC $LIB_X11 $LIB_LZMA $LIB_BZLIB $LIB_ZLIB $LIB_LTDL $LIB_TRIO $LIB_GDI32 $LIB_MATH $LIB_OMP $LIB_UMEM $LIB_THREAD" + MAGICK_DEP_LIBS="$LIBS_USER $LIB_LCMS $LIB_TTF $LIB_GS $LIB_XEXT $LIB_IPC $LIB_X11 $LIB_LZMA $LIB_BZLIB $LIB_ZLIB $LIB_LTDL $LIB_TRIO $LIB_GDI32 $LIB_MATH $LIB_UMEM $LIB_THREAD" else - MAGICK_DEP_LIBS="$LIBS_USER $LIB_JBIG $LIB_WEBP $LIB_LCMS $LIB_TIFF $LIB_TTF $LIB_JP2 $LIB_JPEG $LIB_GS $LIB_PNG $LIB_FPX $LIB_WMF $LIB_DPS $LIB_XEXT $LIB_IPC $LIB_X11 $LIB_LZMA $LIB_BZLIB $LIB_XML $LIB_ZLIB $LIB_TRIO $LIB_GDI32 $LIB_MATH $LIB_OMP $LIB_UMEM $LIB_THREAD" + MAGICK_DEP_LIBS="$LIBS_USER $LIB_JBIG $LIB_WEBP $LIB_LCMS $LIB_TIFF $LIB_TTF $LIB_JP2 $LIB_JPEG $LIB_GS $LIB_PNG $LIB_FPX $LIB_WMF $LIB_DPS $LIB_XEXT $LIB_IPC $LIB_X11 $LIB_LZMA $LIB_BZLIB $LIB_XML $LIB_ZLIB $LIB_ZSTD $LIB_TRIO $LIB_GDI32 $LIB_MATH $LIB_UMEM $LIB_THREAD" fi +MAGICK_EXTRA_DEP_LIBS="$LIB_OMP" # Extra libraries typically added due to CFLAGS + # @@ -29736,13 +30113,14 @@ CXXFLAGS=`echo $CXXFLAGS | sed -e 's/ */ /g'` LDFLAGS=`echo $LDFLAGS | sed -e 's/ */ /g'` TESTED_LIBS=`echo $LIBS | sed -e 's/ */ /g'` MAGICK_DEP_LIBS=`echo $MAGICK_DEP_LIBS | sed -e 's/ */ /g'` +MAGICK_EXTRA_DEP_LIBS=`echo $MAGICK_EXTRA_DEP_LIBS | sed -e 's/ */ /g'` #LIBS=`echo $LIBS | sed -e 's/ */ /g'` MAGICK_API_CFLAGS=$CFLAGS MAGICK_API_CPPFLAGS=`echo $MAGICK_API_CPPFLAGS | sed -e 's/ */ /g'` MAGICK_API_LDFLAGS="-L$LIB_DIR $LDFLAGS" MAGICK_API_DEP_LIBS="$MAGICK_DEP_LIBS" -MAGICK_API_LIBS="-lGraphicsMagick $MAGICK_API_DEP_LIBS" +MAGICK_API_LIBS="-lGraphicsMagick $MAGICK_API_DEP_LIBS $MAGICK_EXTRA_DEP_LIBS" MAGICK_API_DEP_LIBS=`echo $MAGICK_API_DEP_LIBS | sed -e 's/ */ /g'` MAGICK_API_LIBS=`echo $MAGICK_API_LIBS | sed -e 's/ */ /g'` @@ -30030,6 +30408,10 @@ if test -z "${HasLZMA_TRUE}" && test -z "${HasLZMA_FALSE}"; then as_fn_error $? "conditional \"HasLZMA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${HasZSTD_TRUE}" && test -z "${HasZSTD_FALSE}"; then + as_fn_error $? "conditional \"HasZSTD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${HasX11_TRUE}" && test -z "${HasX11_FALSE}"; then as_fn_error $? "conditional \"HasX11\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -30058,10 +30440,6 @@ if test -z "${HasJP2_TRUE}" && test -z "${HasJP2_FALSE}"; then as_fn_error $? "conditional \"HasJP2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HasGS_TRUE}" && test -z "${HasGS_FALSE}"; then - as_fn_error $? "conditional \"HasGS\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${HasTTF_TRUE}" && test -z "${HasTTF_FALSE}"; then as_fn_error $? "conditional \"HasTTF\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -32575,82 +32953,81 @@ fi rm -f magick-version -echo "" - -echo "GraphicsMagick is configured as follows. Please verify that this" -echo "configuration matches your expectations." -echo "" -echo "Host system type : $host" -echo "Build system type : $build" -echo "" -echo "Option Configure option Configured value" -echo "-----------------------------------------------------------------" -echo "Shared libraries --enable-shared=$enable_shared $libtool_build_shared_libs" -echo "Static libraries --enable-static=$enable_static $libtool_build_static_libs" -echo "GNU ld --with-gnu-ld=$with_gnu_ld $lt_cv_prog_gnu_ld" -echo "Quantum depth --with-quantum-depth=$with_quantum_depth $with_quantum_depth" -echo "Modules --with-modules=$with_modules $build_modules" -echo "" -echo "Delegate Configuration:" -echo "BZLIB --with-bzlib=$with_bzlib $have_bzlib" -echo "DPS --with-dps=$with_dps $have_dps" -echo "FlashPIX --with-fpx=$with_fpx $have_fpx" -echo "FreeType 2.0 --with-ttf=$with_ttf $have_ttf" -echo "Ghostscript None $PSDelegate ($GSVersion)" +printf "\n" + +printf "GraphicsMagick is configured as follows. Please verify that this\n" +printf "configuration matches your expectations.\n" +printf "\n" +printf "Host system type : $host\n" +printf "Build system type : $build\n" +printf "\n" +printf "Option Configure option \tConfigured value\n" +printf -- "-----------------------------------------------------------------\n" +printf "Shared libraries --enable-shared=$enable_shared\t\t$libtool_build_shared_libs\n" +printf "Static libraries --enable-static=$enable_static\t\t$libtool_build_static_libs\n" +printf "GNU ld --with-gnu-ld=$with_gnu_ld \t\t$lt_cv_prog_gnu_ld\n" +printf "Quantum depth --with-quantum-depth=$with_quantum_depth\t$with_quantum_depth\n" +printf "Modules --with-modules=$with_modules \t\t$build_modules\n" +printf "\n" +printf "Delegate Configuration:\n" +printf "BZLIB --with-bzlib=$with_bzlib \t$have_bzlib\n" +printf "DPS --with-dps=$with_dps \t$have_dps\n" +printf "FlashPIX --with-fpx=$with_fpx \t$have_fpx\n" +printf "FreeType 2.0 --with-ttf=$with_ttf \t$have_ttf\n" +printf "Ghostscript None \t$PSDelegate ($GSVersion)\n" result_ghostscript_font_dir='none' if test "${ghostscript_font_dir}x" != 'x' then result_ghostscript_font_dir="$ghostscript_font_dir" fi -echo "Ghostscript fonts --with-gs-font-dir=$with_gs_font_dir $result_ghostscript_font_dir" -echo "Ghostscript lib --with-gslib=$with_gslib $have_gslib" -echo "JBIG --with-jbig=$with_jbig $have_jbig" -echo "JPEG v1 --with-jpeg=$with_jpeg $have_jpeg" -echo "JPEG-2000 --with-jp2=$with_jp2 $have_jp2" -echo "LCMS v2 --with-lcms2=$with_lcms2 $have_lcms2" -# echo "MPEG v2 --with-mpeg2=$with_mpeg2 $have_mpeg2" -echo "LZMA --with-lzma=$with_lzma $have_lzma" -echo "Magick++ --with-magick-plus-plus=$with_magick_plus_plus $have_magick_plus_plus" -echo "PERL --with-perl=$with_perl $have_perl" +printf "Ghostscript fonts --with-gs-font-dir=$with_gs_font_dir\t$result_ghostscript_font_dir\n" +printf "JBIG --with-jbig=$with_jbig \t$have_jbig\n" +printf "JPEG v1 --with-jpeg=$with_jpeg \t$have_jpeg\n" +printf "JPEG-2000 --with-jp2=$with_jp2 \t$have_jp2\n" +printf "LCMS v2 --with-lcms2=$with_lcms2 \t$have_lcms2\n" +# printf "MPEG v2 --with-mpeg2=$with_mpeg2 \t$have_mpeg2\n" +printf "LZMA --with-lzma=$with_lzma \t$have_lzma\n" +printf "Magick++ --with-magick-plus-plus=$with_magick_plus_plus\t$have_magick_plus_plus\n" +printf "PERL --with-perl=$with_perl \t$have_perl\n" if test "${LIB_PNG}x" != 'x' then -echo "PNG --with-png=$with_png $have_png ($LIB_PNG)" +printf "PNG --with-png=$with_png \t$have_png ($LIB_PNG)\n" else -echo "PNG --with-png=$with_png $have_png" +printf "PNG --with-png=$with_png \t$have_png\n" fi -echo "TIFF --with-tiff=$with_tiff $have_tiff" -echo "TRIO --with-trio=$with_trio $have_trio" -echo "WEBP --with-webp=$with_webp $have_webp" +printf "TIFF --with-tiff=$with_tiff \t$have_tiff\n" +printf "TRIO --with-trio=$with_trio \t$have_trio\n" +printf "WEBP --with-webp=$with_webp \t$have_webp\n" result_windows_font_dir='none' if test "${windows_font_dir}x" != 'x' then result_windows_font_dir="${windows_font_dir}" fi -echo "Windows fonts --with-windows-font-dir=$with_windows_font_dir $result_windows_font_dir" -echo "WMF --with-wmf=$with_wmf $have_wmf" -echo "X11 --with-x=$with_x $have_x" -echo "XML --with-xml=$with_xml $have_xml" -echo "ZLIB --with-zlib=$with_zlib $have_zlib" -echo "" -echo "X11 Configuration:" +printf "Windows fonts --with-windows-font-dir=$with_windows_font_dir\t$result_windows_font_dir\n" +printf "WMF --with-wmf=$with_wmf \t$have_wmf\n" +printf "X11 --with-x=$with_x \t$have_x\n" +printf "XML --with-xml=$with_xml \t$have_xml\n" +printf "ZLIB --with-zlib=$with_zlib \t$have_zlib\n" +printf "\n" +printf "X11 Configuration:\n" if test "$have_x" != 'no' then - echo " X_CFLAGS = $X_CFLAGS" - echo " X_PRE_LIBS = $X_PRE_LIBS" - echo " X_LIBS = $X_LIBS" - echo " X_EXTRA_LIBS = $X_EXTRA_LIBS" -else - echo "" - echo " Not using X11." -fi -echo "" -echo "Options used to compile and link:" -echo " CC = $CC" -echo " CFLAGS = $CFLAGS" -echo " CPPFLAGS = $CPPFLAGS" -echo " CXX = $CXX" -echo " CXXFLAGS = $CXXFLAGS" -echo " DEFS = $DEFS" -echo " LDFLAGS = $LDFLAGS" -echo " LIBS = $MAGICK_API_DEP_LIBS" -echo "" + printf " X_CFLAGS = $X_CFLAGS\n" + printf " X_PRE_LIBS = $X_PRE_LIBS\n" + printf " X_LIBS = $X_LIBS\n" + printf " X_EXTRA_LIBS = $X_EXTRA_LIBS\n" +else + printf "\n" + printf " Not using X11.\n" +fi +printf "\n" +printf "Options used to compile and link:\n" +printf " CC = $CC\n" +printf " CFLAGS = $CFLAGS\n" +printf " CPPFLAGS = $CPPFLAGS\n" +printf " CXX = $CXX\n" +printf " CXXFLAGS = $CXXFLAGS\n" +printf " DEFS = $DEFS\n" +printf " LDFLAGS = $LDFLAGS\n" +printf " LIBS = $MAGICK_API_DEP_LIBS\n" +printf "\n" diff --git a/configure.ac b/configure.ac index 4bb086c..77d042c 100755 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -# Copyright (C) 2003-2016 GraphicsMagick Group +# Copyright (C) 2003-2018 GraphicsMagick Group # Copyright (C) 2002 ImageMagick Studio # Copyright (C) 1998, 1999 E. I. du Pont de Nemours and Company # @@ -10,7 +10,7 @@ # # Written by Bob Friesenhahn # - + AC_PREREQ(2.69) AC_INIT(magick/magick.h) @@ -302,10 +302,10 @@ fi # # Enable support for POSIX thread APIs AC_ARG_WITH(threads, - AS_HELP_STRING([--without-threads], + AS_HELP_STRING([--without-threads], [disable POSIX threads API support]), - [with_threads=$withval], - [with_threads='yes']) + [with_threads=$withval], + [with_threads='yes']) have_threads=no if test "$with_threads" != 'no' @@ -347,11 +347,11 @@ AC_SUBST(OPENMP_CFLAGS) # Allow the user to disable use of OpenMP where algorithms sometimes run slower. AC_ARG_ENABLE(openmp-slow, - AS_HELP_STRING([--enable-openmp-slow], + AS_HELP_STRING([--enable-openmp-slow], [enable OpenMP for algorithms which sometimes run slower]), - [with_openmp_slow=$enableval], - [with_openmp_slow='no']) + [with_openmp_slow=$enableval], + [with_openmp_slow='no']) if test "$with_openmp_slow" = 'no' then AC_DEFINE(DisableSlowOpenMP,1,[Disable OpenMP for algorithms which sometimes run slower]) @@ -365,7 +365,7 @@ fi # remaps standard functions to their 64-bit equivalents. # # The LFS_CPPFLAGS substition is used to support building PerlMagick. -# +# # ######## AC_SYS_LARGEFILE @@ -393,6 +393,19 @@ fi AC_SUBST(LFS_CPPFLAGS) # +# Decide if setjmp/longjmp is thread safe based on host OS +# +case "${host_os}" in + solaris2* ) + # Documented not to be MT safe + + ;; + *) + AC_DEFINE(SETJMP_IS_THREAD_SAFE,1,[Setjmp/longjmp are thread safe]) + ;; +esac + +# # Configure libtool # @@ -423,11 +436,11 @@ AM_CONDITIONAL(WITH_SHARED_LIBS, test "${libtool_build_shared_libs}" = 'yes') # build_modules='no' AC_ARG_WITH(modules, - AS_HELP_STRING([--with-modules], + AS_HELP_STRING([--with-modules], [enable building dynamically loadable modules]), - [with_modules=$withval], - [with_modules='no']) + [with_modules=$withval], + [with_modules='no']) # Only allow building loadable modules if we are building shared libraries if test "$with_modules" != 'no' ; then @@ -447,10 +460,10 @@ AM_CONDITIONAL(WITH_MODULES, test "$build_modules" != 'no') # Build a version of GraphicsMagick which operates uninstalled. # Used to build distributions located via MAGICK_HOME / executable path AC_ARG_ENABLE(installed, - AS_HELP_STRING([--disable-installed], + AS_HELP_STRING([--disable-installed], [disable building an installed GraphicsMagick]), - [with_installed=$enableval], - [with_installed='yes']) + [with_installed=$enableval], + [with_installed='yes']) if test "$with_installed" = 'yes' then AC_DEFINE(UseInstalledMagick,1,[GraphicsMagick is formally installed under prefix]) @@ -461,10 +474,10 @@ fi # Enable broken/dangerous coders # EnableBrokenCoders CPP define and ENABLE_BROKEN_CODERS Automake conditional) AC_ARG_ENABLE(broken-coders, - AS_HELP_STRING([--enable-broken-coders], + AS_HELP_STRING([--enable-broken-coders], [enable broken/dangerous file formats support]), - [with_broken_coders=$enableval], - [with_broken_coders='no']) + [with_broken_coders=$enableval], + [with_broken_coders='no']) if test "$with_broken_coders" = 'yes' then AC_DEFINE(EnableBrokenCoders,1,[Enable broken/dangerous file formats support]) @@ -478,24 +491,24 @@ AM_MAINTAINER_MODE # Enable prof-based profiling support AC_ARG_ENABLE(prof, - AS_HELP_STRING([--enable-prof], + AS_HELP_STRING([--enable-prof], [enable 'prof' profiling support]), - [with_prof=$enableval], - [with_prof='no']) + [with_prof=$enableval], + [with_prof='no']) # Enable gprof-based profiling support AC_ARG_ENABLE(gprof, - AS_HELP_STRING([--enable-gprof], + AS_HELP_STRING([--enable-gprof], [enable 'gprof' profiling support]), - [with_gprof=$enableval], - [with_gprof='no']) + [with_gprof=$enableval], + [with_gprof='no']) # Enable gcov-based profiling support AC_ARG_ENABLE(gcov, - AS_HELP_STRING([--enable-gcov], + AS_HELP_STRING([--enable-gcov], [enable 'gcov' profiling support]), - [with_gcov=$enableval], - [with_gcov='no']) + [with_gcov=$enableval], + [with_gcov='no']) with_profiling='no' if test "$with_prof" = 'yes' || test "$with_gprof" = 'yes' || test "$with_gcov" = 'yes' @@ -510,10 +523,10 @@ fi # Enable prefixing library symbols with a common string AC_ARG_ENABLE(symbol-prefix, - AS_HELP_STRING([--enable-symbol-prefix], + AS_HELP_STRING([--enable-symbol-prefix], [enable prefixing library symbols with "Gm"]), - [with_symbol_prefix=$enableval], - [with_symbol_prefix='no']) + [with_symbol_prefix=$enableval], + [with_symbol_prefix='no']) if test "$with_symbol_prefix" != 'no' then AC_DEFINE(PREFIX_MAGICK_SYMBOLS,1,[Prefix Magick library symbols with a common string.]) @@ -530,10 +543,10 @@ AM_CONDITIONAL(MAGICK_COMPAT, test "$with_magick_compat" != 'no') # Number of bits in a Quantum AC_ARG_WITH(quantum-depth, - AS_HELP_STRING([--with-quantum-depth], + AS_HELP_STRING([--with-quantum-depth], [number of bits in a pixel quantum (default 8)]), - [with_quantum_depth=$withval], - [with_quantum_depth=8]) + [with_quantum_depth=$withval], + [with_quantum_depth=8]) if test "$with_quantum_depth" != '8' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-quantum-depth=$with_quantum_depth " fi @@ -574,17 +587,17 @@ AC_ARG_WITH(frozenpaths, # Enable build/install of Magick++ AC_ARG_WITH(magick-plus-plus, - AS_HELP_STRING([--without-magick-plus-plus], + AS_HELP_STRING([--without-magick-plus-plus], [disable build/install of Magick++]), - [with_magick_plus_plus=$withval], - [with_magick_plus_plus='yes']) + [with_magick_plus_plus=$withval], + [with_magick_plus_plus='yes']) # Enable build/install of PerlMagick. AC_ARG_WITH(perl, - AS_HELP_STRING([--with-perl@<:@=PERL@:>@], + AS_HELP_STRING([--with-perl@<:@=PERL@:>@], [enable build/install of PerlMagick and optionally specify perl to use]), - [with_perl=$withval], - [with_perl='no']) + [with_perl=$withval], + [with_perl='no']) # Options to pass when configuring PerlMagick AC_ARG_WITH(perl-options, @@ -597,50 +610,40 @@ AC_SUBST(PERL_MAKE_OPTIONS) # Disable BZLIB (bzip2 library) AC_ARG_WITH(bzlib, - AS_HELP_STRING([--without-bzlib], + AS_HELP_STRING([--without-bzlib], [disable BZLIB support]), - [with_bzlib=$withval], - [with_bzlib='yes']) + [with_bzlib=$withval], + [with_bzlib='yes']) if test "$with_bzlib" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-bzlib=$with_bzlib " fi # Disable Display Postscript. AC_ARG_WITH(dps, - AS_HELP_STRING([--without-dps], + AS_HELP_STRING([--without-dps], [disable Display Postscript support]), - [with_dps=$withval], - [with_dps='yes']) + [with_dps=$withval], + [with_dps='yes']) if test "$with_dps" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-dps=$with_dps " fi # Enable FlashPIX. AC_ARG_WITH(fpx, - AS_HELP_STRING([--with-fpx], + AS_HELP_STRING([--with-fpx], [enable FlashPIX support]), - [with_fpx=$withval], - [with_fpx='no']) + [with_fpx=$withval], + [with_fpx='no']) if test "$with_fpx" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-fpx=$with_fpx " fi -# Enable Ghostscript library support. -AC_ARG_WITH(gslib, - AS_HELP_STRING([--with-gslib], - [enable Ghostscript library support (not recommended)]), - [with_gslib=$withval], - [with_gslib='no']) -if test "$with_gslib" != 'yes' ; then - DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-gslib=$with_gslib " -fi - # Disable JBIG. AC_ARG_WITH(jbig, - AS_HELP_STRING([--without-jbig], + AS_HELP_STRING([--without-jbig], [disable JBIG support]), - [with_jbig=$withval], - [with_jbig='yes']) + [with_jbig=$withval], + [with_jbig='yes']) if test "$with_jbig" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-jbig=$with_jbig " fi @@ -657,87 +660,87 @@ fi # Disable JPEG. AC_ARG_WITH(jpeg, - AS_HELP_STRING([--without-jpeg], + AS_HELP_STRING([--without-jpeg], [disable JPEG support]), - [with_jpeg=$withval], - [with_jpeg='yes']) + [with_jpeg=$withval], + [with_jpeg='yes']) if test "$with_jpeg" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-jpeg=$with_jpeg " fi # Disable JPEG Version 2. AC_ARG_WITH(jp2, - AS_HELP_STRING([--without-jp2], + AS_HELP_STRING([--without-jp2], [disable JPEG v2 support]), - [with_jp2=$withval], - [with_jp2='yes']) + [with_jp2=$withval], + [with_jp2='yes']) if test "$with_jp2" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-jp2=$with_jp2 " fi # Disable LCMS2. AC_ARG_WITH(lcms2, - AS_HELP_STRING([--without-lcms2], + AS_HELP_STRING([--without-lcms2], [disable lcms (v2.X) support]), - [with_lcms2=$withval], - [with_lcms2='yes']) + [with_lcms2=$withval], + [with_lcms2='yes']) if test "$with_lcms2" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-lcms2=$with_lcms2 " fi # Disable LZMA (lzma library) AC_ARG_WITH(lzma, - AS_HELP_STRING([--without-lzma], + AS_HELP_STRING([--without-lzma], [disable LZMA support]), - [with_lzma=$withval], - [with_lzma='yes']) + [with_lzma=$withval], + [with_lzma='yes']) if test "$with_lzma" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-lzma=$with_lzma " fi # # Disable MPEG. # AC_ARG_WITH(mpeg2, -# AS_HELP_STRING([--without-mpeg2], +# AS_HELP_STRING([--without-mpeg2], # [disable MPEG support]), -# [with_mpeg2=$withval], -# [with_mpeg2='yes']) +# [with_mpeg2=$withval], +# [with_mpeg2='yes']) # Disable PNG. AC_ARG_WITH(png, - AS_HELP_STRING([--without-png], + AS_HELP_STRING([--without-png], [disable PNG support]), - [with_png=$withval], - [with_png='yes']) + [with_png=$withval], + [with_png='yes']) if test "$with_png" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-png=$with_png " fi # Disable TIFF. AC_ARG_WITH(tiff, - AS_HELP_STRING([--without-tiff], + AS_HELP_STRING([--without-tiff], [disable TIFF support]), - [with_tiff=$withval], - [with_tiff='yes']) + [with_tiff=$withval], + [with_tiff='yes']) if test "$with_tiff" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-tiff=$with_tiff " fi # Disable TRIO. AC_ARG_WITH(trio, - AS_HELP_STRING([--without-trio], + AS_HELP_STRING([--without-trio], [disable TRIO support]), - [with_trio=$withval], - [with_trio='yes']) + [with_trio=$withval], + [with_trio='yes']) if test "$with_trio" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-trio=$with_trio " fi # Disable TTF. AC_ARG_WITH(ttf, - AS_HELP_STRING([--without-ttf], + AS_HELP_STRING([--without-ttf], [disable TrueType support]), - [with_ttf=$withval], - [with_ttf='yes']) + [with_ttf=$withval], + [with_ttf='yes']) if test "$with_ttf" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-ttf=$with_ttf " fi @@ -746,20 +749,20 @@ fi # Available as a SourceForge project http://sourceforge.net/projects/umem/ or # https://labs.omniti.com/trac/portableumem/. AC_ARG_WITH(umem, - AS_HELP_STRING([--with-umem], + AS_HELP_STRING([--with-umem], [enable umem memory allocation library support]), - [with_umem=$withval], - [with_umem='no']) + [with_umem=$withval], + [with_umem='no']) if test "$with_umem" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-umem=$with_umem " fi # Disable WMF. AC_ARG_WITH(wmf, - AS_HELP_STRING([--without-wmf], + AS_HELP_STRING([--without-wmf], [disable WMF support]), - [with_wmf=$withval], - [with_wmf='yes']) + [with_wmf=$withval], + [with_wmf='yes']) if test "$with_wmf" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-wmf=$with_wmf " fi @@ -782,30 +785,30 @@ fi # Set Ghostscript font directory AC_ARG_WITH(gs-font-dir, - AS_HELP_STRING([--with-gs-font-dir=DIR], + AS_HELP_STRING([--with-gs-font-dir=DIR], [directory containing Ghostscript fonts]), - [with_gs_font_dir=$withval], - [with_gs_font_dir='default']) + [with_gs_font_dir=$withval], + [with_gs_font_dir='default']) if test "$with_gs_font_dir" != 'default' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-gs-font-dir=$with_gs_font_dir " fi # Set Windows font directory AC_ARG_WITH(windows-font-dir, - AS_HELP_STRING([--with-windows-font-dir=DIR], + AS_HELP_STRING([--with-windows-font-dir=DIR], [directory containing MS-Windows fonts]), - [with_windows_font_dir=$withval], - [with_windows_font_dir='']) + [with_windows_font_dir=$withval], + [with_windows_font_dir='']) if test "$with_windows_font_dir" != '' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-windows-font-dir=$with_windows_font_dir " fi # Disable XML. AC_ARG_WITH(xml, - AS_HELP_STRING([--without-xml], + AS_HELP_STRING([--without-xml], [disable XML support]), - [with_xml=$withval], - [with_xml='yes']) + [with_xml=$withval], + [with_xml='yes']) if test "$with_xml" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-xml=$with_xml " fi @@ -813,12 +816,22 @@ fi AC_ARG_WITH(zlib, AS_HELP_STRING([--without-zlib], [disable ZLIB support]), - [with_zlib=$withval], - [with_zlib='yes']) + [with_zlib=$withval], + [with_zlib='yes']) if test "$with_zlib" != 'yes' ; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-zlib=$with_zlib " fi +# Disable Zstd (zstd library) +AC_ARG_WITH(zstd, + AS_HELP_STRING([--without-zstd], + [disable Zstd support]), + [with_zstd=$withval], + [with_zstd='yes']) +if test "$with_zstd" != 'yes' ; then + DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-zstd=$with_zstd " +fi + # # Specify path to shared libstdc++ if not in normal location # @@ -842,7 +855,7 @@ AC_PROG_GCC_TRADITIONAL ######## # These options are set for multi-thread DLL module build # libMagick: _DLL _MAGICKMOD_ _MAGICKLIB_ -# module: _DLL +# module: _DLL # executable/Magick++: _DLL _MAGICKMOD_ MODULE_EXTRA_CPPFLAGS='' LIBRARY_EXTRA_CPPFLAGS='' @@ -882,7 +895,7 @@ AC_SUBST(LIBRARY_EXTRA_CPPFLAGS) AC_HEADER_STDC AC_HEADER_DIRENT -# Check additional headers +# Check additional headers AC_CHECK_HEADERS([machine/param.h mach-o/dyld.h process.h sun_prefetch.h sys/mman.h sys/resource.h sys/times.h sys/types.h]) AC_CHECK_HEADERS([wincrypt.h],[],[],[#include ]) @@ -1325,7 +1338,7 @@ AC_CACHE_CHECK(for X11 configure files,gm_cv_x_configure, [# Look for the header file in a standard set of common directories. # Check X11 before X11Rn because it is often a symlink to the current release. for ac_dir in \ - /lib/usr/lib/X11 \ + /lib/usr/lib/X11 \ /usr/X11/lib \ /usr/X11R4/lib \ /usr/X11R5/lib \ @@ -1362,9 +1375,9 @@ AC_CACHE_CHECK(for X11 configure files,gm_cv_x_configure, if test -f "$ac_dir/X11/rgb.txt" then gm_cv_x_configure="$ac_dir/X11/" - break + break elif test -f "$ac_dir/rgb.txt" - then + then gm_cv_x_configure="$ac_dir/" break fi @@ -1566,8 +1579,10 @@ if test "$with_zlib" != 'no' || test "$with_png" != 'no' then AC_MSG_CHECKING(for ZLIB support ) AC_MSG_RESULT() + failed=0 passed=0 + # PKG_CHECK_MODULES([ZLIB], [zlib], [], []) AC_CHECK_HEADER(zconf.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) AC_CHECK_HEADER(zlib.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) AC_CHECK_LIB(z,compress,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) @@ -1659,6 +1674,7 @@ if test "$with_lzma" != 'no' then AC_MSG_CHECKING(for LZMA support ) AC_MSG_RESULT() + # PKG_CHECK_MODULES([LZMA], [liblzma], [], []) failed=0 passed=0 AC_CHECK_HEADER(lzma.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) @@ -1685,6 +1701,41 @@ AM_CONDITIONAL(HasLZMA, test "$have_lzma" = 'yes') AC_SUBST(LIB_LZMA) # +# Check for Zstd +# +have_zstd='no' +LIB_ZSTD='' +if test "$with_zstd" != 'no' +then + AC_MSG_CHECKING(for Zstd support ) + AC_MSG_RESULT() + failed=0 + passed=0 + # PKG_CHECK_MODULES([ZSTD], [libzstd], [], []) + AC_CHECK_HEADER(zstd.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) + AC_CHECK_LIB(zstd,ZSTD_createDStream,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + AC_MSG_CHECKING(if Zstd package is complete) + if test $passed -gt 0 + then + if test $failed -gt 0 + then + AC_MSG_RESULT(no -- some components failed test) + have_zstd='no (failed tests)' + else + LIB_ZSTD='-lzstd' + LIBS="$LIB_ZSTD $LIBS" + AC_DEFINE(HasZSTD,1,Define if you have zstd compression library) + AC_MSG_RESULT(yes) + have_zstd='yes' + fi + else + AC_MSG_RESULT(no) + fi +fi +AM_CONDITIONAL(HasZSTD, test "$have_zstd" = 'yes') +AC_SUBST(LIB_ZSTD) + +# # Find the X11 include and library directories. # LIB_X11='' @@ -1787,15 +1838,15 @@ then then if test $failed -gt 0 then - AC_MSG_RESULT([no -- some components failed test]) + AC_MSG_RESULT([no -- some components failed test]) have_dps='no (failed tests)' - CPPFLAGS="$O_CPPFLAGS" + CPPFLAGS="$O_CPPFLAGS" else - LIB_DPS="-ldpstk -ldps ${LIBDPS_XT}" - LIBS="$LIB_DPS $LIBS" - AC_DEFINE(HasDPS,1,Define if you have Display Postscript) - AC_MSG_RESULT(yes) - have_dps='yes' + LIB_DPS="-ldpstk -ldps ${LIBDPS_XT}" + LIBS="$LIB_DPS $LIBS" + AC_DEFINE(HasDPS,1,Define if you have Display Postscript) + AC_MSG_RESULT(yes) + have_dps='yes' fi else AC_MSG_RESULT(no) @@ -1825,13 +1876,13 @@ then then if test $failed -gt 0 then - AC_MSG_RESULT(no -- some components failed test) - have_fpx='no (failed tests)' + AC_MSG_RESULT(no -- some components failed test) + have_fpx='no (failed tests)' else - LIB_FPX='-lfpx' - # LIBS="$LIB_FPX $LIBS" - AC_DEFINE(HasFPX,1,Define if you have FlashPIX library) - AC_MSG_RESULT(yes) + LIB_FPX='-lfpx' + # LIBS="$LIB_FPX $LIBS" + AC_DEFINE(HasFPX,1,Define if you have FlashPIX library) + AC_MSG_RESULT(yes) have_fpx='yes' PERLMAINCC="$CXX" fi @@ -1855,6 +1906,8 @@ then passed=0 have_lcms_header='no' + # PKG_CHECK_MODULES([LCMS2], [lcms2], [], []) + # Check for AC_CHECK_HEADER(lcms2.h,have_lcms_header='yes',,) if test "$have_lcms_header" = 'yes' @@ -1920,12 +1973,13 @@ then [disable PNG support])], [with_png=$withval], [with_png='yes']) - + # PKG_CHECK_MODULES([PNG], [libpng], [], []) + if test "$with_png" != 'yes'; then DISTCHECK_CONFIG_FLAGS="${DISTCHECK_CONFIG_FLAGS} --with-png=$with_png " fi - - + + if test "$with_png" != 'no' ; then AC_MSG_CHECKING(for PNG support ) AC_MSG_RESULT() @@ -1933,7 +1987,7 @@ then passed=0 AC_CHECK_HEADER(png.h,passed=`expr $passed + 1`, failed=`expr $failed + 1`,) - + if test $passed -gt 0; then for var in 7 6 5 4 2 '' ; do if test "x${var}" = 'x' ; then @@ -1942,9 +1996,9 @@ then pnglib="png1${var}" fi if test "$have_png" = 'no' - then - - # Test for compatible LIBPNG library + then + + # Test for compatible LIBPNG library failed=0 passed=0 if test "$with_png" = 'yes' -o "$with_png" = "libpng1${var}" ; then @@ -1978,7 +2032,7 @@ return 0; AC_MSG_RESULT(yes) fi fi - + if test $passed -gt 0 -a $failed -le 0 then if test "1${var}" = '15' ; then @@ -2005,14 +2059,14 @@ return 0; AC_MSG_CHECKING(if ${pnglib} package is complete) if test $passed -gt 0 ; then if test $failed -gt 0 ; then - AC_MSG_RESULT(no -- some components failed test) - have_png='no (failed tests)' + AC_MSG_RESULT(no -- some components failed test) + have_png='no (failed tests)' else - LIB_PNG="-l${pnglib}" - LIBS="$LIB_PNG $LIBS" - AC_DEFINE(HasPNG,1,Define if you have PNG library) - AC_MSG_RESULT(yes) - have_png='yes' + LIB_PNG="-l${pnglib}" + LIBS="$LIB_PNG $LIBS" + AC_DEFINE(HasPNG,1,Define if you have PNG library) + AC_MSG_RESULT(yes) + have_png='yes' fi fi fi @@ -2038,6 +2092,9 @@ then AC_MSG_RESULT() failed=0 passed=0 + + # PKG_CHECK_MODULES([JPEG], [libturbojpeg, libjpeg], [], []) + AC_CHECK_HEADER(jconfig.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) AC_CHECK_HEADER(jerror.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) AC_CHECK_HEADER(jmorecfg.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) @@ -2074,13 +2131,13 @@ fi then if test $failed -gt 0 then - AC_MSG_RESULT(no -- some components failed test) + AC_MSG_RESULT(no -- some components failed test) have_jpeg='no (failed tests)' else - LIB_JPEG='-ljpeg' - LIBS="$LIB_JPEG $LIBS" - AC_DEFINE(HasJPEG,1,Define if you have JPEG library) - AC_MSG_RESULT(yes) + LIB_JPEG='-ljpeg' + LIBS="$LIB_JPEG $LIBS" + AC_DEFINE(HasJPEG,1,Define if you have JPEG library) + AC_MSG_RESULT(yes) have_jpeg='yes' fi else @@ -2108,14 +2165,14 @@ then then if test $failed -gt 0 then - AC_MSG_RESULT(no -- some components failed test) - have_jp2='no (failed tests)' + AC_MSG_RESULT(no -- some components failed test) + have_jp2='no (failed tests)' else - LIB_JP2='-ljasper' - LIBS="$LIB_JP2 $LIBS" - AC_DEFINE(HasJP2,1,Define if you have JPEG version 2 "Jasper" library) - AC_MSG_RESULT(yes) - have_jp2='yes' + LIB_JP2='-ljasper' + LIBS="$LIB_JP2 $LIBS" + AC_DEFINE(HasJP2,1,Define if you have JPEG version 2 "Jasper" library) + AC_MSG_RESULT(yes) + have_jp2='yes' fi else AC_MSG_RESULT(no) @@ -2124,41 +2181,6 @@ fi AM_CONDITIONAL(HasJP2, test "$have_jp2" = 'yes') AC_SUBST(LIB_JP2) -# -# Check for Ghostscript library -# -# Test for iapi.h & test for gsapi_new_instance in -lgs -have_gslib='no' -LIB_GS='' -if test "$with_gslib" != 'no' -then - AC_MSG_CHECKING(for Ghostscript library support ) - AC_MSG_RESULT() - failed=0 - passed=0 - AC_CHECK_HEADER(ghostscript/iapi.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) - AC_CHECK_LIB(gs,gsapi_new_instance,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) - AC_MSG_CHECKING(if Ghostscript library package is complete) - if test $passed -gt 0 - then - if test $failed -gt 0 - then - AC_MSG_RESULT(no -- some components failed test) - have_gslib='no (failed tests)' - else - LIB_GS='-lgs' - LIBS="$LIB_GS $LIBS" - AC_DEFINE(HasGS,1,Define if you have Ghostscript library) - AC_MSG_RESULT(yes) - have_gslib='yes' - fi - else - AC_MSG_RESULT(no) - fi -fi -AM_CONDITIONAL(HasGS, test "$have_gslib" = 'yes') -AC_SUBST(LIB_GS) - # # # # Check for MPEG2 library # # @@ -2177,14 +2199,14 @@ AC_SUBST(LIB_GS) # then # if test $failed -gt 0 # then -# AC_MSG_RESULT(no -- some components failed test) -# have_mpeg2='no (failed tests)' +# AC_MSG_RESULT(no -- some components failed test) +# have_mpeg2='no (failed tests)' # else -# LIB_MPEG2='-lmpeg2' -# LIBS="$LIB_MPEG2 $LIBS" -# AC_DEFINE(HasMPEG2,1,Define if you have MPEG2 library) -# AC_MSG_RESULT(yes) -# have_mpeg2='yes' +# LIB_MPEG2='-lmpeg2' +# LIBS="$LIB_MPEG2 $LIBS" +# AC_DEFINE(HasMPEG2,1,Define if you have MPEG2 library) +# AC_MSG_RESULT(yes) +# have_mpeg2='yes' # fi # else # AC_MSG_RESULT(no) @@ -2207,25 +2229,27 @@ then OLD_LDFLAGS="$LDFLAGS" OLD_CPPFLAGS="$CPPFLAGS" + # https://autotools.io/pkgconfig/pkg_check_modules.html + # PKG_CHECK_MODULES(prefix, list-of-modules, action-if-found, action-if-not-found) + # % pkg-config --libs freetype2 + # -lfreetype + # % pkg-config --cflags freetype2 + # -I/usr/include/freetype2 -I/usr/include/libpng12 + # + # % grep FT_ config.status + # S["FT_LIBS"]="-R/usr/lib -lfreetype " + # S["FT_CFLAGS"]="-I/usr/include/freetype2 + freetype_cflags='' + freeype_libs='' freetype_config='' - # Allow the user to specify the location of freetype. - if test "$with_ttf" != 'yes' - then - if test -x "${with_ttf}/bin/freetype-config" - then - freetype_config="${with_ttf}/bin/freetype-config" - elif test -x "${with_ttf}" + AC_PATH_PROG(freetype_config,freetype-config,)dnl + PKG_CHECK_MODULES([FT], [freetype2], + [freetype_cflags=$FT_CFLAGS; freeype_libs=$FT_LIBS], + [if test -n "$freetype_config" then - freetype_config=${with_ttf} - fi - fi - if test -z "$freetype_config" - then - AC_PATH_PROG(freetype_config,freetype-config,)dnl - fi - if test -n "$freetype_config" - then - freetype_cflags=`${freetype_config} --cflags` + freetype_cflags=`${freetype_config} --cflags` + freeype_libs=`${freetype_config} --libs` + fi]) # freetype-config --cflags may output values such as # -I/usr/local/include/freetype2 -I/usr/local/include # Take only the first -I option since non-Freetype include @@ -2254,7 +2278,6 @@ then # Freetype. In the future we may need to do something different # if the FreeType library was to depend on some weird library # that we don't normally test for. - freeype_libs=`${freetype_config} --libs` for flag in $freeype_libs do case $flag in @@ -2277,7 +2300,6 @@ then ;; esac done - fi dnl First see if there is a library AC_CHECK_LIB([$LIB_TTF_BASE],[FT_Init_FreeType],[LIB_TTF="-l$LIB_TTF_BASE"],[LIB_TTF=''],[]) @@ -2303,32 +2325,32 @@ dnl Now test for the headers fi if test "$have_freetype_h" = 'yes' then - passed=`expr $passed + 1` + passed=`expr $passed + 1` else - failed=`expr $failed + 1` + failed=`expr $failed + 1` CPPFLAGS="$OLD_CPPFLAGS" fi AC_MSG_CHECKING(if FreeType package is complete) if test $passed -gt 0 then - if test $failed -gt 0 - then + if test $failed -gt 0 + then LIB_TTF='' - AC_MSG_RESULT(no -- some components failed test) - have_ttf='no (failed tests)' - else - LIBS="$LIB_TTF $LIBS" - AC_DEFINE(HasTTF,1,Define if you have FreeType (TrueType font) library) + AC_MSG_RESULT(no -- some components failed test) + have_ttf='no (failed tests)' + else + LIBS="$LIB_TTF $LIBS" + AC_DEFINE(HasTTF,1,Define if you have FreeType (TrueType font) library) if test "$ac_cv_header_ft2build_h" = 'yes' then AC_DEFINE([HAVE_FT2BUILD_H],[1],[Define to 1 if you have the header file.]) fi - AC_MSG_RESULT(yes) - have_ttf='yes' - fi + AC_MSG_RESULT(yes) + have_ttf='yes' + fi else - AC_MSG_RESULT(no) + AC_MSG_RESULT(no) fi fi AM_CONDITIONAL(HasTTF, test "$have_ttf" = 'yes') @@ -2345,6 +2367,7 @@ then AC_MSG_RESULT() failed=0 passed=0 + # PKG_CHECK_MODULES([TIFF], [libtiff-4], [], []) AC_CHECK_HEADER(tiff.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) AC_CHECK_HEADER(tiffio.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) AC_CHECK_LIB(tiff,TIFFOpen,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) @@ -2357,15 +2380,15 @@ then then if test $failed -gt 0 then - AC_MSG_RESULT(no -- some components failed test) - have_tiff='no (failed tests)' + AC_MSG_RESULT(no -- some components failed test) + have_tiff='no (failed tests)' else - LIB_TIFF='-ltiff' - LIBS="$LIB_TIFF $LIBS" - AC_DEFINE(HasTIFF,1,Define if you have TIFF library) - AC_MSG_RESULT(yes) - have_tiff='yes' - AC_CHECK_HEADERS(tiffconf.h) + LIB_TIFF='-ltiff' + LIBS="$LIB_TIFF $LIBS" + AC_DEFINE(HasTIFF,1,Define if you have TIFF library) + AC_MSG_RESULT(yes) + have_tiff='yes' + AC_CHECK_HEADERS(tiffconf.h) AC_CHECK_FUNCS([TIFFIsCODECConfigured \ TIFFMergeFieldInfo \ TIFFSetErrorHandlerExt \ @@ -2398,13 +2421,13 @@ then then if test $failed -gt 0 then - AC_MSG_RESULT(no -- some components failed test) + AC_MSG_RESULT(no -- some components failed test) have_jbig='no (failed tests)' else - LIB_JBIG='-ljbig' - LIBS="$LIB_JBIG $LIBS" - AC_DEFINE(HasJBIG,1,Define if you have JBIG library) - AC_MSG_RESULT(yes) + LIB_JBIG='-ljbig' + LIBS="$LIB_JBIG $LIBS" + AC_DEFINE(HasJBIG,1,Define if you have JBIG library) + AC_MSG_RESULT(yes) have_jbig='yes' fi else @@ -2425,22 +2448,24 @@ then AC_MSG_RESULT() failed=0 passed=0 - AC_CHECK_HEADER(webp/decode.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) - AC_CHECK_LIB(webp,WebPDecodeRGB,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + # PKG_CHECK_MODULES([WEBP], [libwebp], [], []) + AC_CHECK_HEADER([webp/decode.h],[passed=`expr $passed + 1`],[failed=`expr $failed + 1`],[]) + AC_CHECK_HEADER([webp/encode.h],[passed=`expr $passed + 1`],[failed=`expr $failed + 1`],[]) + AC_CHECK_LIB([webp],[WebPDecodeRGB],[passed=`expr $passed + 1`; LIB_WEBP='-lwebp'],[failed=`expr $failed + 1`],[]) + AC_CHECK_LIB([webpmux],[WebPMuxSetImage],[LIB_WEBP="$LIB_WEBP -lwebpmux"],[],[-lwebp]) AC_MSG_CHECKING(if WEBP package is complete) if test $passed -gt 0 then - if test $failed -gt 0 - then - AC_MSG_RESULT(no -- some components failed test) - have_webp='no (failed tests)' - else - LIB_WEBP='-lwebp' - LIBS="$LIB_WEBP $LIBS" - AC_DEFINE(HasWEBP,1,Define if you have WEBP library) - AC_MSG_RESULT(yes) - have_webp='yes' - fi + if test $failed -gt 0 + then + AC_MSG_RESULT(no -- some components failed test) + have_webp='no (failed tests)' + else + LIBS="$LIB_WEBP $LIBS" + AC_DEFINE(HasWEBP,1,Define if you have WEBP library) + AC_MSG_RESULT(yes) + have_webp='yes' + fi else AC_MSG_RESULT(no) fi @@ -2462,18 +2487,29 @@ then AC_MSG_CHECKING([for XML support ]) AC_MSG_RESULT([]) xml2_config='' + xml2_cflags='' + xml2_libs='' AC_PATH_PROG([xml2_config],[xml2-config],[])dnl - if test -n "$xml2_config" - then - # Sample output from xml2-config --cflags: - # -I/usr/include/libxml2 - # -I/usr/local/include/libxml2 -I/usr/local/include - xml2_cflags=`"$xml2_config" --cflags` - for flag in $xml2_cflags - do - case $flag in - -I*) - # Add flag to CPPFLAGS if not already present + PKG_CHECK_MODULES([XML], [libxml-2.0], + [xml2_cflags=$XML_CFLAGS; xml2_libs=$XML_LIBS], + [if test -n "$xml2_config" + then + # Sample output from xml2-config --cflags: + # -I/usr/include/libxml2 + # -I/usr/local/include/libxml2 -I/usr/local/include + xml2_cflags=`"$xml2_config" --cflags` + # Sample output from xml2-config --libs: + # -lxml2 + # -L/usr/lib -R/usr/lib -lxml2 -lz -lpthread -lm -lsocket -lnsl + #-L/usr/local/lib -lxml2 -lz -L/usr/local/lib -liconv -lm + xml2_libs=`$xml2_config --libs` + fi + ]) + for flag in $xml2_cflags + do + case $flag in + -I*) + # Add flag to CPPFLAGS if not already present add=yes; for test_flag in $CPPFLAGS do @@ -2491,15 +2527,10 @@ then ;; *) ;; - esac - done - # Sample output from xml2-config --libs: - # -lxml2 - # -L/usr/lib -R/usr/lib -lxml2 -lz -lpthread -lm -lsocket -lnsl - #-L/usr/local/lib -lxml2 -lz -L/usr/local/lib -liconv -lm - xml2_libs=`$xml2_config --libs` - for flag in $xml2_libs - do + esac + done + for flag in $xml2_libs + do case $flag in -L*) # Add flag to LDFLAGS if not already present @@ -2521,9 +2552,9 @@ then *) ;; esac - done - for flag in $xml2_libs - do + done + for flag in $xml2_libs + do case $flag in -l*) # The first library listed is assumed to be the @@ -2539,8 +2570,7 @@ then *) ;; esac - done - fi + done if test "x$LIB_XML2_BASE" = "x" then LIB_XML2_BASE=xml2 @@ -2561,12 +2591,12 @@ then then if test $failed -gt 0 then - AC_MSG_RESULT([no -- some components failed test]) + AC_MSG_RESULT([no -- some components failed test]) have_xml='no (failed tests)' LDFLAGS="$OLD_LDFLAGS" CPPFLAGS="$OLD_CPPFLAGS" else - LIB_XML="-l$LIB_XML2_BASE" + LIB_XML="-l$LIB_XML2_BASE" # Add lib to LIBS if not already present for test_lib in $LIB_XML $LIB_XML_DEPS do @@ -2584,8 +2614,8 @@ then LIBS="$test_lib $LIBS" fi done - AC_DEFINE([HasXML],[1],[Define if you have XML library]) - AC_MSG_RESULT([yes]) + AC_DEFINE([HasXML],[1],[Define if you have XML library]) + AC_MSG_RESULT([yes]) have_xml='yes' fi else @@ -2630,7 +2660,7 @@ then LIBS="$LIB_WMF $LIBS" have_wmf='yes' else - AC_MSG_RESULT([no -- some components failed test]) + AC_MSG_RESULT([no -- some components failed test]) have_wmf='no (failed tests)' have_wmflite='no (failed tests)' LIBS="$OLIBS" @@ -2923,7 +2953,7 @@ else # # It would be nice to use reg.exe to obtain Ghostscript information # but unfortunately MSYS seems to transform registry key paths into - # filesystem paths so it does not work. Maybe there is a way to + # filesystem paths so it does not work. Maybe there is a way to # prevent that translation? # # reg query "HKLM\Software\GPL Ghostscript" /s @@ -3118,7 +3148,7 @@ then fi AC_MSG_RESULT($GSVersion) - # GSColorDevice # AS_MESSAGE_LOG_FD + # GSColorDevice # AS_MESSAGE_LOG_FD AC_MSG_CHECKING([for gs color device]) if $PSDelegate -q -dBATCH -sDEVICE=pnmraw -sOutputFile=/dev/null < /dev/null 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD then @@ -3246,15 +3276,15 @@ if test "$with_perl" != 'no' then if test "$with_perl" != 'yes' then - AC_CACHE_CHECK(for perl,ac_cv_path_PERL,ac_cv_path_PERL="$with_perl"); - PERL=$ac_cv_path_PERL - AC_SUBST(PERL)dnl - have_perl="$ac_cv_path_PERL" + AC_CACHE_CHECK(for perl,ac_cv_path_PERL,ac_cv_path_PERL="$with_perl"); + PERL=$ac_cv_path_PERL + AC_SUBST(PERL)dnl + have_perl="$ac_cv_path_PERL" else - AC_PATH_PROGS(PERL,perl perl5,)dnl - if test "$ac_cv_path_PERL" + AC_PATH_PROGS(PERL,perl perl5,)dnl + if test "$ac_cv_path_PERL" then - have_perl="$ac_cv_path_PERL" + have_perl="$ac_cv_path_PERL" fi fi fi @@ -3463,14 +3493,17 @@ fi # The build_modules variable is set to 'yes' if coders and filters are # to be built as modules. This requires libltdl ($LIB_LTDL). +# Removed $LIB_OMP and $LIB_THREAD if test "$build_modules" != 'no' then - MAGICK_DEP_LIBS="$LIBS_USER $LIB_LCMS $LIB_TTF $LIB_GS $LIB_XEXT $LIB_IPC $LIB_X11 $LIB_LZMA $LIB_BZLIB $LIB_ZLIB $LIB_LTDL $LIB_TRIO $LIB_GDI32 $LIB_MATH $LIB_OMP $LIB_UMEM $LIB_THREAD" + MAGICK_DEP_LIBS="$LIBS_USER $LIB_LCMS $LIB_TTF $LIB_GS $LIB_XEXT $LIB_IPC $LIB_X11 $LIB_LZMA $LIB_BZLIB $LIB_ZLIB $LIB_LTDL $LIB_TRIO $LIB_GDI32 $LIB_MATH $LIB_UMEM $LIB_THREAD" else - MAGICK_DEP_LIBS="$LIBS_USER $LIB_JBIG $LIB_WEBP $LIB_LCMS $LIB_TIFF $LIB_TTF $LIB_JP2 $LIB_JPEG $LIB_GS $LIB_PNG $LIB_FPX $LIB_WMF $LIB_DPS $LIB_XEXT $LIB_IPC $LIB_X11 $LIB_LZMA $LIB_BZLIB $LIB_XML $LIB_ZLIB $LIB_TRIO $LIB_GDI32 $LIB_MATH $LIB_OMP $LIB_UMEM $LIB_THREAD" + MAGICK_DEP_LIBS="$LIBS_USER $LIB_JBIG $LIB_WEBP $LIB_LCMS $LIB_TIFF $LIB_TTF $LIB_JP2 $LIB_JPEG $LIB_GS $LIB_PNG $LIB_FPX $LIB_WMF $LIB_DPS $LIB_XEXT $LIB_IPC $LIB_X11 $LIB_LZMA $LIB_BZLIB $LIB_XML $LIB_ZLIB $LIB_ZSTD $LIB_TRIO $LIB_GDI32 $LIB_MATH $LIB_UMEM $LIB_THREAD" fi +MAGICK_EXTRA_DEP_LIBS="$LIB_OMP" # Extra libraries typically added due to CFLAGS AC_SUBST(MAGICK_DEP_LIBS) +AC_SUBST(MAGICK_EXTRA_DEP_LIBS) # # Remove extraneous spaces from output variables (asthetic) @@ -3487,13 +3520,14 @@ CXXFLAGS=`echo $CXXFLAGS | sed -e 's/ */ /g'` LDFLAGS=`echo $LDFLAGS | sed -e 's/ */ /g'` TESTED_LIBS=`echo $LIBS | sed -e 's/ */ /g'` MAGICK_DEP_LIBS=`echo $MAGICK_DEP_LIBS | sed -e 's/ */ /g'` +MAGICK_EXTRA_DEP_LIBS=`echo $MAGICK_EXTRA_DEP_LIBS | sed -e 's/ */ /g'` #LIBS=`echo $LIBS | sed -e 's/ */ /g'` MAGICK_API_CFLAGS=$CFLAGS MAGICK_API_CPPFLAGS=`echo $MAGICK_API_CPPFLAGS | sed -e 's/ */ /g'` MAGICK_API_LDFLAGS="-L$LIB_DIR $LDFLAGS" MAGICK_API_DEP_LIBS="$MAGICK_DEP_LIBS" -MAGICK_API_LIBS="-lGraphicsMagick $MAGICK_API_DEP_LIBS" +MAGICK_API_LIBS="-lGraphicsMagick $MAGICK_API_DEP_LIBS $MAGICK_EXTRA_DEP_LIBS" MAGICK_API_DEP_LIBS=`echo $MAGICK_API_DEP_LIBS | sed -e 's/ */ /g'` MAGICK_API_LIBS=`echo $MAGICK_API_LIBS | sed -e 's/ */ /g'` @@ -3533,7 +3567,7 @@ AC_CONFIG_FILES(\ Makefile \ PerlMagick/Magick.pm \ PerlMagick/Makefile.PL \ - PerlMagick/PerlMagickCheck.sh \ + PerlMagick/PerlMagickCheck.sh \ PerlMagick/t/features.pl \ config/delegates.mgk \ config/type-ghostscript.mgk \ @@ -3561,82 +3595,81 @@ AC_OUTPUT rm -f magick-version -echo "" - -echo "GraphicsMagick is configured as follows. Please verify that this" -echo "configuration matches your expectations." -echo "" -echo "Host system type : $host" -echo "Build system type : $build" -echo "" -echo "Option Configure option Configured value" -echo "-----------------------------------------------------------------" -echo "Shared libraries --enable-shared=$enable_shared $libtool_build_shared_libs" -echo "Static libraries --enable-static=$enable_static $libtool_build_static_libs" -echo "GNU ld --with-gnu-ld=$with_gnu_ld $lt_cv_prog_gnu_ld" -echo "Quantum depth --with-quantum-depth=$with_quantum_depth $with_quantum_depth" -echo "Modules --with-modules=$with_modules $build_modules" -echo "" -echo "Delegate Configuration:" -echo "BZLIB --with-bzlib=$with_bzlib $have_bzlib" -echo "DPS --with-dps=$with_dps $have_dps" -echo "FlashPIX --with-fpx=$with_fpx $have_fpx" -echo "FreeType 2.0 --with-ttf=$with_ttf $have_ttf" -echo "Ghostscript None $PSDelegate ($GSVersion)" +printf "\n" + +printf "GraphicsMagick is configured as follows. Please verify that this\n" +printf "configuration matches your expectations.\n" +printf "\n" +printf "Host system type : $host\n" +printf "Build system type : $build\n" +printf "\n" +printf "Option Configure option \tConfigured value\n" +printf -- "-----------------------------------------------------------------\n" +printf "Shared libraries --enable-shared=$enable_shared\t\t$libtool_build_shared_libs\n" +printf "Static libraries --enable-static=$enable_static\t\t$libtool_build_static_libs\n" +printf "GNU ld --with-gnu-ld=$with_gnu_ld \t\t$lt_cv_prog_gnu_ld\n" +printf "Quantum depth --with-quantum-depth=$with_quantum_depth\t$with_quantum_depth\n" +printf "Modules --with-modules=$with_modules \t\t$build_modules\n" +printf "\n" +printf "Delegate Configuration:\n" +printf "BZLIB --with-bzlib=$with_bzlib \t$have_bzlib\n" +printf "DPS --with-dps=$with_dps \t$have_dps\n" +printf "FlashPIX --with-fpx=$with_fpx \t$have_fpx\n" +printf "FreeType 2.0 --with-ttf=$with_ttf \t$have_ttf\n" +printf "Ghostscript None \t$PSDelegate ($GSVersion)\n" result_ghostscript_font_dir='none' if test "${ghostscript_font_dir}x" != 'x' then result_ghostscript_font_dir="$ghostscript_font_dir" fi -echo "Ghostscript fonts --with-gs-font-dir=$with_gs_font_dir $result_ghostscript_font_dir" -echo "Ghostscript lib --with-gslib=$with_gslib $have_gslib" -echo "JBIG --with-jbig=$with_jbig $have_jbig" -echo "JPEG v1 --with-jpeg=$with_jpeg $have_jpeg" -echo "JPEG-2000 --with-jp2=$with_jp2 $have_jp2" -echo "LCMS v2 --with-lcms2=$with_lcms2 $have_lcms2" -# echo "MPEG v2 --with-mpeg2=$with_mpeg2 $have_mpeg2" -echo "LZMA --with-lzma=$with_lzma $have_lzma" -echo "Magick++ --with-magick-plus-plus=$with_magick_plus_plus $have_magick_plus_plus" -echo "PERL --with-perl=$with_perl $have_perl" +printf "Ghostscript fonts --with-gs-font-dir=$with_gs_font_dir\t$result_ghostscript_font_dir\n" +printf "JBIG --with-jbig=$with_jbig \t$have_jbig\n" +printf "JPEG v1 --with-jpeg=$with_jpeg \t$have_jpeg\n" +printf "JPEG-2000 --with-jp2=$with_jp2 \t$have_jp2\n" +printf "LCMS v2 --with-lcms2=$with_lcms2 \t$have_lcms2\n" +# printf "MPEG v2 --with-mpeg2=$with_mpeg2 \t$have_mpeg2\n" +printf "LZMA --with-lzma=$with_lzma \t$have_lzma\n" +printf "Magick++ --with-magick-plus-plus=$with_magick_plus_plus\t$have_magick_plus_plus\n" +printf "PERL --with-perl=$with_perl \t$have_perl\n" if test "${LIB_PNG}x" != 'x' then -echo "PNG --with-png=$with_png $have_png ($LIB_PNG)" +printf "PNG --with-png=$with_png \t$have_png ($LIB_PNG)\n" else -echo "PNG --with-png=$with_png $have_png" +printf "PNG --with-png=$with_png \t$have_png\n" fi -echo "TIFF --with-tiff=$with_tiff $have_tiff" -echo "TRIO --with-trio=$with_trio $have_trio" -echo "WEBP --with-webp=$with_webp $have_webp" +printf "TIFF --with-tiff=$with_tiff \t$have_tiff\n" +printf "TRIO --with-trio=$with_trio \t$have_trio\n" +printf "WEBP --with-webp=$with_webp \t$have_webp\n" result_windows_font_dir='none' if test "${windows_font_dir}x" != 'x' then result_windows_font_dir="${windows_font_dir}" fi -echo "Windows fonts --with-windows-font-dir=$with_windows_font_dir $result_windows_font_dir" -echo "WMF --with-wmf=$with_wmf $have_wmf" -echo "X11 --with-x=$with_x $have_x" -echo "XML --with-xml=$with_xml $have_xml" -echo "ZLIB --with-zlib=$with_zlib $have_zlib" -echo "" -echo "X11 Configuration:" +printf "Windows fonts --with-windows-font-dir=$with_windows_font_dir\t$result_windows_font_dir\n" +printf "WMF --with-wmf=$with_wmf \t$have_wmf\n" +printf "X11 --with-x=$with_x \t$have_x\n" +printf "XML --with-xml=$with_xml \t$have_xml\n" +printf "ZLIB --with-zlib=$with_zlib \t$have_zlib\n" +printf "\n" +printf "X11 Configuration:\n" if test "$have_x" != 'no' then - echo " X_CFLAGS = $X_CFLAGS" - echo " X_PRE_LIBS = $X_PRE_LIBS" - echo " X_LIBS = $X_LIBS" - echo " X_EXTRA_LIBS = $X_EXTRA_LIBS" + printf " X_CFLAGS = $X_CFLAGS\n" + printf " X_PRE_LIBS = $X_PRE_LIBS\n" + printf " X_LIBS = $X_LIBS\n" + printf " X_EXTRA_LIBS = $X_EXTRA_LIBS\n" else - echo "" - echo " Not using X11." -fi -echo "" -echo "Options used to compile and link:" -echo " CC = $CC" -echo " CFLAGS = $CFLAGS" -echo " CPPFLAGS = $CPPFLAGS" -echo " CXX = $CXX" -echo " CXXFLAGS = $CXXFLAGS" -echo " DEFS = $DEFS" -echo " LDFLAGS = $LDFLAGS" -echo " LIBS = $MAGICK_API_DEP_LIBS" -echo "" + printf "\n" + printf " Not using X11.\n" +fi +printf "\n" +printf "Options used to compile and link:\n" +printf " CC = $CC\n" +printf " CFLAGS = $CFLAGS\n" +printf " CPPFLAGS = $CPPFLAGS\n" +printf " CXX = $CXX\n" +printf " CXXFLAGS = $CXXFLAGS\n" +printf " DEFS = $DEFS\n" +printf " LDFLAGS = $LDFLAGS\n" +printf " LIBS = $MAGICK_API_DEP_LIBS\n" +printf "\n" diff --git a/filters/analyze.c b/filters/analyze.c index 52b789f..9d51764 100644 --- a/filters/analyze.c +++ b/filters/analyze.c @@ -49,7 +49,7 @@ % % The format of the AnalyzeImage method is: % -% unsigned int AnalyzeImage(Image *image) +% MagickPassFail AnalyzeImage(Image *image) % % A description of each parameter follows: % @@ -57,30 +57,25 @@ % */ #define PRECISION "%.0f" -ModuleExport unsigned int AnalyzeImage(Image **image, - const int argc,char **argv) +ModuleExport MagickPassFail AnalyzeImage(Image **image, + const int argc,char **argv) { double bsumX = 0.0, bsumX2 = 0.0, - brightness_mean = 0.0, - brightness_stdev = 0.0, ssumX = 0.0, - ssumX2 = 0.0, - saturation_mean = 0.0, - saturation_stdev = 0.0, - total_pixels = 0.0; + ssumX2 = 0.0; double brightness, hue, saturation; - long + unsigned long y; - register long - x; + register unsigned long + x = 0; register PixelPacket *p; @@ -88,58 +83,72 @@ ModuleExport unsigned int AnalyzeImage(Image **image, char text[MaxTextExtent]; + MagickPassFail + status = MagickPass; + ARG_NOT_USED(argc); ARG_NOT_USED(argv); assert(image != (Image **) NULL); assert(*image != (Image *) NULL); - for (y=0; y < (int) (*image)->rows; y++) - { - p=GetImagePixels((*image),0,y,(*image)->columns,1); - if (p == (PixelPacket *) NULL) - break; - if (y == 0) - { - FormatString(text,"#%02x%02x%02x",p->red,p->green,p->blue); - (void) SetImageAttribute((*image),"TopLeftColor",text); - } - if (y == (long) ((*image)->rows-1)) - { - FormatString(text,"#%02x%02x%02x",p->red,p->green,p->blue); - (void) SetImageAttribute((*image),"BottomLeftColor",text); - } - for (x=0; x < (long) (*image)->columns; x++) + for (y=0; y < (*image)->rows; y++) + { + p=GetImagePixels((*image),0,y,(*image)->columns,1); + if (p == (PixelPacket *) NULL) + break; + if (y == 0) + { + FormatString(text,"#%02x%02x%02x",p->red,p->green,p->blue); + (void) SetImageAttribute((*image),"TopLeftColor",text); + } + if (y == ((*image)->rows-1)) + { + FormatString(text,"#%02x%02x%02x",p->red,p->green,p->blue); + (void) SetImageAttribute((*image),"BottomLeftColor",text); + } + for (x=0; x < (*image)->columns; x++) + { + TransformHSL(p->red,p->green,p->blue,&hue,&saturation,&brightness); + brightness *= MaxRGBDouble; + bsumX += brightness; + bsumX2 += brightness * brightness; + saturation *= MaxRGBDouble; + ssumX += saturation; + ssumX2 += saturation * saturation; + p++; + } + p--; /* backup one pixel to allow us to sample */ + if (y == 0) + { + FormatString(text,"#%02x%02x%02x",p->red,p->green,p->blue); + (void) SetImageAttribute((*image),"TopRightColor",text); + } + if (y == ((*image)->rows-1)) + { + FormatString(text,"#%02x%02x%02x",p->red,p->green,p->blue); + (void) SetImageAttribute((*image),"BottomRightColor",text); + } + } + if ((x != (*image)->columns) || (y != (*image)->rows)) { - TransformHSL(p->red,p->green,p->blue,&hue,&saturation,&brightness); - brightness *= MaxRGB; - bsumX += brightness; - bsumX2 += brightness * brightness; - saturation *= MaxRGB; - ssumX += saturation; - ssumX2 += saturation * saturation; - total_pixels++; - p++; + status = MagickFail; } - p--; /* backup one pixel to allow us to sample */ - if (y == 0) - { - FormatString(text,"#%02x%02x%02x",p->red,p->green,p->blue); - (void) SetImageAttribute((*image),"TopRightColor",text); - } - if (y == (long) ((*image)->rows-1)) - { - FormatString(text,"#%02x%02x%02x",p->red,p->green,p->blue); - (void) SetImageAttribute((*image),"BottomRightColor",text); - } - } - if (total_pixels > 0.0) + else { + double + brightness_mean, + brightness_stdev, + saturation_mean, + saturation_stdev, + total_pixels; + + total_pixels = (double) (*image)->columns * (double) (*image)->rows; brightness_mean = bsumX/total_pixels; FormatString(text,PRECISION,brightness_mean); (void) SetImageAttribute((*image),"BrightnessMean",text); /* This formula gives a slightly biased result */ brightness_stdev = - sqrt(bsumX2/total_pixels - (bsumX/total_pixels*bsumX/total_pixels)); + sqrt(bsumX2/total_pixels - (bsumX/total_pixels*bsumX/total_pixels)); FormatString(text,PRECISION,brightness_stdev); (void) SetImageAttribute((*image),"BrightnessStddev",text); /* Now the correction for bias. */ @@ -152,7 +161,7 @@ ModuleExport unsigned int AnalyzeImage(Image **image, (void) SetImageAttribute((*image),"SaturationMean",text); /* This formula gives a slightly biased result */ saturation_stdev = - sqrt(ssumX2/total_pixels - (ssumX/total_pixels*ssumX/total_pixels)); + sqrt(ssumX2/total_pixels - (ssumX/total_pixels*ssumX/total_pixels)); FormatString(text,PRECISION,saturation_stdev); (void) SetImageAttribute((*image),"SaturationStddev",text); /* Now the correction for bias. */ @@ -160,5 +169,5 @@ ModuleExport unsigned int AnalyzeImage(Image **image, /* Now calculate the standard deviation of the mean */ /* saturation_stdevmean = sstdev/sqrt((double)total_pixels); */ } - return(True); + return status; } diff --git a/locale/C.mgk b/locale/C.mgk index bb129c1..8e29841 100644 --- a/locale/C.mgk +++ b/locale/C.mgk @@ -26,6 +26,9 @@ Unrecognized image format + + Unable to deduce image format + @@ -46,6 +49,9 @@ Pixel cache is not open + + Pixel cache dimensions incompatible with image dimensions + Unable to allocate cache view @@ -327,6 +333,18 @@ Unsupported bits per sample + + Unsupported samples per pixel + + + Arithmetic overflow + + + Division by zero + + + Coder did not return an image (this is a bug, please report it!) + @@ -509,6 +527,9 @@ Unsupported number of planes + + Image file has no scenes + @@ -549,6 +570,9 @@ Length and filesize do not match + + Unable to parse embedded profile + @@ -724,6 +748,12 @@ image does not contain resolution + + image is not colormapped + + + CMYKA image lacks an alpha channel (indexes) + image opacity differs @@ -790,12 +820,24 @@ Unable to set clip mask + + Unable to get composite mask + + + Unable to set composite mask + unable to shear image width or height exceeds limit + + unable to export image pixels + + + unable to import image pixels + @@ -1166,6 +1208,9 @@ Improper arguments supplied, please see manual + + Tile is not bounded by image dimensions + @@ -1315,6 +1360,9 @@ unable to add IPTC profile + + unable to add or remove profile + Unable to allocate colormap @@ -1542,7 +1590,7 @@ unable to allocate quantize info - + unable to allocate random kernel @@ -1614,6 +1662,9 @@ unable to obtain random bytes from operating system + + unable to allocate magick map + @@ -1639,6 +1690,9 @@ Unrecognized font encoding + + Font name not specified + diff --git a/m4/pkg.m4 b/m4/pkg.m4 new file mode 100644 index 0000000..13a8890 --- /dev/null +++ b/m4/pkg.m4 @@ -0,0 +1,275 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $2]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR diff --git a/magick/Makefile.am b/magick/Makefile.am index b531136..5a64f02 100644 --- a/magick/Makefile.am +++ b/magick/Makefile.am @@ -297,6 +297,7 @@ MAGICK_NOINST_HDRS = \ magick/floats.h \ magick/locale_c.h \ magick/map.h \ + magick/module_aliases.h \ magick/nt_base.h \ magick/nt_feature.h \ magick/omp_data_view.h \ diff --git a/magick/PreRvIcccm.h b/magick/PreRvIcccm.h index 3852fba..d771535 100644 --- a/magick/PreRvIcccm.h +++ b/magick/PreRvIcccm.h @@ -2,11 +2,11 @@ Copyright (C) 2003 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick X11 compatibility methods. */ #ifndef _MAGICK_PRER5ICCCM_H diff --git a/magick/alpha_composite.h b/magick/alpha_composite.h index d58f7ef..e4841e4 100644 --- a/magick/alpha_composite.h +++ b/magick/alpha_composite.h @@ -1,13 +1,23 @@ /* Copyright (C) 2003, 2005, 2008, 2013 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick Alpha Composite Methods. */ + +/* + References on compositing: + + Porter, Thomas; Tom Duff (1984). "Compositing Digital Images". Computer Graphics. + 18 (3): 253.259. ISBN 0-89791-138-5. doi:10.1145/800031.808606 + + SVG specification REC-SVG11-20110816.pdf, "Simple alpha compositing" +*/ + #ifndef _MAGICK_ALPHA_COMPOSITE_H #define _MAGICK_ALPHA_COMPOSITE_H @@ -25,11 +35,20 @@ static inline magick_uint32_t BlendQuantumOpacity(magick_uint32_t q, if (opacity != 0U) { + /* + The 0==transparent/MaxRGB==opaque value for "opacity" is o = (MaxRGB-opacity), + and the value for "q" is a = (MaxRGB-q), so the output value is o * a / MaxRGB. + This value must be inverted to conform to the 0==opaque/MaxRGB==transparent + convention used in this code. When you work through the algebra you get + result = opacity + q - opacity * q / MaxRGB. + */ #if QuantumDepth > 16 - result = ((magick_uint64_t) opacity*q)/MaxRGB; +#define _TCAST_ magick_uint64_t #else - result = ((magick_uint32_t) opacity*q)/MaxRGB; +#define _TCAST_ magick_uint32_t #endif + result = opacity + q - ((_TCAST_)opacity * (_TCAST_)q + /*round*/(MaxRGB>>1))/MaxRGB; +#undef _TCAST_ } return result; } @@ -45,26 +64,26 @@ static inline void BlendCompositePixel(PixelPacket *composite, if (q->opacity == TransparentOpacity) { - composite->red=p->red; - composite->green=p->green; - composite->blue=p->blue; + composite->red=p->red; + composite->green=p->green; + composite->blue=p->blue; } else if (p->opacity == TransparentOpacity) { - composite->red=q->red; - composite->green=q->green; - composite->blue=q->blue; + composite->red=q->red; + composite->green=q->green; + composite->blue=q->blue; } else { - color=((double) p->red*(MaxRGBDouble-alpha)+q->red*alpha)/MaxRGBDouble; - composite->red=RoundDoubleToQuantum(color); + color=((double) p->red*(MaxRGBDouble-alpha)+q->red*alpha)/MaxRGBDouble; + composite->red=RoundDoubleToQuantum(color); - color=((double) p->green*(MaxRGBDouble-alpha)+q->green*alpha)/MaxRGBDouble; - composite->green=RoundDoubleToQuantum(color); + color=((double) p->green*(MaxRGBDouble-alpha)+q->green*alpha)/MaxRGBDouble; + composite->green=RoundDoubleToQuantum(color); - color=((double) p->blue*(MaxRGBDouble-alpha)+q->blue*alpha)/MaxRGBDouble; - composite->blue=RoundDoubleToQuantum(color); + color=((double) p->blue*(MaxRGBDouble-alpha)+q->blue*alpha)/MaxRGBDouble; + composite->blue=RoundDoubleToQuantum(color); } opacity=((double) p->opacity*(MaxRGBDouble-alpha)+q->opacity*alpha)/MaxRGBDouble; @@ -72,14 +91,42 @@ static inline void BlendCompositePixel(PixelPacket *composite, } /* - Alpha compose pixel 'change' over pixel 'source'. + Alpha compose pixel 'change' over pixel 'base'. The result will be the union of the two image shapes, with opaque areas of change-image obscuring base-image in the region of overlap. */ + +/* + Documentation for macro MagickAlphaCompositeQuantum: + + (1) GM uses the alpha value convention of 0 for opaque and MaxRGB for transparent, which is + the opposite of the "standard" usage (see Porter/Duff and SVG references above). + (2) Using the standard terminology of fg (foreground) and bg (background), and the standard + representation of 0 for transparent and 1 for opaque, let: + + fg_alpha = (1.0 - change_alpha / MaxRGBDouble) + bg_alpha = (1.0 - base_alpha / MaxRGBDouble) + + then MagickAlphaCompositeQuantum computes the following result: + + result = fg_alpha * fg + (1 - fg_alpha) * (bg_alpha * bg) + + This is the "standard" compositing equation when the fg and bg colors have not been premultiplied + by their alpha values. For reference, note that when the fg and bg colors HAVE been premultiplied, + the compositing equation becomes the simple and elegant: + + result = fg + (1 - fg_alpha) * bg + + and this equation works for both the color components AND the alpha channel. For the + non-premultiplied case, the alpha equation is: + + result_alpha = fg_alpha + (1 - fg_alpha) * bg_alpha +*/ + #define MagickAlphaCompositeQuantum(change,change_alpha,base,base_alpha) \ - (1.0-(change_alpha/MaxRGBDouble))*(double) change+(1.0-(base_alpha/MaxRGBDouble))*(double) base*(change_alpha/MaxRGBDouble) + ((1.0-(change_alpha/MaxRGBDouble))*(double) change+(1.0-(base_alpha/MaxRGBDouble))*(double) base*(change_alpha/MaxRGBDouble)) static inline void AlphaCompositePixel(PixelPacket *composite, const PixelPacket *change, const double change_alpha,const PixelPacket *base, @@ -88,7 +135,7 @@ static inline void AlphaCompositePixel(PixelPacket *composite, const PixelPacket if (change_alpha == (double) TransparentOpacity) { if (composite != base) - *composite=*base; + *composite=*base; } else { @@ -96,19 +143,29 @@ static inline void AlphaCompositePixel(PixelPacket *composite, const PixelPacket delta, value; + /* + "delta" is the 0==transparent/1==opaque opacity value for the composited + pixel (I checked the algebra). + */ delta=1.0-(change_alpha/MaxRGBDouble)*(base_alpha/MaxRGBDouble); - - value=MaxRGBDouble*(1.0-delta); + + value=MaxRGBDouble*(1.0-delta); /* invert so 0==opaque, MaxRGB==transparent */ composite->opacity=RoundDoubleToQuantum(value); - + + /* + The multiplicative inverse of "delta" is used to rescale the red, green, and + blue composited pixel values so that they are not premultiplied by the alpha + value. Note the protection against divide-by-zero in case the composited pixel + is completely transparent. + */ delta=1.0/(delta <= MagickEpsilon ? 1.0 : delta); - + value=delta*MagickAlphaCompositeQuantum(change->red,change_alpha,base->red,base_alpha); composite->red=RoundDoubleToQuantum(value); - + value=delta*MagickAlphaCompositeQuantum(change->green,change_alpha,base->green,base_alpha); composite->green=RoundDoubleToQuantum(value); - + value=delta*MagickAlphaCompositeQuantum(change->blue,change_alpha,base->blue,base_alpha); composite->blue=RoundDoubleToQuantum(value); } @@ -131,25 +188,25 @@ static inline void AtopCompositePixel(PixelPacket *composite, opacity=((double)(MaxRGBDouble-change->opacity)* (MaxRGBDouble-base->opacity)+(double) change->opacity* (MaxRGBDouble-base->opacity))/MaxRGBDouble; - + color=((double) (MaxRGBDouble-change->opacity)* (MaxRGBDouble-base->opacity)*change->red/MaxRGBDouble+(double) change->opacity*(MaxRGBDouble-base->opacity)* base->red/MaxRGBDouble)/opacity; composite->red=RoundDoubleToQuantum(color); - + color=((double) (MaxRGBDouble-change->opacity)* (MaxRGBDouble-base->opacity)*change->green/MaxRGBDouble+(double) change->opacity*(MaxRGBDouble-base->opacity)* base->green/MaxRGBDouble)/opacity; composite->green=RoundDoubleToQuantum(color); - + color=((double) (MaxRGBDouble-change->opacity)* (MaxRGBDouble-base->opacity)*change->blue/MaxRGBDouble+(double) change->opacity*(MaxRGBDouble-base->opacity)* base->blue/MaxRGBDouble)/opacity; composite->blue=RoundDoubleToQuantum(color); - + composite->opacity=MaxRGB-RoundDoubleToQuantum(opacity); } diff --git a/magick/analyze.c b/magick/analyze.c index 6c4c489..1d17908 100644 --- a/magick/analyze.c +++ b/magick/analyze.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2009 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2003 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -89,13 +89,13 @@ MagickExport RectangleInfo GetImageBoundingBox(const Image *image, (void) AcquireOnePixelByReference(image,&corners[1],(long) image->columns-1,0,exception); (void) AcquireOnePixelByReference(image,&corners[2],0,(long) image->rows-1,exception); #if defined(HAVE_OPENMP) -# pragma omp parallel for schedule(static,4) shared(row_count, status) +# pragma omp parallel for schedule(static,4) shared(bounds, row_count, status) #endif for (y=0; y < (long) image->rows; y++) { register const PixelPacket * restrict p; - + register long x; @@ -121,13 +121,13 @@ MagickExport RectangleInfo GetImageBoundingBox(const Image *image, if (thread_status != MagickFail) { if ((image->matte) && - (corners[0].opacity != OpaqueOpacity) && - (corners[0].opacity == corners[1].opacity) && - (corners[1].opacity == corners[2].opacity)) - /* - Consider only the opacity channel. Not currently fuzzy - so only applied for simple transparency. - */ + (corners[0].opacity != OpaqueOpacity) && + (corners[0].opacity == corners[1].opacity) && + (corners[1].opacity == corners[2].opacity)) + /* + Consider only the opacity channel. Not currently fuzzy + so only applied for simple transparency. + */ for (x=0; x < (long) image->columns; x++) { if (p->opacity != corners[0].opacity) @@ -145,31 +145,31 @@ MagickExport RectangleInfo GetImageBoundingBox(const Image *image, p++; } else if (image->fuzz <= MagickEpsilon) - { - /* - Consider only the RGB channels using absolute comparison - */ - for (x=0; x < (long) image->columns; x++) - { - if (!ColorMatch(p,&corners[0])) - if (x < thread_bounds.x) - thread_bounds.x=x; - if (!ColorMatch(p,&corners[1])) - if (x > (long) thread_bounds.width) - thread_bounds.width=x; - if (!ColorMatch(p,&corners[0])) - if (y < thread_bounds.y) - thread_bounds.y=y; - if (!ColorMatch(p,&corners[2])) - if (y > (long) thread_bounds.height) - thread_bounds.height=y; - p++; - } - } - else - /* - Consider only the RGB channels using fuzzy comparison - */ + { + /* + Consider only the RGB channels using absolute comparison + */ + for (x=0; x < (long) image->columns; x++) + { + if (!ColorMatch(p,&corners[0])) + if (x < thread_bounds.x) + thread_bounds.x=x; + if (!ColorMatch(p,&corners[1])) + if (x > (long) thread_bounds.width) + thread_bounds.width=x; + if (!ColorMatch(p,&corners[0])) + if (y < thread_bounds.y) + thread_bounds.y=y; + if (!ColorMatch(p,&corners[2])) + if (y > (long) thread_bounds.height) + thread_bounds.height=y; + p++; + } + } + else + /* + Consider only the RGB channels using fuzzy comparison + */ for (x=0; x < (long) image->columns; x++) { if (!FuzzyColorMatch(p,&corners[0],image->fuzz)) @@ -189,15 +189,18 @@ MagickExport RectangleInfo GetImageBoundingBox(const Image *image, } #if defined(HAVE_OPENMP) +# pragma omp atomic +#endif + row_count++; + if (QuantumTick(row_count,image->rows)) + if (!MagickMonitorFormatted(row_count,image->rows,exception, + GetImageBoundingBoxText,image->filename)) + thread_status=MagickFail; + +#if defined(HAVE_OPENMP) # pragma omp critical (GM_GetImageBoundingBox) #endif { - row_count++; - if (QuantumTick(row_count,image->rows)) - if (!MagickMonitorFormatted(row_count,image->rows,exception, - GetImageBoundingBoxText,image->filename)) - thread_status=MagickFail; - if (thread_bounds.x < bounds.x) bounds.x=thread_bounds.x; if (thread_bounds.y < bounds.y) @@ -206,10 +209,15 @@ MagickExport RectangleInfo GetImageBoundingBox(const Image *image, bounds.width=thread_bounds.width; if (thread_bounds.height > bounds.height) bounds.height=thread_bounds.height; + } - if (thread_status == MagickFail) + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif + } } if ((bounds.width != 0) || (bounds.height != 0)) { @@ -273,28 +281,28 @@ static inline unsigned char MinimumDepthForValue(const Quantum quantum) register unsigned int depth, scale; - + for (depth=1 ; depth < MaxRGB; depth++) { scale=MaxRGB / (MaxRGB >> (QuantumDepth-depth)); if (quantum == scale*(quantum/scale)) break; } - + return depth; } #if MaxMap == MaxRGB static magick_uint8_t* AllocateDepthMap(void) { - magick_uint8_t + magick_uint8_t *map; - + map = MagickAllocateArray(unsigned char *, MaxMap+1, sizeof(magick_uint8_t)); if (map != (unsigned char *) NULL) { unsigned int i; - + for (i=0; i <= MaxMap; i++) map[i] = (magick_uint8_t) MinimumDepthForValue(i); } @@ -306,11 +314,11 @@ static magick_uint8_t* AllocateDepthMap(void) static MagickPassFail GetImageDepthCallBack(void *mutable_data, /* User provided mutable data */ const void *immutable_data, /* User provided immutable data */ - const Image *image, /* Input image */ - const PixelPacket *pixels, /* Pixel row */ - const IndexPacket *indexes, /* Pixel indexes */ + const Image * restrict image, /* Input image */ + const PixelPacket * restrict pixels, /* Pixel row */ + const IndexPacket * restrict indexes, /* Pixel indexes */ const long npixels, /* Number of pixels in row */ - ExceptionInfo *exception /* Exception report */ + ExceptionInfo * restrict exception /* Exception report */ ) { unsigned int @@ -429,11 +437,11 @@ MagickExport unsigned long GetImageDepth(const Image *image, { /* DirectClass. - + Notice that all pixels in the image must be inspected if the image depth is less than QuantumDepth. */ - + (void) PixelIterateMonoRead(GetImageDepthCallBack, NULL, GetImageDepthText, @@ -861,7 +869,7 @@ MagickExport MagickBool IsMonochromeImage(const Image *image, if (image->colorspace == CMYKColorspace) return(MagickFalse); if (image->is_monochrome) - return(MagickTrue); + return(MagickTrue); is_monochrome=MagickTrue; switch (image->storage_class) { diff --git a/magick/analyze.h b/magick/analyze.h index 5530a87..1b22acd 100644 --- a/magick/analyze.h +++ b/magick/analyze.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003 - 2009 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick Image Analysis Methods. */ #ifndef _MAGICK_ANALYZE_H @@ -30,7 +30,7 @@ typedef struct _ImageCharacteristics /* Functions which return unsigned int to indicate operation pass/fail */ extern MagickExport MagickPassFail GetImageCharacteristics(const Image *image,ImageCharacteristics *characteristics, - const MagickBool optimize,ExceptionInfo *exception); + const MagickBool optimize,ExceptionInfo *exception); extern MagickExport unsigned long GetImageDepth(const Image *,ExceptionInfo *); diff --git a/magick/animate.c b/magick/animate.c index b290931..bc84486 100644 --- a/magick/animate.c +++ b/magick/animate.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2015 GraphicsMagick Group +% Copyright (C) 2003-2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -917,10 +917,10 @@ MagickExport void MagickXAnimateBackgroundImage(Display *display, */ MagickExport Image * MagickXAnimateImages(Display *display, - MagickXResourceInfo *resource_info, - char *argv[], - const int argc, - Image *images) + MagickXResourceInfo *resource_info, + char *argv[], + const int argc, + Image *images) { #define MagickMenus 4 #define MaxWindows 8 @@ -1830,7 +1830,7 @@ MagickXAnimateImages(Display *display, { char name[MaxTextExtent]; - + FormatString(name, "GraphicsMagick: %.1024s[%lu of %lu]",p,scene, number_scenes); diff --git a/magick/animate.h b/magick/animate.h index df03b6e..8434c81 100644 --- a/magick/animate.h +++ b/magick/animate.h @@ -2,11 +2,11 @@ Copyright (C) 2003 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + Methods to Interactively Animate an Image Sequence. */ #ifndef _MAGICK_ANIMATE_H diff --git a/magick/annotate.c b/magick/annotate.c index f0fe124..21117fc 100644 --- a/magick/annotate.c +++ b/magick/annotate.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2015 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -779,6 +779,54 @@ MagickExport MagickPassFail GetTypeMetrics(Image *image,const DrawInfo *draw_inf return(status); } + +/* + Find a single font family name in a comma-separated list; returns a pointer + to where next search should start (i.e., to the terminating character), or null + if not found. Trims leading and trailing white space, and surrounding single + quotes. +*/ +static +char const *FindCommaDelimitedName +( + char const * pSearchStart, /*start search here*/ + char const ** ppStart, /*return pointer to first character in found string*/ + char const ** ppEnd /*return pointer to just past last character in found string*/ + ) +{ /*FindCommaDelimitedName*/ + + int c; + char const * pStart; + char const * pEnd; + char const * pNextSearchStart; + + if ( pSearchStart == 0 ) + return(0); + + for ( pStart = pSearchStart; (c = *pStart) && (isspace(c) || (c == ',')); + pStart++ ); /*skip leading spaces and commas*/ + if ( c == '\0' ) + return(0); /*didn't find anything!*/ + + for ( pEnd = pStart + 1; (c = *pEnd) && (c != ','); pEnd++ ); /*find terminating comma*/ + pNextSearchStart = pEnd; + + for ( ; isspace(pEnd[-1]); pEnd-- ); /*trim trailing space; we know there is a non-space character there*/ + + /* trim off surrounding single quotes */ + if ((*pStart == '\'') && (*pEnd == '\'') && ((pEnd-pStart) >= 3)) + { + pStart++; + pEnd--; + } + + *ppStart = pStart; + *ppEnd = pEnd; + return(pNextSearchStart); + +} /*FindCommaDelimitedName*/ + + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % @@ -814,17 +862,23 @@ MagickExport MagickPassFail GetTypeMetrics(Image *image,const DrawInfo *draw_inf % */ static MagickPassFail RenderType(Image *image,const DrawInfo *draw_info, - const PointInfo *offset,TypeMetric *metrics) + const PointInfo *offset,TypeMetric *metrics) { const TypeInfo *type_info; DrawInfo - *clone_info; + *clone_info; MagickPassFail status; + char + OneFontFamilyName[2048]; /*special handling only if font name this long or less*/ + + char const * + pTheFoundFontFamilyName; + type_info=(const TypeInfo *) NULL; if (draw_info->font != (char *) NULL) { @@ -837,9 +891,94 @@ static MagickPassFail RenderType(Image *image,const DrawInfo *draw_info, if (IsAccessible(draw_info->font)) return(RenderFreetype(image,draw_info,(char *) NULL,offset,metrics)); } + + /* draw_info->family may be a comma-separated list of names ... */ + pTheFoundFontFamilyName = draw_info->family; if (type_info == (const TypeInfo *) NULL) - type_info=GetTypeInfoByFamily(draw_info->family,draw_info->style, - draw_info->stretch,draw_info->weight,&image->exception); + { /*type_info not yet found*/ + + /* stay consistent with previous behavior unless font family contains comma(s) */ + if (draw_info->family == 0 || (strchr(draw_info->family,',') == 0)) + { /*null ptr, or no commas in string; preserve previous behavior*/ + + type_info=GetTypeInfoByFamily(draw_info->family,draw_info->style, + draw_info->stretch,draw_info->weight, + &image->exception); + + } /*null ptr, or no commas in string; preserve previous behavior*/ + else + { /*process as font family list*/ + + char const * pNext = draw_info->family, * pStart = 0, * pEnd = 0; + while ((pNext = FindCommaDelimitedName(pNext,&pStart,&pEnd)) != 0) + { /*found a name*/ + + unsigned int NameLength = pEnd - pStart; + if ( NameLength >= sizeof(OneFontFamilyName) ) + continue; + memcpy(OneFontFamilyName,pStart,NameLength); + OneFontFamilyName[NameLength] = '\0'; + type_info = GetTypeInfoByFamily(OneFontFamilyName, + draw_info->style, + draw_info->stretch, + draw_info->weight, + &image->exception); + /*do not allow font substitution*/ + if ( type_info && (LocaleCompare(OneFontFamilyName, + type_info->family) == 0) ) + { + pTheFoundFontFamilyName = OneFontFamilyName; + break; + } + + } /*found a name*/ + + } /*process as font family list*/ + + } /*type_info not yet found*/ + + /* + We may have performed font substitution. If so (i.e., font family + name does not match), try again assuming draw_info->family is + actually a font name. If we get a font name match, that will + override the font substitution. + */ + if ((type_info == (const TypeInfo *) NULL) + || /*found font family, but ...*/ + (pTheFoundFontFamilyName && + (LocaleCompare(pTheFoundFontFamilyName,type_info->family) != 0))) + {/*either not found, or different font family (probably font substitution)*/ + + /* try to match a font name */ + const TypeInfo *type_info2 = 0; + if (((type_info2 = GetTypeInfo(pTheFoundFontFamilyName, + &image->exception)) + == (const TypeInfo *) NULL) + && (pTheFoundFontFamilyName != 0) + && strlen(pTheFoundFontFamilyName) < sizeof(OneFontFamilyName)) + {/*change ' ' to '-' and try again*/ + + /* + Change blanks to hyphens (i.e. make it look like a font + name vs. font family). Will only do this for font names + sizeof(OneFontFamilyName) long or less. + */ + char FontNameWithHyphens[sizeof(OneFontFamilyName)]; + char *pWithHyphens = FontNameWithHyphens; + char c; + const char *pFound; + for (pFound = pTheFoundFontFamilyName; + (*pWithHyphens = (((c = *pFound) != ' ') ? c : '-')); + pFound++, pWithHyphens++); + type_info2 = GetTypeInfo(FontNameWithHyphens,&image->exception); + + } /*change ' ' to '-' and try again*/ + + if ( type_info2 != (const TypeInfo *) NULL ) + type_info = type_info2; + + } /*either not found, or different font family (probably font substitution)*/ + if (type_info == (const TypeInfo *) NULL) return(RenderPostscript(image,draw_info,offset,metrics)); clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info); @@ -1043,6 +1182,9 @@ static MagickPassFail RenderFreetype(Image *image,const DrawInfo *draw_info, MagickPassFail status=MagickPass; + if (draw_info->font == (char *) NULL) + ThrowBinaryException(TypeError,FontNotSpecified,image->filename); + glyph.image=(FT_Glyph) 0; last_glyph.image=(FT_Glyph) 0; @@ -1052,7 +1194,7 @@ static MagickPassFail RenderFreetype(Image *image,const DrawInfo *draw_info, ft_status=FT_Init_FreeType(&library); if (ft_status) ThrowBinaryException(TypeError,UnableToInitializeFreetypeLibrary, - draw_info->font); + draw_info->font); if (*draw_info->font != '@') ft_status=FT_New_Face(library,draw_info->font,0,&face); else @@ -1194,12 +1336,12 @@ static MagickPassFail RenderFreetype(Image *image,const DrawInfo *draw_info, (void) FT_Done_Face(face); (void) FT_Done_FreeType(library); (void) LogMagickEvent(AnnotateEvent,GetMagickModule(), - "Text encoding failed: encoding_type=%ld " - "draw_info->encoding=\"%s\" draw_info->text=\"%s\" length=%ld", - (long) encoding_type, - (draw_info->encoding ? draw_info->encoding : "(null)"), - (draw_info->text ? draw_info->text : "(null)"), - (long) length); + "Text encoding failed: encoding_type=%ld " + "draw_info->encoding=\"%s\" draw_info->text=\"%s\" length=%ld", + (long) encoding_type, + (draw_info->encoding ? draw_info->encoding : "(null)"), + (draw_info->text ? draw_info->text : "(null)"), + (long) length); ThrowBinaryException(ResourceLimitError,MemoryAllocationFailed, draw_info->font) } @@ -1370,7 +1512,12 @@ static MagickPassFail RenderFreetype(Image *image,const DrawInfo *draw_info, { continue; } - opacity=((MaxRGB-opacity)*(MaxRGB-fill_color.opacity))/MaxRGB; + /* + At this point, opacity is 0==transparent to MaxRGB==opaque, and represents an + anti-aliasing edge blending value. The computation below integrates in the + fill color opacity, and converts the result to 0=opaque to MaxRGB=transparent. + */ + opacity=MaxRGB-(opacity*(MaxRGB-fill_color.opacity)+/*round*/(MaxRGB>>1))/MaxRGB; AlphaCompositePixel(q,&fill_color,opacity,q, image->matte ? q->opacity : OpaqueOpacity); if (!active) diff --git a/magick/api.h b/magick/api.h index 6817c06..8a51223 100644 --- a/magick/api.h +++ b/magick/api.h @@ -2,11 +2,11 @@ Copyright (C) 2003 - 2012 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick Application Programming Interface declarations. */ diff --git a/magick/attribute.c b/magick/attribute.c index 9a77c11..010eca2 100644 --- a/magick/attribute.c +++ b/magick/attribute.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2016 GraphicsMagick Group +% Copyright (C) 2003-2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % % This program is covered by multiple licenses, which are described in @@ -61,7 +61,7 @@ static void DestroyImageAttribute(ImageAttribute *attribute); % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% CloneImageAttributes() copies the text attibutes from one image to another. +% CloneImageAttributes() copies the text attributes from one image to another. % Any text attributes in the destination image are preserved. % CloneImageAttributes returns MagickPass if all of the attribututes are % successfully cloned or MagickFail if there is a memory allocation error. @@ -81,7 +81,7 @@ static void DestroyImageAttribute(ImageAttribute *attribute); */ MagickExport MagickPassFail CloneImageAttributes(Image* clone_image, - const Image* original_image) + const Image* original_image) { MagickPassFail status; @@ -98,19 +98,22 @@ CloneImageAttributes(Image* clone_image, /* Search for tail of list (if any) */ - for(cloned_attributes=clone_image->attributes; - cloned_attributes != (ImageAttribute *) NULL; - cloned_attributes=cloned_attributes->next); + if ((cloned_attributes=clone_image->attributes)) + { + for( ; + cloned_attributes->next != (ImageAttribute *) NULL; + cloned_attributes=cloned_attributes->next); + } attribute=GetImageAttribute(original_image,(char *) NULL); for ( ; attribute != (const ImageAttribute *) NULL; - attribute=attribute->next) + attribute=attribute->next) { /* Construct AttributeInfo to append. */ cloned_attribute=MagickAllocateMemory(ImageAttribute *, - sizeof(ImageAttribute)); + sizeof(ImageAttribute)); if (cloned_attribute == (ImageAttribute *) NULL) { status = MagickFail; @@ -119,7 +122,7 @@ CloneImageAttributes(Image* clone_image, cloned_attribute->key=AcquireString(attribute->key); cloned_attribute->length=attribute->length; cloned_attribute->value= - MagickAllocateMemory(char *,cloned_attribute->length+1); + MagickAllocateMemory(char *,cloned_attribute->length+1); cloned_attribute->previous=(ImageAttribute *) NULL; cloned_attribute->next=(ImageAttribute *) NULL; if ((cloned_attribute->value == (char *) NULL) || @@ -331,22 +334,22 @@ GenerateIPTCAttribute(Image *image,const char *key) for (i=0; i < (long) profile_length; i++) { if (profile[i] != 0x1cU) - continue; + continue; if (profile[i+1] != dataset) - { - /* fprintf(stderr,"Skipping dataset %d\n",profile[i+1]); */ - continue; - } + { + /* fprintf(stderr,"Skipping dataset %d\n",profile[i+1]); */ + continue; + } if (profile[i+2] != record) - { - /* fprintf(stderr,"Skipping record %d\n",profile[i+2]); */ - continue; - } + { + /* fprintf(stderr,"Skipping record %d\n",profile[i+2]); */ + continue; + } length=profile[i+3] << 8; length|=profile[i+4]; attribute=MagickAllocateMemory(char *,length+1); if (attribute == (char *) NULL) - continue; + continue; (void) strlcpy(attribute,(char *) profile+i+5,length+1); (void) SetImageAttribute(image,key,(const char *) attribute); MagickFreeMemory(attribute); @@ -368,7 +371,7 @@ ReadByte(unsigned char **p,size_t *length) return(c); } -static long +static magick_int32_t ReadMSBLong(unsigned char **p,size_t *length) { int @@ -401,7 +404,7 @@ ReadMSBLong(unsigned char **p,size_t *length) return(value.s); } -static int +static magick_int32_t ReadMSBShort(unsigned char **p,size_t *length) { int @@ -433,13 +436,28 @@ ReadMSBShort(unsigned char **p,size_t *length) } /* - FIXME: length is defined as type size_t, and then code incorrectly - assumes that size_t is a signed type + Advance 'blob' by 'amount' or the amount remaining in 'length'. + Decrement 'length' by 'amount' or to zero. */ +static inline size_t AdvanceBlob(const size_t amount, size_t length, unsigned char **blob) +{ + if (length > amount) + { + *blob+=amount; + length-=amount; + } + else + { + *blob+=length; + length=0U; + } + return length; +} + static char * TracePSClippingPath(unsigned char *blob,size_t length, - unsigned long columns, - unsigned long rows) + const unsigned long columns, + const unsigned long rows) { char *path, @@ -506,170 +524,166 @@ TracePSClippingPath(unsigned char *blob,size_t length, { selector=ReadMSBShort(&blob,&length); switch (selector) - { - case 0: - case 3: - { - if (knot_count == 0) - { - /* - Expected subpath length record - */ - knot_count=ReadMSBShort(&blob,&length); - blob+=22; - length-=22; - } - else - { - blob+=24; - length-=24; - } - break; - } - case 1: - case 2: - case 4: - case 5: - { - if (knot_count == 0) - { - /* - Unexpected subpath knot - */ - blob+=24; - length-=24; - } - else - { - /* - Add sub-path knot - */ - for (i=0; i < 3; i++) - { - y=ReadMSBLong(&blob,&length); - x=ReadMSBLong(&blob,&length); - point[i].x=(double) x/4096/4096; - point[i].y=1.0-(double) y/4096/4096; - } - if (!in_subpath) - { - FormatString(message,"%.6f %.6f m\n", - point[1].x,point[1].y); - for (i=0; i < 3; i++) - { - first[i]=point[i]; - last[i]=point[i]; - } - } - else - { - /* - Handle special cases when Bezier curves are used - to describe corners and straight lines. This - special handling is desirable to bring down the - size in bytes of the clipping path data. - */ - if ((last[1].x == last[2].x) && - (last[1].y == last[2].y) && - (point[0].x == point[1].x) && - (point[0].y == point[1].y)) - { - /* - First control point equals first anchor - point and last control point equals last - anchow point. Straigt line between anchor - points. - */ - FormatString(message,"%.6f %.6f l\n", - point[1].x,point[1].y); - } - else if ((last[1].x == last[2].x) && - (last[1].y == last[2].y)) - { - /* First control point equals first anchor point */ - FormatString(message,"%.6f %.6f %.6f %.6f v\n", - point[0].x,point[0].y, - point[1].x,point[1].y); - } - else if ((point[0].x == point[1].x) && - (point[0].y == point[1].y)) - { - /* Last control point equals last anchow point. */ - FormatString(message,"%.6f %.6f %.6f %.6f y\n", - last[2].x,last[2].y, - point[1].x,point[1].y); - } - else - { - /* The full monty */ - FormatString(message, - "%.6f %.6f %.6f %.6f %.6f %.6f c\n", - last[2].x,last[2].y,point[0].x, - point[0].y,point[1].x, - point[1].y); - } - for (i=0; i < 3; i++) - last[i]=point[i]; - } - (void) ConcatenateString(&path,message); - in_subpath=True; - knot_count--; - /* - Close the subpath if there are no more knots. - */ - if (knot_count == 0) - { - /* - Same special handling as above except we compare - to the first point in the path and close the - path. - */ - if ((last[1].x == last[2].x) && - (last[1].y == last[2].y) && - (first[0].x == first[1].x) && - (first[0].y == first[1].y)) - { - FormatString(message,"%.6f %.6f l z\n", - first[1].x,first[1].y); - } - else if ((last[1].x == last[2].x) && - (last[1].y == last[2].y)) - { - FormatString(message,"%.6f %.6f %.6f %.6f v z\n", - first[0].x,first[0].y, - first[1].x,first[1].y); - } - else if ((first[0].x == first[1].x) && - (first[0].y == first[1].y)) - { - FormatString(message,"%.6f %.6f %.6f %.6f y z\n", - last[2].x,last[2].y, - first[1].x,first[1].y); - } - else - { - FormatString(message, - "%.6f %.6f %.6f %.6f %.6f %.6f c z\n", - last[2].x,last[2].y, - first[0].x,first[0].y, - first[1].x,first[1].y); - } - (void) ConcatenateString(&path,message); - in_subpath=False; - } - } - break; - } - case 6: - case 7: - case 8: - default: - { - blob+=24; - length-=24; - break; - } - } + { + case 0: + case 3: + { + if (knot_count == 0) + { + /* + Expected subpath length record + */ + knot_count=ReadMSBShort(&blob,&length); + length=AdvanceBlob(22U,length,&blob); + } + else + { + length=AdvanceBlob(24U,length,&blob); + } + break; + } + case 1: + case 2: + case 4: + case 5: + { + if (knot_count == 0) + { + /* + Unexpected subpath knot + */ + length=AdvanceBlob(24U,length,&blob); + } + else + { + /* + Add sub-path knot + */ + for (i=0; i < 3; i++) + { + y=ReadMSBLong(&blob,&length); + x=ReadMSBLong(&blob,&length); + point[i].x=(double) x/4096/4096; + point[i].y=1.0-(double) y/4096/4096; + } + if (!in_subpath) + { + FormatString(message,"%.6f %.6f m\n", + point[1].x,point[1].y); + for (i=0; i < 3; i++) + { + first[i]=point[i]; + last[i]=point[i]; + } + } + else + { + /* + Handle special cases when Bezier curves are used + to describe corners and straight lines. This + special handling is desirable to bring down the + size in bytes of the clipping path data. + */ + if ((last[1].x == last[2].x) && + (last[1].y == last[2].y) && + (point[0].x == point[1].x) && + (point[0].y == point[1].y)) + { + /* + First control point equals first anchor + point and last control point equals last + anchow point. Straigt line between anchor + points. + */ + FormatString(message,"%.6f %.6f l\n", + point[1].x,point[1].y); + } + else if ((last[1].x == last[2].x) && + (last[1].y == last[2].y)) + { + /* First control point equals first anchor point */ + FormatString(message,"%.6f %.6f %.6f %.6f v\n", + point[0].x,point[0].y, + point[1].x,point[1].y); + } + else if ((point[0].x == point[1].x) && + (point[0].y == point[1].y)) + { + /* Last control point equals last anchow point. */ + FormatString(message,"%.6f %.6f %.6f %.6f y\n", + last[2].x,last[2].y, + point[1].x,point[1].y); + } + else + { + /* The full monty */ + FormatString(message, + "%.6f %.6f %.6f %.6f %.6f %.6f c\n", + last[2].x,last[2].y,point[0].x, + point[0].y,point[1].x, + point[1].y); + } + for (i=0; i < 3; i++) + last[i]=point[i]; + } + (void) ConcatenateString(&path,message); + in_subpath=True; + knot_count--; + /* + Close the subpath if there are no more knots. + */ + if (knot_count == 0) + { + /* + Same special handling as above except we compare + to the first point in the path and close the + path. + */ + if ((last[1].x == last[2].x) && + (last[1].y == last[2].y) && + (first[0].x == first[1].x) && + (first[0].y == first[1].y)) + { + FormatString(message,"%.6f %.6f l z\n", + first[1].x,first[1].y); + } + else if ((last[1].x == last[2].x) && + (last[1].y == last[2].y)) + { + FormatString(message,"%.6f %.6f %.6f %.6f v z\n", + first[0].x,first[0].y, + first[1].x,first[1].y); + } + else if ((first[0].x == first[1].x) && + (first[0].y == first[1].y)) + { + FormatString(message,"%.6f %.6f %.6f %.6f y z\n", + last[2].x,last[2].y, + first[1].x,first[1].y); + } + else + { + FormatString(message, + "%.6f %.6f %.6f %.6f %.6f %.6f c z\n", + last[2].x,last[2].y, + first[0].x,first[0].y, + first[1].x,first[1].y); + } + (void) ConcatenateString(&path,message); + in_subpath=False; + } + } + break; + } + case 6: + case 7: + case 8: + default: + { + length=AdvanceBlob(24U,length,&blob); + break; + } + } } /* Returns an empty PS path if the path has no knots. @@ -682,13 +696,11 @@ TracePSClippingPath(unsigned char *blob,size_t length, return(path); } -/* - FIXME: length is defined as type size_t, and then code incorrectly - assumes that size_t is a signed type. -*/ static char * -TraceSVGClippingPath(unsigned char *blob,size_t length, - unsigned long columns,unsigned long rows) +TraceSVGClippingPath(unsigned char *blob, + size_t length, + const unsigned long columns, + const unsigned long rows) { char *path, @@ -746,137 +758,133 @@ TraceSVGClippingPath(unsigned char *blob,size_t length, { selector=ReadMSBShort(&blob,&length); switch (selector) - { - case 0: - case 3: - { - if (knot_count == 0) - { - /* - Expected subpath length record - */ - knot_count=ReadMSBShort(&blob,&length); - blob+=22; - length-=22; - } - else - { - blob+=24; - length-=24; - } - break; - } - case 1: - case 2: - case 4: - case 5: - { - if (knot_count == 0) - { - /* - Unexpected subpath knot - */ - blob+=24; - length-=24; - } - else - { - /* - Add sub-path knot - */ - for (i=0; i < 3; i++) - { - y=ReadMSBLong(&blob,&length); - x=ReadMSBLong(&blob,&length); - point[i].x=(double) x*columns/4096/4096; - point[i].y=(double) y*rows/4096/4096; - } - if (!in_subpath) - { - FormatString(message,"M %.6f,%.6f\n", - point[1].x,point[1].y); - for (i=0; i < 3; i++) - { - first[i]=point[i]; - last[i]=point[i]; - } - } - else - { - /* - Handle special case when Bezier curves are used - to describe straight lines. - */ - if ((last[1].x == last[2].x) && - (last[1].y == last[2].y) && - (point[0].x == point[1].x) && - (point[0].y == point[1].y)) - { - /* - First control point equals first anchor - point and last control point equals last - anchow point. Straigt line between anchor - points. - */ - FormatString(message,"L %.6f,%.6f\n", - point[1].x,point[1].y); - } - else - { - FormatString(message, - "C %.6f,%.6f %.6f,%.6f %.6f,%.6f\n", - last[2].x,last[2].y, - point[0].x,point[0].y, - point[1].x,point[1].y); - } - for (i=0; i < 3; i++) - last[i]=point[i]; - } - (void) ConcatenateString(&path,message); - in_subpath=True; - knot_count--; - /* - Close the subpath if there are no more knots. - */ - if (knot_count == 0) - { - /* - Same special handling as above except we compare - to the first point in the path and close the - path. - */ - if ((last[1].x == last[2].x) && - (last[1].y == last[2].y) && - (first[0].x == first[1].x) && - (first[0].y == first[1].y)) - { - FormatString(message, - "L %.6f,%.6f Z\n",first[1].x,first[1].y); - } - else - { - FormatString(message, - "C %.6f,%.6f %.6f,%.6f %.6f,%.6f Z\n", - last[2].x,last[2].y, - first[0].x,first[0].y, - first[1].x,first[1].y); - (void) ConcatenateString(&path,message); - } - in_subpath=False; - } - } - break; - } - case 6: - case 7: - case 8: - default: - { - blob+=24; - length-=24; - break; - } - } + { + case 0: + case 3: + { + if (knot_count == 0) + { + /* + Expected subpath length record + */ + knot_count=ReadMSBShort(&blob,&length); + length=AdvanceBlob(22U,length,&blob); + } + else + { + length=AdvanceBlob(24U,length,&blob); + } + break; + } + case 1: + case 2: + case 4: + case 5: + { + if (knot_count == 0) + { + /* + Unexpected subpath knot + */ + length=AdvanceBlob(24U,length,&blob); + } + else + { + /* + Add sub-path knot + */ + for (i=0; i < 3; i++) + { + y=ReadMSBLong(&blob,&length); + x=ReadMSBLong(&blob,&length); + point[i].x=(double) x*columns/4096/4096; + point[i].y=(double) y*rows/4096/4096; + } + if (!in_subpath) + { + FormatString(message,"M %.6f,%.6f\n", + point[1].x,point[1].y); + for (i=0; i < 3; i++) + { + first[i]=point[i]; + last[i]=point[i]; + } + } + else + { + /* + Handle special case when Bezier curves are used + to describe straight lines. + */ + if ((last[1].x == last[2].x) && + (last[1].y == last[2].y) && + (point[0].x == point[1].x) && + (point[0].y == point[1].y)) + { + /* + First control point equals first anchor + point and last control point equals last + anchow point. Straigt line between anchor + points. + */ + FormatString(message,"L %.6f,%.6f\n", + point[1].x,point[1].y); + } + else + { + FormatString(message, + "C %.6f,%.6f %.6f,%.6f %.6f,%.6f\n", + last[2].x,last[2].y, + point[0].x,point[0].y, + point[1].x,point[1].y); + } + for (i=0; i < 3; i++) + last[i]=point[i]; + } + (void) ConcatenateString(&path,message); + in_subpath=True; + knot_count--; + /* + Close the subpath if there are no more knots. + */ + if (knot_count == 0) + { + /* + Same special handling as above except we compare + to the first point in the path and close the + path. + */ + if ((last[1].x == last[2].x) && + (last[1].y == last[2].y) && + (first[0].x == first[1].x) && + (first[0].y == first[1].y)) + { + FormatString(message, + "L %.6f,%.6f Z\n",first[1].x,first[1].y); + } + else + { + FormatString(message, + "C %.6f,%.6f %.6f,%.6f %.6f,%.6f Z\n", + last[2].x,last[2].y, + first[0].x,first[0].y, + first[1].x,first[1].y); + (void) ConcatenateString(&path,message); + } + in_subpath=False; + } + } + break; + } + case 6: + case 7: + case 8: + default: + { + length=AdvanceBlob(24U,length,&blob); + break; + } + } } /* Returns an empty SVG image if the path has no knots. @@ -958,34 +966,34 @@ Generate8BIMAttribute(Image *image,const char *key) while ((length > 0) && (status == False)) { if (ReadByte(&info,&length) != '8') - continue; + continue; if (ReadByte(&info,&length) != 'B') - continue; + continue; if (ReadByte(&info,&length) != 'I') - continue; + continue; if (ReadByte(&info,&length) != 'M') - continue; + continue; id=ReadMSBShort(&info,&length); if (id < start) - continue; + continue; if (id > stop) - continue; + continue; if (resource != (char *)NULL) MagickFreeMemory(resource); count=ReadByte(&info,&length); if ((count > 0) && ((size_t) count <= length)) - { - resource=(char *) MagickAllocateMemory(char *, + { + resource=(char *) MagickAllocateMemory(char *, (size_t) count+MaxTextExtent); - if (resource != (char *) NULL) - { - for (i=0; i < count; i++) - resource[i]=(char) ReadByte(&info,&length); - resource[count]='\0'; - } - } + if (resource != (char *) NULL) + { + for (i=0; i < count; i++) + resource[i]=(char) ReadByte(&info,&length); + resource[count]='\0'; + } + } if (!(count & 0x01)) - (void) ReadByte(&info,&length); + (void) ReadByte(&info,&length); count=ReadMSBLong(&info,&length); /* ReadMSBLong() can return negative values such as -1 or any @@ -997,59 +1005,59 @@ Generate8BIMAttribute(Image *image,const char *key) continue; } if ((*name != '\0') && (*name != '#')) - { - if ((resource == (char *) NULL) || - (LocaleCompare(name,resource) != 0)) - { - /* - No name match, scroll forward and try next resource. - */ - info+=count; - length-=count; - continue; - } - } + { + if ((resource == (char *) NULL) || + (LocaleCompare(name,resource) != 0)) + { + /* + No name match, scroll forward and try next resource. + */ + info+=count; + length-=count; + continue; + } + } if ((*name == '#') && (sub_number != 1)) - { - /* - No numbered match, scroll forward and try next resource. - */ - sub_number--; - info+=count; - length-=count; - continue; - } + { + /* + No numbered match, scroll forward and try next resource. + */ + sub_number--; + info+=count; + length-=count; + continue; + } /* - We have the resource of interest. + We have the resource of interest. */ attribute=(char *) MagickAllocateMemory(char *, (size_t) count+MaxTextExtent); if (attribute != (char *) NULL) - { - (void) memcpy(attribute,(char *) info,(size_t) count); - attribute[count]='\0'; - info+=count; - length-=count; - if ((id <= 1999) || (id >= 2999)) - { - (void) SetImageAttribute(image,key,(const char *) attribute); - } - else - { - char - *path; - if (LocaleCompare("SVG",format) == 0) - path=TraceSVGClippingPath((unsigned char *) attribute,count, - image->columns,image->rows); - else - path=TracePSClippingPath((unsigned char *) attribute,count, - image->columns,image->rows); - (void) SetImageAttribute(image,key,(const char *) path); - MagickFreeMemory(path); - } - MagickFreeMemory(attribute); - status=True; - } + { + (void) memcpy(attribute,(char *) info,(size_t) count); + attribute[count]='\0'; + info+=count; + length-=count; + if ((id <= 1999) || (id >= 2999)) + { + (void) SetImageAttribute(image,key,(const char *) attribute); + } + else + { + char + *path; + if (LocaleCompare("SVG",format) == 0) + path=TraceSVGClippingPath((unsigned char *) attribute,count, + image->columns,image->rows); + else + path=TracePSClippingPath((unsigned char *) attribute,count, + image->columns,image->rows); + (void) SetImageAttribute(image,key,(const char *) path); + MagickFreeMemory(path); + } + MagickFreeMemory(attribute); + status=True; + } } if (resource != (char *)NULL) MagickFreeMemory(resource); @@ -1359,19 +1367,19 @@ static const TagInfo */ static const char * -EXIFTagToDescription(int t, char *tag_description) +EXIFTagToDescription(unsigned int t, char *tag_description) { unsigned int i; - for (i=0; i < sizeof(tag_table)/sizeof(tag_table[0]); i++) + for (i=0; i < ArraySize(tag_table); i++) { if (tag_table[i].tag == t) - { - (void) strlcpy(tag_description,tag_table[i].description, - MaxTextExtent); - return tag_description; - } + { + (void) strlcpy(tag_description,tag_table[i].description, + MaxTextExtent); + return tag_description; + } } FormatString(tag_description,"0x%04X",t); @@ -1395,7 +1403,7 @@ EXIFDescriptionToTag(const char *description) } static const char * -EXIFFormatToDescription(int f) +EXIFFormatToDescription(unsigned int f) { const char *description; @@ -1445,7 +1453,7 @@ EXIFFormatToDescription(int f) return description; } -static int +static unsigned int format_bytes[] = { 0, @@ -1463,55 +1471,61 @@ static int 8 /* DOUBLE */ }; -static short -Read16s(int morder,void *ishort) +static magick_int16_t +Read16s(int morder,unsigned char *ishort) { - short - value; + union + { + magick_uint16_t u; + magick_int16_t s; + } value; if (morder) - value=(((unsigned char *) ishort)[0] << 8) | ((unsigned char *) ishort)[1]; + value.u=((magick_uint16_t) ishort[0] << 8) | ishort[1]; else - value=(((unsigned char *) ishort)[1] << 8) | ((unsigned char *) ishort)[0]; - return(value); + value.u=((magick_uint16_t) ishort[1] << 8) | ishort[0]; + return(value.s); } -static unsigned short -Read16u(int morder,void *ishort) +static magick_uint16_t +Read16u(int morder,unsigned char *ishort) { - unsigned short + magick_uint16_t value; if (morder) - value=(((unsigned char *) ishort)[0] << 8) | ((unsigned char *) ishort)[1]; + value=((magick_uint16_t) ishort[0] << 8) | ishort[1]; else - value=(((unsigned char *) ishort)[1] << 8) | ((unsigned char *) ishort)[0]; + value=((magick_uint16_t) ishort[1] << 8) | ishort[0]; return(value); } -static long -Read32s(int morder,void *ilong) +static magick_int32_t +Read32s(int morder,unsigned char *ilong) { - long - value; + union + { + magick_uint32_t u; + magick_int32_t s; + } value; if (morder) - value=(((char *) ilong)[0] << 24) | (((unsigned char *) ilong)[1] << 16) | - (((unsigned char *) ilong)[2] << 8) | (((unsigned char *) ilong)[3]); + value.u=((magick_uint32_t) ilong[0] << 24) | (ilong[1] << 16) | + (ilong[2] << 8) | (ilong[3]); else - value=(((char *) ilong)[3] << 24) | (((unsigned char *) ilong)[2] << 16) | - (((unsigned char *) ilong)[1] << 8 ) | (((unsigned char *) ilong)[0]); - return(value); + value.u=((magick_uint32_t) ilong[3] << 24) | (ilong[2] << 16) | + (ilong[1] << 8 ) | (ilong[0]); + return(value.s); } -static unsigned long -Read32u(int morder, void *ilong) +static magick_uint32_t +Read32u(int morder, unsigned char *ilong) { - return(Read32s(morder,ilong) & 0xffffffffUL); + return(Read32s(morder,ilong) & 0xffffffff); } static void -Write16u(int morder, void *location, unsigned short value) +Write16u(int morder, void *location, magick_uint16_t value) { char *pval; @@ -1519,13 +1533,13 @@ Write16u(int morder, void *location, unsigned short value) pval = (char *)location; if (morder) { - *pval++ = (char)((value >> 8) & 0xffL); - *pval++ = (char)(value & 0xffL); + *pval++ = (char)((value >> 8) & 0xff); + *pval++ = (char)(value & 0xff); } else { - *pval++ = (char)(value & 0xffL); - *pval++ = (char)((value >> 8) & 0xffL); + *pval++ = (char)(value & 0xff); + *pval++ = (char)((value >> 8) & 0xff); } } @@ -1573,7 +1587,7 @@ GenerateEXIFAttribute(Image *image,const char *specification) const unsigned char *profile_info; - + size_t profile_length; @@ -1584,19 +1598,19 @@ GenerateEXIFAttribute(Image *image,const char *specification) MagickBool debug=MagickFalse; - assert((sizeof(format_bytes)/sizeof(format_bytes[0])-1) == EXIF_NUM_FORMATS); + assert((ArraySize(format_bytes)-1) == EXIF_NUM_FORMATS); { const char * env_value; - + /* Allow enabling debug of EXIF tags */ if ((env_value=getenv("MAGICK_DEBUG_EXIF"))) { - if (LocaleCompare(env_value,"TRUE") == 0) - debug=MagickTrue; + if (LocaleCompare(env_value,"TRUE") == 0) + debug=MagickTrue; } } gpsfound=MagickFalse; @@ -1625,72 +1639,72 @@ GenerateEXIFAttribute(Image *image,const char *specification) switch(*key) { /* - Caller has asked for all the tags in the EXIF data. + Caller has asked for all the tags in the EXIF data. */ case '*': { - tag=0; - all=1; /* return the data in description=value format */ - break; + tag=0; + all=1; /* return the data in description=value format */ + break; } case '!': { - tag=0; - all=2; /* return the data in tageid=value format */ - break; + tag=0; + all=2; /* return the data in tageid=value format */ + break; } /* - Check for a hex based tag specification first. + Check for a hex based tag specification first. */ case '#': { - char - c; - - size_t - n; - - tag=0; - key++; - n=strlen(key); - if (n != 4) - goto generate_attribute_failure; - else - { - /* - Parse tag specification as a hex number. - */ - n/=4; - do - { - for (i=(long) n-1; i >= 0; i--) - { - c=(*key++); - tag<<=4; - if ((c >= '0') && (c <= '9')) - tag|=c-'0'; - else - if ((c >= 'A') && (c <= 'F')) - tag|=c-('A'-10); - else - if ((c >= 'a') && (c <= 'f')) - tag|=c-('a'-10); - else - goto generate_attribute_failure; - } - } while (*key != '\0'); - } - break; + char + c; + + size_t + n; + + tag=0; + key++; + n=strlen(key); + if (n != 4) + goto generate_attribute_failure; + else + { + /* + Parse tag specification as a hex number. + */ + n/=4; + do + { + for (i=(long) n-1; i >= 0; i--) + { + c=(*key++); + tag<<=4; + if ((c >= '0') && (c <= '9')) + tag|=c-'0'; + else + if ((c >= 'A') && (c <= 'F')) + tag|=c-('A'-10); + else + if ((c >= 'a') && (c <= 'f')) + tag|=c-('a'-10); + else + goto generate_attribute_failure; + } + } while (*key != '\0'); + } + break; } default: { - /* - Try to match the text with a tag name instead. - */ - tag=EXIFDescriptionToTag(key); - if (debug) - fprintf(stderr,"Found tag %d for key \"%s\"\n",tag,key); - break; + /* + Try to match the text with a tag name instead. + */ + tag=EXIFDescriptionToTag(key); + if (debug) + fprintf(stderr,"Found tag %d for key \"%s\"\n",tag,key); + break; } } if (tag < 0) @@ -1700,17 +1714,17 @@ GenerateEXIFAttribute(Image *image,const char *specification) while (length != 0) { if (ReadByte(&info,&length) != 0x45) - continue; + continue; if (ReadByte(&info,&length) != 0x78) - continue; + continue; if (ReadByte(&info,&length) != 0x69) - continue; + continue; if (ReadByte(&info,&length) != 0x66) - continue; + continue; if (ReadByte(&info,&length) != 0x00) - continue; + continue; if (ReadByte(&info,&length) != 0x00) - continue; + continue; break; } if (length < 16) @@ -1762,328 +1776,333 @@ GenerateEXIFAttribute(Image *image,const char *specification) if (nde > MAX_TAGS_PER_IFD) nde=MAX_TAGS_PER_IFD; for (; de < nde; de++) - { - unsigned int - n; + { + size_t + n; - int - t, - f, - c; + unsigned int + c, + f, + t; - unsigned char - *pde, + unsigned char + *pde, *pval; - pde=(unsigned char *) (ifdp+2+(12*de)); + pde=(unsigned char *) (ifdp+2+(12*de)); if (pde + 12 > tiffp + length) { if (debug) fprintf(stderr, "EXIF: Invalid Exif, entry is beyond metadata limit.\n"); goto generate_attribute_failure; } - t=Read16u(morder,pde); /* get tag value */ - f=Read16u(morder,pde+2); /* get the format */ - if ((f < 0) || - ((size_t) f >= sizeof(format_bytes)/sizeof(format_bytes[0]))) - break; - c=(long) Read32u(morder,pde+4); /* get number of components */ - n=c*format_bytes[f]; - if (n <= 4) - pval=(unsigned char *) pde+8; - else - { - unsigned long - oval; - - /* - The directory entry contains an offset. - */ - oval=Read32u(morder,pde+8); - if ((oval+n) > length) - continue; - pval=(unsigned char *)(tiffp+oval); - } - - if (debug) - { - fprintf(stderr, - "EXIF: TagVal=%d TagDescr=\"%s\" Format=%d " - "FormatDescr=\"%s\" Components=%d\n",t, - EXIFTagToDescription(t,tag_description),f, - EXIFFormatToDescription(f),c); - } - - if (gpsfound) - { - if ((t < GPS_TAG_START) || (t > GPS_TAG_STOP)) - { - if (debug) - fprintf(stderr, - "EXIF: Skipping bogus GPS IFD tag %d ...\n",t); - continue; - } - } - else - { - if ((t < EXIF_TAG_START) || ( t > EXIF_TAG_STOP)) - { - if (debug) - fprintf(stderr, - "EXIF: Skipping bogus EXIF IFD tag %d ...\n",t); - continue; - } - } - - /* - Return values for all the tags, or for a specific requested tag. - - Tags from the GPS sub-IFD are in a bit of a chicken and - egg situation in that the tag for the GPS sub-IFD will not - be seen unless we pass that tag through so it can be - processed. So we pass the GPS_OFFSET tag through, but if - it was not requested, then we don't return a string value - for it. - */ - if (all || (tag == t) || (GPS_OFFSET == t)) - { - char - s[MaxTextExtent]; - - switch (f) - { - case EXIF_FMT_SBYTE: - { - /* 8-bit signed integer */ - FormatString(s,"%ld",(long) (*(char *) pval)); - value=AllocateString(s); - break; - } - case EXIF_FMT_BYTE: - { - /* 8-bit unsigned integer */ - value=MagickAllocateMemory(char *,n+1); - if (value != (char *) NULL) - { - unsigned int - a; - - for (a=0; a < n; a++) - { - value[a]='.'; - if (isprint((int) pval[a])) - value[a]=pval[a]; - } - value[a]='\0'; - break; - } + t=Read16u(morder,pde); /* get tag value */ + f=Read16u(morder,pde+2); /* get the format */ + if ((size_t) f >= ArraySize(format_bytes)) + break; + c=Read32u(morder,pde+4); /* get number of components */ + n=MagickArraySize(c,format_bytes[f]); + if ((n == 0) && (c != 0) && (format_bytes[f] != 0)) + { + if (debug) + fprintf(stderr, "EXIF: Invalid Exif, too many components (%u).\n",c); + goto generate_attribute_failure; + } + if (n <= 4) + pval=(unsigned char *) pde+8; + else + { + unsigned long + oval; + + /* + The directory entry contains an offset. + */ + oval=Read32u(morder,pde+8); + if ((oval+n) > length) + continue; + pval=(unsigned char *)(tiffp+oval); + } + + if (debug) + { + fprintf(stderr, + "EXIF: TagVal=%d TagDescr=\"%s\" Format=%d " + "FormatDescr=\"%s\" Components=%u\n",t, + EXIFTagToDescription(t,tag_description),f, + EXIFFormatToDescription(f),c); + } + + if (gpsfound) + { + if ((t < GPS_TAG_START) || (t > GPS_TAG_STOP)) + { + if (debug) + fprintf(stderr, + "EXIF: Skipping bogus GPS IFD tag %d ...\n",t); + continue; + } + } + else + { + if ((t < EXIF_TAG_START) || ( t > EXIF_TAG_STOP)) + { + if (debug) + fprintf(stderr, + "EXIF: Skipping bogus EXIF IFD tag %d ...\n",t); + continue; + } + } + + /* + Return values for all the tags, or for a specific requested tag. + + Tags from the GPS sub-IFD are in a bit of a chicken and + egg situation in that the tag for the GPS sub-IFD will not + be seen unless we pass that tag through so it can be + processed. So we pass the GPS_OFFSET tag through, but if + it was not requested, then we don't return a string value + for it. + */ + if (all || (tag == (int) t) || (GPS_OFFSET == t)) + { + char + s[MaxTextExtent]; + + switch (f) + { + case EXIF_FMT_SBYTE: + { + /* 8-bit signed integer */ + FormatString(s,"%ld",(long) (*(char *) pval)); + value=AllocateString(s); + break; + } + case EXIF_FMT_BYTE: + { + /* 8-bit unsigned integer */ + value=MagickAllocateMemory(char *,n+1); + if (value != (char *) NULL) + { + unsigned int + a; + + for (a=0; a < n; a++) + { + value[a]='.'; + if (isprint((int) pval[a])) + value[a]=pval[a]; + } + value[a]='\0'; + break; + } #if 0 - printf("format %u, length %u\n",f,n); - FormatString(s,"%ld",(long) (*(unsigned char *) pval)); - value=AllocateString(s); + printf("format %u, length %u\n",f,n); + FormatString(s,"%ld",(long) (*(unsigned char *) pval)); + value=AllocateString(s); #endif - break; - } - case EXIF_FMT_SSHORT: - { - /* 16-bit signed integer */ - FormatString(s,"%hd",Read16u(morder,pval)); - value=AllocateString(s); - break; - } - case EXIF_FMT_USHORT: - { - /* 16-bit unsigned integer */ - FormatString(s,"%hu",Read16s(morder,pval)); - value=AllocateString(s); - break; - } - case EXIF_FMT_ULONG: - { - offset=Read32u(morder,pval); - /* - Only report value if this tag was requested. - */ - if (all || (tag == t)) - { - FormatString(s,"%lu",offset); - value=AllocateString(s); - } - if (GPS_OFFSET == t) - gpsoffset=offset; - break; - } - case EXIF_FMT_SLONG: - { - FormatString(s,"%ld",Read32s(morder,pval)); - value=AllocateString(s); - break; - } - case EXIF_FMT_URATIONAL: - { - if (gpsfound && - (t == GPS_LATITUDE || - t == GPS_LONGITUDE || - t == GPS_TIMESTAMP)) - { - FormatString(s,"%ld/%ld,%ld/%ld,%ld/%ld" - ,Read32u(morder,pval), - Read32u(morder,4+(char *) pval) - ,Read32u(morder,8+(char *)pval), - Read32u(morder,12+(char *) pval) - ,Read32u(morder,16+(char *)pval), - Read32u(morder,20+(char *) pval) - ); - } - else - { - FormatString(s,"%ld/%ld" - ,Read32u(morder,pval), - Read32u(morder,4+(char *) pval) - ); - } - value=AllocateString(s); - break; - } - case EXIF_FMT_SRATIONAL: - { - FormatString(s,"%ld/%ld",Read32s(morder,pval), - Read32s(morder,4+(char *) pval)); - value=AllocateString(s); - break; - } - case EXIF_FMT_SINGLE: - { - FormatString(s,"%f",(double) *(float *) pval); - value=AllocateString(s); - break; - } - case EXIF_FMT_DOUBLE: - { - FormatString(s,"%f",*(double *) pval); - value=AllocateString(s); - break; - } - default: - case EXIF_FMT_UNDEFINED: - case EXIF_FMT_STRING: - { - unsigned int - a; - - size_t - allocation_size; - - MagickBool - binary=MagickFalse; - - allocation_size=n+1; - for (a=0; a < n; a++) - if (!(isprint((int) pval[a]))) - allocation_size += 3; - - value=MagickAllocateMemory(char *,allocation_size); - if (value != (char *) NULL) - { - i=0; - for (a=0; a < n; a++) - { - if ((f == EXIF_FMT_STRING) && (pval[a] == '\0')) - break; - if ((isprint((int) pval[a])) || - ((pval[a] == '\0') && - (a == (n-1) && (!binary)))) - { - value[i++]=pval[a]; - } - else - { - i += sprintf(&value[i],"\\%03o", - (unsigned int) pval[a]); - binary |= MagickTrue; - } - } - value[i]='\0'; - } - break; - } - } - if (value != (char *) NULL) - { - const char - *description; - - if (strlen(final) != 0) - (void) ConcatenateString(&final,EXIF_DELIMITER); - description=(const char *) NULL; - switch (all) - { - case 1: - { - description=EXIFTagToDescription(t,tag_description); - FormatString(s,"%.1024s=",description); - (void) ConcatenateString(&final,s); - break; - } - case 2: - { - FormatString(s,"#%04x=",t); - (void) ConcatenateString(&final,s); - break; - } - } - (void) ConcatenateString(&final,value); - MagickFreeMemory(value); - } - } - if (t == GPS_OFFSET && (gpsoffset != 0)) - { - if ((gpsoffset < length) && (level < (DE_STACK_SIZE-2))) - { - /* - Push our current directory state onto the stack. - */ - ifdstack[level]=ifdp; - de++; /* bump to the next entry */ - destack[level]=de; - gpsfoundstack[level]=gpsfound; - level++; - /* - Push new state onto of stack to cause a jump. - */ - ifdstack[level]=tiffp+gpsoffset; - destack[level]=0; - gpsfoundstack[level]=MagickTrue; - level++; - } - gpsoffset=0; - break; /* break out of the for loop */ - } - - if ((t == TAG_EXIF_OFFSET) || (t == TAG_INTEROP_OFFSET)) - { - offset=Read32u(morder,pval); - if ((offset < length) && (level < (DE_STACK_SIZE-2))) - { - /* - Push our current directory state onto the stack. - */ - ifdstack[level]=ifdp; - de++; /* bump to the next entry */ - destack[level]=de; - gpsfoundstack[level]=gpsfound; - level++; - /* - Push new state onto of stack to cause a jump. - */ - ifdstack[level]=tiffp+offset; - destack[level]=0; - gpsfoundstack[level]=MagickFalse; - level++; - } - break; /* break out of the for loop */ - } - } + break; + } + case EXIF_FMT_SSHORT: + { + /* 16-bit signed integer */ + FormatString(s,"%hd",Read16u(morder,pval)); + value=AllocateString(s); + break; + } + case EXIF_FMT_USHORT: + { + /* 16-bit unsigned integer */ + FormatString(s,"%hu",Read16s(morder,pval)); + value=AllocateString(s); + break; + } + case EXIF_FMT_ULONG: + { + offset=Read32u(morder,pval); + /* + Only report value if this tag was requested. + */ + if (all || (tag == (int) t)) + { + FormatString(s,"%lu",offset); + value=AllocateString(s); + } + if (GPS_OFFSET == t) + gpsoffset=offset; + break; + } + case EXIF_FMT_SLONG: + { + FormatString(s,"%d",(int) Read32s(morder,pval)); + value=AllocateString(s); + break; + } + case EXIF_FMT_URATIONAL: + { + if (gpsfound && + (t == GPS_LATITUDE || + t == GPS_LONGITUDE || + t == GPS_TIMESTAMP)) + { + FormatString(s,"%u/%u,%u/%u,%u/%u" + ,(unsigned) Read32u(morder,pval), + (unsigned) Read32u(morder,4+pval) + ,(unsigned) Read32u(morder,8+pval), + (unsigned) Read32u(morder,12+pval) + ,(unsigned) Read32u(morder,16+pval), + (unsigned) Read32u(morder,20+pval) + ); + } + else + { + FormatString(s,"%u/%u" + ,(unsigned) Read32u(morder,pval), + (unsigned) Read32u(morder,4+pval) + ); + } + value=AllocateString(s); + break; + } + case EXIF_FMT_SRATIONAL: + { + FormatString(s,"%d/%d",(int) Read32s(morder,pval), + (int) Read32s(morder,4+pval)); + value=AllocateString(s); + break; + } + case EXIF_FMT_SINGLE: + { + FormatString(s,"%f",(double) *(float *) pval); + value=AllocateString(s); + break; + } + case EXIF_FMT_DOUBLE: + { + FormatString(s,"%f",*(double *) pval); + value=AllocateString(s); + break; + } + default: + case EXIF_FMT_UNDEFINED: + case EXIF_FMT_STRING: + { + unsigned int + a; + + size_t + allocation_size; + + MagickBool + binary=MagickFalse; + + allocation_size=n+1; + for (a=0; a < n; a++) + if (!(isprint((int) pval[a]))) + allocation_size += 3; + + value=MagickAllocateMemory(char *,allocation_size); + if (value != (char *) NULL) + { + i=0; + for (a=0; a < n; a++) + { + if ((f == EXIF_FMT_STRING) && (pval[a] == '\0')) + break; + if ((isprint((int) pval[a])) || + ((pval[a] == '\0') && + (a == (n-1) && (!binary)))) + { + value[i++]=pval[a]; + } + else + { + i += sprintf(&value[i],"\\%03o", + (unsigned int) pval[a]); + binary |= MagickTrue; + } + } + value[i]='\0'; + } + break; + } + } + if (value != (char *) NULL) + { + const char + *description; + + if (strlen(final) != 0) + (void) ConcatenateString(&final,EXIF_DELIMITER); + description=(const char *) NULL; + switch (all) + { + case 1: + { + description=EXIFTagToDescription(t,tag_description); + FormatString(s,"%.1024s=",description); + (void) ConcatenateString(&final,s); + break; + } + case 2: + { + FormatString(s,"#%04x=",t); + (void) ConcatenateString(&final,s); + break; + } + } + (void) ConcatenateString(&final,value); + MagickFreeMemory(value); + } + } + if (t == GPS_OFFSET && (gpsoffset != 0)) + { + if ((gpsoffset < length) && (level < (DE_STACK_SIZE-2))) + { + /* + Push our current directory state onto the stack. + */ + ifdstack[level]=ifdp; + de++; /* bump to the next entry */ + destack[level]=de; + gpsfoundstack[level]=gpsfound; + level++; + /* + Push new state onto of stack to cause a jump. + */ + ifdstack[level]=tiffp+gpsoffset; + destack[level]=0; + gpsfoundstack[level]=MagickTrue; + level++; + } + gpsoffset=0; + break; /* break out of the for loop */ + } + + if ((t == TAG_EXIF_OFFSET) || (t == TAG_INTEROP_OFFSET)) + { + offset=Read32u(morder,pval); + if ((offset < length) && (level < (DE_STACK_SIZE-2))) + { + /* + Push our current directory state onto the stack. + */ + ifdstack[level]=ifdp; + de++; /* bump to the next entry */ + destack[level]=de; + gpsfoundstack[level]=gpsfound; + level++; + /* + Push new state onto of stack to cause a jump. + */ + ifdstack[level]=tiffp+offset; + destack[level]=0; + gpsfoundstack[level]=MagickFalse; + level++; + } + break; /* break out of the for loop */ + } + } } while (level > 0); if (strlen(final) == 0) (void) ConcatenateString(&final,"unknown"); @@ -2285,7 +2304,7 @@ GetImageClippingPathAttribute(const Image *image) */ MagickExport const ImageAttribute * GetImageInfoAttribute(const ImageInfo *image_info,const Image *image, - const char *key) + const char *key) { char attribute[MaxTextExtent], @@ -2296,191 +2315,191 @@ GetImageInfoAttribute(const ImageInfo *image_info,const Image *image, { case 'b': { - if (LocaleNCompare("base",key,2) == 0) - { - GetPathComponent(image->magick_filename,BasePath,filename); - (void) strlcpy(attribute,filename,MaxTextExtent); - break; - } - break; + if (LocaleNCompare("base",key,2) == 0) + { + GetPathComponent(image->magick_filename,BasePath,filename); + (void) strlcpy(attribute,filename,MaxTextExtent); + break; + } + break; } case 'd': { - if (LocaleNCompare("depth",key,2) == 0) - { - FormatString(attribute,"%u",image->depth); - break; - } - if (LocaleNCompare("directory",key,2) == 0) - { - GetPathComponent(image->magick_filename,HeadPath,filename); - (void) strlcpy(attribute,filename,MaxTextExtent); - break; - } - break; + if (LocaleNCompare("depth",key,2) == 0) + { + FormatString(attribute,"%u",image->depth); + break; + } + if (LocaleNCompare("directory",key,2) == 0) + { + GetPathComponent(image->magick_filename,HeadPath,filename); + (void) strlcpy(attribute,filename,MaxTextExtent); + break; + } + break; } case 'e': { - if (LocaleNCompare("extension",key,2) == 0) - { - GetPathComponent(image->magick_filename,ExtensionPath,filename); - (void) strlcpy(attribute,filename,MaxTextExtent); - break; - } - break; + if (LocaleNCompare("extension",key,2) == 0) + { + GetPathComponent(image->magick_filename,ExtensionPath,filename); + (void) strlcpy(attribute,filename,MaxTextExtent); + break; + } + break; } case 'g': { - if (LocaleNCompare("group",key,2) == 0) - { - FormatString(attribute,"0x%lx",image_info->group); - break; - } - break; + if (LocaleNCompare("group",key,2) == 0) + { + FormatString(attribute,"0x%lx",image_info->group); + break; + } + break; } case 'h': { - if (LocaleNCompare("height",key,2) == 0) - { - FormatString(attribute,"%lu", - image->magick_rows ? image->magick_rows : 256L); - break; - } - break; + if (LocaleNCompare("height",key,2) == 0) + { + FormatString(attribute,"%lu", + image->magick_rows ? image->magick_rows : 256L); + break; + } + break; } case 'i': { - if (LocaleNCompare("input",key,2) == 0) - { - (void) strlcpy(attribute,image->filename,MaxTextExtent); - break; - } - break; + if (LocaleNCompare("input",key,2) == 0) + { + (void) strlcpy(attribute,image->filename,MaxTextExtent); + break; + } + break; } case 'm': { - if (LocaleNCompare("magick",key,2) == 0) - { - (void) strlcpy(attribute,image->magick,MaxTextExtent); - break; - } - break; + if (LocaleNCompare("magick",key,2) == 0) + { + (void) strlcpy(attribute,image->magick,MaxTextExtent); + break; + } + break; } case 'n': { - if (LocaleNCompare("name",key,2) == 0) - { - (void) strlcpy(attribute,filename,MaxTextExtent); - break; - } - break; + if (LocaleNCompare("name",key,2) == 0) + { + (void) strlcpy(attribute,filename,MaxTextExtent); + break; + } + break; } case 's': { - if (LocaleNCompare("size",key,2) == 0) - { - char - format[MaxTextExtent]; - - FormatSize(GetBlobSize(image),format); - FormatString(attribute,"%.1024s",format); - break; - } - if (LocaleNCompare("scene",key,2) == 0) - { - FormatString(attribute,"%lu",image->scene); - if (image_info->subrange != 0) - FormatString(attribute,"%lu",image_info->subimage); - break; - } - if (LocaleNCompare("scenes",key,6) == 0) - { - FormatString(attribute,"%lu", - (unsigned long) GetImageListLength(image)); - break; - } - break; + if (LocaleNCompare("size",key,2) == 0) + { + char + format[MaxTextExtent]; + + FormatSize(GetBlobSize(image),format); + FormatString(attribute,"%.1024s",format); + break; + } + if (LocaleNCompare("scene",key,2) == 0) + { + FormatString(attribute,"%lu",image->scene); + if (image_info->subrange != 0) + FormatString(attribute,"%lu",image_info->subimage); + break; + } + if (LocaleNCompare("scenes",key,6) == 0) + { + FormatString(attribute,"%lu", + (unsigned long) GetImageListLength(image)); + break; + } + break; } case 'o': { - if (LocaleNCompare("output",key,2) == 0) - { - (void) strlcpy(attribute,image_info->filename,MaxTextExtent); - break; - } - break; + if (LocaleNCompare("output",key,2) == 0) + { + (void) strlcpy(attribute,image_info->filename,MaxTextExtent); + break; + } + break; } case 'p': { - if (LocaleNCompare("page",key,2) == 0) - { - register const Image - *p; - - unsigned int - page; - - p=image; - for (page=1; p->previous != (Image *) NULL; page++) - p=p->previous; - FormatString(attribute,"%u",page); - break; - } - break; + if (LocaleNCompare("page",key,2) == 0) + { + register const Image + *p; + + unsigned int + page; + + p=image; + for (page=1; p->previous != (Image *) NULL; page++) + p=p->previous; + FormatString(attribute,"%u",page); + break; + } + break; } case 'u': { - if (LocaleNCompare("unique",key,2) == 0) - { - (void) strlcpy(filename,image_info->unique,MaxTextExtent); - if (*filename == '\0') - if(!AcquireTemporaryFileName(filename)) - return((ImageAttribute *) NULL); - (void) strlcpy(attribute,filename,MaxTextExtent); - break; - } - break; + if (LocaleNCompare("unique",key,2) == 0) + { + (void) strlcpy(filename,image_info->unique,MaxTextExtent); + if (*filename == '\0') + if(!AcquireTemporaryFileName(filename)) + return((ImageAttribute *) NULL); + (void) strlcpy(attribute,filename,MaxTextExtent); + break; + } + break; } case 'w': { - if (LocaleNCompare("width",key,2) == 0) - { - FormatString(attribute,"%lu", - image->magick_columns ? image->magick_columns : 256L); - break; - } - break; + if (LocaleNCompare("width",key,2) == 0) + { + FormatString(attribute,"%lu", + image->magick_columns ? image->magick_columns : 256L); + break; + } + break; } case 'x': { - if (LocaleNCompare("xresolution",key,2) == 0) - { - FormatString(attribute,"%g",image->x_resolution); - break; - } - break; + if (LocaleNCompare("xresolution",key,2) == 0) + { + FormatString(attribute,"%g",image->x_resolution); + break; + } + break; } case 'y': { - if (LocaleNCompare("yresolution",key,2) == 0) - { - FormatString(attribute,"%g",image->y_resolution); - break; - } - break; + if (LocaleNCompare("yresolution",key,2) == 0) + { + FormatString(attribute,"%g",image->y_resolution); + break; + } + break; } case 'z': { - if (LocaleNCompare("zero",key,2) == 0) - { - (void) strlcpy(filename,image_info->zero,MaxTextExtent); - if (*filename == '\0') - if(!AcquireTemporaryFileName(filename)) - return((ImageAttribute *) NULL); - (void) strlcpy(attribute,filename,MaxTextExtent); - break; - } - break; + if (LocaleNCompare("zero",key,2) == 0) + { + (void) strlcpy(filename,image_info->zero,MaxTextExtent); + if (*filename == '\0') + if(!AcquireTemporaryFileName(filename)) + return((ImageAttribute *) NULL); + (void) strlcpy(attribute,filename,MaxTextExtent); + break; + } + break; } } if (strlen(image->magick_filename) != 0) @@ -2584,7 +2603,7 @@ FindEXIFAttribute(const unsigned char *profile_info, attribp = (unsigned char *)NULL; - assert((sizeof(format_bytes)/sizeof(format_bytes[0])-1) == EXIF_NUM_FORMATS); + assert((ArraySize(format_bytes)-1) == EXIF_NUM_FORMATS); { const char * @@ -2670,13 +2689,13 @@ FindEXIFAttribute(const unsigned char *profile_info, nde=MAX_TAGS_PER_IFD; for (; de < nde; de++) { - unsigned int + size_t n; - int - t, + unsigned int + c, f, - c; + t; unsigned char *pde, @@ -2692,11 +2711,16 @@ FindEXIFAttribute(const unsigned char *profile_info, } t=Read16u(morder,pde); /* get tag value */ f=Read16u(morder,pde+2); /* get the format */ - if ((f < 0) || - ((size_t) f >= sizeof(format_bytes)/sizeof(format_bytes[0]))) + if ((size_t) f >= ArraySize(format_bytes)) break; - c=(long) Read32u(morder,pde+4); /* get number of components */ - n=c*format_bytes[f]; + c=Read32u(morder,pde+4); /* get number of components */ + n=MagickArraySize(c,format_bytes[f]); + if ((n == 0) && (c != 0) && (format_bytes[f] != 0)) + { + if (debug) + fprintf(stderr, "EXIF: Invalid Exif, too many components (%u).\n",c); + goto find_attribute_failure; + } if (n <= 4) pval=(unsigned char *) pde+8; else @@ -2717,7 +2741,7 @@ FindEXIFAttribute(const unsigned char *profile_info, { fprintf(stderr, "EXIF: TagVal=%d TagDescr=\"%s\" Format=%d " - "FormatDescr=\"%s\" Components=%d\n",t, + "FormatDescr=\"%s\" Components=%u\n",t, EXIFTagToDescription(t,tag_description),f, EXIFFormatToDescription(f),c); } diff --git a/magick/attribute.h b/magick/attribute.h index 9567648..b0d8393 100644 --- a/magick/attribute.h +++ b/magick/attribute.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + Methods to Get/Set/Destroy Image Text Attributes. */ #ifndef _MAGICK_ATTRIBUTE_H diff --git a/magick/average.c b/magick/average.c index aba6120..56721f9 100644 --- a/magick/average.c +++ b/magick/average.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2008 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2003 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -66,7 +66,7 @@ MagickExport Image *AverageImages(const Image *image,ExceptionInfo *exception) double number_scenes; - + unsigned long number_pixels; @@ -86,7 +86,7 @@ MagickExport Image *AverageImages(const Image *image,ExceptionInfo *exception) { const Image *next; - + for (next=image; next != (Image *) NULL; next=next->next) { if ((next->columns != image->columns) || (next->rows != image->rows)) @@ -136,9 +136,6 @@ MagickExport Image *AverageImages(const Image *image,ExceptionInfo *exception) MagickBool thread_status; -#if defined(HAVE_OPENMP) -# pragma omp critical (GM_AverageImages) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -213,19 +210,22 @@ MagickExport Image *AverageImages(const Image *image,ExceptionInfo *exception) } #if defined(HAVE_OPENMP) -# pragma omp critical (GM_AverageImages) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,average_image->rows)) - if (!MagickMonitorFormatted(row_count,average_image->rows,exception, - "[%s,...,%s] Average image sequence...", - image->filename,last_image->filename)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,average_image->rows)) + if (!MagickMonitorFormatted(row_count,average_image->rows,exception, + "[%s,...,%s] Average image sequence...", + image->filename,last_image->filename)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif + } } DestroyThreadViewDataSet(pixels_sums); @@ -238,4 +238,3 @@ MagickExport Image *AverageImages(const Image *image,ExceptionInfo *exception) return(average_image); } - diff --git a/magick/average.h b/magick/average.h index b0c7ee0..88cc0d9 100644 --- a/magick/average.h +++ b/magick/average.h @@ -2,11 +2,11 @@ Copyright (C) 2003 - 2009 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick Image Averaging Methods. */ #ifndef _MAGICK_AVERAGE_H diff --git a/magick/bit_stream.c b/magick/bit_stream.c index 6fd852c..8c321bb 100644 --- a/magick/bit_stream.c +++ b/magick/bit_stream.c @@ -1,13 +1,13 @@ /* Copyright (C) 2003 - 2015 GraphicsMagick Group - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. Interfaces to deal with marshalling quantums to and from a bit-stream. Written by Bob Friesenhahn, September 2003 - + */ #include "magick/studio.h" @@ -32,7 +32,7 @@ static const unsigned int BitAndMasks[33] = Initialize Bit Stream for reading */ MagickExport void MagickBitStreamInitializeRead(BitStreamReadHandle *bit_stream, - const unsigned char *bytes) + const unsigned char *bytes) { bit_stream->bytes = bytes; bit_stream->bits_remaining = 8; @@ -42,53 +42,53 @@ MagickExport void MagickBitStreamInitializeRead(BitStreamReadHandle *bit_stream, Return the requested number of bits from the current position in a bit stream. Stream is read in most-significant bit/byte "big endian" order. - + bit_stream - already initialized bit stream. requested_bits - number of bits to read */ MagickExport unsigned int MagickBitStreamMSBRead(BitStreamReadHandle *bit_stream, - const unsigned int requested_bits) + const unsigned int requested_bits) { register unsigned int remaining_quantum_bits, quantum; - + remaining_quantum_bits = requested_bits; quantum = 0; - + while (remaining_quantum_bits != 0) { register unsigned int - octet_bits; - + octet_bits; + octet_bits = remaining_quantum_bits; if (octet_bits > bit_stream->bits_remaining) - octet_bits = bit_stream->bits_remaining; - + octet_bits = bit_stream->bits_remaining; + remaining_quantum_bits -= octet_bits; bit_stream->bits_remaining -= octet_bits; - + quantum = (quantum << octet_bits) | - ((*bit_stream->bytes >> (bit_stream->bits_remaining)) - & BitAndMasks[octet_bits]); - + ((*bit_stream->bytes >> (bit_stream->bits_remaining)) + & BitAndMasks[octet_bits]); + if (bit_stream->bits_remaining == 0) - { - bit_stream->bytes++; - bit_stream->bits_remaining=8; - } + { + bit_stream->bytes++; + bit_stream->bits_remaining=8; + } } return quantum; } /* Initialize Bit Stream for writing - + bit_stream - bit stream to initialize. bytes - byte array to write bits to */ MagickExport void MagickBitStreamInitializeWrite(BitStreamWriteHandle *bit_stream, - unsigned char *bytes) + unsigned char *bytes) { bit_stream->bytes = bytes; bit_stream->bits_remaining = 8; @@ -98,99 +98,99 @@ MagickExport void MagickBitStreamInitializeWrite(BitStreamWriteHandle *bit_strea Write quantum using the specified number of bits at the current position in the bit stream. Stream is written in most-significant bit/byte "big endian" order. - + bit_stream - already initialized bit stream. requested_bits - number of bits to write to stream. quantum - value to write. */ MagickExport void MagickBitStreamMSBWrite(BitStreamWriteHandle *bit_stream, - const unsigned int requested_bits, - const unsigned int quantum) + const unsigned int requested_bits, + const unsigned int quantum) { register unsigned int remaining_quantum_bits = requested_bits; - + while (remaining_quantum_bits != 0) { register unsigned int - octet_bits; - + octet_bits; + octet_bits = remaining_quantum_bits; if (octet_bits > bit_stream->bits_remaining) - octet_bits = bit_stream->bits_remaining; + octet_bits = bit_stream->bits_remaining; remaining_quantum_bits -= octet_bits; if (bit_stream->bits_remaining == 8) - *bit_stream->bytes = 0; + *bit_stream->bytes = 0; bit_stream->bits_remaining -= octet_bits; *bit_stream->bytes |= - (((quantum >> (remaining_quantum_bits)) & - BitAndMasks[octet_bits]) << (bit_stream->bits_remaining)); + (((quantum >> (remaining_quantum_bits)) & + BitAndMasks[octet_bits]) << (bit_stream->bits_remaining)); if (bit_stream->bits_remaining == 0) - { - bit_stream->bytes++; - bit_stream->bits_remaining=8; - } + { + bit_stream->bytes++; + bit_stream->bits_remaining=8; + } } } - + /* Initialize Word Stream for reading - + word_stream - stream to initialize. read_func - function to retrieve the next word. read_func_state - state to pass to read_func. */ MagickExport void MagickWordStreamInitializeRead(WordStreamReadHandle *word_stream, - WordStreamReadFunc read_func, - void *read_func_state) + WordStreamReadFunc read_func, + void *read_func_state) { word_stream->word = 0; word_stream->bits_remaining = 0; word_stream->read_func = read_func; word_stream->read_func_state = read_func_state; } - + /* Return the requested number of bits from the current position in a 32-bit word stream. Stream is read starting with the least significant bits of the word. - + word_stream - an initialized word reader stream. requested_bits - number of bits to retrieve from the stream. */ MagickExport unsigned int MagickWordStreamLSBRead(WordStreamReadHandle *word_stream, - const unsigned int requested_bits) + const unsigned int requested_bits) { register unsigned int remaining_quantum_bits, quantum; - + remaining_quantum_bits = requested_bits; quantum = 0; - + while (remaining_quantum_bits != 0) { register unsigned int - word_bits; - + word_bits; + if (word_stream->bits_remaining == 0) - { - word_stream->word=word_stream->read_func(word_stream->read_func_state); - word_stream->bits_remaining=32; - } - + { + word_stream->word=word_stream->read_func(word_stream->read_func_state); + word_stream->bits_remaining=32; + } + word_bits = remaining_quantum_bits; if (word_bits > word_stream->bits_remaining) - word_bits = word_stream->bits_remaining; - + word_bits = word_stream->bits_remaining; + quantum |= (((word_stream->word >> (32-word_stream->bits_remaining)) - & BitAndMasks[word_bits]) << (requested_bits-remaining_quantum_bits)); - + & BitAndMasks[word_bits]) << (requested_bits-remaining_quantum_bits)); + remaining_quantum_bits -= word_bits; word_stream->bits_remaining -= word_bits; } @@ -199,14 +199,14 @@ MagickExport unsigned int MagickWordStreamLSBRead(WordStreamReadHandle *word_str /* Initialize Word Stream for writing - + word_stream - stream to initialize. write_func_state - state to pass to write_func. write_func - function to retrieve the next word. */ MagickExport void MagickWordStreamInitializeWrite(WordStreamWriteHandle *word_stream, - WordStreamWriteFunc write_func, - void *write_func_state) + WordStreamWriteFunc write_func, + void *write_func_state) { word_stream->word = 0U; word_stream->bits_remaining = 32U; @@ -218,18 +218,18 @@ MagickExport void MagickWordStreamInitializeWrite(WordStreamWriteHandle *word_st Write quantum using the specified number of bits at the current position in a 32-bit word stream. Samples are output to words starting at the least significant bits of the word. - + Note that since a callback function is used to output the words, the remaining bits in the last word need to be flushed out by invoking MagickWordStreamLSBWriteFlush(). - + word_stream - already initialized word stream. requested_bits - number of bits to write to stream. quantum - value to write. */ MagickExport void MagickWordStreamLSBWrite(WordStreamWriteHandle *word_stream, - const unsigned int requested_bits, - const unsigned int quantum) + const unsigned int requested_bits, + const unsigned int quantum) { register unsigned int remaining_quantum_bits = requested_bits; @@ -237,26 +237,26 @@ MagickExport void MagickWordStreamLSBWrite(WordStreamWriteHandle *word_stream, while (remaining_quantum_bits > 0U) { register unsigned int - word_bits; + word_bits; word_bits = remaining_quantum_bits; if (word_bits > word_stream->bits_remaining) - word_bits = word_stream->bits_remaining; + word_bits = word_stream->bits_remaining; word_stream->word |= - (((quantum >> (requested_bits-remaining_quantum_bits)) & - BitAndMasks[word_bits]) << (32-word_stream->bits_remaining)); + (((quantum >> (requested_bits-remaining_quantum_bits)) & + BitAndMasks[word_bits]) << (32-word_stream->bits_remaining)); remaining_quantum_bits -= word_bits; word_stream->bits_remaining -= word_bits; if (word_stream->bits_remaining == 0U) - { - (void) word_stream->write_func(word_stream->write_func_state, - word_stream->word); - word_stream->word=0U; - word_stream->bits_remaining=32U; - } + { + (void) word_stream->write_func(word_stream->write_func_state, + word_stream->word); + word_stream->word=0U; + word_stream->bits_remaining=32U; + } } } @@ -265,9 +265,9 @@ MagickExport void MagickWordStreamLSBWrite(WordStreamWriteHandle *word_stream, are set to zero. Should be used to ensure that last word in word stream is written to the output. May also be used to apply word-level padding at the end of an image row. - + word_stream - already initialized word stream. -*/ +*/ MagickExport void MagickWordStreamLSBWriteFlush(WordStreamWriteHandle *word_stream) { if (word_stream->bits_remaining != 32U) diff --git a/magick/bit_stream.h b/magick/bit_stream.h index 74f5bf9..3c9f7a6 100644 --- a/magick/bit_stream.h +++ b/magick/bit_stream.h @@ -1,13 +1,13 @@ /* Copyright (C) 2003, 2005, 2009 GraphicsMagick Group - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. Interfaces to deal with marshalling quantums to and from a bit-stream. Written by Bob Friesenhahn, September 2003 - + */ #ifndef _MAGICK_BIT_STREAM_H #define _MAGICK_BIT_STREAM_H @@ -40,7 +40,7 @@ extern "C" { read_func_state - state to pass to word reading function. */ typedef unsigned long (*WordStreamReadFunc) (void *read_func_state); - + /* Word stream word reader "handle" */ @@ -75,39 +75,39 @@ extern "C" { extern MagickExport void MagickBitStreamInitializeRead(BitStreamReadHandle *bit_stream, - const unsigned char *bytes); + const unsigned char *bytes); extern MagickExport unsigned int MagickBitStreamMSBRead(BitStreamReadHandle *bit_stream, - const unsigned int requested_bits); + const unsigned int requested_bits); extern MagickExport void MagickBitStreamInitializeWrite(BitStreamWriteHandle *bit_stream, - unsigned char *bytes); + unsigned char *bytes); extern MagickExport void MagickBitStreamMSBWrite(BitStreamWriteHandle *bit_stream, - const unsigned int requested_bits, - const unsigned int quantum); + const unsigned int requested_bits, + const unsigned int quantum); extern MagickExport void MagickWordStreamInitializeRead(WordStreamReadHandle *word_stream, - WordStreamReadFunc read_func, - void *read_func_state); + WordStreamReadFunc read_func, + void *read_func_state); extern MagickExport unsigned int MagickWordStreamLSBRead(WordStreamReadHandle *word_stream, - const unsigned int requested_bits); + const unsigned int requested_bits); extern MagickExport void MagickWordStreamInitializeWrite(WordStreamWriteHandle *word_stream, - WordStreamWriteFunc write_func, - void *write_func_state); + WordStreamWriteFunc write_func, + void *write_func_state); extern MagickExport void MagickWordStreamLSBWrite(WordStreamWriteHandle *word_stream, - const unsigned int requested_bits, - const unsigned int quantum); + const unsigned int requested_bits, + const unsigned int quantum); extern MagickExport void MagickWordStreamLSBWriteFlush(WordStreamWriteHandle *word_stream); diff --git a/magick/blob.c b/magick/blob.c index 9d1876d..56028ed 100644 --- a/magick/blob.c +++ b/magick/blob.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2016 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -118,7 +118,8 @@ struct _BlobInfo exempt, /* True if file descriptor should not be closed.*/ temporary; /* Associated file is a temporary file */ - unsigned int + int + first_errno, /* First reported errno */ status; /* Error status. 0 == good */ StreamType @@ -255,19 +256,23 @@ static const char *BlobStreamTypeToString(StreamType stream_type) static inline size_t ReadBlobStream(Image *image,const size_t length, void **data) { + BlobInfo + * restrict blob; + size_t available; - if (image->blob->offset >= (magick_off_t) image->blob->length) + blob=image->blob; + if (blob->offset >= (magick_off_t) blob->length) { - image->blob->eof=MagickTrue; + blob->eof=MagickTrue; return 0; } - *data=(void *)(image->blob->data+image->blob->offset); - available=Min(length,image->blob->length-image->blob->offset); - image->blob->offset+=available; + *data=(void *)(blob->data+blob->offset); + available=Min(length,blob->length-blob->offset); + blob->offset+=available; if (available < length) - image->blob->eof=True; + blob->eof=True; return available; } @@ -302,36 +307,56 @@ static inline size_t ReadBlobStream(Image *image,const size_t length, */ static void *ExtendBlobWriteStream(Image *image,const size_t length) { - if ((image->blob->offset+length) >= image->blob->extent) + BlobInfo + * restrict blob; + + blob=image->blob; + if ((blob->offset+length) >= blob->extent) { /* In-memory Blob */ - image->blob->quantum<<=1; - image->blob->extent+=length+image->blob->quantum; - MagickReallocMemory(unsigned char *,image->blob->data,image->blob->extent+1); + blob->quantum<<=1; + blob->extent+=length+blob->quantum; +#if 0 + if (image->logging) + (void) LogMagickEvent(BlobEvent,GetMagickModule(), + "MagickReallocMemory blob->data=%p," + " blob->extent=%" MAGICK_SIZE_T_F "u", + blob->data, (MAGICK_SIZE_T) blob->extent); +#endif + MagickReallocMemory(unsigned char *,blob->data,blob->extent+1); (void) SyncBlob(image); - if (image->blob->data == (unsigned char *) NULL) + if (blob->data == (unsigned char *) NULL) { - DetachBlob(image->blob); +#if 0 + if (image->logging) + (void) LogMagickEvent(BlobEvent,GetMagickModule(), + "MagickReallocMemory failed! Detatching Blob..."); +#endif + DetachBlob(blob); return 0; } } - return image->blob->data+image->blob->offset; + return blob->data+blob->offset; } static inline size_t WriteBlobStream(Image *image,const size_t length, const void *data) { + BlobInfo + * restrict blob; + void *dest; - dest=image->blob->data+image->blob->offset; - if ((image->blob->offset+length) >= image->blob->extent) + blob=image->blob; + dest=blob->data+blob->offset; + if ((blob->offset+length) >= blob->extent) if ((dest=ExtendBlobWriteStream(image,length)) == (void *) NULL) return 0; (void) memcpy(dest,data,length); - image->blob->offset+=length; - if (image->blob->offset > (magick_off_t) image->blob->length) - image->blob->length=image->blob->offset; + blob->offset+=length; + if (blob->offset > (magick_off_t) blob->length) + blob->length=blob->offset; return length; } @@ -408,11 +433,14 @@ MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob, */ MagickExport MagickBool BlobIsSeekable(const Image *image) { + BlobInfo + * restrict blob; + assert(image != (const Image *) NULL); assert(image->blob != (const BlobInfo *) NULL); - return ((image->blob->type == FileStream) || - (image->blob->type == BlobStream)); + blob=image->blob; + return ((blob->type == FileStream) || (blob->type == BlobStream)); } /* @@ -446,23 +474,35 @@ MagickExport MagickBool BlobIsSeekable(const Image *image) */ MagickExport MagickPassFail BlobReserveSize(Image *image, magick_off_t size) { + BlobInfo + * restrict blob; + MagickPassFail status; + assert(image != (const Image *) NULL); + assert(image->blob != (const BlobInfo *) NULL); + + blob=image->blob; status=MagickPass; - if ((FileStream == image->blob->type) || - ((BlobStream == image->blob->type) && - (image->blob->mapped) && (image->blob->handle.std != (FILE *) NULL))) + if ((FileStream == blob->type) || + ((BlobStream == blob->type) && + (blob->mapped) && (blob->handle.std != (FILE *) NULL))) { #if defined(HAVE_POSIX_FALLOCATE) /* FIXME: Solaris 11.2 documentation says that posix_fallocate() - reports EINVAL for anything but UFS */ + reports EINVAL for anything but UFS. + + FreeBSD 11 (as of changeset r325320) now reports EINVAL when + used on a ZFS filesystem and Illumos and ZFS-On-Linux (ZoL) + are reported to do the same thing. + */ int err_status; - if ((err_status=posix_fallocate(fileno(image->blob->handle.std), + if ((err_status=posix_fallocate(fileno(blob->handle.std), 0UL, size)) != 0) { /* ThrowException(&image->exception,BlobError,UnableToWriteBlob,strerror(err_status)); */ @@ -471,21 +511,21 @@ MagickExport MagickPassFail BlobReserveSize(Image *image, magick_off_t size) #endif /* HAVE_POSIX_FALLOCATE */ } - if (BlobStream == image->blob->type) + if (BlobStream == blob->type) { /* In-memory blob */ - image->blob->extent=size; - MagickReallocMemory(unsigned char *,image->blob->data,image->blob->extent+1); + blob->extent=size; + MagickReallocMemory(unsigned char *,blob->data,blob->extent+1); (void) SyncBlob(image); - - if (image->blob->data == (unsigned char *) NULL) + + if (blob->data == (unsigned char *) NULL) { ThrowException(&image->exception,ResourceLimitError,MemoryAllocationFailed, NULL); - DetachBlob(image->blob); + DetachBlob(blob); status=MagickFail; } } @@ -533,7 +573,7 @@ MagickExport MagickPassFail BlobReserveSize(Image *image, magick_off_t size) % */ MagickExport MagickPassFail BlobToFile(const char *filename,const void *blob, - const size_t length,ExceptionInfo *exception) + const size_t length,ExceptionInfo *exception) { ssize_t count; @@ -550,7 +590,7 @@ MagickExport MagickPassFail BlobToFile(const char *filename,const void *blob, assert(filename != (const char *) NULL); assert(blob != (const void *) NULL); (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Copying memory BLOB to file %s",filename); + "Copying memory BLOB to file %s",filename); if (MagickConfirmAccess(FileWriteConfirmAccessMode,filename,exception) == MagickFail) return MagickFail; @@ -563,7 +603,7 @@ MagickExport MagickPassFail BlobToFile(const char *filename,const void *blob, if (status != MagickFail) { const char - *env = NULL; + *env = NULL; size_t block_size; @@ -571,10 +611,10 @@ MagickExport MagickPassFail BlobToFile(const char *filename,const void *blob, block_size=MagickGetFileSystemBlockSize(); /* - Write data to file. + Write data to file. */ for (i=0; i < length; i+=count) - { + { size_t remaining; @@ -587,37 +627,37 @@ MagickExport MagickPassFail BlobToFile(const char *filename,const void *blob, else amount=(MAGICK_POSIX_IO_SIZE_T) remaining; - count=write(file,(char *) blob+i,amount); - if (count <= 0) - break; - } + count=write(file,(char *) blob+i,amount); + if (count <= 0) + break; + } if (i < length) - { - if (status != MagickFail) - ThrowException(exception,BlobError,UnableToWriteBlob,filename); - status=MagickFail; - } + { + if (status != MagickFail) + ThrowException(exception,BlobError,UnableToWriteBlob,filename); + status=MagickFail; + } /* - Explicitly synchronize file to disk if requested. + Explicitly synchronize file to disk if requested. */ env = getenv("MAGICK_IO_FSYNC"); if ((env != (const char *) NULL) && (LocaleCompare(env,"TRUE") == 0)) - { - if (fsync(file) == -1) - { - if (status != MagickFail) - ThrowException(exception,BlobError,UnableToWriteBlob,filename); - status=MagickFail; - } - } + { + if (fsync(file) == -1) + { + if (status != MagickFail) + ThrowException(exception,BlobError,UnableToWriteBlob,filename); + status=MagickFail; + } + } if (close(file) == -1) - { - if (status != MagickFail) - ThrowException(exception,BlobError,UnableToWriteBlob,filename); - status=MagickFail; - } + { + if (status != MagickFail) + ThrowException(exception,BlobError,UnableToWriteBlob,filename); + status=MagickFail; + } } return status; } @@ -655,7 +695,7 @@ MagickExport MagickPassFail BlobToFile(const char *filename,const void *blob, % */ MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob, - const size_t length,ExceptionInfo *exception) + const size_t length,ExceptionInfo *exception) { const MagickInfo *magick_info; @@ -671,13 +711,16 @@ MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob, assert(exception != (ExceptionInfo *) NULL); image=(Image *) NULL; - (void) LogMagickEvent(BlobEvent,GetMagickModule(), "Entering BlobToImage"); + (void) LogMagickEvent(BlobEvent,GetMagickModule(), + "Entering BlobToImage: blob=%p," + " length=%" MAGICK_SIZE_T_F "u", + blob, (MAGICK_SIZE_T) length); if ((blob == (const void *) NULL) || (length == 0)) { ThrowException(exception,OptionError,NullBlobArgument, - image_info->magick); + image_info->magick); (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Leaving BlobToImage"); + "Leaving BlobToImage"); return((Image *) NULL); } clone_info=CloneImageInfo(image_info); @@ -689,12 +732,23 @@ MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob, */ if (clone_info->magick[0] == '\0') (void) SetImageInfo(clone_info,SETMAGICK_READ,exception); + (void) LogMagickEvent(BlobEvent,GetMagickModule(), + "Blob magick=\"%s\"", clone_info->magick); + if (clone_info->magick[0] == '\0') + { + ThrowException(exception,BlobError,UnableToDeduceImageFormat,clone_info->filename); + DestroyImageInfo(clone_info); + (void) LogMagickEvent(BlobEvent,GetMagickModule(), + "Leaving BlobToImage"); + return((Image *) NULL); + } magick_info=GetMagickInfo(clone_info->magick,exception); if (magick_info == (const MagickInfo *) NULL) { + ThrowException(exception,BlobError,UnrecognizedImageFormat,clone_info->filename); DestroyImageInfo(clone_info); (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Leaving BlobToImage"); + "Leaving BlobToImage"); return((Image *) NULL); } if (magick_info->blob_support) @@ -703,16 +757,19 @@ MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob, Native blob support for this image format. */ (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Using native BLOB support"); + "Using native BLOB support"); (void) strlcpy(clone_info->filename,image_info->filename, - MaxTextExtent); + MaxTextExtent); (void) strlcpy(clone_info->magick,image_info->magick,MaxTextExtent); image=ReadImage(clone_info,exception); if (image != (Image *) NULL) DetachBlob(image->blob); DestroyImageInfo(clone_info); (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Leaving BlobToImage"); + "Leaving BlobToImage"); + if ((image == (Image *) NULL) && + (exception->severity < ErrorException)) + ThrowException(exception,CoderError,DecodedImageNotReturned,"blob"); return(image); } /* @@ -723,49 +780,52 @@ MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob, temporary_file[MaxTextExtent]; (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Using temporary file"); + "Using temporary file"); clone_info->blob=(void *) NULL; clone_info->length=0; - - if(!AcquireTemporaryFileName(temporary_file)) + + if (!AcquireTemporaryFileName(temporary_file)) { - ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile, - clone_info->filename); + ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile, + clone_info->filename); } else { - if (BlobToFile(temporary_file,blob,length,exception) != MagickFail) - { - clone_info->filename[0]='\0'; - if (clone_info->magick[0] != '\0') - { - (void) strlcpy(clone_info->filename,clone_info->magick,sizeof(clone_info->filename)); - (void) strlcat(clone_info->filename,":",sizeof(clone_info->filename)); - } - (void) strlcat(clone_info->filename,temporary_file,sizeof(clone_info->filename)); - image=ReadImage(clone_info,exception); - /* - Restore original user-provided file name field to images - in list so that user does not see a temporary file name. - */ - if (image != (Image *) NULL) - { - Image - *list_image; - - list_image = GetFirstImageInList(image); - while (list_image != (Image *) NULL) - { - (void) strlcpy(list_image->magick_filename,image_info->filename,sizeof(list_image->magick_filename)); - (void) strlcpy(list_image->filename,image_info->filename,sizeof(list_image->filename)); - list_image = GetNextImageInList(list_image); - } - } - } - (void) LiberateTemporaryFile(temporary_file); + if (BlobToFile(temporary_file,blob,length,exception) != MagickFail) + { + clone_info->filename[0]='\0'; + if (clone_info->magick[0] != '\0') + { + (void) strlcpy(clone_info->filename,clone_info->magick,sizeof(clone_info->filename)); + (void) strlcat(clone_info->filename,":",sizeof(clone_info->filename)); + } + (void) strlcat(clone_info->filename,temporary_file,sizeof(clone_info->filename)); + image=ReadImage(clone_info,exception); + /* + Restore original user-provided file name field to images + in list so that user does not see a temporary file name. + */ + if (image != (Image *) NULL) + { + Image + *list_image; + + list_image = GetFirstImageInList(image); + while (list_image != (Image *) NULL) + { + (void) strlcpy(list_image->magick_filename,image_info->filename,sizeof(list_image->magick_filename)); + (void) strlcpy(list_image->filename,image_info->filename,sizeof(list_image->filename)); + list_image = GetNextImageInList(list_image); + } + } + } + (void) LiberateTemporaryFile(temporary_file); } } DestroyImageInfo(clone_info); + if ((image == (Image *) NULL) && + (exception->severity < ErrorException)) + ThrowException(exception,CoderError,DecodedImageNotReturned,"blob"); (void) LogMagickEvent(BlobEvent,GetMagickModule(), "Leaving BlobToImage"); return(image); } @@ -832,14 +892,16 @@ MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info) % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% CloseBlob() closes a stream associated with the image. +% CloseBlob() closes a stream associated with the image. The final error +% status (based on any prior error occuring while doing I/O, including while +% closing the blob) is provided as a MagickPassFail indication. % % If the blob 'exempt' member is MagickTrue, then any passed file descriptor % is left open, otherwise it is closed. % % The format of the CloseBlob method is: % -% void CloseBlob(Image *image) +% MagickPassFail CloseBlob(Image *image) % % A description of each parameter follows: % @@ -847,8 +909,11 @@ MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info) % % */ -MagickExport void CloseBlob(Image *image) +MagickExport MagickPassFail CloseBlob(Image *image) { + BlobInfo + * restrict blob; + int status; @@ -857,22 +922,22 @@ MagickExport void CloseBlob(Image *image) */ assert(image != (Image *) NULL); assert(image->signature == MagickSignature); + blob=image->blob; /* If blob was not allocated, is UndefinedStream (closed) then it doesn't need to be closed. */ - if ((image->blob == (BlobInfo *) NULL) || - (image->blob->type == UndefinedStream)) - return; + if ((blob == (BlobInfo *) NULL) || (blob->type == UndefinedStream)) + return MagickPass; if (image->logging) (void) LogMagickEvent(BlobEvent,GetMagickModule(), "Closing %sStream blob: image %p, blob %p, ref %lu", - BlobStreamTypeToString(image->blob->type), - image,image->blob,image->blob->reference_count); + BlobStreamTypeToString(blob->type), + image,blob,blob->reference_count); status=0; - switch (image->blob->type) + switch (blob->type) { case UndefinedStream: break; @@ -880,25 +945,66 @@ MagickExport void CloseBlob(Image *image) case StandardStream: case PipeStream: { - if (image->blob->fsync) + if (blob->fsync) { - (void) fflush(image->blob->handle.std); - (void) fsync(fileno(image->blob->handle.std)); + if (fflush(blob->handle.std) != 0) + { + if (!status) + { + status=1; + if (errno != 0) + blob->first_errno=errno; + } + } + if (fsync(fileno(blob->handle.std)) != 0) + { + if (!status) + { + status=1; + if (errno != 0) + blob->first_errno=errno; + } + } } - status=ferror(image->blob->handle.std); + if (!(status) && ferror(blob->handle.std)) + status=1; break; } case ZipStream: { #if defined(HasZLIB) - (void) gzerror(image->blob->handle.gz,&status); + if (!(status)) + { + int + gzerror_errnum=Z_OK; + + (void) gzerror(blob->handle.gz,&gzerror_errnum); + if (gzerror_errnum != Z_OK) + { + blob->status=1; + if ((gzerror_errnum == Z_ERRNO) && (errno != 0)) + blob->first_errno=errno; + } + } #endif break; } case BZipStream: { #if defined(HasBZLIB) - (void) BZ2_bzerror(image->blob->handle.bz,&status); + if (!(status)) + { + int + bzerror_errnum=BZ_OK; + + (void) BZ2_bzerror(blob->handle.bz,&bzerror_errnum); + if (bzerror_errnum != BZ_OK) + { + blob->status=1; + if ((bzerror_errnum == BZ_IO_ERROR) && (errno != 0)) + blob->first_errno=errno; + } + } #endif break; } @@ -907,48 +1013,74 @@ MagickExport void CloseBlob(Image *image) } errno=0; image->taint=MagickFalse; - image->blob->size=GetBlobSize(image); - image->blob->eof=MagickFalse; - image->blob->status=status < 0; - image->blob->mode=UndefinedBlobMode; + blob->size=GetBlobSize(image); + blob->eof=MagickFalse; + blob->status=status != 0; + blob->mode=UndefinedBlobMode; /* If we are allowed to close the stream and detatch (destroy) the blob. */ - if (! image->blob->exempt ) + if (! blob->exempt ) { /* Close the underlying stream. */ - switch (image->blob->type) + switch (blob->type) { case UndefinedStream: break; case FileStream: case StandardStream: { - status=fclose(image->blob->handle.std); + if (fclose(blob->handle.std) != 0) + { + if (!status) + { + status=1; + if (errno != 0) + blob->first_errno=errno; + } + } break; } case PipeStream: { #if defined(HAVE_PCLOSE) - status=pclose(image->blob->handle.std); + if (pclose(blob->handle.std) != 0) + { + if (!status) + { + status=1; + if (errno != 0) + blob->first_errno=errno; + } + } #endif /* defined(HAVE_PCLOSE) */ break; } case ZipStream: { #if defined(HasZLIB) - status=gzclose(image->blob->handle.gz); + int + gzerror_errnum; + + gzerror_errnum=gzclose(blob->handle.gz); + if (gzerror_errnum != Z_OK) + { + blob->status=1; + if ((gzerror_errnum == Z_ERRNO) && (errno != 0)) + blob->first_errno=errno; + } #endif break; } case BZipStream: { #if defined(HasBZLIB) - BZ2_bzclose(image->blob->handle.bz); + /* Returns void */ + BZ2_bzclose(blob->handle.bz); #endif break; } @@ -960,10 +1092,18 @@ MagickExport void CloseBlob(Image *image) /* Detatch (destroy) the blob. */ - DetachBlob(image->blob); + DetachBlob(blob); } - image->blob->type=UndefinedStream; - image->blob->status=(status != 0); + blob->type=UndefinedStream; + blob->status=(status != 0); + if (image->logging && blob->status) + (void) LogMagickEvent(BlobEvent,GetMagickModule(), + "Closed blob: image %p, blob %p with " + "errno %d (\"%s\")", + image,blob,blob->first_errno, + strerror(blob->first_errno)); + return (blob->status ? MagickFail : MagickPass); + } /* @@ -993,46 +1133,47 @@ MagickExport void CloseBlob(Image *image) */ MagickExport void DestroyBlob(Image *image) { + MagickBool + destroy; + assert(image != (Image *) NULL); assert(image->signature == MagickSignature); - if (image->blob != (BlobInfo *) NULL) - { - MagickBool - destroy; - assert(image->blob->signature == MagickSignature); - LockSemaphoreInfo(image->blob->semaphore); + if (image->blob == (BlobInfo *) NULL) + return; + + assert(image->blob->signature == MagickSignature); + LockSemaphoreInfo(image->blob->semaphore); + if (image->logging) + (void) LogMagickEvent(BlobEvent,GetMagickModule(), + "Destroy blob (ref counted): image %p, blob %p," + " ref %lu, filename \"%s\"", + image,image->blob,image->blob->reference_count, + image->filename); + image->blob->reference_count--; + assert(image->blob->reference_count >= 0); + destroy=(image->blob->reference_count > 0 ? MagickFalse : MagickTrue); + UnlockSemaphoreInfo(image->blob->semaphore); + if (destroy) + { + /* + Destroy blob object. + */ if (image->logging) (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Destroy blob (ref counted): image %p, blob %p," + " Destroy blob (real): image %p, blob %p," " ref %lu, filename \"%s\"", - image,image->blob,image->blob->reference_count, - image->filename); - image->blob->reference_count--; - assert(image->blob->reference_count >= 0); - destroy=(image->blob->reference_count > 0 ? MagickFalse : MagickTrue); - UnlockSemaphoreInfo(image->blob->semaphore); - if (destroy) - { - /* - Destroy blob object. - */ - if (image->logging) - (void) LogMagickEvent(BlobEvent,GetMagickModule(), - " Destroy blob (real): image %p, blob %p," - " ref %lu, filename \"%s\"", - image,image->blob, - image->blob->reference_count,image->filename); - if (image->blob->type != UndefinedStream) - CloseBlob(image); - if (image->blob->mapped) - (void) UnmapBlob(image->blob->data,image->blob->length); - DestroySemaphoreInfo(&image->blob->semaphore); - (void) memset((void *) image->blob,0xbf,sizeof(BlobInfo)); - MagickFreeMemory(image->blob); - } - image->blob=(BlobInfo *) NULL; + image,image->blob, + image->blob->reference_count,image->filename); + if (image->blob->type != UndefinedStream) + CloseBlob(image); + if (image->blob->mapped) + (void) UnmapBlob(image->blob->data,image->blob->length); + DestroySemaphoreInfo(&image->blob->semaphore); + (void) memset((void *) image->blob,0xbf,sizeof(BlobInfo)); + MagickFreeMemory(image->blob); } + image->blob=(BlobInfo *) NULL; } /* @@ -1083,7 +1224,7 @@ MagickExport void DestroyBlobInfo(BlobInfo *blob) { if (blob->mapped) (void) UnmapBlob(blob->data,blob->length); - DestroySemaphoreInfo(&blob->semaphore); + DestroySemaphoreInfo(&blob->semaphore); (void) memset((void *)blob,0xbf,sizeof(BlobInfo)); MagickFreeMemory(blob); } @@ -1169,11 +1310,15 @@ MagickExport void DetachBlob(BlobInfo *blob_info) */ MagickExport int EOFBlob(const Image *image) { + BlobInfo + * restrict blob; + assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); - switch (image->blob->type) + blob=image->blob; + switch (blob->type) { case UndefinedStream: break; @@ -1181,12 +1326,14 @@ MagickExport int EOFBlob(const Image *image) case StandardStream: case PipeStream: { - image->blob->eof=feof(image->blob->handle.std); + blob->eof=feof(blob->handle.std); break; } case ZipStream: { - image->blob->eof=MagickFalse; +#if defined(HasZLIB) + blob->eof=gzeof(blob->handle.gz); +#endif /* defined(HasZLIB) */ break; } case BZipStream: @@ -1195,15 +1342,15 @@ MagickExport int EOFBlob(const Image *image) int status; - (void) BZ2_bzerror(image->blob->handle.bz,&status); - image->blob->eof=status == BZ_UNEXPECTED_EOF; -#endif + (void) BZ2_bzerror(blob->handle.bz,&status); + blob->eof=status == BZ_UNEXPECTED_EOF; +#endif /* defined(HasBZLIB) */ break; } case BlobStream: break; } - return(image->blob->eof); + return(blob->eof); } /* @@ -1259,6 +1406,26 @@ MagickExport void *FileToBlob(const char *filename,size_t *length, assert(exception != (ExceptionInfo *) NULL); blob=(unsigned char *) NULL; + + /* + Verify that read access to this file path is allowed + */ + if (MagickConfirmAccess(FileReadConfirmAccessMode,filename, + exception) == MagickFail) + { + length=0; + return blob; + } + /* + Validate that filename exists, is a normal file, and contains at + least one byte of data + */ + if (!IsAccessibleAndNotEmpty(filename)) + { + ThrowException(exception,BlobError,UnableToOpenFile,filename); + length=0; + return blob; + } /* Open file */ if ((file=fopen(filename,"rb")) != (FILE *) NULL) { @@ -1500,9 +1667,9 @@ MagickExport magick_off_t GetBlobSize(const Image *image) break; case FileStream: { - offset=(MagickFstat(fileno(image->blob->handle.std),&attributes) < 0 ? 0 : - attributes.st_size); - break; + offset=(MagickFstat(fileno(image->blob->handle.std),&attributes) < 0 ? 0 : + attributes.st_size); + break; } case StandardStream: case PipeStream: @@ -1510,14 +1677,14 @@ MagickExport magick_off_t GetBlobSize(const Image *image) case ZipStream: case BZipStream: { - offset=(MagickStat(image->filename,&attributes) < 0 ? 0 : - attributes.st_size); - break; + offset=(MagickStat(image->filename,&attributes) < 0 ? 0 : + attributes.st_size); + break; } case BlobStream: { - offset=image->blob->length; - break; + offset=image->blob->length; + break; } } return(offset); @@ -1534,7 +1701,9 @@ MagickExport magick_off_t GetBlobSize(const Image *image) % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% GetBlobStatus() returns the blob error status. +% GetBlobStatus() returns the blob error status. For GraphicsMagick +% 1.3.26 and earlier, this was only set by CloseBlob() but now it is +% set immediately upon error. % % The format of the GetBlobStatus method is: % @@ -1558,6 +1727,39 @@ MagickExport int GetBlobStatus(const Image *image) % % % % % % +% G e t B l o b F i r s t E r r n o % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% GetBlobFirstErrno() returns the errno present (if any) when the blob +% first encountered as error, as indicated by GetBlobStatus(). The +% the purpose of this function is to help improve the quality of error +% reporting. +% +% The format of the GetBlobFirstErrno method is: +% +% int GetBlobFirstErrno(const Image *image) +% +% A description of each parameter follows: +% +% o image: The image. +% +% +*/ +MagickExport int GetBlobFirstErrno(const Image *image) +{ + assert(image != (const Image *) NULL); + assert(image->signature == MagickSignature); + return(image->blob->first_errno); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % % G e t B l o b S t r e a m D a t a % % % % % @@ -1714,6 +1916,13 @@ MagickExport void *GetConfigureBlob(const char *filename,char *path, (void) strlcpy(path,filename,MaxTextExtent); path_map=MagickMapAllocateMap(MagickMapCopyString,MagickMapDeallocateString); + if (path_map == (MagickMap) NULL) + { + /* MagickMap is a tiny allocation so failure to allocate it is fatal */ + ThrowException3(exception,ResourceLimitFatalError,MemoryAllocationFailed, + UnableToAllocateMagickMap); + return (void *) NULL; + } { /* @@ -1727,19 +1936,19 @@ MagickExport void *GetConfigureBlob(const char *filename,char *path, const char *end = NULL, *start = magick_configure_path; - + end=start+strlen(start); while ( start < end ) { char buffer[MaxTextExtent]; - + const char *separator; - + int string_length; - + separator = strchr(start,DirectoryListSeparator); if (separator) string_length=separator-start; @@ -1793,7 +2002,7 @@ MagickExport void *GetConfigureBlob(const char *filename,char *path, { const char *magick_home; - + /* Search under MAGICK_HOME. */ @@ -1873,7 +2082,7 @@ MagickExport void *GetConfigureBlob(const char *filename,char *path, (void) ConcatenateString(&search_path, (const char *) MagickMapDereferenceIterator(path_map_iterator,0)); } - + (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), "Searching for file \"%s\" in path \"%s\"",filename,search_path); @@ -1918,12 +2127,12 @@ MagickExport void *GetConfigureBlob(const char *filename,char *path, } if (logging) - { - (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), - "Tried: %.1024s [%.1024s]",test_path, - strerror(errno)); - errno=0; - } + { + (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), + "Tried: %.1024s [%.1024s]",test_path, + strerror(errno)); + errno=0; + } } MagickMapDeallocateIterator(path_map_iterator); MagickMapDeallocateMap(path_map); @@ -1984,7 +2193,7 @@ MagickExport void *GetConfigureBlob(const char *filename,char *path, % */ MagickExport void *ImageToBlob(const ImageInfo *image_info,Image *image, - size_t *length,ExceptionInfo *exception) + size_t *length,ExceptionInfo *exception) { char filename[MaxTextExtent], @@ -2018,11 +2227,11 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,Image *image, if (magick_info == (const MagickInfo *) NULL) { ThrowException(exception,MissingDelegateError, - NoDecodeDelegateForThisImageFormat,clone_info->magick); + NoDecodeDelegateForThisImageFormat,clone_info->magick); DestroyImageInfo(clone_info); if (image->logging) - (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Exiting ImageToBlob"); + (void) LogMagickEvent(BlobEvent,GetMagickModule(), + "Exiting ImageToBlob"); return((void *) NULL); } if (magick_info->blob_support) @@ -2034,7 +2243,7 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,Image *image, if (clone_info->blob == (void *) NULL) { ThrowException(exception,ResourceLimitError,MemoryAllocationFailed, - MagickMsg(BlobError,UnableToCreateBlob)); + MagickMsg(BlobError,UnableToCreateBlob)); DestroyImageInfo(clone_info); if (image->logging) (void) LogMagickEvent(BlobEvent,GetMagickModule(), @@ -2051,10 +2260,10 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,Image *image, status=WriteImage(clone_info,image); if (status == MagickFalse) { - /* Only assert our own exception if an exception was not already reported. */ - if (image->exception.severity == UndefinedException) - ThrowException(exception,BlobError,UnableToWriteBlob, - clone_info->magick); + /* Only assert our own exception if an exception was not already reported. */ + if (image->exception.severity == UndefinedException) + ThrowException(exception,BlobError,UnableToWriteBlob, + clone_info->magick); MagickFreeMemory(image->blob->data); DestroyImageInfo(clone_info); if (image->logging) @@ -2063,7 +2272,8 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,Image *image, return((void *) NULL); } /* Request to truncate memory allocation down to memory actually used. */ - MagickReallocMemory(unsigned char *,image->blob->data,image->blob->length+1); + if (image->blob->length) + MagickReallocMemory(unsigned char *,image->blob->data,image->blob->length+1); /* Pass blob data and length to user parameters */ blob=image->blob->data; *length=image->blob->length; @@ -2082,13 +2292,13 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,Image *image, if (!AcquireTemporaryFileName(unique)) { ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile, - unique); + unique); DestroyImageInfo(clone_info); return((void *) NULL); } if (image->logging) (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Allocated temporary file \"%s\"",unique); + "Allocated temporary file \"%s\"",unique); FormatString(image->filename,"%.1024s:%.1024s",image->magick,unique); status=WriteImage(clone_info,image); DestroyImageInfo(clone_info); @@ -2107,7 +2317,7 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,Image *image, blob=(unsigned char *) FileToBlob(image->filename,length,exception); if (image->logging) (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Liberating temporary file \"%s\"",image->filename); + "Liberating temporary file \"%s\"",image->filename); (void) LiberateTemporaryFile(image->filename); (void) strlcpy(image->filename,filename,MaxTextExtent); if (blob == (unsigned char *) NULL) @@ -2306,17 +2516,17 @@ MagickExport void *MapBlob(int file,const MapMode mode,magick_off_t offset, if (map == (void *) MAP_FAILED) { (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Failed to mmap fd %d using %s mode at offset %" - MAGICK_OFF_F "u and length %" MAGICK_OFF_F - "u (%d=\"%s\").",file,MapModeToString(mode),offset, - (magick_off_t) length,errno,strerror(errno)); + "Failed to mmap fd %d using %s mode at offset %" + MAGICK_OFF_F "u and length %" MAGICK_OFF_F + "u (%d=\"%s\").",file,MapModeToString(mode),offset, + (magick_off_t) length,errno,strerror(errno)); return((void *) NULL); } (void) LogMagickEvent(BlobEvent,GetMagickModule(), - "Mmapped fd %d using %s mode at offset %" MAGICK_OFF_F - "u and length %" MAGICK_OFF_F "u to address %p", - file,MapModeToString(mode),offset,(magick_off_t) length, - map); + "Mmapped fd %d using %s mode at offset %" MAGICK_OFF_F + "u and length %" MAGICK_OFF_F "u to address %p", + file,MapModeToString(mode),offset,(magick_off_t) length, + map); return((void *) map); #else (void) file; @@ -2587,15 +2797,23 @@ MagickExport MagickPassFail OpenBlob(const ImageInfo *image_info,Image *image, if (MagickConfirmAccess((type[0] == 'r' ? FileReadConfirmAccessMode : FileWriteConfirmAccessMode),filename, exception) != MagickFail) - image->blob->handle.gz=gzopen(filename,type); + image->blob->handle.gz=gzopen(filename,*type == 'w' ? "wb" : "rb" ); if (image->blob->handle.gz != (gzFile) NULL) { image->blob->type=ZipStream; if (image->logging) (void) LogMagickEvent(BlobEvent,GetMagickModule(), " opened file %s as ZipStream image" - " %p, blob %p", - filename,image,image->blob); + " %p, blob %p, mode %s", + filename,image,image->blob,type); + } + else + { + if (image->logging) + (void) LogMagickEvent(BlobEvent,GetMagickModule(), + " failed to open file %s as ZipStream image" + " %p, blob %p, mode %s", + filename,image,image->blob,type); } } else @@ -2762,7 +2980,7 @@ MagickExport MagickPassFail OpenBlob(const ImageInfo *image_info,Image *image, { /* Support reading from a file using memory mapping. - + This code was used for years and definitely speeds re-reading of the same file, but it has been discovered that some operating systems (e.g. FreeBSD @@ -2775,7 +2993,7 @@ MagickExport MagickPassFail OpenBlob(const ImageInfo *image_info,Image *image, { const MagickInfo *magick_info; - + MagickStatStruct_t attributes; @@ -2789,10 +3007,10 @@ MagickExport MagickPassFail OpenBlob(const ImageInfo *image_info,Image *image, { size_t length; - + void *blob; - + length=(size_t) attributes.st_size; if (AcquireMagickResource(MapResource,length)) @@ -2825,6 +3043,7 @@ MagickExport MagickPassFail OpenBlob(const ImageInfo *image_info,Image *image, } } image->blob->status=MagickFalse; + image->blob->first_errno=0; if (image->blob->type != UndefinedStream) image->blob->size=GetBlobSize(image); if (*type == 'r') @@ -2835,7 +3054,7 @@ MagickExport MagickPassFail OpenBlob(const ImageInfo *image_info,Image *image, if (UndefinedStream == image->blob->type) { if (UndefinedException == exception->severity) - ThrowException(exception,FileOpenError,UnableToOpenFile,filename); + ThrowException(exception,FileOpenError,UnableToOpenFile,filename); return MagickFail; } return MagickPass; @@ -2930,6 +3149,9 @@ MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob, */ MagickExport size_t ReadBlob(Image *image,const size_t length,void *data) { + BlobInfo + * restrict blob; + size_t count; @@ -2939,124 +3161,175 @@ MagickExport size_t ReadBlob(Image *image,const size_t length,void *data) assert(image->blob->type != UndefinedStream); assert(data != (void *) NULL); + blob=image->blob; count=0; - switch (image->blob->type) - { + switch (blob->type) + { case UndefinedStream: break; case FileStream: case StandardStream: case PipeStream: - { - if (length == 1) - { - int - c; + { + if (length == 1) + { + int + c; - if ((c=getc(image->blob->handle.std)) != EOF) - { - *((unsigned char *)data)=(unsigned char) c; - count=1; - } - else - { - count=0; - } - } - else - { - count=fread(data,1,length,image->blob->handle.std); - } - break; - } + if ((c=getc(blob->handle.std)) != EOF) + { + *((unsigned char *)data)=(unsigned char) c; + count=1; + } + else + { + count=0; + } + } + else + { + count=fread(data,1,length,blob->handle.std); + } + if (count != length) + { + if (!(blob->status) && ferror(blob->handle.std)) + { + blob->status=1; + if (errno != 0) + blob->first_errno=errno; + } + } + break; + } case ZipStream: - { + { #if defined(HasZLIB) - size_t - i; + size_t + i; - for (i=0; i < length; i+=count) - { - size_t - remaining; + int + gz_count = 0; - unsigned int - amount; + for (i=0; i < length; i+=gz_count) + { + size_t + remaining; - remaining=length - i; - if (remaining > image->blob->block_size) - amount=(unsigned int) image->blob->block_size; - else - amount=(unsigned int) remaining; + unsigned int + amount; - count=gzread(image->blob->handle.gz, - (void *) ((unsigned char *) data+i),amount); - if (count <= 0) - break; - } - count=i; + remaining=length - i; + if (remaining > blob->block_size) + amount=(unsigned int) blob->block_size; + else + amount=(unsigned int) remaining; + + gz_count=gzread(blob->handle.gz, + (void *) ((unsigned char *) data+i),amount); + if (gz_count <= 0) + break; + } + count=i; + if (count != length) + { + if (!(blob->status)) + { + int + gzerror_errnum=Z_OK; + + (void) gzerror(blob->handle.gz,&gzerror_errnum); + if (gzerror_errnum != Z_OK) + { + blob->status=1; + if ((gzerror_errnum == Z_ERRNO) && (errno != 0)) + blob->first_errno=errno; + } + } + if (!blob->eof) + blob->eof = gzeof(blob->handle.gz); + } #endif - break; - } + break; + } case BZipStream: - { + { #if defined(HasBZLIB) - size_t - i; + size_t + i; - for (i=0; i < length; i+=count) - { - size_t - remaining; + int + bz_count = 0; - int - amount; + for (i=0; i < length; i+=bz_count) + { + size_t + remaining; - remaining=length - i; - if (remaining > image->blob->block_size) - amount=(int) image->blob->block_size; - else - amount=(int) remaining; + int + amount; - count=BZ2_bzread(image->blob->handle.bz, - (void *) ((unsigned char *) data+i),amount); - if (count <= 0) - break; - } - count=i; + remaining=length - i; + if (remaining > blob->block_size) + amount=(int) blob->block_size; + else + amount=(int) remaining; + + bz_count=BZ2_bzread(blob->handle.bz, + (void *) ((unsigned char *) data+i),amount); + if (bz_count <= 0) + break; + } + count=i; + if (count != length) + { + if (!(blob->status)) + { + int + bzerror_errnum=BZ_OK; + + (void) BZ2_bzerror(blob->handle.bz,&bzerror_errnum); + if (bzerror_errnum != BZ_OK) + { + blob->status=1; + if ((bzerror_errnum == BZ_IO_ERROR) && (errno != 0)) + blob->first_errno=errno; + } + } + } #endif - break; - } + break; + } case BlobStream: - { - void - *source_void = 0; + { + void + *source_void = 0; - const unsigned char - *source; + const unsigned char + *source; - count=ReadBlobStream(image,length,&source_void); - source=source_void; - if (count <= 10) - { - register size_t - i; + count=ReadBlobStream(image,length,&source_void); + source=source_void; + if (count <= 10) + { + register size_t + i; - register unsigned char - *target=(unsigned char*) data; + register unsigned char + *target=(unsigned char*) data; - for(i=count; i > 0; i--) - { - *target=*source; - target++; - source++; - } - } - else - (void) memcpy(data,source,count); - break; + for(i=count; i > 0; i--) + { + *target=*source; + target++; + source++; + } + } + else + (void) memcpy(data,source,count); + break; + } } - } + assert(count <= length); return(count); } @@ -3141,39 +3414,59 @@ MagickExport size_t ReadBlobZC(Image *image,const size_t length,void **data) */ MagickExport int ReadBlobByte(Image *image) { + BlobInfo + * restrict blob; + + int + c = EOF; + unsigned char - c; - + octet; + assert(image != (Image *) NULL); assert(image->signature == MagickSignature); - - switch (image->blob->type) + + blob=image->blob; + + switch (blob->type) { case FileStream: case StandardStream: case PipeStream: { - return getc(image->blob->handle.std); + if ((c=getc(blob->handle.std)) == EOF) + { + if (!(blob->status) && ferror(blob->handle.std)) + { + blob->status=1; + if (errno != 0) + blob->first_errno=errno; + } + } + break; } case BlobStream: { - if (image->blob->offset < (magick_off_t) image->blob->length) + if (blob->offset < (magick_off_t) blob->length) + { + octet=*((unsigned char *)blob->data+blob->offset); + blob->offset++; + c=octet; + } + else { - c=*((unsigned char *)image->blob->data+image->blob->offset); - image->blob->offset++; - return (c); + blob->eof=True; } - image->blob->eof=True; break; } default: { /* Do things the slow way */ - if (ReadBlob(image,1,&c) == 1) - return (c); + if (ReadBlob(image,1,&octet) == 1) + c=octet; } } - return(EOF); + return c; } /* @@ -3224,6 +3517,9 @@ MagickExport double ReadBlobLSBDouble(Image * image) MagickSwabDouble(&dbl_buffer.d); #endif + if (MAGICK_ISNAN(dbl_buffer.d)) + dbl_buffer.d = 0.0; + return (dbl_buffer.d); } @@ -3262,6 +3558,7 @@ MagickExport double ReadBlobLSBDouble(Image * image) MagickExport size_t ReadBlobLSBDoubles(Image *image, size_t octets, double *data) { size_t + i, octets_read; assert(image != (Image *) NULL); @@ -3269,11 +3566,17 @@ MagickExport size_t ReadBlobLSBDoubles(Image *image, size_t octets, double *data assert(data != (double *) NULL); octets_read=ReadBlob(image,octets,data); -#if defined(WORDS_BIGENDIAN) if (octets_read >= sizeof(double)) - MagickSwabArrayOfDouble(data,(octets_read+sizeof(double)-1)/sizeof(double)); + { +#if defined(WORDS_BIGENDIAN) + MagickSwabArrayOfDouble(data,(octets_read+sizeof(double)-1)/sizeof(double)); #endif + for (i=0; i < octets_read/sizeof(double); i++) + if (MAGICK_ISNAN(data[i])) + data[i] = 0.0; + } + return octets_read; } @@ -3320,10 +3623,10 @@ MagickExport magick_uint32_t ReadBlobLSBLong(Image *image) if (ReadBlob(image,4,buffer) != 4) return(0U); - value=buffer[3] << 24; - value|=buffer[2] << 16; - value|=buffer[1] << 8; - value|=buffer[0]; + value=(magick_uint32_t) buffer[3] << 24; + value|=(magick_uint32_t) buffer[2] << 16; + value|=(magick_uint32_t) buffer[1] << 8; + value|=(magick_uint32_t) buffer[0]; return(value & 0xffffffff); } @@ -3370,10 +3673,10 @@ MagickExport magick_int32_t ReadBlobLSBSignedLong(Image *image) if (ReadBlob(image,4,buffer) != 4) return(0U); - value.uint32=buffer[3] << 24; - value.uint32|=buffer[2] << 16; - value.uint32|=buffer[1] << 8; - value.uint32|=buffer[0]; + value.uint32=(magick_uint32_t) buffer[3] << 24; + value.uint32|=(magick_uint32_t) buffer[2] << 16; + value.uint32|=(magick_uint32_t) buffer[1] << 8; + value.uint32|=(magick_uint32_t) buffer[0]; value.uint32&=0xffffffff; return value.int32; } @@ -3473,8 +3776,8 @@ MagickExport magick_uint16_t ReadBlobLSBShort(Image *image) if (ReadBlob(image,2,buffer) != 2) return(0U); - value=buffer[1] << 8; - value|=buffer[0]; + value=(magick_uint16_t) buffer[1] << 8; + value|=(magick_uint16_t) buffer[0]; return(value & 0xffff); } @@ -3521,8 +3824,8 @@ MagickExport magick_int16_t ReadBlobLSBSignedShort(Image *image) if (ReadBlob(image,2,buffer) != 2) return(0U); - value.uint16=buffer[1] << 8; - value.uint16|=buffer[0]; + value.uint16=(magick_uint16_t) buffer[1] << 8; + value.uint16|=(magick_uint16_t) buffer[0]; value.uint16&=0xffff; return value.int16; } @@ -3575,6 +3878,9 @@ MagickExport float ReadBlobLSBFloat(Image * image) MagickSwabFloat(&flt_buffer.f); #endif + if (MAGICK_ISNAN(flt_buffer.f)) + flt_buffer.f = 0.0; + return (flt_buffer.f); } @@ -3613,6 +3919,7 @@ MagickExport float ReadBlobLSBFloat(Image * image) MagickExport size_t ReadBlobLSBFloats(Image *image, size_t octets, float *data) { size_t + i, octets_read; assert(image != (Image *) NULL); @@ -3625,6 +3932,10 @@ MagickExport size_t ReadBlobLSBFloats(Image *image, size_t octets, float *data) MagickSwabArrayOfFloat(data,(octets_read+sizeof(float)-1)/sizeof(float)); #endif + for (i=0; i < octets_read/sizeof(float); i++) + if (MAGICK_ISNAN(data[i])) + data[i] = 0.0; + return octets_read; } @@ -3676,6 +3987,9 @@ MagickExport float ReadBlobMSBFloat(Image * image) MagickSwabFloat(&flt_buffer.f); #endif + if (MAGICK_ISNAN(flt_buffer.f)) + flt_buffer.f = 0.0; + return (flt_buffer.f); } @@ -3714,6 +4028,7 @@ MagickExport float ReadBlobMSBFloat(Image * image) MagickExport size_t ReadBlobMSBFloats(Image *image, size_t octets, float *data) { size_t + i, octets_read; assert(image != (Image *) NULL); @@ -3726,6 +4041,10 @@ MagickExport size_t ReadBlobMSBFloats(Image *image, size_t octets, float *data) MagickSwabArrayOfFloat(data,(octets_read+sizeof(float)-1)/sizeof(float)); #endif + for (i=0; i < octets_read/sizeof(float); i++) + if (MAGICK_ISNAN(data[i])) + data[i] = 0.0; + return octets_read; } @@ -3765,7 +4084,7 @@ MagickExport double ReadBlobMSBDouble(Image * image) double d; unsigned char chars[8]; } dbl_buffer; - + assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(sizeof(dbl_buffer) == sizeof(double)); @@ -3777,6 +4096,9 @@ MagickExport double ReadBlobMSBDouble(Image * image) MagickSwabDouble(&dbl_buffer.d); #endif + if (MAGICK_ISNAN(dbl_buffer.d)) + dbl_buffer.d = 0.0; + return (dbl_buffer.d); } @@ -3815,6 +4137,7 @@ MagickExport double ReadBlobMSBDouble(Image * image) MagickExport size_t ReadBlobMSBDoubles(Image *image, size_t octets, double *data) { size_t + i, octets_read; assert(image != (Image *) NULL); @@ -3822,11 +4145,17 @@ MagickExport size_t ReadBlobMSBDoubles(Image *image, size_t octets, double *data assert(data != (double *) NULL); octets_read=ReadBlob(image,octets,data); + if (octets_read >= sizeof(double)) + { #if !defined(WORDS_BIGENDIAN) - if (octets_read > 0) - MagickSwabArrayOfDouble(data,(octets_read+sizeof(double)-1)/sizeof(double)); + MagickSwabArrayOfDouble(data,(octets_read+sizeof(double)-1)/sizeof(double)); #endif + for (i=0; i < octets_read/sizeof(double); i++) + if (MAGICK_ISNAN(data[i])) + data[i] = 0.0; + } + return octets_read; } @@ -3874,9 +4203,9 @@ MagickExport magick_uint32_t ReadBlobMSBLong(Image *image) if (ReadBlob(image,4,buffer) != 4) return(0U); - value=buffer[0] << 24; - value|=buffer[1] << 16; - value|=buffer[2] << 8; + value=(magick_uint32_t) buffer[0] << 24; + value|=(magick_uint32_t) buffer[1] << 16; + value|=(magick_uint32_t) buffer[2] << 8; value|=buffer[3]; return(value & 0xffffffff); } @@ -3925,10 +4254,10 @@ MagickExport magick_int32_t ReadBlobMSBSignedLong(Image *image) if (ReadBlob(image,4,buffer) != 4) return(0); - value.uint32=buffer[0] << 24; - value.uint32|=buffer[1] << 16; - value.uint32|=buffer[2] << 8; - value.uint32|=buffer[3]; + value.uint32=(magick_uint32_t) buffer[0] << 24; + value.uint32|=(magick_uint32_t) buffer[1] << 16; + value.uint32|=(magick_uint32_t) buffer[2] << 8; + value.uint32|=(magick_uint32_t) buffer[3]; value.uint32&=0xffffffff; return value.int32; } @@ -3976,8 +4305,8 @@ MagickExport magick_uint16_t ReadBlobMSBShort(Image *image) if (ReadBlob(image,2,buffer) != 2) return(0U); - value=buffer[0] << 8; - value|=buffer[1]; + value=(magick_uint16_t) buffer[0] << 8; + value|=(magick_uint16_t) buffer[1]; return(value & 0xffff); } @@ -4024,8 +4353,8 @@ MagickExport magick_int16_t ReadBlobMSBSignedShort(Image *image) if (ReadBlob(image,2,buffer) != 2) return(0U); - value.uint16=buffer[0] << 8; - value.uint16|=buffer[1]; + value.uint16=(magick_uint16_t) buffer[0] << 8; + value.uint16|=(magick_uint16_t) buffer[1]; value.uint16&=0xffff; return value.int16; } @@ -4218,84 +4547,82 @@ MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob) % */ MagickExport magick_off_t SeekBlob(Image *image,const magick_off_t offset, - const int whence) + const int whence) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); +#if 0 + if (image->logging) + (void) LogMagickEvent(BlobEvent,GetMagickModule(), + "Seek %" MAGICK_OFF_F "d, whence = %s", + offset, + (whence == SEEK_SET ? "SEEK_SET" : + (whence == SEEK_CUR ? "SEEK_CUR" : + (whence == SEEK_END ? "SEEK_END" : + "?")))); +#endif switch (image->blob->type) - { + { case UndefinedStream: break; case FileStream: - { - if (MagickFseek(image->blob->handle.std,offset,whence) < 0) - return(-1); - image->blob->offset=TellBlob(image); - break; - } + { + if (MagickFseek(image->blob->handle.std,offset,whence) < 0) + return(-1); + image->blob->offset=TellBlob(image); + break; + } case StandardStream: case PipeStream: return(-1); case ZipStream: - { + { #if defined(HasZLIB) - if (gzseek(image->blob->handle.gz,(off_t) offset,whence) < 0) - return(-1); + if (gzseek(image->blob->handle.gz,(off_t) offset,whence) < 0) + return(-1); #endif - image->blob->offset=TellBlob(image); - break; - } + image->blob->offset=TellBlob(image); + break; + } case BZipStream: return(-1); case BlobStream: - { - switch (whence) { - case SEEK_SET: - default: - { - if (offset < 0) - return(-1); - image->blob->offset=offset; - break; - } - case SEEK_CUR: - { - if ((image->blob->offset+offset) < 0) - return(-1); - image->blob->offset+=offset; - break; - } - case SEEK_END: - { - if ((magick_off_t) - (image->blob->offset+image->blob->length+offset) < 0) - return(-1); - image->blob->offset=image->blob->length+offset; - break; - } - } - if (image->blob->offset <= (magick_off_t) image->blob->length) - image->blob->eof=MagickFalse; - else - if (image->blob->mapped) - return(-1); - else + switch (whence) { - image->blob->extent=image->blob->offset+image->blob->quantum; - MagickReallocMemory(unsigned char *,image->blob->data,image->blob->extent+1); - (void) SyncBlob(image); - if (image->blob->data == (unsigned char *) NULL) - { - DetachBlob(image->blob); + case SEEK_SET: + default: + { + if (offset < 0) return(-1); - } + image->blob->offset=offset; + break; + } + case SEEK_CUR: + { + if ((image->blob->offset+offset) < 0) + return(-1); + image->blob->offset+=offset; + break; + } + case SEEK_END: + { + if ((magick_off_t) + (image->blob->offset+image->blob->length+offset) < 0) + return(-1); + image->blob->offset=image->blob->length+offset; + break; + } } - break; + if (image->blob->offset <= (magick_off_t) image->blob->length) + { + image->blob->eof=MagickFalse; + } + break; + } } - } return(image->blob->offset); } @@ -4345,7 +4672,7 @@ MagickExport void SetBlobClosable(Image *image, MagickBool closeable) % % SetBlobTemporary() sets a boolean flag (default False) to specify if % the file associated with the blob is a temporary file and should be -% removed when the associated image is destroyed. +% removed when the associated image is destroyed. % % The format of the SetBlobTemporary method is: % @@ -4415,7 +4742,7 @@ static int SyncBlob(Image *image) the current image (as desired). */ for ( p=GetFirstImageInList(image); p != (Image *) NULL; - p=SyncNextImageInList(p)); + p=SyncNextImageInList(p)); } #endif @@ -4599,6 +4926,9 @@ MagickExport MagickPassFail UnmapBlob(void *map,const size_t length) */ MagickExport size_t WriteBlob(Image *image,const size_t length,const void *data) { + BlobInfo + * restrict blob; + size_t count; @@ -4607,92 +4937,134 @@ MagickExport size_t WriteBlob(Image *image,const size_t length,const void *data) assert(data != (const char *) NULL); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); + blob=image->blob; count=length; - switch (image->blob->type) - { + switch (blob->type) + { case UndefinedStream: break; case FileStream: case StandardStream: case PipeStream: - { - if (length == 1) - { - if((putc((int)*((unsigned char *)data),image->blob->handle.std)) != EOF) - count=1; - else - count=0; - } - else - { - count=fwrite((char *) data,1,length,image->blob->handle.std); - } - break; - } + { + if (length == 1) + { + if ((putc((int)*((unsigned char *)data),blob->handle.std)) == EOF) + count=0; + } + else + { + count=fwrite((char *) data,1,length,blob->handle.std); + } + if (count != length) + { + if (!(blob->status) && ferror(blob->handle.std)) + { + blob->status=1; + if (errno != 0) + blob->first_errno=errno; + } + } + break; + } case ZipStream: - { + { #if defined(HasZLIB) - size_t - i; + size_t + i; - for (i=0; i < length; i+=count) - { - size_t - remaining; + int + gz_count = 0; - unsigned int - amount; + for (i=0; i < length; i+=gz_count) + { + size_t + remaining; - remaining=length - i; - if (remaining > image->blob->block_size) - amount=(unsigned int) image->blob->block_size; - else - amount=(unsigned int) remaining; + unsigned int + amount; - count=gzwrite(image->blob->handle.gz, - (void *) ((unsigned char *) data+i),amount); - if (count <= 0) - break; - } - count=i; + remaining=length - i; + if (remaining > blob->block_size) + amount=(unsigned int) blob->block_size; + else + amount=(unsigned int) remaining; + + gz_count=gzwrite(blob->handle.gz, + (void *) ((unsigned char *) data+i),amount); + if (gz_count <= 0) + break; + } + count=i; + if ((count != length) && !(blob->status)) + { + int + gzerror_errnum=Z_OK; + + (void) gzerror(blob->handle.gz,&gzerror_errnum); + if (gzerror_errnum != Z_OK) + { + blob->status=1; + if ((gzerror_errnum == Z_ERRNO) && (errno != 0)) + blob->first_errno=errno; + } + } #endif - break; - } + break; + } case BZipStream: - { + { #if defined(HasBZLIB) - size_t - i; + size_t + i; - for (i=0; i < length; i+=count) - { - size_t - remaining; + int + bz_count = 0; - int - amount; + for (i=0; i < length; i+=bz_count) + { + size_t + remaining; - remaining=length - i; - if (remaining > image->blob->block_size) - amount=(int) image->blob->block_size; - else - amount=(int) remaining; + int + amount; - count=BZ2_bzwrite(image->blob->handle.gz, - (void *) ((unsigned char *) data+i),amount); - if (count <= 0) - break; - } - count=i; + remaining=length - i; + if (remaining > blob->block_size) + amount=(int) blob->block_size; + else + amount=(int) remaining; + + bz_count=BZ2_bzwrite(blob->handle.gz, + (void *) ((unsigned char *) data+i),amount); + if (bz_count <= 0) + break; + } + count=i; + if ((count != length) && !(blob->status)) + { + int + bzerror_errnum=BZ_OK; + + (void) BZ2_bzerror(blob->handle.bz,&bzerror_errnum); + if (bzerror_errnum != BZ_OK) + { + blob->status=1; + if ((bzerror_errnum == BZ_IO_ERROR) && (errno != 0)) + blob->first_errno=errno; + } + } #endif - break; - } + break; + } case BlobStream: - { - count=WriteBlobStream(image,length,data); - break; + { + count=WriteBlobStream(image,length,data); + if (count != length) + blob->status=1; + break; + } } - } return(count); } @@ -4726,30 +5098,46 @@ MagickExport size_t WriteBlob(Image *image,const size_t length,const void *data) */ MagickExport size_t WriteBlobByte(Image *image,const magick_uint8_t value) { + BlobInfo + * restrict blob; + + size_t + count=1; + unsigned char c; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); - switch (image->blob->type) + blob=image->blob; + + switch (blob->type) { case FileStream: case StandardStream: case PipeStream: { - if(putc((int) value,image->blob->handle.std) != EOF) - return 1; - return 0; + if (putc((int) value,blob->handle.std) == EOF) + { + count=0; + if (!(blob->status) && ferror(blob->handle.std)) + { + blob->status=1; + if (errno != 0) + blob->first_errno=errno; + } + } } + break; /* case BlobStream: TBD */ default: { c=(unsigned char) value; - return(WriteBlob(image,1,&c)); + count=WriteBlob(image,1,&c); } } - + return count; } /* @@ -4787,7 +5175,7 @@ MagickExport MagickPassFail WriteBlobFile(Image *image,const char *filename) status=MagickFail; if (MagickConfirmAccess(FileReadConfirmAccessMode,filename, - &image->exception) == MagickFail) + &image->exception) == MagickFail) return MagickFail; file=open(filename,O_RDONLY | O_BINARY,0777); if (file != -1) diff --git a/magick/blob.h b/magick/blob.h index 327d736..10669aa 100644 --- a/magick/blob.h +++ b/magick/blob.h @@ -1,12 +1,12 @@ /* - Copyright (C) 2003-2016 GraphicsMagick Group + Copyright (C) 2003-2018 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + Image Compression/Decompression Methods. */ #ifndef _MAGICK_BLOB_H @@ -144,7 +144,7 @@ extern "C" { /* Close I/O to the file or BLOB. */ - extern MagickExport void CloseBlob(Image *image); + extern MagickExport MagickPassFail CloseBlob(Image *image); /* @@ -189,14 +189,21 @@ extern "C" { /* Test to see if an error has been encountered while doing I/O to the file - or BLOB. + or BLOB. Non-zero is returned if an error occured. + */ + extern MagickExport int GetBlobStatus(const Image *image) MAGICK_FUNC_PURE; + + /* + Return the first errno present when an error has been encountered while + doing I/O to the file or BLOB. This is only useful if GetBlobStatus() has + already reported that an error occured. */ - extern MagickExport int GetBlobStatus(const Image *image); + extern MagickExport int GetBlobFirstErrno(const Image *image) MAGICK_FUNC_PURE; /* Test to see if blob is currently open. */ - extern MagickExport MagickBool GetBlobIsOpen(const Image *image); + extern MagickExport MagickBool GetBlobIsOpen(const Image *image) MAGICK_FUNC_PURE; /* Obtain the current size of the file or BLOB. Zero is returned if @@ -209,14 +216,14 @@ extern "C" { /* Obtain the underlying stdio FILE* for the file (if any). */ - extern MagickExport FILE *GetBlobFileHandle(const Image *image); + extern MagickExport FILE *GetBlobFileHandle(const Image *image) MAGICK_FUNC_PURE; /* Obtain a pointer to the base of where BLOB data is stored. The data is only available if the data is stored on the heap, or is memory mapped. Otherwise NULL is returned. */ - extern MagickExport unsigned char *GetBlobStreamData(const Image *image); + extern MagickExport unsigned char *GetBlobStreamData(const Image *image) MAGICK_FUNC_PURE; /* @@ -436,7 +443,7 @@ extern "C" { Blob supports seek operations. BlobSeek() and BlobTell() may safely be used. */ - extern MagickExport MagickBool BlobIsSeekable(const Image *image); + extern MagickExport MagickBool BlobIsSeekable(const Image *image) MAGICK_FUNC_PURE; /* Allow file descriptor to be closed (if True). @@ -454,7 +461,7 @@ extern "C" { Returns MagickTrue if the file associated with the blob is a temporary file and should be removed when the associated image is destroyed. */ - extern MagickExport MagickBool GetBlobTemporary(const Image *image); + extern MagickExport MagickBool GetBlobTemporary(const Image *image) MAGICK_FUNC_PURE; /* * diff --git a/magick/cdl.c b/magick/cdl.c index 7d19c41..9a77688 100644 --- a/magick/cdl.c +++ b/magick/cdl.c @@ -77,12 +77,12 @@ typedef struct _CdlImageParameters_t const PixelPacket *lut; - + } CdlImageParameters_t; static Quantum CdlQuantum(const Quantum quantum, const double slope, const double offset, - const double power, const double saturation) + const double power, const double saturation) { double v, @@ -99,46 +99,46 @@ CdlQuantum(const Quantum quantum, const double slope, const double offset, static MagickPassFail CdlImagePixels(void *mutable_data, /* User provided mutable data */ - const void *immutable_data, /* User provided immutable data */ - Image *image, /* Modify image */ - PixelPacket *pixels, /* Pixel row */ - IndexPacket *indexes, /* Pixel row indexes */ - const long npixels, /* Number of pixels in row */ - ExceptionInfo *exception) /* Exception report */ + const void *immutable_data, /* User provided immutable data */ + Image * restrict image, /* Modify image */ + PixelPacket * restrict pixels, /* Pixel row */ + IndexPacket * restrict indexes, /* Pixel row indexes */ + const long npixels, /* Number of pixels in row */ + ExceptionInfo *exception) /* Exception report */ { const CdlImageParameters_t param = *(const CdlImageParameters_t *) immutable_data; - + register long i; - + ARG_NOT_USED(mutable_data); ARG_NOT_USED(image); ARG_NOT_USED(indexes); - ARG_NOT_USED(exception); + ARG_NOT_USED(exception); if (param.lut != (PixelPacket *) NULL) { for(i = 0; i < npixels; i++) - { - pixels[i].red=param.lut[pixels[i].red].red; - pixels[i].green=param.lut[pixels[i].green].green; - pixels[i].blue=param.lut[pixels[i].blue].blue; - } + { + pixels[i].red=param.lut[pixels[i].red].red; + pixels[i].green=param.lut[pixels[i].green].green; + pixels[i].blue=param.lut[pixels[i].blue].blue; + } } else { for(i = 0; i < npixels; i++) - { - pixels[i].red=CdlQuantum(pixels[i].red,param.redslope,param.redoffset, - param.redpower,param.saturation); - pixels[i].green=CdlQuantum(pixels[i].green,param.greenslope,param.greenoffset, - param.greenpower,param.saturation); - pixels[i].blue=CdlQuantum(pixels[i].blue,param.blueslope,param.blueoffset, - param.bluepower,param.saturation); - } + { + pixels[i].red=CdlQuantum(pixels[i].red,param.redslope,param.redoffset, + param.redpower,param.saturation); + pixels[i].green=CdlQuantum(pixels[i].green,param.greenslope,param.greenoffset, + param.greenpower,param.saturation); + pixels[i].blue=CdlQuantum(pixels[i].blue,param.blueslope,param.blueoffset, + param.bluepower,param.saturation); + } } - + return MagickPass; } @@ -178,12 +178,12 @@ MagickExport MagickPassFail CdlImage(Image *image,const char *cdl) param.lut=(PixelPacket *) NULL; (void) sscanf(cdl, - "%lf%*[,/]%lf%*[,/]%lf%*[:/]%lf%*[,/]%lf%*[,/]%lf%*" - "[:/]%lf%*[,/]%lf%*[,/]%lf%*[:/]%lf", - ¶m.redslope,¶m.redoffset,¶m.redpower, - ¶m.greenslope,¶m.greenoffset,¶m.greenpower - ,¶m.blueslope,¶m.blueoffset,¶m.bluepower, - ¶m.saturation); + "%lf%*[,/]%lf%*[,/]%lf%*[:/]%lf%*[,/]%lf%*[,/]%lf%*" + "[:/]%lf%*[,/]%lf%*[,/]%lf%*[:/]%lf", + ¶m.redslope,¶m.redoffset,¶m.redpower, + ¶m.greenslope,¶m.greenoffset,¶m.greenpower + ,¶m.blueslope,¶m.blueoffset,¶m.bluepower, + ¶m.saturation); param.redslope=AbsoluteValue(param.redslope); param.redpower=AbsoluteValue(param.redpower); @@ -193,11 +193,11 @@ MagickExport MagickPassFail CdlImage(Image *image,const char *cdl) param.bluepower=AbsoluteValue(param.bluepower); FormatString(progress_message, - "[%%s] cdl %g/%g/%g/%g/%g/%g/%g/%g/%g/%g image...", - param.redslope,param.redoffset,param.redpower, - param.greenslope,param.greenoffset,param.greenpower, - param.blueslope,param.blueoffset,param.bluepower, - param.saturation); + "[%%s] cdl %g/%g/%g/%g/%g/%g/%g/%g/%g/%g image...", + param.redslope,param.redoffset,param.redpower, + param.greenslope,param.greenoffset,param.greenpower, + param.blueslope,param.blueoffset,param.bluepower, + param.saturation); if (!IsRGBCompatibleColorspace(image->colorspace)) TransformColorspace(image,RGBColorspace); @@ -209,7 +209,7 @@ MagickExport MagickPassFail CdlImage(Image *image,const char *cdl) { lut=MagickAllocateMemory(PixelPacket *,(MaxMap+1)*sizeof(PixelPacket)); if (lut != (PixelPacket *) NULL) - { + { #if (MaxMap > 256) && defined(HAVE_OPENMP) # if defined(USE_STATIC_SCHEDULING_ONLY) # pragma omp parallel for schedule(static,4) @@ -217,36 +217,34 @@ MagickExport MagickPassFail CdlImage(Image *image,const char *cdl) # pragma omp parallel for schedule(guided) # endif #endif - for (i=0; i <= (long) MaxMap; i++) - { - lut[i].red=CdlQuantum((Quantum) i,param.redslope,param.redoffset, - param.redpower,param.saturation); - lut[i].green=CdlQuantum((Quantum) i,param.greenslope,param.greenoffset, - param.greenpower,param.saturation); - lut[i].blue=CdlQuantum((Quantum) i,param.blueslope,param.blueoffset, - param.bluepower,param.saturation); - } - param.lut=lut; - } + for (i=0; i <= (long) MaxMap; i++) + { + lut[i].red=CdlQuantum((Quantum) i,param.redslope,param.redoffset, + param.redpower,param.saturation); + lut[i].green=CdlQuantum((Quantum) i,param.greenslope,param.greenoffset, + param.greenpower,param.saturation); + lut[i].blue=CdlQuantum((Quantum) i,param.blueslope,param.blueoffset, + param.bluepower,param.saturation); + } + param.lut=lut; + } } if (image->storage_class == PseudoClass) { (void) CdlImagePixels(NULL,¶m,image,image->colormap, - (IndexPacket *) NULL,image->colors, - &image->exception); + (IndexPacket *) NULL,image->colors, + &image->exception); status=SyncImage(image); } else { status=PixelIterateMonoModify(CdlImagePixels,NULL,progress_message, - NULL,¶m,0,0,image->columns,image->rows, - image,&image->exception); + NULL,¶m,0,0,image->columns,image->rows, + image,&image->exception); } MagickFreeMemory(lut); return(status); } - - diff --git a/magick/channel.c b/magick/channel.c index 468cec2..cb2018a 100644 --- a/magick/channel.c +++ b/magick/channel.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2004 - 2016 GraphicsMagick Group +% Copyright (C) 2004 - 2018 GraphicsMagick Group % % This program is covered by multiple licenses, which are described in % Copyright.txt. You should have received a copy of Copyright.txt with this @@ -50,8 +50,8 @@ correct transform, and the transform is lossy. */ static MagickPassFail ValidateChannelRequest(const ColorspaceType image_colorspace, - const ChannelType channel, - ExceptionInfo *exception) + const ChannelType channel, + ExceptionInfo *exception) { MagickPassFail status = MagickPass; @@ -63,13 +63,13 @@ static MagickPassFail ValidateChannelRequest(const ColorspaceType image_colorspa case YellowChannel: case BlackChannel: if (image_colorspace != CMYKColorspace) - status = MagickFail; + status = MagickFail; break; case RedChannel: case GreenChannel: case BlueChannel: if (image_colorspace == CMYKColorspace) - status = MagickFail;; + status = MagickFail;; break; default: { @@ -117,7 +117,7 @@ static MagickPassFail ValidateChannelRequest(const ColorspaceType image_colorspa static MagickPassFail ChannelImagePixels(void *mutable_data, /* User provided mutable data */ const void *immutable_data, /* User provided immutable data */ - Image *image, /* Modify image */ + Image * restrict image, /* Modify image */ PixelPacket * restrict pixels, /* Pixel row */ IndexPacket * restrict indexes,/* Pixel row indexes */ const long npixels, /* Number of pixels in row */ @@ -130,7 +130,7 @@ ChannelImagePixels(void *mutable_data, /* User provided mutable data channel = *((const ChannelType *) immutable_data); register long - i; + i; ARG_NOT_USED(mutable_data); ARG_NOT_USED(exception); @@ -243,7 +243,7 @@ MagickExport MagickPassFail ChannelImage(Image *image,const ChannelType channel) assert(image->signature == MagickSignature); FormatString(progress_message,"[%%s] Extract %s channel... ", - ChannelTypeToString(channel)); + ChannelTypeToString(channel)); /* Verify that image colorspace is compatible with with requested @@ -324,12 +324,12 @@ MagickExport MagickPassFail ChannelImage(Image *image,const ChannelType channel) static MagickPassFail ExportImageChannelPixels(void *mutable_data, /* User provided mutable data */ const void *immutable_data, /* User provided immutable data */ - const Image *source_image, /* Source image */ - const PixelPacket *source_pixels, /* Pixel row in source image */ - const IndexPacket *source_indexes, /* Pixel row indexes in source image */ - Image *new_image, /* New image */ - PixelPacket *new_pixels, /* Pixel row in new image */ - IndexPacket *new_indexes, /* Pixel row indexes in new image */ + const Image * restrict source_image, /* Source image */ + const PixelPacket * restrict source_pixels, /* Pixel row in source image */ + const IndexPacket * restrict source_indexes, /* Pixel row indexes in source image */ + Image * restrict new_image, /* New image */ + PixelPacket * restrict new_pixels, /* Pixel row in new image */ + IndexPacket * restrict new_indexes, /* Pixel row indexes in new image */ const long npixels, /* Number of pixels in row */ ExceptionInfo *exception /* Exception report */ ) @@ -369,7 +369,7 @@ ExportImageChannelPixels(void *mutable_data, /* User provided mut { register long i; - + for (i=0; i < npixels; i++) { new_pixels[i].red=new_pixels[i].green= @@ -392,7 +392,7 @@ ExportImageChannelPixels(void *mutable_data, /* User provided mut { } } - + return MagickPass; } #define ExportImageChannelText "[%s] Exporting channel... " @@ -402,7 +402,7 @@ MagickExport Image *ExportImageChannel(const Image *source_image, { ChannelType channel_type = channel; - + Image *new_image; @@ -433,7 +433,7 @@ MagickExport Image *ExportImageChannel(const Image *source_image, source_image->columns,source_image->rows, source_image,0,0, new_image,0,0, - exception); + exception); new_image->is_grayscale=True; new_image->is_monochrome=source_image->is_monochrome; @@ -506,9 +506,9 @@ MagickExport Image *ExportImageChannel(const Image *source_image, static MagickPassFail GetImageChannelDepthPixels(void *mutable_data, /* User provided mutable data */ const void *immutable_data, /* User provided immutable data */ - const Image *image, /* Input image */ - const PixelPacket *pixels, /* Pixel row */ - const IndexPacket *indexes, /* Pixel indexes */ + const Image * restrict image, /* Input image */ + const PixelPacket * restrict pixels, /* Pixel row */ + const IndexPacket * restrict indexes, /* Pixel indexes */ const long npixels, /* Number of pixels in row */ ExceptionInfo *exception /* Exception report */ ) @@ -669,12 +669,12 @@ GetImageChannelDepth(const Image *image, static MagickPassFail ImportImageChannelPixels(void *mutable_data, /* User provided mutable data */ const void *immutable_data, /* User provided immutable data */ - const Image *source_image, /* Source image */ - const PixelPacket *source_pixels, /* Pixel row in source image */ - const IndexPacket *source_indexes, /* Pixel row indexes in source image */ - Image *update_image, /* Update image */ - PixelPacket *update_pixels, /* Pixel row in update image */ - IndexPacket *update_indexes, /* Pixel row indexes in update image */ + const Image * restrict source_image, /* Source image */ + const PixelPacket * restrict source_pixels, /* Pixel row in source image */ + const IndexPacket * restrict source_indexes, /* Pixel row indexes in source image */ + Image * restrict update_image, /* Update image */ + PixelPacket * restrict update_pixels, /* Pixel row in update image */ + IndexPacket * restrict update_indexes, /* Pixel row indexes in update image */ const long npixels, /* Number of pixels in row */ ExceptionInfo *exception /* Exception report */ ) @@ -800,12 +800,12 @@ MagickPassFail ImportImageChannel(const Image *source_image, static MagickPassFail ImportImageChannelsMaskedPixels(void *mutable_data, /* User provided mutable data */ const void *immutable_data, /* User provided immutable data */ - const Image *source_image, /* Source image */ - const PixelPacket *source_pixels, /* Pixel row in source image */ - const IndexPacket *source_indexes, /* Pixel row indexes in source image */ - Image *update_image, /* Update image */ - PixelPacket *update_pixels, /* Pixel row in update image */ - IndexPacket *update_indexes, /* Pixel row indexes in update image */ + const Image * restrict source_image, /* Source image */ + const PixelPacket * restrict source_pixels, /* Pixel row in source image */ + const IndexPacket * restrict source_indexes, /* Pixel row indexes in source image */ + Image * restrict update_image, /* Update image */ + PixelPacket * restrict update_pixels, /* Pixel row in update image */ + IndexPacket * restrict update_indexes, /* Pixel row indexes in update image */ const long npixels, /* Number of pixels in row */ ExceptionInfo *exception /* Exception report */ ) @@ -866,10 +866,10 @@ MagickPassFail ImportImageChannelsMasked(const Image *source_image, { ChannelType channel_type = channels; - + MagickPassFail status=MagickPass; - + assert(update_image != (Image *) NULL); assert(update_image->signature == MagickSignature); assert(source_image != (Image *) NULL); diff --git a/magick/channel.h b/magick/channel.h index 5dceaee..56e983a 100644 --- a/magick/channel.h +++ b/magick/channel.h @@ -1,10 +1,10 @@ /* Copyright (C) 2004 GraphicsMagick Group - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + */ #ifndef _MAGICK_CHANNEL_H #define _MAGICK_CHANNEL_H diff --git a/magick/color.c b/magick/color.c index 835cf71..1dff591 100644 --- a/magick/color.c +++ b/magick/color.c @@ -155,16 +155,16 @@ ComputeCubeInfo(const Image *image,ExceptionInfo *exception) CubeInfo *cube_info; - + long y; - + NodeInfo *node_info; - + register const PixelPacket *p; - + register long i, x; diff --git a/magick/color.h b/magick/color.h index f25c745..27654c1 100644 --- a/magick/color.h +++ b/magick/color.h @@ -1,11 +1,11 @@ /* - Copyright (C) 2003 - 2010 GraphicsMagick Group + Copyright (C) 2003 - 2018 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick Color Utility Methods. */ #ifndef _MAGICK_COLOR_H @@ -61,28 +61,28 @@ extern MagickExport MagickBool /* Compare two colors */ -#define ColorMatch(p,q) \ - (((p)->red == (q)->red) && \ - ((p)->green == (q)->green) && \ +#define ColorMatch(p,q) \ + (((p)->red == (q)->red) && \ + ((p)->green == (q)->green) && \ ((p)->blue == (q)->blue)) -#define NotColorMatch(p,q) \ - (((p)->red != (q)->red) || \ - ((p)->green != (q)->green) || \ +#define NotColorMatch(p,q) \ + (((p)->red != (q)->red) || \ + ((p)->green != (q)->green) || \ ((p)->blue != (q)->blue)) extern MagickExport unsigned int - FuzzyColorMatch(const PixelPacket *p,const PixelPacket *q,const double fuzz); + FuzzyColorMatch(const PixelPacket *p,const PixelPacket *q,const double fuzz) MAGICK_FUNC_PURE; /* Compare two pixels (including opacity) */ -#define PixelMatch(p,q,matte) \ - (ColorMatch(p,q) && \ +#define PixelMatch(p,q,matte) \ + (ColorMatch(p,q) && \ (!matte || ((p)->opacity == (q)->opacity))) -#define NotPixelMatch(p,q,matte) \ - (NotColorMatch(p,q) || \ +#define NotPixelMatch(p,q,matte) \ + (NotColorMatch(p,q) || \ (matte && ((p)->opacity != (q)->opacity))) diff --git a/magick/color_lookup.c b/magick/color_lookup.c index b0d88a3..d33fbcb 100644 --- a/magick/color_lookup.c +++ b/magick/color_lookup.c @@ -672,7 +672,7 @@ DestroyColorInfoEntry(ColorInfo *entry) MagickFreeMemory(entry->path); MagickFreeMemory(entry->name); } - MagickFreeMemory(entry); + MagickFreeMemory(entry); } MagickExport void DestroyColorInfo(void) @@ -759,16 +759,16 @@ GetColorInfo(const char *name,ExceptionInfo *exception) { /* Check common synonyms */ const char - *pos; + *pos; LocaleUpper(colorname); if ((pos = strstr(colorname,"GREY")) != (const char *) NULL) - { - colorname[pos-colorname+2]='A'; - for (p=color_list; p != (ColorInfo *) NULL; p=p->next) - if (LocaleCompare(colorname,p->name) == 0) - break; - } + { + colorname[pos-colorname+2]='A'; + for (p=color_list; p != (ColorInfo *) NULL; p=p->next) + if (LocaleCompare(colorname,p->name) == 0) + break; + } } if (p == (ColorInfo *) NULL) ThrowException(exception,OptionWarning,UnrecognizedColor,name); @@ -1046,15 +1046,15 @@ ListColorInfo(FILE *file,ExceptionInfo *exception) if (p->color.opacity == OpaqueOpacity) (void) fprintf(file,"%5d,%5d,%5d ", - ScaleQuantumToChar(p->color.red), - ScaleQuantumToChar(p->color.green), - ScaleQuantumToChar(p->color.blue)); + ScaleQuantumToChar(p->color.red), + ScaleQuantumToChar(p->color.green), + ScaleQuantumToChar(p->color.blue)); else (void) fprintf(file,"%5d,%5d,%5d,%5d ", - ScaleQuantumToChar(p->color.red), - ScaleQuantumToChar(p->color.green), - ScaleQuantumToChar(p->color.blue), - ScaleQuantumToChar(p->color.opacity)); + ScaleQuantumToChar(p->color.red), + ScaleQuantumToChar(p->color.green), + ScaleQuantumToChar(p->color.blue), + ScaleQuantumToChar(p->color.opacity)); if ((unsigned int) p->compliance & (unsigned int) SVGCompliance) (void) fprintf(file,"SVG "); if ((unsigned int) p->compliance & (unsigned int) X11Compliance) @@ -1127,7 +1127,7 @@ InitializeColorInfo(void) */ MagickExport unsigned int QueryColorDatabase(const char *name,PixelPacket *color, - ExceptionInfo *exception) + ExceptionInfo *exception) { double scale; @@ -1234,7 +1234,7 @@ QueryColorDatabase(const char *name,PixelPacket *color, { unsigned int divisor=1; - + n<<=2; for( i=n-1; i; i--) { @@ -1257,31 +1257,47 @@ QueryColorDatabase(const char *name,PixelPacket *color, if (LocaleNCompare(name,"rgb(",4) == 0) { DoublePixelPacket - pixel; + pixel; + + int + count; scale=strchr(name,'%') == (char *) NULL ? 1.0 : ScaleQuantumToChar(MaxRGB)/100.0; - (void) sscanf(name,"%*[^(](%lf%*[%,]%lf%*[%,]%lf", + pixel.red=pixel.green=pixel.blue=0.0; + count=sscanf(name,"%*[^(](%lf%*[%,]%lf%*[%,]%lf", &pixel.red,&pixel.green,&pixel.blue); - color->red=ScaleCharToQuantum(scale*pixel.red); - color->green=ScaleCharToQuantum(scale*pixel.green); - color->blue=ScaleCharToQuantum(scale*pixel.blue); + if (count > 0) + color->red=ScaleCharToQuantum(scale*pixel.red); + if (count > 1) + color->green=ScaleCharToQuantum(scale*pixel.green); + if (count > 2) + color->blue=ScaleCharToQuantum(scale*pixel.blue); color->opacity=OpaqueOpacity; return(True); } if (LocaleNCompare(name,"rgba(",5) == 0) { DoublePixelPacket - pixel; + pixel; + + int + count; scale=strchr(name,'%') == (char *) NULL ? 1.0 : ScaleQuantumToChar(MaxRGB)/100.0; - (void) sscanf(name,"%*[^(](%lf%*[%,]%lf%*[%,]%lf%*[%,]%lf", + pixel.red=pixel.green=pixel.blue=0.0; + color->opacity=OpaqueOpacity; + count = sscanf(name,"%*[^(](%lf%*[%,]%lf%*[%,]%lf%*[%,]%lf", &pixel.red,&pixel.green,&pixel.blue,&pixel.opacity); - color->red=ScaleCharToQuantum(scale*pixel.red); - color->green=ScaleCharToQuantum(scale*pixel.green); - color->blue=ScaleCharToQuantum(scale*pixel.blue); - color->opacity=ScaleCharToQuantum(scale*pixel.opacity); + if (count > 0) + color->red=ScaleCharToQuantum(scale*pixel.red); + if (count > 1) + color->green=ScaleCharToQuantum(scale*pixel.green); + if (count > 2) + color->blue=ScaleCharToQuantum(scale*pixel.blue); + if (count > 3) + color->opacity=ScaleCharToQuantum(scale*pixel.opacity); return(True); } p=GetColorInfo(name,exception); @@ -1336,8 +1352,8 @@ QueryColorDatabase(const char *name,PixelPacket *color, */ MagickExport unsigned int QueryColorname(const Image *image,const PixelPacket *color, - const ComplianceType compliance,char *name, - ExceptionInfo *exception) + const ComplianceType compliance,char *name, + ExceptionInfo *exception) { register const ColorInfo *p; @@ -1402,8 +1418,8 @@ QueryColorname(const Image *image,const PixelPacket *color, */ static MagickPassFail ReadColorConfigureFile(const char *basename, - const unsigned int depth, - ExceptionInfo *exception) + const unsigned int depth, + ExceptionInfo *exception) { size_t length; @@ -1415,40 +1431,40 @@ ReadColorConfigureFile(const char *basename, if (depth == 0) { size_t - i; + i; /* - Load default set of colors from the static color table. + Load default set of colors from the static color table. */ for (i=0 ; i < sizeof(StaticColors)/sizeof(StaticColors[0]); i++) - { - ColorInfo - *color_info; + { + ColorInfo + *color_info; - color_info=MagickAllocateMemory(ColorInfo *,sizeof(ColorInfo)); - if (color_info == (ColorInfo *) NULL) - MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, - UnableToAllocateColorInfo); - color_info->path=(char *) BuiltInPath; - color_info->name=(char *) StaticColors[i].name; - color_info->compliance=(ComplianceType) StaticColors[i].compliance; - color_info->color.red=ScaleCharToQuantum(StaticColors[i].red); - color_info->color.green=ScaleCharToQuantum(StaticColors[i].green); - color_info->color.blue=ScaleCharToQuantum(StaticColors[i].blue); - color_info->color.opacity=ScaleCharToQuantum(StaticColors[i].opacity); - color_info->stealth=MagickFalse; - color_info->signature=MagickSignature; - color_info->previous=(ColorInfo *) NULL; - color_info->next=(ColorInfo *) NULL; - if (color_list == (ColorInfo *) NULL) - { - color_list=color_info; - continue; - } - color_list->next=color_info; - color_info->previous=color_list; - color_list=color_list->next; - } + color_info=MagickAllocateMemory(ColorInfo *,sizeof(ColorInfo)); + if (color_info == (ColorInfo *) NULL) + MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, + UnableToAllocateColorInfo); + color_info->path=(char *) BuiltInPath; + color_info->name=(char *) StaticColors[i].name; + color_info->compliance=(ComplianceType) StaticColors[i].compliance; + color_info->color.red=ScaleCharToQuantum(StaticColors[i].red); + color_info->color.green=ScaleCharToQuantum(StaticColors[i].green); + color_info->color.blue=ScaleCharToQuantum(StaticColors[i].blue); + color_info->color.opacity=ScaleCharToQuantum(StaticColors[i].opacity); + color_info->stealth=MagickFalse; + color_info->signature=MagickSignature; + color_info->previous=(ColorInfo *) NULL; + color_info->next=(ColorInfo *) NULL; + if (color_list == (ColorInfo *) NULL) + { + color_list=color_info; + continue; + } + color_list->next=color_info; + color_info->previous=color_list; + color_list=color_list->next; + } } /* @@ -1458,12 +1474,12 @@ ReadColorConfigureFile(const char *basename, if (depth == 0) { ExceptionInfo - exception_local; + exception_local; GetExceptionInfo(&exception_local); xml=(char *) GetConfigureBlob(basename,path,&length,&exception_local); if (exception_local.severity != ConfigureError) - CopyException(exception,&exception_local); + CopyException(exception,&exception_local); DestroyExceptionInfo(&exception_local); } else @@ -1473,220 +1489,220 @@ ReadColorConfigureFile(const char *basename, if (xml != (char *) NULL) { char - keyword[MaxTextExtent], - *q, - *token; + keyword[MaxTextExtent], + *q, + *token; size_t token_max_length; MagickBool - in_entry; + in_entry; token=AcquireString(xml); token_max_length=strlen(token); in_entry=MagickFalse; for (q=xml; *q != '\0'; ) - { - /* - Interpret XML. - */ - MagickGetToken(q,&q,token,token_max_length); - if (*token == '\0') - break; - (void) strlcpy(keyword,token,sizeof(keyword)); - if (LocaleNCompare(keyword," x=49.999 + x==50.000 --> x=49.000 + + Pretty sure this was not the intention of the original + author. Also, this can result in x_start > x_end, which + can cause the call to GetImagePixelsEx() to blow up due to + a column count <= 0 (see code below). + + Changed the code to first check for starting bounds beyond + right/bottom of image, and ending bounds beyond left/top + of image. When this is the case, there is nothing to do, + since the object lies completely outside the image. If + not, clip based on columns-1 and rows-1 instead of columns + and rows. + */ + + /* sanity check for excessively big stroke_width (ticket #515) */ + if ( (stroke_width_limited = STROKE_WIDTH_LIMIT(image)) > draw_info->stroke_width ) + stroke_width_limited = draw_info->stroke_width; + + mid=ExpandAffine(&draw_info->affine)*stroke_width_limited/2.0; bounds.x1-=(mid+1.0); - bounds.x1=bounds.x1 < 0.0 ? 0.0 : bounds.x1 >= image->columns ? - image->columns-1 : bounds.x1; bounds.y1-=(mid+1.0); - bounds.y1=bounds.y1 < 0.0 ? 0.0 : bounds.y1 >= image->rows ? - image->rows-1 : bounds.y1; bounds.x2+=(mid+1.0); - bounds.x2=bounds.x2 < 0.0 ? 0.0 : bounds.x2 >= image->columns ? - image->columns-1 : bounds.x2; bounds.y2+=(mid+1.0); - bounds.y2=bounds.y2 < 0.0 ? 0.0 : bounds.y2 >= image->rows ? + if ( (bounds.x1 >= image->columns) || (bounds.y1 >= image->rows) + || (bounds.x2 <= 0.0) || (bounds.y2 <= 0.0) ) + { + /* object completely outside image */ + DestroyThreadViewDataSet(polygon_set); + polygon_set = (ThreadViewDataSet *) NULL; + return(MagickPass); + } + bounds.x1=bounds.x1 <= 0.0 ? 0.0 : bounds.x1 >= image->columns-1 ? + image->columns-1 : bounds.x1; + bounds.y1=bounds.y1 <= 0.0 ? 0.0 : bounds.y1 >= image->rows-1 ? + image->rows-1 : bounds.y1; + bounds.x2=bounds.x2 <= 0.0 ? 0.0 : bounds.x2 >= image->columns-1 ? + image->columns-1 : bounds.x2; + bounds.y2=bounds.y2 <= 0.0 ? 0.0 : bounds.y2 >= image->rows-1 ? image->rows-1 : bounds.y2; } @@ -3868,94 +5006,91 @@ DrawPolygonPrimitive(Image *image,const DrawInfo *draw_info, Draw point. */ long - x_start, - x_stop, - y_start, - y_stop, - y; + x_start, + x_stop, + y_start, + y_stop, + y; PixelPacket - stroke_color; + stroke_color; - stroke_color=draw_info->stroke; - x_start=(long) ceil(bounds.x1-0.5); - x_stop=(long) floor(bounds.x2+0.5); + stroke_color=draw_info->stroke; + x_start=(long) ceil(bounds.x1-0.5); /* rounds n.5 to n */ + x_stop=(long) floor(bounds.x2+0.5); /* rounds n.5 to n+1 */ y_start=(long) ceil(bounds.y1-0.5); y_stop=(long) floor(bounds.y2+0.5); #if defined(HAVE_OPENMP) # if defined(TUNE_OPENMP) # pragma omp parallel for schedule(runtime) shared(status) # else -# pragma omp parallel for schedule(static) shared(status) +# pragma omp parallel for schedule(guided) shared(status) # endif #endif for (y=y_start; y <= y_stop; y++) - { - long - x; + { + long + x; - PixelPacket - * restrict q; + PixelPacket + * restrict q; - MagickPassFail - thread_status; + MagickPassFail + thread_status; + thread_status=status; + if (thread_status == MagickFail) + continue; + + x=x_start; + q=GetImagePixelsEx(image,x,y,x_stop-x+1,1,&image->exception); + if (q == (PixelPacket *) NULL) + thread_status=MagickFail; + if (thread_status != MagickFail) + { + for ( ; x <= x_stop; x++) + { + if ((x == (long) ceil(primitive_info->point.x-0.5)) && + (y == (long) ceil(primitive_info->point.y-0.5))) + *q=stroke_color; + q++; + } + if (!SyncImagePixelsEx(image,&image->exception)) + thread_status=MagickFail; + } + if (thread_status == MagickFail) + { + status=thread_status; #if defined(HAVE_OPENMP) -# pragma omp critical (GM_DrawPolygonPrimitive_Status) -#endif - thread_status=status; - if (thread_status == MagickFail) - continue; - - x=x_start; - q=GetImagePixelsEx(image,x,y,x_stop-x+1,1,&image->exception); - if (q == (PixelPacket *) NULL) - thread_status=MagickFail; - if (thread_status != MagickFail) - { - for ( ; x <= x_stop; x++) - { - if ((x == (long) ceil(primitive_info->point.x-0.5)) && - (y == (long) ceil(primitive_info->point.y-0.5))) - *q=stroke_color; - q++; - } - if (!SyncImagePixelsEx(image,&image->exception)) - thread_status=MagickFail; - } - if (thread_status == MagickFail) - { -#if defined(HAVE_OPENMP) -# pragma omp critical (GM_DrawPolygonPrimitive_Status) +# pragma omp flush (status) #endif - status=thread_status; - } - } + } + } } /* if (primitive_info->coordinates == 1) */ else { /* - Draw polygon or line. + Draw polygon or line. */ long - x_start, - x_stop, - y_start, - y_stop, - y; + x_start, + x_stop, + y_start, + y_stop, + y; const Image - *fill_pattern=draw_info->fill_pattern, - *stroke_pattern=draw_info->stroke_pattern; + *fill_pattern=draw_info->fill_pattern, + *stroke_pattern=draw_info->stroke_pattern; unsigned int - fill; + fill; fill=(primitive_info->method == FillToBorderMethod) || - (primitive_info->method == FloodfillMethod); + (primitive_info->method == FloodfillMethod); - x_start=(long) ceil(bounds.x1-0.5); - x_stop=(long) floor(bounds.x2+0.5); + x_start=(long) ceil(bounds.x1-0.5); /* rounds n.5 to n */ + x_stop=(long) floor(bounds.x2+0.5); /* rounds n.5 to n+1 */ y_start=(long) ceil(bounds.y1-0.5); y_stop=(long) floor(bounds.y2+0.5); #if 1 @@ -3968,104 +5103,136 @@ DrawPolygonPrimitive(Image *image,const DrawInfo *draw_info, #endif #endif for (y=y_start; y <= y_stop; y++) - { - PixelPacket - fill_color, - stroke_color; + { + PixelPacket + fill_color, + stroke_color; - double - fill_opacity, - stroke_opacity; + double + fill_opacity, + stroke_opacity; - long - x; + long + x; - PolygonInfo - * restrict polygon_info; + PolygonInfo + * restrict polygon_info; - PixelPacket - * restrict q; + PixelPacket + * restrict q; - MagickPassFail - thread_status; + MagickPassFail + thread_status; -#if defined(HAVE_OPENMP) -# pragma omp critical (GM_DrawPolygonPrimitive_Status) -#endif - thread_status=status; - if (thread_status == MagickFail) - continue; - - polygon_info=(PolygonInfo *) AccessThreadViewData(polygon_set); - fill_color=draw_info->fill; - stroke_color=draw_info->stroke; - x=x_start; - q=GetImagePixelsEx(image,x,y,x_stop-x+1,1,&image->exception); - if (q == (PixelPacket *) NULL) - thread_status=MagickFail; - - if (thread_status != MagickFail) - { - for ( ; x <= x_stop; x++) - { - /* - Fill and/or stroke. - */ - fill_opacity=GetPixelOpacity(polygon_info,mid,fill, - draw_info->fill_rule, - x,y,&stroke_opacity); - if (!draw_info->stroke_antialias) - { - /* When stroke antialiasing is disabled, only draw for - opacities >= 0.99 in order to ensure that lines are not - drawn wider than requested. */ - if (fill_opacity < 0.99) - fill_opacity=0.0; - if (stroke_opacity < 0.99) - stroke_opacity=0.0; - } - if ((fill_pattern != (Image *) NULL) && + thread_status=status; + if (thread_status == MagickFail) + continue; + + polygon_info=(PolygonInfo *) AccessThreadViewData(polygon_set); + fill_color=draw_info->fill; + stroke_color=draw_info->stroke; + x=x_start; + q=GetImagePixelsEx(image,x,y,x_stop-x+1,1,&image->exception); + if (q == (PixelPacket *) NULL) + thread_status=MagickFail; + + if (thread_status != MagickFail) + { + for ( ; x <= x_stop; x++) + { + /* + Fill and/or stroke. The fill_opacity returned by GetPixelOpacity() + handles partial pixel coverage at the edge of a polygon, where + 0==no coverage and 1==full coverage + */ + fill_opacity=GetPixelOpacity(polygon_info,mid,fill, + draw_info->fill_rule, + x,y,&stroke_opacity); + if (!draw_info->stroke_antialias) + { + /* When stroke antialiasing is disabled, only draw for + opacities >= 0.99 in order to ensure that lines are not + drawn wider than requested. */ + if (fill_opacity < 0.99) + fill_opacity=0.0; + if (stroke_opacity < 0.99) + stroke_opacity=0.0; + } + if ((fill_pattern != (Image *) NULL) && (fill_pattern->columns != 0) && (fill_pattern->rows != 0)) - (void) AcquireOnePixelByReference - (fill_pattern,&fill_color, - (long) (x-fill_pattern->tile_info.x) % fill_pattern->columns, - (long) (y-fill_pattern->tile_info.y) % fill_pattern->rows, - &image->exception); - fill_opacity=MaxRGBDouble-fill_opacity* - (MaxRGBDouble-(double) fill_color.opacity); - AlphaCompositePixel(q,&fill_color,fill_opacity,q, - (q->opacity == TransparentOpacity) - ? OpaqueOpacity : q->opacity); - if ((stroke_pattern != (Image *) NULL) && + { + (void) AcquireOnePixelByReference + (fill_pattern,&fill_color, + (long) (x-fill_pattern->tile_info.x) % fill_pattern->columns, + (long) (y-fill_pattern->tile_info.y) % fill_pattern->rows, + &image->exception); + /* apply the group opacity value to the pattern pixel */ + fill_color.opacity = MaxRGB-((MaxRGB-fill_color.opacity)*(MaxRGB-draw_info->opacity)+(MaxRGB>>1))/MaxRGB; + } + /* combine fill_opacity with the fill color's opacity */ + fill_opacity=MaxRGBDouble-fill_opacity* + (MaxRGBDouble-(double) fill_color.opacity); + /* + Notes on call to AlphaCompositePixel(): + + fill_color: the polygon or pattern fill color, not premultiplied + by its opacity value + fill_opacity: product of the fill color opacity and opacity due + to partial pixel coverage (e.g., at the edge of the polygon) + q: (input) the background pixel, (output) the composited pixel; + neither is premultiplied by its opacity value + q->opacity: the background pixel opacity + + The previous version of this code substituted "OpaqueOpacity" + for q->opacity if q->opacity was transparent. I think this was + orignally done to avoid a divide-by-zero in AlphaCompositePixel(). + However, this substitution results in an incorrect result if the + background pixel is completely transparent. Since the current + version of AlphaCompositePixel() has code in it to prevent a + divide-by-zero, the code has been fixed to always use q->opacity + as the background pixel opacity. + */ + AlphaCompositePixel(q,&fill_color,fill_opacity,q,q->opacity); + if ((stroke_pattern != (Image *) NULL) && (stroke_pattern->columns != 0) && (stroke_pattern->rows != 0)) - (void) AcquireOnePixelByReference - (stroke_pattern,&stroke_color, - (long) (x-stroke_pattern->tile_info.x) % stroke_pattern->columns, - (long) (y-stroke_pattern->tile_info.y) % stroke_pattern->rows, - &image->exception); - stroke_opacity=MaxRGBDouble-stroke_opacity* - (MaxRGBDouble-(double)stroke_color.opacity); - AlphaCompositePixel(q,&stroke_color,stroke_opacity,q, - (q->opacity == TransparentOpacity) - ? OpaqueOpacity : q->opacity); - q++; - } /* for ( ; x <= x_stop; x++) */ - if (!SyncImagePixelsEx(image,&image->exception)) - thread_status=MagickFail; - - if (thread_status == MagickFail) - { + { + (void) AcquireOnePixelByReference + (stroke_pattern,&stroke_color, + (long) (x-stroke_pattern->tile_info.x) % stroke_pattern->columns, + (long) (y-stroke_pattern->tile_info.y) % stroke_pattern->rows, + &image->exception); + /* apply the group opacity value to the pattern pixel */ + stroke_color.opacity = MaxRGB-((MaxRGB-stroke_color.opacity)*(MaxRGB-draw_info->opacity)+(MaxRGB>>1))/MaxRGB; + } + stroke_opacity=MaxRGBDouble-stroke_opacity* + (MaxRGBDouble-(double)stroke_color.opacity); + /* + In the call to AlphaCompositePixel() below, q->opacity is now always + used as the background pixel opacity for the same reason as described + in the call to AlphaCompositePixel() above. + */ + AlphaCompositePixel(q,&stroke_color,stroke_opacity,q,q->opacity); + q++; + } /* for ( ; x <= x_stop; x++) */ + if (!SyncImagePixelsEx(image,&image->exception)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { + status=thread_status; #if defined(HAVE_OPENMP) -# pragma omp critical (GM_DrawPolygonPrimitive_Status) +# pragma omp flush (status) #endif - status=thread_status; - } - } - } + } + } + } } (void) LogMagickEvent(RenderEvent,GetMagickModule()," end draw-polygon"); + + draw_polygon_primitive_end:; + DestroyThreadViewDataSet(polygon_set); return(status); @@ -4517,6 +5684,7 @@ DrawPrimitive(Image *image,const DrawInfo *draw_info, { double mid, + stroke_width_limited, scale; DrawInfo @@ -4541,7 +5709,12 @@ DrawPrimitive(Image *image,const DrawInfo *draw_info, status&=DrawDashPolygon(draw_info,primitive_info,image); break; } - mid=ExpandAffine(&draw_info->affine)*draw_info->stroke_width/2.0; + + /* sanity check for excessively big stroke_width (ticket #515) */ + if ( (stroke_width_limited = STROKE_WIDTH_LIMIT(image)) > draw_info->stroke_width ) + stroke_width_limited = draw_info->stroke_width; + + mid=ExpandAffine(&draw_info->affine)*stroke_width_limited/2.0; if ((mid > 1.0) && (draw_info->stroke.opacity != TransparentOpacity)) { unsigned int @@ -4550,10 +5723,7 @@ DrawPrimitive(Image *image,const DrawInfo *draw_info, /* Draw strokes while respecting line cap/join attributes. */ - for (i=0; primitive_info[i].primitive != UndefinedPrimitive; i++); - closed_path= - (primitive_info[i-1].point.x == primitive_info[0].point.x) && - (primitive_info[i-1].point.y == primitive_info[0].point.y); + closed_path=PRIMINF_GET_IS_CLOSED_SUBPATH(&primitive_info[0]); i=(long) primitive_info[0].coordinates; if ((((draw_info->linecap == RoundCap) || closed_path) && (draw_info->linejoin == RoundJoin)) || @@ -4562,11 +5732,13 @@ DrawPrimitive(Image *image,const DrawInfo *draw_info, status&=DrawPolygonPrimitive(image,draw_info,primitive_info); break; } + /* first fill the polygon by cloning and turning off stroking ... */ clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info); clone_info->stroke_width=0.0; clone_info->stroke.opacity=TransparentOpacity; status&=DrawPolygonPrimitive(image,clone_info,primitive_info); DestroyDrawInfo(clone_info); + /* ... and then stroke the polygon */ status&=DrawStrokePolygon(image,draw_info,primitive_info); break; } @@ -4670,13 +5842,41 @@ DrawStrokePolygon(Image *image,const DrawInfo *draw_info, status=MagickPass; for (p=primitive_info; p->primitive != UndefinedPrimitive; p+=p->coordinates) { - stroke_polygon=TraceStrokePolygon(draw_info,p); + /* + Per the SVG spec: A subpath (see Paths) consisting of a + single moveto shall not be stroked. + */ + if ( p->coordinates == 1 ) + continue; + /* + *** BUG ALERT! *** + + The sequence below has a bug in it somewhere. "Thin" polygons that are + stroked with a stroke-width whose magnitude is close to the size of the + "thinness" of the polygon are rendered incorrectly. For example, this + SVG path renders correctly: + + + + But this one does not: + + + + The only difference is the y coordinate of the last path point (10.5 vs. 10.4). + + The "stroke_polygon" produced by TraceStrokePolygon() for the second path is + significantly different from that for the first path, so my suspicion is that + that's where the bug is. However, it could also be in DrawPolygonPrimitive(). + */ + stroke_polygon=TraceStrokePolygon(image,draw_info,p); status&=DrawPolygonPrimitive(image,clone_info,stroke_polygon); MagickFreeMemory(stroke_polygon); if (status == MagickFail) break; q=p+p->coordinates-1; - closed_path=(q->point.x == p->point.x) && (q->point.y == p->point.y); + closed_path=PRIMINF_GET_IS_CLOSED_SUBPATH(p); if ((draw_info->linecap == RoundCap) && !closed_path) { DrawRoundLinecap(image,draw_info,p); @@ -4720,11 +5920,22 @@ GetDrawInfo(const ImageInfo *image_info,DrawInfo *draw_info) ImageInfo *clone_info; + DrawInfoExtra + *DIExtra; + /* Initialize draw attributes. */ assert(draw_info != (DrawInfo *) NULL); (void) memset(draw_info,0,sizeof(DrawInfo)); + + /* allocate and initialize struct for extra DrawInfo members */ + DIExtra = MagickAllocateMemory(DrawInfoExtra *,sizeof(DrawInfoExtra)); + if ( DIExtra == (DrawInfoExtra *) NULL ) + MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,UnableToAllocateDrawInfo); + memset(DIExtra,0,sizeof(*DIExtra)); + draw_info->extra = DIExtra; + clone_info=CloneImageInfo(image_info); IdentityAffine(&draw_info->affine); draw_info->gravity=NorthWestGravity; @@ -4751,6 +5962,8 @@ GetDrawInfo(const ImageInfo *image_info,DrawInfo *draw_info) draw_info->server_name=AllocateString(clone_info->server_name); draw_info->render=True; draw_info->signature=MagickSignature; + SetDrawInfoSVGCompliant(draw_info,MagickFalse); + SetDrawInfoClippingPath(draw_info,MagickFalse); DestroyImageInfo(clone_info); } @@ -4813,8 +6026,8 @@ Permutate(const long n,const long k) % */ -static void -TraceArc(PrimitiveInfo *primitive_info,const PointInfo start, +static MagickPassFail +TraceArc(PrimitiveInfoMgr *p_PIMgr,const PointInfo start, const PointInfo end,const PointInfo arc) { PointInfo @@ -4825,11 +6038,11 @@ TraceArc(PrimitiveInfo *primitive_info,const PointInfo start, center.y=0.5*(end.y+start.y); radius.x=fabs(center.x-start.x); radius.y=fabs(center.y-start.y); - TraceEllipse(primitive_info,center,radius,arc); + return TraceEllipse(p_PIMgr,center,radius,arc); } -static void -TraceArcPath(PrimitiveInfo *primitive_info,const PointInfo start, +static MagickPassFail +TraceArcPath(PrimitiveInfoMgr *p_PIMgr,const PointInfo start, const PointInfo end,const PointInfo arc,const double angle, const unsigned int large_arc,const unsigned int sweep) { @@ -4859,14 +6072,32 @@ TraceArcPath(PrimitiveInfo *primitive_info,const PointInfo start, unsigned long arc_segments; - if ((start.x == end.x) && (start.y == end.y)) - return; + PrimitiveInfo + **pp_PrimitiveInfo, + *primitive_info; + + size_t + InitialStoreStartingAt; + + pp_PrimitiveInfo = p_PIMgr->pp_PrimitiveInfo; + InitialStoreStartingAt = p_PIMgr->StoreStartingAt; + primitive_info = *pp_PrimitiveInfo + InitialStoreStartingAt; + + primitive_info->coordinates = 0; /* in case we return without doing anything */ + /* + Per the SVG spec: If the endpoints (x1, y1) and (x2, y2) are identical, then + this is equivalent to omitting the elliptical arc segment entirely. + */ + if ( (fabs(start.x-end.x) < MagickEpsilon) && (fabs(start.y-end.y) < MagickEpsilon) ) + { + /* substitute a lineto command (so zero length arc looks like a zero length segment) */ + return (TracePoint(primitive_info,end)); + } radii.x=fabs(arc.x); radii.y=fabs(arc.y); if ((radii.x == 0.0) || (radii.y == 0.0)) { - TraceLine(primitive_info,start,end); - return; + return (TraceLine(primitive_info,start,end)); } cosine=cos(DegreesToRadians(fmod(angle,360.0))); sine=sin(DegreesToRadians(fmod(angle,360.0))); @@ -4935,19 +6166,26 @@ TraceArcPath(PrimitiveInfo *primitive_info,const PointInfo start, (p+3)->point.y=sine*radii.x*points[2].x+cosine*radii.y*points[2].y; if (i == (long) (arc_segments-1)) (p+3)->point=end; - TraceBezier(p,4); + if (TraceBezier(p_PIMgr,4) == MagickFail) + return MagickFail; + p = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base addr might have changed */ + p_PIMgr->StoreStartingAt+=p->coordinates; p+=p->coordinates; } + primitive_info = *pp_PrimitiveInfo + InitialStoreStartingAt; + p_PIMgr->StoreStartingAt = InitialStoreStartingAt; /* restore original value */ primitive_info->coordinates=p-primitive_info; + PRIMINF_CLEAR_FLAGS(primitive_info); for (i=0; i < (long) primitive_info->coordinates; i++) { p->primitive=primitive_info->primitive; p--; } + return MagickPass; } -static void -TraceBezier(PrimitiveInfo *primitive_info, +static MagickPassFail +TraceBezier(PrimitiveInfoMgr *p_PIMgr, const unsigned long number_coordinates) { double @@ -4960,6 +6198,10 @@ TraceBezier(PrimitiveInfo *primitive_info, point, *points; + PrimitiveInfo + *primitive_info, + **pp_PrimitiveInfo; + register PrimitiveInfo *p; @@ -4967,10 +6209,18 @@ TraceBezier(PrimitiveInfo *primitive_info, i, j; + size_t + control_points; + unsigned long - control_points, quantum; + MagickPassFail + status = MagickPass; + + pp_PrimitiveInfo = p_PIMgr->pp_PrimitiveInfo; + primitive_info = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; + /* Allocate coeficients. */ @@ -4988,7 +6238,13 @@ TraceBezier(PrimitiveInfo *primitive_info, } } quantum=Min(quantum/number_coordinates,BezierQuantum); - control_points=quantum*number_coordinates; + control_points=(size_t) quantum*number_coordinates; + + /* make sure we have enough space */ + if (PrimitiveInfoRealloc(p_PIMgr,control_points+1) == MagickFail) + return MagickFail; + primitive_info = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; + coefficients=MagickAllocateArray(double *,number_coordinates,sizeof(double)); points=MagickAllocateArray(PointInfo *,control_points,sizeof(PointInfo)); if ((coefficients == (double *) NULL) || (points == (PointInfo *) NULL)) @@ -5023,23 +6279,28 @@ TraceBezier(PrimitiveInfo *primitive_info, p=primitive_info; for (i=0; i < (long) control_points; i++) { - TracePoint(p,points[i]); + if ((status=TracePoint(p,points[i])) != MagickPass) + goto trace_bezier_done; p+=p->coordinates; } - TracePoint(p,end); + if ((status=TracePoint(p,end)) == MagickFail) + goto trace_bezier_done; p+=p->coordinates; primitive_info->coordinates=p-primitive_info; + PRIMINF_CLEAR_FLAGS(primitive_info); for (i=0; i < (long) primitive_info->coordinates; i++) { p->primitive=primitive_info->primitive; p--; } + trace_bezier_done:; MagickFreeMemory(points); MagickFreeMemory(coefficients); + return status; } -static void -TraceCircle(PrimitiveInfo *primitive_info,const PointInfo start, +static MagickPassFail +TraceCircle(PrimitiveInfoMgr *p_PIMgr,const PointInfo start, const PointInfo end) { double @@ -5058,15 +6319,16 @@ TraceCircle(PrimitiveInfo *primitive_info,const PointInfo start, offset.y=radius; degrees.x=0.0; degrees.y=360.0; - TraceEllipse(primitive_info,start,offset,degrees); + return TraceEllipse(p_PIMgr,start,offset,degrees); } -static void -TraceEllipse(PrimitiveInfo *primitive_info,const PointInfo start, +static MagickPassFail +TraceEllipse(PrimitiveInfoMgr *p_PIMgr,const PointInfo start, const PointInfo stop,const PointInfo degrees) { double delta, + points_length, step, y; @@ -5077,57 +6339,102 @@ TraceEllipse(PrimitiveInfo *primitive_info,const PointInfo start, register PrimitiveInfo *p; - register long - i; + PrimitiveInfo + *primitive_info, + **pp_PrimitiveInfo; + + MagickPassFail + status = MagickPass; /* Ellipses are just short segmented polys. */ - if (stop.x == 0.0 || stop.y == 0.0) - return; + pp_PrimitiveInfo = p_PIMgr->pp_PrimitiveInfo; + primitive_info = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; + primitive_info->coordinates = 0; /* in case we return without doing anything */ + if (stop.x == 0.0 || stop.y == 0.0) /* actually the x and y radii of the corner ellipse */ + return MagickPass; delta=2.0/Max(stop.x,stop.y); step=MagickPI/8.0; if (delta < (MagickPI/8.0)) - step=MagickPI/(4*ceil(MagickPI/delta/2)); + step=(MagickPI/4.0)/ceil(MagickPI/delta/2.0); angle.x=DegreesToRadians(degrees.x); y=degrees.y; while (y < degrees.x) y+=360.0; angle.y=DegreesToRadians(y); + + /* FIXME: The number of points could become arbitrarily large. It + would be good to add an algorithm which decreases ellipse drawing + quality when necessary in order to limit the number of points + required. */ + + /* make sure we have enough space */ + points_length = ceil(1.0 + ceil((angle.y - angle.x) / step)); + if ((size_t) points_length < points_length) + { + /* points_length too big to be represented as a size_t */ + status=MagickFail; + ThrowException3(p_PIMgr->p_Exception,ResourceLimitError, + MemoryAllocationFailed,UnableToDrawOnImage); + goto trace_ellipse_done; + } + if ((status=PrimitiveInfoRealloc(p_PIMgr,(size_t) points_length)) == MagickFail) + goto trace_ellipse_done; + primitive_info = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; + for (p=primitive_info; angle.x < angle.y; angle.x+=step) { point.x=cos(fmod(angle.x,DegreesToRadians(360.0)))*stop.x+start.x; point.y=sin(fmod(angle.x,DegreesToRadians(360.0)))*stop.y+start.y; - TracePoint(p,point); + if ((status=TracePoint(p,point)) == MagickFail) + goto trace_ellipse_done; p+=p->coordinates; } point.x=cos(fmod(angle.y,DegreesToRadians(360.0)))*stop.x+start.x; point.y=sin(fmod(angle.y,DegreesToRadians(360.0)))*stop.y+start.y; - TracePoint(p,point); + if ((status=TracePoint(p,point)) == MagickFail) + goto trace_ellipse_done; p+=p->coordinates; primitive_info->coordinates=p-primitive_info; - for (i=0; i < (long) primitive_info->coordinates; i++) - { + PRIMINF_CLEAR_FLAGS(primitive_info); + if ( + (fabs(primitive_info[0].point.x-primitive_info[primitive_info->coordinates-1].point.x) < MagickEpsilon) + && (fabs(primitive_info[0].point.y-primitive_info[primitive_info->coordinates-1].point.y) < MagickEpsilon) + ) + PRIMINF_SET_IS_CLOSED_SUBPATH(primitive_info,1); + /* NOTE: p pointing just past last traced point! */ + for (p--; p > primitive_info; p--) p->primitive=primitive_info->primitive; - p--; - } + trace_ellipse_done: + return status; } -static void +static MagickPassFail TraceLine(PrimitiveInfo *primitive_info,const PointInfo start, const PointInfo end) { - TracePoint(primitive_info,start); + MagickPassFail + status = MagickPass; + + if ((status=TracePoint(primitive_info,start)) == MagickFail) + goto trace_line_done; if ((AbsoluteValue(start.x-end.x) <= MagickEpsilon) && (AbsoluteValue(start.y-end.y) <= MagickEpsilon)) { primitive_info->primitive=PointPrimitive; primitive_info->coordinates=1; - return; + goto trace_line_done; } - TracePoint(primitive_info+1,end); + if ((status=TracePoint(primitive_info+1,end)) == MagickFail) + goto trace_line_done; (primitive_info+1)->primitive=primitive_info->primitive; primitive_info->coordinates=2; + PRIMINF_CLEAR_FLAGS(primitive_info); + + trace_line_done: + + return status; } /* @@ -5173,7 +6480,7 @@ TraceLine(PrimitiveInfo *primitive_info,const PointInfo start, static unsigned long -TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) +TracePath(Image *image,PrimitiveInfoMgr *p_PIMgr,const char *path) { char token[MaxTextExtent]; @@ -5198,6 +6505,10 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) PrimitiveType primitive_type; + PrimitiveInfo + *primitive_info, + **pp_PrimitiveInfo; + register PrimitiveInfo *q; @@ -5208,6 +6519,15 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) number_coordinates, z_count; + size_t + SubpathOffset; /* index to start of current subpath */ + + MagickPassFail + status = MagickPass; + + pp_PrimitiveInfo = p_PIMgr->pp_PrimitiveInfo; + SubpathOffset = p_PIMgr->StoreStartingAt; + primitive_info = *pp_PrimitiveInfo + SubpathOffset; attribute=0; number_coordinates=0; z_count=0; @@ -5274,7 +6594,10 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) MagickTracePathAtoF(token,&y); end.x=attribute == 'A' ? x : point.x+x; end.y=attribute == 'A' ? y : point.y+y; - TraceArcPath(q,point,end,arc,angle,large_arc,sweep); + if ((status=TraceArcPath(p_PIMgr,point,end,arc,angle,large_arc,sweep)) == MagickFail) + goto trace_path_done; + q = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base address might have changed */ + p_PIMgr->StoreStartingAt += q->coordinates; q+=q->coordinates; point=end; while (isspace((int) ((unsigned char) *p)) != 0) @@ -5312,9 +6635,17 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) } for (i=0; i < 4; i++) (q+i)->point=points[i]; - TraceBezier(q,4); + if ((status=TraceBezier(p_PIMgr,4)) == MagickFail) + goto trace_path_done; + q = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base address might have changed */ + p_PIMgr->StoreStartingAt += q->coordinates; q+=q->coordinates; point=end; + /* consume comma if present (as in elliptical arc above) */ + while (isspace((int) ((unsigned char) *p)) != 0) + p++; + if (*p == ',') + p++; } while (IsPoint(p)); break; } @@ -5328,8 +6659,22 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) MagickGetTracePathToken(p,&p,token,MaxTextExtent); MagickTracePathAtoF(token,&x); point.x=attribute == 'H' ? x: point.x+x; - TracePoint(q,point); + /* make sure we have at least 100 elements available */ + if ((p_PIMgr->StoreStartingAt + 100) > *p_PIMgr->p_AllocCount) + { + if (PrimitiveInfoRealloc(p_PIMgr,100) == MagickFail) + return 0; /* FIXME: How to return useful error? */ + q = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base address might have changed */ + } + if ((status=TracePoint(q,point)) == MagickFail) + goto trace_path_done; + p_PIMgr->StoreStartingAt += q->coordinates; q+=q->coordinates; + /* consume comma if present (as in elliptical arc above) */ + while (isspace((int) ((unsigned char) *p)) != 0) + p++; + if (*p == ',') + p++; } while (IsPoint(p)); break; } @@ -5351,8 +6696,22 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) MagickTracePathAtoF(token,&y); point.x=attribute == 'L' ? x : point.x+x; point.y=attribute == 'L' ? y : point.y+y; - TracePoint(q,point); + /* make sure we have at least 100 elements available */ + if ((p_PIMgr->StoreStartingAt + 100) > *p_PIMgr->p_AllocCount) + { + if ((status=PrimitiveInfoRealloc(p_PIMgr,100)) == MagickFail) + goto trace_path_done; + q = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base address might have changed */ + } + if ((status=TracePoint(q,point)) == MagickFail) + goto trace_path_done; + p_PIMgr->StoreStartingAt += q->coordinates; q+=q->coordinates; + /* consume comma if present (as in elliptical arc above) */ + while (isspace((int) ((unsigned char) *p)) != 0) + p++; + if (*p == ',') + p++; } while (IsPoint(p)); break; } @@ -5362,11 +6721,13 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) case 'M': case 'm': { - if (q != primitive_info) + if ( p_PIMgr->StoreStartingAt != SubpathOffset ) { + primitive_info = *pp_PrimitiveInfo + SubpathOffset; primitive_info->coordinates=q-primitive_info; number_coordinates+=primitive_info->coordinates; primitive_info=q; + SubpathOffset=p_PIMgr->StoreStartingAt; } i=0; do @@ -5382,15 +6743,27 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) point.x=attribute == 'M' ? x : point.x+x; point.y=attribute == 'M' ? y : point.y+y; if (i == 0) - start=point; + start=point; /*otherwise it's an implied lineto command for both 'M' and 'm'*/ i++; - TracePoint(q,point); - q+=q->coordinates; - if ((i != 0) && (attribute == 'M')) + /* make sure we have at least 100 elements available */ + if ((p_PIMgr->StoreStartingAt + 100) > *p_PIMgr->p_AllocCount) { - TracePoint(q,point); - q+=q->coordinates; + if (PrimitiveInfoRealloc(p_PIMgr,100) == MagickFail) + return 0; /* FIXME: How to return useful error? */ + q = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base address might have changed */ } + if ((status=TracePoint(q,point)) == MagickFail) + goto trace_path_done; + p_PIMgr->StoreStartingAt += q->coordinates; + q+=q->coordinates; + + /* there was code here that added the point again, but only if 'M' (?) ... deleted */ + + /* consume comma if present (as in elliptical arc above) */ + while (isspace((int) ((unsigned char) *p)) != 0) + p++; + if (*p == ',') + p++; } while (IsPoint(p)); break; } @@ -5424,9 +6797,17 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) } for (i=0; i < 3; i++) (q+i)->point=points[i]; - TraceBezier(q,3); + if ((status=TraceBezier(p_PIMgr,3)) == MagickFail) + goto trace_path_done; + q = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; + p_PIMgr->StoreStartingAt += q->coordinates; q+=q->coordinates; point=end; + /* consume comma if present (as in elliptical arc above) */ + while (isspace((int) ((unsigned char) *p)) != 0) + p++; + if (*p == ',') + p++; } while (IsPoint(p)); break; } @@ -5439,6 +6820,11 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) /* Compute bezier points. */ + /* + Handle multiple pairs of cubic Bezier points when the previous path data + command was not a cubic Bezier (i.e., not 'c' or 's'). + */ + int previous_path_data_command = last_attribute; /* the previous path data command upon entry to this 'case' */ do { points[0]=points[3]; @@ -5460,16 +6846,25 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) end.y=attribute == 'S' ? y : point.y+y; points[i]=end; } - if (strchr("CcSs",last_attribute) == (char *) NULL) + if (strchr("CcSs",previous_path_data_command) == (char *) NULL) /* check the ACTUAL previous command */ { points[0]=point; points[1]=point; } for (i=0; i < 4; i++) (q+i)->point=points[i]; - TraceBezier(q,4); + if ((TraceBezier(p_PIMgr,4)) == MagickFail) + goto trace_path_done; + q = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; + p_PIMgr->StoreStartingAt += q->coordinates; q+=q->coordinates; point=end; + previous_path_data_command = attribute; /* current path data command becomes previous for next loop iteration */ + /* consume comma if present (as in elliptical arc above) */ + while (isspace((int) ((unsigned char) *p)) != 0) + p++; + if (*p == ',') + p++; } while (IsPoint(p)); break; } @@ -5482,6 +6877,11 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) /* Compute bezier points. */ + /* + Handle multiple pairs of quadratic Bezier points when the previous path data + command was not a quadratic Bezier (i.e., not 'q' or 't'). + */ + int previous_path_data_command = last_attribute; /* the previous path data command upon entry to this 'case' */ do { points[0]=points[2]; @@ -5501,16 +6901,25 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) end.y=attribute == 'T' ? y : point.y+y; points[i]=end; } - if (strchr("QqTt",last_attribute) == (char *) NULL) + if (strchr("QqTt",previous_path_data_command) == (char *) NULL) /* check the ACTUAL previous command */ { points[0]=point; points[1]=point; } for (i=0; i < 3; i++) (q+i)->point=points[i]; - TraceBezier(q,3); + if ((status=TraceBezier(p_PIMgr,3)) == MagickFail) + goto trace_path_done; + q = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; + p_PIMgr->StoreStartingAt += q->coordinates; q+=q->coordinates; point=end; + previous_path_data_command = attribute; /* current path data command becomes previous for next loop iteration */ + /* consume comma if present (as in elliptical arc above) */ + while (isspace((int) ((unsigned char) *p)) != 0) + p++; + if (*p == ',') + p++; } while (IsPoint(p)); break; } @@ -5527,8 +6936,22 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) MagickGetTracePathToken(p,&p,token,MaxTextExtent); MagickTracePathAtoF(token,&y); point.y=attribute == 'V' ? y : point.y+y; - TracePoint(q,point); + /* make sure we have at least 100 elements available */ + if ((p_PIMgr->StoreStartingAt + 100) > *p_PIMgr->p_AllocCount) + { + if ((status=PrimitiveInfoRealloc(p_PIMgr,100)) == MagickFail) + goto trace_path_done; + q = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base address might have changed */ + } + if ((status=TracePoint(q,point)) == MagickFail) + goto trace_path_done; + p_PIMgr->StoreStartingAt += q->coordinates; q+=q->coordinates; + /* consume comma if present (as in elliptical arc above) */ + while (isspace((int) ((unsigned char) *p)) != 0) + p++; + if (*p == ',') + p++; } while (IsPoint(p)); break; } @@ -5539,11 +6962,23 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) case 'Z': { point=start; - TracePoint(q,point); + /* make sure we have at least 100 elements available */ + if ((p_PIMgr->StoreStartingAt + 100) > *p_PIMgr->p_AllocCount) + { + if ((status=PrimitiveInfoRealloc(p_PIMgr,100)) == MagickFail) + goto trace_path_done; + q = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base address might have changed */ + } + if ((status=TracePoint(q,point)) == MagickFail) + goto trace_path_done; + p_PIMgr->StoreStartingAt += q->coordinates; q+=q->coordinates; + primitive_info = *pp_PrimitiveInfo + SubpathOffset; primitive_info->coordinates=q-primitive_info; + PRIMINF_SET_IS_CLOSED_SUBPATH(primitive_info,1); number_coordinates+=primitive_info->coordinates; primitive_info=q; + SubpathOffset = p_PIMgr->StoreStartingAt; z_count++; break; } @@ -5556,6 +6991,7 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) } } + primitive_info = *pp_PrimitiveInfo + SubpathOffset; primitive_info->coordinates=q-primitive_info; number_coordinates+=primitive_info->coordinates; for (i=0; i < (long) number_coordinates; i++) @@ -5566,17 +7002,25 @@ TracePath(Image *image,PrimitiveInfo *primitive_info,const char *path) q->method=FillToBorderMethod; } q=primitive_info; + + trace_path_done:; + + if (status == MagickFail) + number_coordinates = 0; + return(number_coordinates); } -static void +static MagickPassFail TracePoint(PrimitiveInfo *primitive_info,const PointInfo point) { primitive_info->coordinates=1; + PRIMINF_CLEAR_FLAGS(primitive_info); primitive_info->point=point; + return MagickPass; } -static void +static MagickPassFail TraceRectangle(PrimitiveInfo *primitive_info,const PointInfo start, const PointInfo end) { @@ -5589,31 +7033,54 @@ TraceRectangle(PrimitiveInfo *primitive_info,const PointInfo start, register long i; + MagickPassFail + status = MagickPass; + + /* + Per the SVG spec, if the width and/or height are zero, rendering + the element is disabled. + */ + if ((start.x == end.x) || (start.y == end.y)) + { + primitive_info->coordinates = 0; + goto trace_rectangle_done; + } p=primitive_info; - TracePoint(p,start); + if ((status = TracePoint(p,start)) == MagickFail) + goto trace_rectangle_done; p+=p->coordinates; point.x=start.x; point.y=end.y; - TracePoint(p,point); + if ((status = TracePoint(p,point)) == MagickFail) + goto trace_rectangle_done; p+=p->coordinates; - TracePoint(p,end); + if ((status = TracePoint(p,end)) == MagickFail) + goto trace_rectangle_done; p+=p->coordinates; point.x=end.x; point.y=start.y; - TracePoint(p,point); + if ((status = TracePoint(p,point)) == MagickFail) + goto trace_rectangle_done; p+=p->coordinates; - TracePoint(p,start); + if ((status = TracePoint(p,start)) == MagickFail) + goto trace_rectangle_done; p+=p->coordinates; primitive_info->coordinates=p-primitive_info; + PRIMINF_CLEAR_FLAGS(primitive_info); + PRIMINF_SET_IS_CLOSED_SUBPATH(primitive_info,1); for (i=0; i < (long) primitive_info->coordinates; i++) { p->primitive=primitive_info->primitive; p--; } + + trace_rectangle_done: + + return status; } -static void -TraceRoundRectangle(PrimitiveInfo *primitive_info, +static MagickPassFail +TraceRoundRectangle(PrimitiveInfoMgr *p_PIMgr, const PointInfo start,const PointInfo end,PointInfo arc) { PointInfo @@ -5624,51 +7091,98 @@ TraceRoundRectangle(PrimitiveInfo *primitive_info, register PrimitiveInfo *p; - register long - i; + size_t + InitialStoreStartingAt; + + PrimitiveInfo + *primitive_info, + **pp_PrimitiveInfo; + + MagickPassFail + status = MagickPass; + + pp_PrimitiveInfo = p_PIMgr->pp_PrimitiveInfo; + InitialStoreStartingAt = p_PIMgr->StoreStartingAt; + + offset.x=AbsoluteValue(end.x-start.x); /* rect width */ + offset.y=AbsoluteValue(end.y-start.y); /* rect height */ + /* + Per the SVG spec, if the width and/or height are zero, rendering + the element is disabled. + */ + if ((offset.x == 0.0) || (offset.y == 0.0)) + { + (*pp_PrimitiveInfo+InitialStoreStartingAt)->coordinates = 0; + goto round_rectangle_done; + } - p=primitive_info; - offset.x=AbsoluteValue(end.x-start.x); - offset.y=AbsoluteValue(end.y-start.y); if (arc.x > (0.5*offset.x)) arc.x=0.5*offset.x; if (arc.y > (0.5*offset.y)) arc.y=0.5*offset.y; + point.x=start.x+offset.x-arc.x; point.y=start.y+arc.y; degrees.x=270.0; degrees.y=360.0; - TraceEllipse(p,point,arc,degrees); - p+=p->coordinates; + if ((status=TraceEllipse(p_PIMgr,point,arc,degrees)) == MagickFail) + goto round_rectangle_done; + p = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base addr might have moved */ + p_PIMgr->StoreStartingAt += p->coordinates; + point.x=start.x+offset.x-arc.x; point.y=start.y+offset.y-arc.y; degrees.x=0.0; degrees.y=90.0; - TraceEllipse(p,point,arc,degrees); - p+=p->coordinates; + if ((status=TraceEllipse(p_PIMgr,point,arc,degrees)) == MagickFail) + goto round_rectangle_done; + p = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base addr might have moved */ + p_PIMgr->StoreStartingAt += p->coordinates; + point.x=start.x+arc.x; point.y=start.y+offset.y-arc.y; degrees.x=90.0; degrees.y=180.0; - TraceEllipse(p,point,arc,degrees); - p+=p->coordinates; + if ((status=TraceEllipse(p_PIMgr,point,arc,degrees)) == MagickFail) + goto round_rectangle_done; + p = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base addr might have moved */ + p_PIMgr->StoreStartingAt += p->coordinates; + point.x=start.x+arc.x; point.y=start.y+arc.y; degrees.x=180.0; degrees.y=270.0; - TraceEllipse(p,point,arc,degrees); - p+=p->coordinates; - TracePoint(p,primitive_info->point); + if ((status=TraceEllipse(p_PIMgr,point,arc,degrees)) == MagickFail) + goto round_rectangle_done; + p = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; /* base addr might have moved */ + p_PIMgr->StoreStartingAt += p->coordinates; + + /* need only one element, but make sure there is some headroom */ + if ((p_PIMgr->StoreStartingAt + 100) > *p_PIMgr->p_AllocCount) + { + if ((status=PrimitiveInfoRealloc(p_PIMgr,100)) == MagickFail) + goto round_rectangle_done; + } + p = *pp_PrimitiveInfo + p_PIMgr->StoreStartingAt; + if ((status=TracePoint(p,(*pp_PrimitiveInfo+InitialStoreStartingAt)->point)) == MagickFail) + goto round_rectangle_done; p+=p->coordinates; + p_PIMgr->StoreStartingAt = InitialStoreStartingAt; /* restore original value */ + + primitive_info = *pp_PrimitiveInfo + InitialStoreStartingAt; primitive_info->coordinates=p-primitive_info; - for (i=0; i < (long) primitive_info->coordinates; i++) - { + PRIMINF_CLEAR_FLAGS(primitive_info); + PRIMINF_SET_IS_CLOSED_SUBPATH(primitive_info,1); + /* NOTE: p pointing just past last traced point! */ + for (p--; p > primitive_info; p--) p->primitive=primitive_info->primitive; - p--; - } + + round_rectangle_done:; + + return status; } -static void +static MagickPassFail TraceSquareLinecap(PrimitiveInfo *primitive_info, const unsigned long number_vertices,const double offset) { @@ -5713,10 +7227,13 @@ TraceSquareLinecap(PrimitiveInfo *primitive_info, dx*(distance+offset)/distance; primitive_info[number_vertices-1].point.y=primitive_info[j].point.y+ dy*(distance+offset)/distance; + + return MagickPass; } static PrimitiveInfo * -TraceStrokePolygon(const DrawInfo *draw_info, +TraceStrokePolygon(const Image *image, /* added Image* param so DrawInfo::stroke_width can be clamped */ + const DrawInfo *draw_info, const PrimitiveInfo *primitive_info) { typedef struct _LineSegment @@ -5740,7 +7257,8 @@ TraceStrokePolygon(const DrawInfo *draw_info, delta_theta, dot_product, mid, - miterlimit; + miterlimit, + stroke_width_limited; PointInfo box_p[5], @@ -5752,14 +7270,16 @@ TraceStrokePolygon(const DrawInfo *draw_info, PrimitiveInfo *polygon_primitive, - *stroke_polygon; + *stroke_polygon = (PrimitiveInfo *) NULL; register long i; unsigned long arc_segments, - max_strokes, + max_strokes_p, + max_strokes_q, + max_strokes_extra, number_vertices; unsigned long @@ -5768,34 +7288,31 @@ TraceStrokePolygon(const DrawInfo *draw_info, p, q; + MagickPassFail + status = MagickPass; + /* - Allocate paths. + Compute initial sizes for paths based on the number of primitive coordinates. We + will always allocate max_strokes_extra additional points, so that for each loop + iteration there will always be enough space, provided we haven't passed + max_strokes_{p|q} yet. */ number_vertices=primitive_info->coordinates; - max_strokes=2*number_vertices+6*BezierQuantum+360; - path_p=MagickAllocateArray(PointInfo *,max_strokes,sizeof(PointInfo)); - if (path_p == (PointInfo *) NULL) - return((PrimitiveInfo *) NULL); - path_q=MagickAllocateArray(PointInfo *,max_strokes,sizeof(PointInfo)); - if (path_q == (PointInfo *) NULL) - { - MagickFreeMemory(path_p); - return((PrimitiveInfo *) NULL); - } + max_strokes_p=max_strokes_q=2*number_vertices; + max_strokes_extra=6*BezierQuantum+360; /* will always allocate this much extra */ + + /* moved path_p and path_q mem alloc to later since we might not need them */ + polygon_primitive= MagickAllocateArray(PrimitiveInfo *,(number_vertices+2), - sizeof(PrimitiveInfo)); + sizeof(PrimitiveInfo)); if (polygon_primitive == (PrimitiveInfo *) NULL) { - MagickFreeMemory(path_p); - MagickFreeMemory(path_q); return((PrimitiveInfo *) NULL); } (void) memcpy(polygon_primitive,primitive_info,number_vertices* sizeof(PrimitiveInfo)); - closed_path= - (primitive_info[number_vertices-1].point.x == primitive_info[0].point.x) && - (primitive_info[number_vertices-1].point.y == primitive_info[0].point.y); + closed_path=PRIMINF_GET_IS_CLOSED_SUBPATH(&primitive_info[0]); if ((draw_info->linejoin == RoundJoin) || ((draw_info->linejoin == MiterJoin) && closed_path)) { @@ -5814,10 +7331,50 @@ TraceStrokePolygon(const DrawInfo *draw_info, break; } if (n == number_vertices) - n=number_vertices-1; + { + /* + If we get here the subpath consists entirely of "zero length" (within MagickEpsilon) + segments. According to the SVG spec: "Any zero length subpath shall not be stroked + if the 'stroke-linecap' property has a value of butt but shall be stroked if the + 'stroke-linecap' property has a value of round or square". Since 'stroke-linecap' + is only used for open paths, this is only significant if the path is not closed. + */ + MagickBool DoStroke; + DoStroke = (!closed_path && (draw_info->linecap == RoundCap)); + if ( !DoStroke ) + {/*skip stroking*/ + /* create polygon with one element and 0 coords; DrawPolygonPrimitive() will ignore it */ + stroke_polygon = MagickAllocateArray(PrimitiveInfo *,1,sizeof(PrimitiveInfo)); + stroke_polygon[0] = polygon_primitive[0]; + stroke_polygon[0].coordinates = 0; + MagickFreeMemory(polygon_primitive); + return(stroke_polygon); + }/*skip stroking*/ + n=number_vertices-1; + } + + /* moved path_p and path_q mem allocs to here */ + + /* + Allocate paths. + */ + path_p=MagickAllocateArray(PointInfo *,max_strokes_p+max_strokes_extra,sizeof(PointInfo)); + if (path_p == (PointInfo *) NULL) + { + MagickFreeMemory(polygon_primitive); + return((PrimitiveInfo *) NULL); + } + path_q=MagickAllocateArray(PointInfo *,max_strokes_q+max_strokes_extra,sizeof(PointInfo)); + if (path_q == (PointInfo *) NULL) + { + MagickFreeMemory(path_p); + MagickFreeMemory(polygon_primitive); + return((PrimitiveInfo *) NULL); + } + slope.p=0.0; inverse_slope.p=0.0; - if (fabs(dx.p) <= MagickEpsilon) + if (fabs(dx.p) < MagickEpsilon) { if (dx.p >= 0.0) slope.p=dy.p < 0.0 ? -1.0/MagickEpsilon : 1.0/MagickEpsilon; @@ -5825,7 +7382,7 @@ TraceStrokePolygon(const DrawInfo *draw_info, slope.p=dy.p < 0.0 ? 1.0/MagickEpsilon : -1.0/MagickEpsilon; } else - if (fabs(dy.p) <= MagickEpsilon) + if (fabs(dy.p) < MagickEpsilon) { if (dy.p >= 0.0) inverse_slope.p=dx.p < 0.0 ? -1.0/MagickEpsilon : 1.0/MagickEpsilon; @@ -5837,10 +7394,18 @@ TraceStrokePolygon(const DrawInfo *draw_info, slope.p=dy.p/dx.p; inverse_slope.p=(-1.0/slope.p); } - mid=ExpandAffine(&draw_info->affine)*draw_info->stroke_width/2.0;/* FIXME: 'mid' BLOWS UP */ + + /* sanity check for excessively big stroke_width (ticket #515) */ + if ( (stroke_width_limited = STROKE_WIDTH_LIMIT(image)) > draw_info->stroke_width ) + stroke_width_limited = draw_info->stroke_width; + + mid=ExpandAffine(&draw_info->affine)*stroke_width_limited/2.0; miterlimit=draw_info->miterlimit*draw_info->miterlimit*mid*mid; if ((draw_info->linecap == SquareCap) && !closed_path) - TraceSquareLinecap(polygon_primitive,number_vertices,mid); + { + if ((status=TraceSquareLinecap(polygon_primitive,number_vertices,mid)) == MagickFail) + goto trace_stroke_polygon_done; + } offset.x=sqrt(mid*mid/(inverse_slope.p*inverse_slope.p+1.0)); offset.y=offset.x*inverse_slope.p; if ((dy.p*offset.x-dx.p*offset.y) > 0.0) @@ -5892,7 +7457,7 @@ TraceStrokePolygon(const DrawInfo *draw_info, slope.q=dy.q < 0.0 ? 1.0/MagickEpsilon : -1.0/MagickEpsilon; } else - if (fabs(dy.q) <= MagickEpsilon) + if (fabs(dy.q) < MagickEpsilon) { if (dy.q >= 0.0) inverse_slope.q=dx.q < 0.0 ? -1.0/MagickEpsilon : 1.0/MagickEpsilon; @@ -5943,19 +7508,30 @@ TraceStrokePolygon(const DrawInfo *draw_info, box_q[3].y)/(slope.p-slope.q); box_q[4].y=slope.p*(box_q[4].x-box_q[0].x)+box_q[0].y; } - if (q >= (max_strokes-6*BezierQuantum-360)) + if (p >= max_strokes_p) + {/*p pointing into extra; time to realloc*/ + max_strokes_p+=max_strokes_extra; + MagickReallocMemory(PointInfo *,path_p,MagickArraySize(max_strokes_p+max_strokes_extra,sizeof(PointInfo))); + if (path_p == (PointInfo *) NULL) { - max_strokes+=6*BezierQuantum+360; - MagickReallocMemory(PointInfo *,path_p,MagickArraySize(max_strokes,sizeof(PointInfo))); - MagickReallocMemory(PointInfo *,path_q,MagickArraySize(max_strokes,sizeof(PointInfo))); - if ((path_p == (PointInfo *) NULL) || (path_q == (PointInfo *) NULL)) + MagickFreeMemory(path_p); + MagickFreeMemory(path_q); + MagickFreeMemory(polygon_primitive); + return((PrimitiveInfo *) NULL); + } + }/*p pointing into extra; time to realloc*/ + if (q >= max_strokes_q) + {/*q pointing into extra; time to realloc*/ + max_strokes_q+=max_strokes_extra; + MagickReallocMemory(PointInfo *,path_q,MagickArraySize(max_strokes_q+max_strokes_extra,sizeof(PointInfo))); + if (path_q == (PointInfo *) NULL) { MagickFreeMemory(path_p); MagickFreeMemory(path_q); MagickFreeMemory(polygon_primitive); return((PrimitiveInfo *) NULL); } - } + }/*q pointing into extra; time to realloc*/ dot_product=dx.q*dy.p-dx.p*dy.q; if (dot_product <= 0.0) switch (draw_info->linejoin) @@ -6010,6 +7586,19 @@ TraceStrokePolygon(const DrawInfo *draw_info, if (theta.q < theta.p) theta.q+=2.0*MagickPI; arc_segments=(long) ceil((theta.q-theta.p)/(2.0*sqrt(1.0/mid))); + /* in case arc_segments is big */ + if ( (q+arc_segments) >= max_strokes_q ) + {/*q+arc_segments will point into extra; time to realloc*/ + max_strokes_q+=arc_segments+max_strokes_extra; + MagickReallocMemory(PointInfo *,path_q,MagickArraySize(max_strokes_q+max_strokes_extra,sizeof(PointInfo))); + if (path_q == (PointInfo *) NULL) + { + MagickFreeMemory(path_p); + MagickFreeMemory(path_q); + MagickFreeMemory(polygon_primitive); + return((PrimitiveInfo *) NULL); + } + }/*q+arc_segments will point into extra; time to realloc*/ path_q[q].x=box_q[1].x; path_q[q].y=box_q[1].y; q++; @@ -6081,6 +7670,19 @@ TraceStrokePolygon(const DrawInfo *draw_info, if (theta.p < theta.q) theta.p+=2.0*MagickPI; arc_segments=(long) ceil((theta.p-theta.q)/(2.0*sqrt(1.0/mid))); + /* in case arc_segments is big */ + if ( (p+arc_segments) >= max_strokes_p ) + {/*p+arc_segments will point into extra; time to realloc*/ + max_strokes_p+=arc_segments+max_strokes_extra; + MagickReallocMemory(PointInfo *,path_p,MagickArraySize(max_strokes_p+max_strokes_extra,sizeof(PointInfo))); + if (path_p == (PointInfo *) NULL) + { + MagickFreeMemory(path_p); + MagickFreeMemory(path_q); + MagickFreeMemory(polygon_primitive); + return((PrimitiveInfo *) NULL); + } + }/*p+arc_segments will point into extra; time to realloc*/ path_p[p++]=box_p[1]; for (j=1; j < arc_segments; j++) { @@ -6114,7 +7716,7 @@ TraceStrokePolygon(const DrawInfo *draw_info, */ stroke_polygon= MagickAllocateArray(PrimitiveInfo *,(p+q+2*closed_path+2), - sizeof(PrimitiveInfo)); + sizeof(PrimitiveInfo)); if (stroke_polygon != (PrimitiveInfo *) NULL) { for (i=0; i < (long) p; i++) @@ -6145,8 +7747,48 @@ TraceStrokePolygon(const DrawInfo *draw_info, stroke_polygon[i].primitive=UndefinedPrimitive; stroke_polygon[0].coordinates=p+q+2*closed_path+1; } + + trace_stroke_polygon_done:; + MagickFreeMemory(path_p); MagickFreeMemory(path_q); MagickFreeMemory(polygon_primitive); return(stroke_polygon); } + +#if 0 +/* is the DrawInfo drawn as SVG compliant */ +static MagickBool +IsDrawInfoClippingPath(const DrawInfo * draw_info) +{ + return(((draw_info->flags&0x2U)==2U)?MagickTrue:MagickFalse); +} +#endif + +/* is the DrawInfo drawn as SVG compliant */ +static MagickBool +IsDrawInfoSVGCompliant(const DrawInfo * draw_info) +{ + return(((draw_info->flags&0x1U)==1U)?MagickTrue:MagickFalse); +} + +/* is the DrawInfo drawn as an SVG compliant clipping path */ +static MagickBool +IsDrawInfoSVGCompliantClippingPath(const DrawInfo * draw_info) +{ + return(((draw_info->flags&0x3U)==3U)?MagickTrue:MagickFalse); +} + +/* tag the DrawInfo as being a clipping path or not */ +static void +SetDrawInfoClippingPath(DrawInfo * draw_info, MagickBool ClippingPath) +{ + draw_info->flags = (draw_info->flags & (~0x2U)) | (ClippingPath?2U:0U); +} + +/* tag the DrawInfo as being drawn as SVG compliant or not */ +static void +SetDrawInfoSVGCompliant(DrawInfo * draw_info, MagickBool SVGCompliant) +{ + draw_info->flags = (draw_info->flags & (~0x1U)) | (SVGCompliant?1U:0U); +} diff --git a/magick/render.h b/magick/render.h index c131029..8e922f8 100644 --- a/magick/render.h +++ b/magick/render.h @@ -1,11 +1,11 @@ /* - Copyright (C) 2003 - 2009 GraphicsMagick Group + Copyright (C) 2003 - 2018 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + Drawing methods. */ #ifndef _MAGICK_RENDER_H @@ -164,6 +164,8 @@ typedef struct _ElementReference *next; } ElementReference; +struct _DrawInfoExtra; /* forward decl.; see member "extra" below */ + typedef struct _DrawInfo { char @@ -252,8 +254,20 @@ typedef struct _DrawInfo double *dash_pattern; /* Terminated by value 0.0 (i.e. < MagickEpsilon)*/ +#if 0 char *clip_path; +#endif + /* + Allow for expansion of DrawInfo without increasing its size. The + internals are defined only in render.c. Clients outside of render.c + can access the internals via the provided access functions (see below). + + This location in DrawInfo used to be occupied by char *clip_path. The + clip_path member now lives in _DrawInfoExtra. + */ + struct _DrawInfoExtra + *extra; SegmentInfo bounds; @@ -266,7 +280,26 @@ typedef struct _DrawInfo unsigned int render, - unused1; /* Spare. Was long-deprecated 'debug' */ + /* + Bit fields in flags: + + Bit 0: should this DrawInfo should be drawn as: + 0: normal (original behavior) + 1: SVG compliant + Bit 1: is the DrawInfo a clipping path: + 0: is not a clipping path + 1: is a clipping path + + Access to these bits should be through functions (defined in render.c): + IsDrawInfoClippingPath() + IsDrawInfoSVGCompliant() + IsDrawInfoSVGCompliantClippingPath() + SetDrawInfoClippingPath() + SetDrawInfoSVGCompliant() + + At the present time the SVG compliance bit only affects how clipping paths are drawn. + */ + flags; /* previously "unused1" */ ElementReference element_reference; @@ -275,6 +308,8 @@ typedef struct _DrawInfo signature; } DrawInfo; +#if defined(MAGICK_IMPLEMENTATION) + typedef struct _ElementInfo { double @@ -285,6 +320,8 @@ typedef struct _ElementInfo angle; } ElementInfo; +#endif /* if defined(MAGICK_IMPLEMENTATION) */ + typedef struct _PointInfo { double @@ -292,6 +329,8 @@ typedef struct _PointInfo y; } PointInfo; +#if defined(MAGICK_IMPLEMENTATION) + typedef struct _PrimitiveInfo { PointInfo @@ -308,8 +347,24 @@ typedef struct _PrimitiveInfo char *text; + + /* + "flags" indicates: + + bit 0: shape/subpath is closed (e.g., rectangle, path with 'z' or 'Z') + + Macro arg "pi" is a PrimitiveInfo *. + Macro arg "zero_or_one" should be 0 (turn off) or 1 (turn on). + */ + unsigned long + flags; +#define PRIMINF_CLEAR_FLAGS(pi) ((pi)->flags=0) +#define PRIMINF_GET_IS_CLOSED_SUBPATH(pi) ((MagickBool)((pi)->flags&1U)) +#define PRIMINF_SET_IS_CLOSED_SUBPATH(pi,zero_or_one) ((pi)->flags=((pi)->flags&(~1U))|(unsigned long)zero_or_one) } PrimitiveInfo; +#endif /* if defined(MAGICK_IMPLEMENTATION) */ + typedef struct _TypeMetric { PointInfo @@ -348,6 +403,14 @@ extern MagickExport void DestroyDrawInfo(DrawInfo *), GetDrawInfo(const ImageInfo *,DrawInfo *); +/* provide public access to the clip_path member of DrawInfo */ +extern MagickExport char + **DrawInfoGetClipPath(const DrawInfo *) MAGICK_FUNC_PURE; + +/* provide public access to the composite_path member of DrawInfo */ +extern MagickExport char + **DrawInfoGetCompositePath(const DrawInfo *) MAGICK_FUNC_PURE; + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/magick/resize.c b/magick/resize.c index fc7b7e5..56fabf2 100644 --- a/magick/resize.c +++ b/magick/resize.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2015 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % % This program is covered by multiple licenses, which are described in @@ -271,26 +271,26 @@ static double BesselOrderOne(double x) % % */ -MagickExport Image *MagnifyImage(const Image *image,ExceptionInfo *exception) +MagickExport Image *MagnifyImage(const Image * restrict image,ExceptionInfo *exception) { #define MagnifyImageText "[%s] Magnify... " Image - *magnify_image; + * restrict magnify_image; long rows, y; PixelPacket - *scanline; + * restrict scanline; register long x; register PixelPacket - *p, - *q, + * restrict p, + * restrict q, *r; /* @@ -318,8 +318,8 @@ MagickExport Image *MagnifyImage(const Image *image,ExceptionInfo *exception) { DestroyImage(magnify_image); ThrowImageException3(ResourceLimitError,MemoryAllocationFailed, - UnableToMagnifyImage) - } + UnableToMagnifyImage); + } /* Initialize magnify image pixels. */ @@ -457,7 +457,7 @@ MagickExport Image *MagnifyImage(const Image *image,ExceptionInfo *exception) % % */ -MagickExport Image *MinifyImage(const Image *image,ExceptionInfo *exception) +MagickExport Image *MinifyImage(const Image * restrict image,ExceptionInfo *exception) { #define Minify(weight) \ total.red+=(weight)*(r->red); \ @@ -468,11 +468,11 @@ MagickExport Image *MinifyImage(const Image *image,ExceptionInfo *exception) #define MinifyImageText "[%s] Minify..." Image - *minify_image; + *restrict minify_image; long y; - + /* Initialize minified image. */ @@ -535,9 +535,6 @@ MagickExport Image *MinifyImage(const Image *image,ExceptionInfo *exception) MagickBool thread_status; -#if defined(HAVE_OPENMP) -# pragma omp critical (GM_MinifyImage) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -573,17 +570,20 @@ MagickExport Image *MinifyImage(const Image *image,ExceptionInfo *exception) thread_status=MagickFail; } #if defined(HAVE_OPENMP) -# pragma omp critical (GM_MinifyImage) +# pragma omp atomic #endif + row_count++; + if (QuantumTick(row_count,image->rows)) + if (!MagickMonitorFormatted(row_count,image->rows,exception, + MinifyImageText,image->filename)) + thread_status=MagickFail; + + if (thread_status == MagickFail) { - row_count++; - if (QuantumTick(row_count,image->rows)) - if (!MagickMonitorFormatted(row_count,image->rows,exception, - MinifyImageText,image->filename)) - thread_status=MagickFail; - - if (thread_status == MagickFail) - status=MagickFail; + status=MagickFail; +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif } } } @@ -808,14 +808,14 @@ static double Triangle(const double x,const double support) } static MagickPassFail -HorizontalFilter(const Image *source,Image *destination, - const double x_factor,const FilterInfo *filter_info, +HorizontalFilter(const Image * restrict source,Image * restrict destination, + const double x_factor,const FilterInfo * restrict filter_info, const double blur,ThreadViewDataSet *view_data_set, - const size_t span,unsigned long *quantum, + const size_t span,unsigned long * restrict quantum_p, ExceptionInfo *exception) { #define ResizeImageText "[%s] Resize..." - + double scale, support; @@ -826,6 +826,9 @@ HorizontalFilter(const Image *source,Image *destination, long x; + unsigned long + quantum; + MagickPassFail status=MagickPass; @@ -833,6 +836,8 @@ HorizontalFilter(const Image *source,Image *destination, (void) LogMagickEvent(TransformEvent,GetMagickModule(), "Enter HorizontalFilter() ..."); + quantum = *quantum_p; + scale=blur*Max(1.0/x_factor,1.0); support=scale*filter_info->support; destination->storage_class=source->storage_class; @@ -850,12 +855,12 @@ HorizontalFilter(const Image *source,Image *destination, (void) memset(&zero,0,sizeof(DoublePixelPacket)); #if defined(HAVE_OPENMP) # if defined(TUNE_OPENMP) -# pragma omp parallel for schedule(runtime) shared(status) +# pragma omp parallel for schedule(runtime) shared(status, quantum) # else # if defined(USE_STATIC_SCHEDULING_ONLY) -# pragma omp parallel for schedule(static) shared(status) +# pragma omp parallel for schedule(static) shared(status, quantum) # else -# pragma omp parallel for schedule(guided) shared(status) +# pragma omp parallel for schedule(guided) shared(status, quantum) # endif # endif #endif @@ -866,19 +871,19 @@ HorizontalFilter(const Image *source,Image *destination, density; ContributionInfo - *contribution; + * restrict contribution; register const PixelPacket - *p; + * restrict p; register PixelPacket - *q = (PixelPacket *) NULL; + * restrict q = (PixelPacket *) NULL; const IndexPacket - *source_indexes; + * restrict source_indexes; IndexPacket - *indexes; + * restrict indexes; long n, @@ -889,9 +894,6 @@ HorizontalFilter(const Image *source,Image *destination, MagickBool thread_status; -#if defined(HAVE_OPENMP) -# pragma omp critical (GM_HorizontalFilter) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -926,10 +928,10 @@ HorizontalFilter(const Image *source,Image *destination, contribution[n-1].pixel-contribution[0].pixel+1, source->rows,exception); if (p == (const PixelPacket *) NULL) - thread_status=MagickFail; + thread_status=MagickFail; if (thread_status != MagickFail) - q=SetImagePixelsEx(destination,x,0,1,destination->rows,exception); + q=SetImagePixelsEx(destination,x,0,1,destination->rows,exception); if (q == (PixelPacket *) NULL) thread_status=MagickFail; @@ -954,11 +956,11 @@ HorizontalFilter(const Image *source,Image *destination, pixel=zero; if ((destination->matte) || (destination->colorspace == CMYKColorspace)) { - double - transparency_coeff, - normalize; + double + transparency_coeff, + normalize; - normalize=0.0; + normalize=0.0; for (i=0; i < n; i++) { j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+ @@ -972,9 +974,9 @@ HorizontalFilter(const Image *source,Image *destination, normalize += transparency_coeff; } normalize = 1.0 / (AbsoluteValue(normalize) <= MagickEpsilon ? 1.0 : normalize); - pixel.red *= normalize; - pixel.green *= normalize; - pixel.blue *= normalize; + pixel.red *= normalize; + pixel.green *= normalize; + pixel.blue *= normalize; q[y].red=RoundDoubleToQuantum(pixel.red); q[y].green=RoundDoubleToQuantum(pixel.green); q[y].blue=RoundDoubleToQuantum(pixel.blue); @@ -1010,34 +1012,42 @@ HorizontalFilter(const Image *source,Image *destination, thread_status=MagickFail; } #if defined(HAVE_OPENMP) -# pragma omp critical (GM_HorizontalFilter) +# pragma omp flush (quantum) #endif - { - if (QuantumTick(*quantum,span)) - if (!MagickMonitorFormatted(*quantum,span,exception, - ResizeImageText,source->filename)) - thread_status=MagickFail; + if (QuantumTick(quantum,span)) + if (!MagickMonitorFormatted(quantum,span,exception, + ResizeImageText,source->filename)) + thread_status=MagickFail; - (*quantum)++; - - if (thread_status == MagickFail) +#if defined(HAVE_OPENMP) +# pragma omp atomic +#endif + quantum++; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif + } } if (IsEventLogging()) (void) LogMagickEvent(TransformEvent,GetMagickModule(), "%s exit HorizontalFilter()", - (status == MagickFail ? "Error" : "Normal")); + (status == MagickFail ? "Error" : "Normal")); + + *quantum_p = quantum; return (status); } static MagickPassFail -VerticalFilter(const Image *source,Image *destination, - const double y_factor,const FilterInfo *filter_info, +VerticalFilter(const Image * restrict source,Image * restrict destination, + const double y_factor,const FilterInfo * restrict filter_info, const double blur,ThreadViewDataSet *view_data_set, - const size_t span,unsigned long *quantum, + const size_t span,unsigned long * restrict quantum_p, ExceptionInfo *exception) { double @@ -1050,6 +1060,9 @@ VerticalFilter(const Image *source,Image *destination, long y; + unsigned long + quantum; + MagickPassFail status=MagickPass; @@ -1057,6 +1070,8 @@ VerticalFilter(const Image *source,Image *destination, (void) LogMagickEvent(TransformEvent,GetMagickModule(), "Enter VerticalFilter() ..."); + quantum = *quantum_p; + /* Apply filter to resize vertically from source to destination. */ @@ -1077,12 +1092,12 @@ VerticalFilter(const Image *source,Image *destination, (void) memset(&zero,0,sizeof(DoublePixelPacket)); #if defined(HAVE_OPENMP) # if defined(TUNE_OPENMP) -# pragma omp parallel for schedule(runtime) shared(status) +# pragma omp parallel for schedule(runtime) shared(status, quantum) # else # if defined(USE_STATIC_SCHEDULING_ONLY) -# pragma omp parallel for schedule(static) shared(status) +# pragma omp parallel for schedule(static) shared(status, quantum) # else -# pragma omp parallel for schedule(guided) shared(status) +# pragma omp parallel for schedule(guided) shared(status, quantum) # endif # endif #endif @@ -1093,19 +1108,19 @@ VerticalFilter(const Image *source,Image *destination, density; ContributionInfo - *contribution; + * restrict contribution; register const PixelPacket - *p; - + * restrict p; + register PixelPacket - *q = (PixelPacket *) NULL; + * restrict q = (PixelPacket *) NULL; const IndexPacket - *source_indexes; + * restrict source_indexes; IndexPacket - *indexes; + * restrict indexes; long n, @@ -1116,9 +1131,6 @@ VerticalFilter(const Image *source,Image *destination, MagickBool thread_status; -#if defined(HAVE_OPENMP) -# pragma omp critical (GM_VerticalFilter) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -1152,10 +1164,10 @@ VerticalFilter(const Image *source,Image *destination, contribution[n-1].pixel-contribution[0].pixel+1, exception); if (p == (const PixelPacket *) NULL) - thread_status=MagickFail; + thread_status=MagickFail; if (thread_status != MagickFail) - q=SetImagePixelsEx(destination,0,y,destination->columns,1,exception); + q=SetImagePixelsEx(destination,0,y,destination->columns,1,exception); if (q == (PixelPacket *) NULL) thread_status=MagickFail; @@ -1180,11 +1192,11 @@ VerticalFilter(const Image *source,Image *destination, pixel=zero; if ((source->matte) || (source->colorspace == CMYKColorspace)) { - double - transparency_coeff, - normalize; + double + transparency_coeff, + normalize; - normalize=0.0; + normalize=0.0; for (i=0; i < n; i++) { j=(long) ((contribution[i].pixel-contribution[0].pixel)* @@ -1199,9 +1211,9 @@ VerticalFilter(const Image *source,Image *destination, } normalize = 1.0 / (AbsoluteValue(normalize) <= MagickEpsilon ? 1.0 : normalize); - pixel.red *= normalize; - pixel.green *= normalize; - pixel.blue *= normalize; + pixel.red *= normalize; + pixel.green *= normalize; + pixel.blue *= normalize; q[x].red=RoundDoubleToQuantum(pixel.red); q[x].green=RoundDoubleToQuantum(pixel.green); q[x].blue=RoundDoubleToQuantum(pixel.blue); @@ -1237,25 +1249,33 @@ VerticalFilter(const Image *source,Image *destination, thread_status=MagickFail; } #if defined(HAVE_OPENMP) -# pragma omp critical (GM_VerticalFilter) +# pragma omp flush (quantum) #endif - { - if (QuantumTick(*quantum,span)) - if (!MagickMonitorFormatted(*quantum,span,exception, - ResizeImageText,source->filename)) - thread_status=MagickFail; - - (*quantum)++; - - if (thread_status == MagickFail) + if (QuantumTick(quantum,span)) + if (!MagickMonitorFormatted(quantum,span,exception, + ResizeImageText,source->filename)) + thread_status=MagickFail; + +#if defined(HAVE_OPENMP) +# pragma omp atomic +#endif + quantum++; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif + } } if (IsEventLogging()) (void) LogMagickEvent(TransformEvent,GetMagickModule(), - "%s exit VerticalFilter()", - (status == MagickFail ? "Error" : "Normal")); + "%s exit VerticalFilter()", + (status == MagickFail ? "Error" : "Normal")); + + *quantum_p = quantum; return (status); } @@ -1391,19 +1411,19 @@ MagickExport Image *ResizeImage(const Image *image,const unsigned long columns, { span=source_image->columns+resize_image->rows; status=HorizontalFilter(image,source_image,x_factor,&filters[i],blur, - view_data_set,span,&quantum,exception); + view_data_set,span,&quantum,exception); if (status != MagickFail) - status=VerticalFilter(source_image,resize_image,y_factor,&filters[i], - blur,view_data_set,span,&quantum,exception); + status=VerticalFilter(source_image,resize_image,y_factor,&filters[i], + blur,view_data_set,span,&quantum,exception); } else { span=resize_image->columns+source_image->rows; status=VerticalFilter(image,source_image,y_factor,&filters[i],blur, - view_data_set,span,&quantum,exception); + view_data_set,span,&quantum,exception); if (status != MagickFail) - status=HorizontalFilter(source_image,resize_image,x_factor,&filters[i], - blur,view_data_set,span,&quantum,exception); + status=HorizontalFilter(source_image,resize_image,x_factor,&filters[i], + blur,view_data_set,span,&quantum,exception); } /* Free allocated memory. diff --git a/magick/resize.h b/magick/resize.h index e00f42c..1d5eb42 100644 --- a/magick/resize.h +++ b/magick/resize.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003 - 2012 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + ImageMagick Image Resize Methods. */ #ifndef _MAGICK_RESIZE_H diff --git a/magick/resource.c b/magick/resource.c index f5664e9..4f3f30a 100644 --- a/magick/resource.c +++ b/magick/resource.c @@ -151,7 +151,7 @@ static ResourceInfo *GetResourceInfo(const ResourceType type) MagickExport MagickPassFail AcquireMagickResource(const ResourceType type, - const magick_uint64_t size) + const magick_uint64_t size) { magick_uint64_t value; @@ -577,12 +577,12 @@ MagickExport void InitializeMagickResources(void) #if defined(HAVE_OPENMP) max_threads=omp_get_num_procs(); (void) LogMagickEvent(ResourceEvent,GetMagickModule(), - "%i CPU cores are available",(int) max_threads); + "%i CPU cores are available",(int) max_threads); if ((envp=getenv("OMP_NUM_THREADS"))) { - max_threads=MagickSizeStrToInt64(envp,1024); - (void) LogMagickEvent(ResourceEvent,GetMagickModule(), - "OMP_NUM_THREADS requests %i threads",(int) max_threads); + max_threads=MagickSizeStrToInt64(envp,1024); + (void) LogMagickEvent(ResourceEvent,GetMagickModule(), + "OMP_NUM_THREADS requests %i threads",(int) max_threads); } if (max_threads < 1) max_threads=1; @@ -595,67 +595,67 @@ MagickExport void InitializeMagickResources(void) # if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) { struct rlimit - rlimits; + rlimits; rlim_t - margin, - target; + margin, + target; margin=128; target=(rlim_t) max_files+margin; if (getrlimit(RLIMIT_NOFILE, &rlimits) != -1) - { - (void) LogMagickEvent(ResourceEvent,GetMagickModule(), - "System file open limits are %lu soft," - " %lu hard", - (unsigned long) rlimits.rlim_cur, - (unsigned long) rlimits.rlim_max); + { + (void) LogMagickEvent(ResourceEvent,GetMagickModule(), + "System file open limits are %lu soft," + " %lu hard", + (unsigned long) rlimits.rlim_cur, + (unsigned long) rlimits.rlim_max); # if defined(HAVE_SETRLIMIT) - if (rlimits.rlim_max < target) - rlimits.rlim_cur=rlimits.rlim_max; - if (rlimits.rlim_cur < target) - { - (void) LogMagickEvent(ResourceEvent,GetMagickModule(), - "Increasing file open soft limit from %lu " - "to %lu", - (unsigned long) rlimits.rlim_cur, - (unsigned long) target); - rlimits.rlim_cur=target; - (void) setrlimit(RLIMIT_NOFILE, &rlimits); - } - if (getrlimit(RLIMIT_NOFILE, &rlimits) != -1) - { - if (rlimits.rlim_cur < target) - { - if (rlimits.rlim_cur > margin*2) - max_files=rlimits.rlim_cur-margin; - else - max_files=rlimits.rlim_cur/2; - } - } + if (rlimits.rlim_max < target) + rlimits.rlim_cur=rlimits.rlim_max; + if (rlimits.rlim_cur < target) + { + (void) LogMagickEvent(ResourceEvent,GetMagickModule(), + "Increasing file open soft limit from %lu " + "to %lu", + (unsigned long) rlimits.rlim_cur, + (unsigned long) target); + rlimits.rlim_cur=target; + (void) setrlimit(RLIMIT_NOFILE, &rlimits); + } + if (getrlimit(RLIMIT_NOFILE, &rlimits) != -1) + { + if (rlimits.rlim_cur < target) + { + if (rlimits.rlim_cur > margin*2) + max_files=rlimits.rlim_cur-margin; + else + max_files=rlimits.rlim_cur/2; + } + } # endif - } + } } # elif defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) { long - margin, - open_max, - target; + margin, + open_max, + target; margin=128; target=max_files+margin; open_max=sysconf(_SC_OPEN_MAX); (void) LogMagickEvent(ResourceEvent,GetMagickModule(), - "System file open limit is %lu", - (unsigned long) open_max); + "System file open limit is %lu", + (unsigned long) open_max); if (open_max < target) - { - if (open_max > margin*2) - max_files=open_max-margin; - else - max_files=open_max/2; - } + { + if (open_max > margin*2) + max_files=open_max-margin; + else + max_files=open_max/2; + } } # endif @@ -812,7 +812,7 @@ MagickExport MagickPassFail ListMagickResourceInfo(FILE *file, index; ARG_NOT_USED(exception); - + LockSemaphoreInfo(resource_semaphore); if (file == (const FILE *) NULL) file=stdout; @@ -917,10 +917,10 @@ MagickExport MagickPassFail SetMagickResourceLimit(const ResourceType type, FormatSize((magick_int64_t) limit, f_limit); - info->maximum = limit; + info->maximum = limit; #if defined(HAVE_OPENMP) - if (ThreadsResource == type) - omp_set_num_threads((int) limit); + if (ThreadsResource == type) + omp_set_num_threads((int) limit); #endif /* HAVE_OPENMP */ (void) LogMagickEvent(ResourceEvent,GetMagickModule(), "Set %s resource limit to %s%s", diff --git a/magick/resource.h b/magick/resource.h index ae7b5d1..8bde9d5 100644 --- a/magick/resource.h +++ b/magick/resource.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003 - 2015 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + Resource methods. */ #ifndef _MAGICK_RESOURCE_H diff --git a/magick/segment.c b/magick/segment.c index 7ec5952..6426fae 100644 --- a/magick/segment.c +++ b/magick/segment.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2015 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -165,6 +165,7 @@ static int DefineRegion(const short *,ExtentPacket *); static void + FreeNodes(IntervalTree *node), ScaleSpace(const long *,const double,double *), ZeroCrossHistogram(double *,const double,short *); @@ -251,21 +252,21 @@ typedef struct _Cluster { struct _Cluster *next; - + ExtentPacket red, green, blue; - + magick_int64_t count; - + short id; } Cluster; static MagickPassFail -Classify(Image *image,short **extrema, +Classify(Image * restrict image,short **extrema, const double cluster_threshold, const double weighting_exponent, const unsigned int verbose) @@ -294,23 +295,23 @@ Classify(Image *image,short **extrema, y; PixelPacket - *colormap=0; + * restrict colormap=0; register const PixelPacket - *p; + * restrict p; register double - *squares; + * restrict squares; register IndexPacket - *indexes; + * restrict indexes; register long i, x; register PixelPacket - *q; + * restrict q; unsigned long number_clusters; @@ -629,11 +630,8 @@ Classify(Image *image,short **extrema, thread_status; int - num_threads; + num_threads; -#if defined(HAVE_OPENMP) -# pragma omp critical (GM_Classify) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -675,13 +673,13 @@ Classify(Image *image,short **extrema, q[x]=image->colormap[indexes[x]]; classified=MagickTrue; - /* - Re-sort array so that most frequent occurs first. + /* + Re-sort array so that most frequent occurs first. - Updating cluster_array causes a multithread race - condition so this chunk is only enabled in the - case of one thread. - */ + Updating cluster_array causes a multithread race + condition so this chunk is only enabled in the + case of one thread. + */ if ((num_threads == 1) && (count > 0) && (cluster_array[count]->count > cluster_array[count-1]->count)) { @@ -760,19 +758,22 @@ Classify(Image *image,short **extrema, thread_status=MagickFail; } #if defined(HAVE_OPENMP) -# pragma omp critical (GM_Classify) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,image->rows)) - if (!MagickMonitorFormatted(row_count+image->rows,image->rows << 1, - &image->exception, - SegmentImageText,image->filename)) - thread_status=MagickFail; + row_count++; + if (QuantumTick(row_count,image->rows)) + if (!MagickMonitorFormatted(row_count+image->rows,image->rows << 1, + &image->exception, + SegmentImageText,image->filename)) + thread_status=MagickFail; - if (thread_status == MagickFail) + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif + } } /* Free memory. @@ -1191,16 +1192,24 @@ InitializeIntervalTree(const ZeroCrossing *zero_crossing, */ list=MagickAllocateMemory(IntervalTree **,TreeLength*sizeof(IntervalTree *)); if (list == (IntervalTree **) NULL) - return((IntervalTree *) NULL); + return ((IntervalTree *) NULL); /* The root is the entire histogram. */ root=MagickAllocateMemory(IntervalTree *,sizeof(IntervalTree)); + if (root == (IntervalTree *) NULL) + { + MagickFreeMemory(list); + return ((IntervalTree *) NULL); + } root->child=(IntervalTree *) NULL; root->sibling=(IntervalTree *) NULL; root->tau=0.0; root->left=0; root->right=255; + root->mean_stability=0.0; + root->stability=0.0; + (void) memset(list,0,TreeLength*sizeof(IntervalTree *)); for (i=(-1); i < (long) number_crossings; i++) { /* @@ -1232,6 +1241,8 @@ InitializeIntervalTree(const ZeroCrossing *zero_crossing, sizeof(IntervalTree)); node=node->sibling; } + if (node == (IntervalTree *) NULL) + goto interval_tree_alloc_failure; node->tau=zero_crossing[i+1].tau; node->child=(IntervalTree *) NULL; node->sibling=(IntervalTree *) NULL; @@ -1243,6 +1254,8 @@ InitializeIntervalTree(const ZeroCrossing *zero_crossing, if (left != head->left) { node->sibling=MagickAllocateMemory(IntervalTree *,sizeof(IntervalTree)); + if (node->sibling == (IntervalTree *) NULL) + goto interval_tree_alloc_failure; node=node->sibling; node->tau=zero_crossing[i+1].tau; node->child=(IntervalTree *) NULL; @@ -1259,6 +1272,12 @@ InitializeIntervalTree(const ZeroCrossing *zero_crossing, MeanStability(root->child); MagickFreeMemory(list); return(root); + + interval_tree_alloc_failure: + + MagickFreeMemory(list); + FreeNodes(root); + return ((IntervalTree *) NULL); } /* @@ -1380,7 +1399,10 @@ OptimalTau(const long *histogram,const double max_tau, count=(unsigned long) ((max_tau-min_tau)/delta_tau)+2; zero_crossing=MagickAllocateMemory(ZeroCrossing *,count*sizeof(ZeroCrossing)); if (zero_crossing == (ZeroCrossing *) NULL) - return(0.0); + { + MagickFreeMemory(list); + return(0.0); + } for (i=0; i < (long) count; i++) zero_crossing[i].tau=(-1); /* @@ -1439,7 +1461,11 @@ OptimalTau(const long *histogram,const double max_tau, */ root=InitializeIntervalTree(zero_crossing,number_crossings); if (root == (IntervalTree *) NULL) - return(0.0); + { + MagickFreeMemory(zero_crossing); + MagickFreeMemory(list); + return(0.0); + } /* Find active nodes: stability is greater (or equal) to the mean stability of its children. diff --git a/magick/semaphore.c b/magick/semaphore.c index bccfe6b..c837ede 100644 --- a/magick/semaphore.c +++ b/magick/semaphore.c @@ -48,89 +48,89 @@ #if defined(USE_PTHREAD_LOCKS) # include -# define PTHREAD_MUTEX_DESTROY(semaphore_mutex) \ - { \ - int \ - err_status; \ - \ - if ((err_status = pthread_mutex_destroy(semaphore_mutex)) != 0) \ - { \ - errno=err_status; \ - MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ - UnableToDestroySemaphore); \ - } \ +# define PTHREAD_MUTEX_DESTROY(semaphore_mutex) \ + { \ + int \ + err_status; \ + \ + if ((err_status = pthread_mutex_destroy(semaphore_mutex)) != 0) \ + { \ + errno=err_status; \ + MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ + UnableToDestroySemaphore); \ + } \ } -# define PTHREAD_MUTEXATTR_DESTROY(mutexattr) \ - { \ - int \ - err_status; \ - \ - if ((err_status = pthread_mutexattr_destroy(mutexattr)) != 0) \ - { \ - errno=err_status; \ - MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ - UnableToDestroySemaphore); \ - } \ +# define PTHREAD_MUTEXATTR_DESTROY(mutexattr) \ + { \ + int \ + err_status; \ + \ + if ((err_status = pthread_mutexattr_destroy(mutexattr)) != 0) \ + { \ + errno=err_status; \ + MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ + UnableToDestroySemaphore); \ + } \ } -# define PTHREAD_MUTEXATTR_INIT(mutexattr) \ - { \ - int \ - err_status; \ - \ - if ((err_status = pthread_mutexattr_init(mutexattr)) != 0) \ - { \ - errno=err_status; \ - MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ - UnableToInitializeSemaphore); \ - } \ +# define PTHREAD_MUTEXATTR_INIT(mutexattr) \ + { \ + int \ + err_status; \ + \ + if ((err_status = pthread_mutexattr_init(mutexattr)) != 0) \ + { \ + errno=err_status; \ + MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ + UnableToInitializeSemaphore); \ + } \ } -# define PTHREAD_MUTEXATTR_SETTYPE(mutexattr,mutexattrtype) \ - { \ - int \ - err_status; \ - \ +# define PTHREAD_MUTEXATTR_SETTYPE(mutexattr,mutexattrtype) \ + { \ + int \ + err_status; \ + \ if ((err_status = pthread_mutexattr_settype(mutexattr,mutexattrtype)) != 0) \ - { \ - errno=err_status; \ - MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ - UnableToInitializeSemaphore); \ - } \ + { \ + errno=err_status; \ + MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ + UnableToInitializeSemaphore); \ + } \ } -# define PTHREAD_MUTEX_INIT(semaphore_mutex,mutexattr) \ - { \ - int \ - err_status; \ - \ +# define PTHREAD_MUTEX_INIT(semaphore_mutex,mutexattr) \ + { \ + int \ + err_status; \ + \ if ((err_status = pthread_mutex_init(semaphore_mutex,mutexattr)) != 0) \ - { \ - errno=err_status; \ - MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ - UnableToInitializeSemaphore); \ - } \ + { \ + errno=err_status; \ + MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ + UnableToInitializeSemaphore); \ + } \ } -# define PTHREAD_MUTEX_LOCK(semaphore_mutex) \ - { \ - int \ - err_status; \ - \ - if ((err_status = pthread_mutex_lock(semaphore_mutex)) != 0) \ - { \ - errno=err_status; \ - MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ - UnableToLockSemaphore); \ - } \ +# define PTHREAD_MUTEX_LOCK(semaphore_mutex) \ + { \ + int \ + err_status; \ + \ + if ((err_status = pthread_mutex_lock(semaphore_mutex)) != 0) \ + { \ + errno=err_status; \ + MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ + UnableToLockSemaphore); \ + } \ } -# define PTHREAD_MUTEX_UNLOCK(semaphore_mutex) \ - { \ - int \ - err_status; \ - \ - if ((err_status = pthread_mutex_unlock(semaphore_mutex)) != 0) \ - { \ - errno=err_status; \ - MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ - UnableToUnlockSemaphore); \ - } \ +# define PTHREAD_MUTEX_UNLOCK(semaphore_mutex) \ + { \ + int \ + err_status; \ + \ + if ((err_status = pthread_mutex_unlock(semaphore_mutex)) != 0) \ + { \ + errno=err_status; \ + MagickFatalError3(ResourceLimitFatalError,SemaporeOperationFailed, \ + UnableToUnlockSemaphore); \ + } \ } #endif @@ -153,22 +153,22 @@ struct _SemaphoreInfo #endif /* defined(USE_OPENMP_LOCKS) */ #if defined(USE_PTHREAD_LOCKS) pthread_mutex_t - mutex; /* POSIX thread mutex */ + mutex; /* POSIX thread mutex */ #endif /* if defined(USE_PTHREAD_LOCKS) */ #if defined(USE_WIN32_LOCKS) CRITICAL_SECTION - mutex; /* Windows critical section */ + mutex; /* Windows critical section */ #endif /* defined(USE_WIN32_LOCKS) */ unsigned long - signature; /* Used to validate structure */ + signature; /* Used to validate structure */ }; /* Static declaractions. */ #if defined(USE_OPENMP_LOCKS) -static omp_lock_t +static omp_lock_t semaphore_mutex; static unsigned int @@ -323,8 +323,8 @@ MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void) Allocate semaphore. */ semaphore_info=MagickAllocateAlignedMemory(SemaphoreInfo *, - MAGICK_CACHE_LINE_SIZE, - sizeof(SemaphoreInfo)); + MAGICK_CACHE_LINE_SIZE, + sizeof(SemaphoreInfo)); if (semaphore_info == (SemaphoreInfo *) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, UnableToAllocateSemaphoreInfo); @@ -337,7 +337,7 @@ MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void) #endif /* defined(USE_OPENMP_LOCKS) */ #if defined(USE_PTHREAD_LOCKS) { - pthread_mutexattr_t + pthread_mutexattr_t mutexattr; PTHREAD_MUTEXATTR_INIT(&mutexattr); @@ -359,7 +359,7 @@ MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void) #if defined(USE_WIN32_LOCKS) InitializeCriticalSection(&semaphore_info->mutex); #endif - + semaphore_info->signature=MagickSignature; return(semaphore_info); } diff --git a/magick/semaphore.h b/magick/semaphore.h index c413b44..50332f1 100644 --- a/magick/semaphore.h +++ b/magick/semaphore.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003-2010 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + Methods to lock and unlock semaphores. */ #ifndef _MAGICK_SEMAPHORE_H diff --git a/magick/shear.c b/magick/shear.c index 3a228ea..6b6170a 100644 --- a/magick/shear.c +++ b/magick/shear.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2016 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -85,7 +85,7 @@ */ MagickExport Image * AffineTransformImage(const Image *image,const AffineMatrix *affine, - ExceptionInfo *exception) + ExceptionInfo *exception) { AffineMatrix transform; @@ -171,7 +171,7 @@ AffineTransformImage(const Image *image,const AffineMatrix *affine, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % AutoOrientImage() returns an image adjusted so that its orientation is -% suitable for viewing (i.e. top-left orientation). +% suitable for viewing (i.e. top-left orientation). % % The format of the AutoOrientImage method is: % @@ -319,9 +319,9 @@ AutoOrientImage(const Image *image, */ static MagickPassFail CropToFitImage(Image **image, - const double x_shear,const double y_shear, - const double width,const double height, - const unsigned int rotate,ExceptionInfo *exception) + const double x_shear,const double y_shear, + const double width,const double height, + const unsigned int rotate,ExceptionInfo *exception) { Image *crop_image; @@ -424,7 +424,7 @@ CropToFitImage(Image **image, #endif static Image * IntegralRotateImage(const Image *image,unsigned int rotations, - ExceptionInfo *exception) + ExceptionInfo *exception) { char message[MaxTextExtent]; @@ -456,58 +456,58 @@ IntegralRotateImage(const Image *image,unsigned int rotations, unsigned long clone_columns=0, clone_rows=0; - + switch (rotations) { case 0: - clone_columns=0; - clone_rows=0; - break; + clone_columns=0; + clone_rows=0; + break; case 2: - clone_columns=image->columns; - clone_rows=image->rows; - break; + clone_columns=image->columns; + clone_rows=image->rows; + break; case 1: case 3: - clone_columns=image->rows; - clone_rows=image->columns; - break; + clone_columns=image->rows; + clone_rows=image->columns; + break; } rotate_image=CloneImage(image,clone_columns,clone_rows,True,exception); if (rotate_image == (Image *) NULL) return((Image *) NULL); if (rotations != 0) if (ModifyCache(rotate_image,exception) != MagickPass) - { - DestroyImage(rotate_image); - return (Image *) NULL; - } + { + DestroyImage(rotate_image); + return (Image *) NULL; + } } tile_height_max=tile_width_max=2048/sizeof(PixelPacket); /* 2k x 2k = 4MB */ if ((rotations == 1) || (rotations == 3)) { /* - Allow override of tile geometry for testing. + Allow override of tile geometry for testing. */ const char * - value; + value; if (!GetPixelCacheInCore(image) || !GetPixelCacheInCore(rotate_image)) - tile_height_max=tile_width_max=8192/sizeof(PixelPacket); /* 8k x 8k = 64MB */ + tile_height_max=tile_width_max=8192/sizeof(PixelPacket); /* 8k x 8k = 64MB */ if ((value=getenv("MAGICK_ROTATE_TILE_GEOMETRY"))) - { - double - width, - height; - - if (GetMagickDimension(value,&width,&height,NULL,NULL) == 2) - { - tile_height_max=(unsigned long) height; - tile_width_max=(unsigned long) width; - } - } + { + double + width, + height; + + if (GetMagickDimension(value,&width,&height,NULL,NULL) == 2) + { + tile_height_max=(unsigned long) height; + tile_width_max=(unsigned long) width; + } + } } /* @@ -520,10 +520,10 @@ IntegralRotateImage(const Image *image,unsigned int rotations, /* Rotate 0 degrees (nothing more to do). */ - (void) strlcpy(message,"[%s] Rotate: 0 degrees...",sizeof(message)); - if (!MagickMonitorFormatted(image->rows-1,image->rows,exception, - message,image->filename)) - status=MagickFail; + (void) strlcpy(message,"[%s] Rotate: 0 degrees...",sizeof(message)); + if (!MagickMonitorFormatted(image->rows-1,image->rows,exception, + message,image->filename)) + status=MagickFail; break; } case 1: @@ -549,7 +549,7 @@ IntegralRotateImage(const Image *image,unsigned int rotations, (void) strlcpy(message,"[%s] Rotate: 90 degrees...",sizeof(message)); total_tiles=(((image->rows/tile_height_max)+1)* - ((image->columns/tile_width_max)+1)); + ((image->columns/tile_width_max)+1)); tile=0; #if defined(IntegralRotateImageUseOpenMP) @@ -569,11 +569,6 @@ IntegralRotateImage(const Image *image,unsigned int rotations, MagickPassFail thread_status; -#if defined(IntegralRotateImageUseOpenMP) -# if defined(HAVE_OPENMP) -# pragma omp critical (GM_IntegralRotateImage) -# endif -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -589,7 +584,7 @@ IntegralRotateImage(const Image *image,unsigned int rotations, tile_height; const PixelPacket - *tile_pixels; + *tile_pixels=(const PixelPacket *) NULL; long y; @@ -627,13 +622,13 @@ IntegralRotateImage(const Image *image,unsigned int rotations, { register const PixelPacket *p; - + register PixelPacket *q; register const IndexPacket *indexes; - + IndexPacket *rotate_indexes; @@ -651,7 +646,7 @@ IntegralRotateImage(const Image *image,unsigned int rotations, DirectClass pixels */ p=tile_pixels+(tile_height-1)*tile_width + y; - for (x=tile_height; x != 0; x--) + for (x=tile_height; x != 0; x--) { *q = *p; q++; @@ -668,13 +663,13 @@ IntegralRotateImage(const Image *image,unsigned int rotations, { register IndexPacket *iq; - + register const IndexPacket *ip; iq=rotate_indexes; ip=indexes+(tile_height-1)*tile_width + y; - for (x=tile_height; x != 0; x--) + for (x=tile_height; x != 0; x--) { *iq = *ip; iq++; @@ -691,19 +686,33 @@ IntegralRotateImage(const Image *image,unsigned int rotations, #if defined(IntegralRotateImageUseOpenMP) # if defined(HAVE_OPENMP) -# pragma omp critical (GM_IntegralRotateImage) +# pragma omp atomic # endif #endif - { - tile++; - if (QuantumTick(tile,total_tiles)) - if (!MagickMonitorFormatted(tile,total_tiles,exception, - message,image->filename)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + tile++; + if (QuantumTick(tile,total_tiles)) + if (!MagickMonitorFormatted(tile,total_tiles,exception, + message,image->filename)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(IntegralRotateImageUseOpenMP) +# if defined(HAVE_OPENMP) +# pragma omp flush (status) +# endif +#endif + } + } + if (thread_status == MagickFail) + { + status = thread_status; +#if defined(IntegralRotateImageUseOpenMP) +# if defined(HAVE_OPENMP) +# pragma omp flush (status) +# endif +#endif } } Swap(page.width,page.height); @@ -749,7 +758,7 @@ IntegralRotateImage(const Image *image,unsigned int rotations, register const IndexPacket *indexes; - + IndexPacket *rotate_indexes; @@ -759,11 +768,6 @@ IntegralRotateImage(const Image *image,unsigned int rotations, MagickPassFail thread_status; -#if defined(IntegralRotateImageUseOpenMP) -# if defined(HAVE_OPENMP) -# pragma omp critical (GM_IntegralRotateImage) -# endif -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -789,19 +793,24 @@ IntegralRotateImage(const Image *image,unsigned int rotations, } #if defined(IntegralRotateImageUseOpenMP) # if defined(HAVE_OPENMP) -# pragma omp critical (GM_IntegralRotateImage) +# pragma omp atomic # endif #endif - { - row_count++; - if (QuantumTick(row_count,image->rows)) - if (!MagickMonitorFormatted(row_count,image->rows,exception, - message,image->filename)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,image->rows)) + if (!MagickMonitorFormatted(row_count,image->rows,exception, + message,image->filename)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(IntegralRotateImageUseOpenMP) +# if defined(HAVE_OPENMP) +# pragma omp flush (status) +# endif +#endif + } } page.x=(long) (page.width-rotate_image->columns-page.x); page.y=(long) (page.height-rotate_image->rows-page.y); @@ -850,11 +859,6 @@ IntegralRotateImage(const Image *image,unsigned int rotations, MagickPassFail thread_status; -#if defined(IntegralRotateImageUseOpenMP) -# if defined(HAVE_OPENMP) -# pragma omp critical (GM_IntegralRotateImage) -# endif -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -866,15 +870,15 @@ IntegralRotateImage(const Image *image,unsigned int rotations, tile_height; long - dest_tile_x, - dest_tile_y; + dest_tile_x=0, + dest_tile_y=0; long - y; + y=0; const PixelPacket - *tile_pixels; - + *tile_pixels = (const PixelPacket *) NULL; + /* Compute image region corresponding to tile. */ @@ -908,7 +912,7 @@ IntegralRotateImage(const Image *image,unsigned int rotations, { register const PixelPacket *p; - + register PixelPacket *q; @@ -949,7 +953,7 @@ IntegralRotateImage(const Image *image,unsigned int rotations, { register IndexPacket *iq; - + register const IndexPacket *ip; @@ -972,22 +976,37 @@ IntegralRotateImage(const Image *image,unsigned int rotations, #if defined(IntegralRotateImageUseOpenMP) # if defined(HAVE_OPENMP) -# pragma omp critical (GM_IntegralRotateImage) +# pragma omp atomic # endif #endif - { - tile++; - if (QuantumTick(tile,total_tiles)) - if (!MagickMonitorFormatted(tile,total_tiles,exception, - message,image->filename)) - thread_status=MagickFail; + tile++; + if (QuantumTick(tile,total_tiles)) + if (!MagickMonitorFormatted(tile,total_tiles,exception, + message,image->filename)) + thread_status=MagickFail; - if (thread_status == MagickFail) - status=MagickFail; - } + if (thread_status == MagickFail) + { + status=MagickFail; +#if defined(IntegralRotateImageUseOpenMP) +# if defined(HAVE_OPENMP) +# pragma omp flush (status) +# endif +#endif + } if (thread_status == MagickFail) - break; + break; + } + + if (thread_status == MagickFail) + { + status = thread_status; +#if defined(IntegralRotateImageUseOpenMP) +# if defined(HAVE_OPENMP) +# pragma omp flush (status) +# endif +#endif } } Swap(page.width,page.height); @@ -997,9 +1016,17 @@ IntegralRotateImage(const Image *image,unsigned int rotations, } } - rotate_image->page=page; - rotate_image->is_grayscale=image->is_grayscale; - rotate_image->is_monochrome=image->is_monochrome; + if (status == MagickFail) + { + DestroyImage(rotate_image); + rotate_image = (Image *) NULL; + } + else + { + rotate_image->page=page; + rotate_image->is_grayscale=image->is_grayscale; + rotate_image->is_monochrome=image->is_monochrome; + } return(rotate_image); } @@ -1041,8 +1068,8 @@ IntegralRotateImage(const Image *image,unsigned int rotations, static MagickPassFail XShearImage(Image *image,const double degrees, - const unsigned long width,const unsigned long height, - const long x_offset,long y_offset,ExceptionInfo *exception) + const unsigned long width,const unsigned long height, + const long x_offset,long y_offset,ExceptionInfo *exception) { #define XShearImageText "[%s] X Shear: %+g degrees, region %lux%lu%+ld%+ld... " @@ -1110,9 +1137,6 @@ XShearImage(Image *image,const double degrees, MagickPassFail thread_status; -#if defined(HAVE_OPENMP) -# pragma omp critical (GM_XShearImage) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -1181,20 +1205,23 @@ XShearImage(Image *image,const double degrees, thread_status=MagickFail; #if defined(HAVE_OPENMP) -# pragma omp critical (GM_XShearImage) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,height)) - if (!MagickMonitorFormatted(row_count,height,exception, - XShearImageText,image->filename, - degrees,width,height, - x_offset,y_offset)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,height)) + if (!MagickMonitorFormatted(row_count,height,exception, + XShearImageText,image->filename, + degrees,width,height, + x_offset,y_offset)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif + } continue; } @@ -1268,20 +1295,23 @@ XShearImage(Image *image,const double degrees, if (!SyncImagePixelsEx(image,exception)) thread_status=MagickFail; #if defined(HAVE_OPENMP) -# pragma omp critical (GM_XShearImage) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,height)) - if (!MagickMonitorFormatted(row_count,height,exception, - XShearImageText,image->filename, - degrees,width,height, - x_offset,y_offset)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,height)) + if (!MagickMonitorFormatted(row_count,height,exception, + XShearImageText,image->filename, + degrees,width,height, + x_offset,y_offset)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif + } } if (is_grayscale && IsGray(image->background_color)) image->is_grayscale=True; @@ -1327,8 +1357,8 @@ XShearImage(Image *image,const double degrees, */ static MagickPassFail YShearImage(Image *image,const double degrees, - const unsigned long width,const unsigned long height,long x_offset, - const long y_offset,ExceptionInfo *exception) + const unsigned long width,const unsigned long height,long x_offset, + const long y_offset,ExceptionInfo *exception) { #define YShearImageText "[%s] Y Shear: %+g degrees, region %lux%lu%+ld%+ld... " @@ -1396,9 +1426,6 @@ YShearImage(Image *image,const double degrees, MagickPassFail thread_status; -#if defined(HAVE_OPENMP) -# pragma omp critical (GM_YShearImage) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -1467,20 +1494,23 @@ YShearImage(Image *image,const double degrees, thread_status=MagickFail; #if defined(HAVE_OPENMP) -# pragma omp critical (GM_YShearImage) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,width)) - if (!MagickMonitorFormatted(row_count,width,exception, - YShearImageText,image->filename, - degrees,width,height, - x_offset,y_offset)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,width)) + if (!MagickMonitorFormatted(row_count,width,exception, + YShearImageText,image->filename, + degrees,width,height, + x_offset,y_offset)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif + } continue; } @@ -1555,20 +1585,23 @@ YShearImage(Image *image,const double degrees, thread_status=MagickFail; #if defined(HAVE_OPENMP) -# pragma omp critical (GM_YShearImage) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,width)) - if (!MagickMonitorFormatted(row_count,width,exception, - YShearImageText,image->filename, - degrees,width,height, - x_offset,y_offset)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,width)) + if (!MagickMonitorFormatted(row_count,width,exception, + YShearImageText,image->filename, + degrees,width,height, + x_offset,y_offset)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif + } } if (is_grayscale && IsGray(image->background_color)) image->is_grayscale=True; @@ -1657,9 +1690,9 @@ RotateImage(const Image *image,const double degrees,ExceptionInfo *exception) assert(image->signature == MagickSignature); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); - angle=degrees; - while (angle < -45.0) - angle+=360.0; + angle = degrees - 360.0*(int)(degrees / 360); + if(angle < -45.0) angle+=360.0; + for (rotations=0; angle > 45.0; rotations++) angle-=90.0; rotations%=4; @@ -1707,19 +1740,19 @@ RotateImage(const Image *image,const double degrees,ExceptionInfo *exception) */ rotate_image->storage_class=DirectClass; rotate_image->matte|=rotate_image->background_color.opacity != OpaqueOpacity; - + if (XShearImage(rotate_image,shear.x,width,height, x_offset,y_offset,exception) != MagickPass) goto rotate_image_exception; if (YShearImage(rotate_image,shear.y,shear1_width,height, - (long) (rotate_image->columns-shear1_width)/2,y_offset,exception) + (long) (rotate_image->columns-shear1_width)/2,y_offset,exception) != MagickPass) goto rotate_image_exception; if (XShearImage(rotate_image,shear.x,shear1_width,shear2_height, - (long) (rotate_image->columns-shear1_width)/2, - (long) (rotate_image->rows-shear2_height)/2,exception) + (long) (rotate_image->columns-shear1_width)/2, + (long) (rotate_image->rows-shear2_height)/2,exception) != MagickPass) goto rotate_image_exception; @@ -1785,7 +1818,7 @@ RotateImage(const Image *image,const double degrees,ExceptionInfo *exception) */ MagickExport Image * ShearImage(const Image *image,const double x_shear, - const double y_shear,ExceptionInfo *exception) + const double y_shear,ExceptionInfo *exception) { Image *integral_image = (Image *) NULL, @@ -1820,7 +1853,7 @@ ShearImage(const Image *image,const double x_shear, shear.x=(-tan(DegreesToRadians(x_shear)/2.0)); shear.y=sin(DegreesToRadians(y_shear)); (void) LogMagickEvent(TransformEvent,GetMagickModule(), - "Shear angles x,y: %g,%g degrees", shear.x, shear.y); + "Shear angles x,y: %g,%g degrees", shear.x, shear.y); if ((shear.x == 0.0) && (shear.y == 0.0)) return(integral_image); @@ -1846,19 +1879,19 @@ ShearImage(const Image *image,const double x_shear, */ shear_image->storage_class=DirectClass; shear_image->matte|=shear_image->background_color.opacity != OpaqueOpacity; - + if (XShearImage(shear_image,shear.x,image->columns,image->rows,x_offset, - (long) (shear_image->rows-image->rows)/2,exception) + (long) (shear_image->rows-image->rows)/2,exception) != MagickPass) goto shear_image_exception; - + if (YShearImage(shear_image,shear.y,y_width,image->rows, - (long) (shear_image->columns-y_width)/2,y_offset,exception) + (long) (shear_image->columns-y_width)/2,y_offset,exception) != MagickPass) goto shear_image_exception; - + if (CropToFitImage(&shear_image,shear.x,shear.y,image->columns,image->rows, - False,exception) != MagickPass) + False,exception) != MagickPass) goto shear_image_exception; shear_image->page.width=0; diff --git a/magick/shear.h b/magick/shear.h index 865b5f8..f08f609 100644 --- a/magick/shear.h +++ b/magick/shear.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003-2012 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + ImageMagick Image Shear Methods. */ #ifndef _MAGICK_SHEAR_H diff --git a/magick/signature.h b/magick/signature.h index f466ee2..a9431be 100644 --- a/magick/signature.h +++ b/magick/signature.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + Digital signature methods. */ #ifndef _MAGICK_SIGNATURE_H @@ -24,7 +24,7 @@ extern "C" { Typedef declarations. */ typedef struct _SignatureInfo -{ +{ unsigned long digest[8], low_order, diff --git a/magick/spinlock.h b/magick/spinlock.h index 3aa7a18..4035c87 100644 --- a/magick/spinlock.h +++ b/magick/spinlock.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + ImageMagick Spinlock Methods. These are highly lightweight functions that are used to prevent deadlocks on access to global data when the normal semaphore system has not yet been initialized. They are intended to only @@ -58,7 +58,7 @@ static void _spinlock_release (LONG volatile *sl) To operate on a pointer variable, use the InterlockedExchangePointer function. - + To operate on a 64-bit variable, use the InterlockedExchange64 function. */ diff --git a/magick/static.c b/magick/static.c index fd140a9..66c1d76 100644 --- a/magick/static.c +++ b/magick/static.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2016 GraphicsMagick Group +% Copyright (C) 2003-2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % % This program is covered by multiple licenses, which are described in @@ -36,10 +36,365 @@ Include declarations. */ #include "magick/studio.h" +#include "magick/log.h" #include "magick/module.h" #include "magick/static.h" #include "magick/utility.h" +#if !defined(SupportMagickModules) + +#include "magick/module_aliases.h" + +typedef struct _StaticModule +{ + const char* name; + void (*register_fn)(void); + void (*unregister_fn)(void); + MagickBool loaded; + const unsigned int name_length; + +} StaticModule; + +/* + This list must be ordered by 'name' in an ascending order based on + strcmp(). +*/ +static StaticModule +StaticModules[] = +{ +#define STATICM(name,register_fn,unregister_fn) {name,register_fn,unregister_fn,MagickFalse,sizeof(name)-1} + STATICM("ART",RegisterARTImage,UnregisterARTImage), + STATICM("AVS",RegisterAVSImage,UnregisterAVSImage), + STATICM("BMP",RegisterBMPImage,UnregisterBMPImage), + STATICM("CALS",RegisterCALSImage,UnregisterCALSImage), + STATICM("CAPTION",RegisterCAPTIONImage,UnregisterCAPTIONImage), + STATICM("CINEON",RegisterCINEONImage,UnregisterCINEONImage), +#if defined(HasWINGDI32) + STATICM("CLIPBOARD",RegisterCLIPBOARDImage,UnregisterCLIPBOARDImage), +#endif + STATICM("CMYK",RegisterCMYKImage,UnregisterCMYKImage), + STATICM("CUT",RegisterCUTImage,UnregisterCUTImage), + STATICM("DCM",RegisterDCMImage,UnregisterDCMImage), + STATICM("DCRAW",RegisterDCRAWImage,UnregisterDCRAWImage), + STATICM("DIB",RegisterDIBImage,UnregisterDIBImage), +#if defined(HasDPS) + STATICM("DPS",RegisterDPSImage,UnregisterDPSImage), +#endif + STATICM("DPX",RegisterDPXImage,UnregisterDPXImage), +#if defined(HasWINGDI32) + STATICM("EMF",RegisterEMFImage,UnregisterEMFImage), +#endif +#if defined(HasTIFF) + STATICM("EPT",RegisterEPTImage,UnregisterEPTImage), +#endif + STATICM("FAX",RegisterFAXImage,UnregisterFAXImage), + STATICM("FITS",RegisterFITSImage,UnregisterFITSImage), +#if defined(HasFPX) + STATICM("FPX",RegisterFPXImage,UnregisterFPXImage), +#endif + STATICM("GIF",RegisterGIFImage,UnregisterGIFImage), + STATICM("GRAY",RegisterGRAYImage,UnregisterGRAYImage), + STATICM("GRADIENT",RegisterGRADIENTImage,UnregisterGRADIENTImage), + STATICM("HISTOGRAM",RegisterHISTOGRAMImage,UnregisterHISTOGRAMImage), + STATICM("HRZ",RegisterHRZImage,UnregisterHRZImage), + STATICM("HTML",RegisterHTMLImage,UnregisterHTMLImage), + STATICM("ICON",RegisterICONImage,UnregisterICONImage), + STATICM("IDENTITY",RegisterIDENTITYImage,UnregisterIDENTITYImage), + STATICM("INFO",RegisterINFOImage,UnregisterINFOImage), +#if defined(HasJBIG) + STATICM("JBIG",RegisterJBIGImage,UnregisterJBIGImage), +#endif +#if defined(HasJPEG) + STATICM("JNX",RegisterJNXImage,UnregisterJNXImage), +#endif +#if defined(HasJPEG) + STATICM("JPEG",RegisterJPEGImage,UnregisterJPEGImage), +#endif +#if defined(HasJP2) + STATICM("JP2",RegisterJP2Image,UnregisterJP2Image), +#endif + STATICM("LABEL",RegisterLABELImage,UnregisterLABELImage), + STATICM("LOCALE",RegisterLOCALEImage,UnregisterLOCALEImage), + STATICM("LOGO",RegisterLOGOImage,UnregisterLOGOImage), + STATICM("MAC",RegisterMACImage,UnregisterMACImage), + STATICM("MAP",RegisterMAPImage,UnregisterMAPImage), + STATICM("MAT",RegisterMATImage,UnregisterMATImage), + STATICM("MATTE",RegisterMATTEImage,UnregisterMATTEImage), + STATICM("META",RegisterMETAImage,UnregisterMETAImage), + STATICM("MIFF",RegisterMIFFImage,UnregisterMIFFImage), + STATICM("MONO",RegisterMONOImage,UnregisterMONOImage), + STATICM("MPC",RegisterMPCImage,UnregisterMPCImage), + STATICM("MPEG",RegisterMPEGImage,UnregisterMPEGImage), + STATICM("MPR",RegisterMPRImage,UnregisterMPRImage), + STATICM("MSL",RegisterMSLImage,UnregisterMSLImage), + STATICM("MTV",RegisterMTVImage,UnregisterMTVImage), + STATICM("MVG",RegisterMVGImage,UnregisterMVGImage), + STATICM("NULL",RegisterNULLImage,UnregisterNULLImage), + STATICM("OTB",RegisterOTBImage,UnregisterOTBImage), + STATICM("PALM",RegisterPALMImage,UnregisterPALMImage), + STATICM("PCD",RegisterPCDImage,UnregisterPCDImage), + STATICM("PCL",RegisterPCLImage,UnregisterPCLImage), + STATICM("PCX",RegisterPCXImage,UnregisterPCXImage), + STATICM("PDB",RegisterPDBImage,UnregisterPDBImage), + STATICM("PDF",RegisterPDFImage,UnregisterPDFImage), + STATICM("PICT",RegisterPICTImage,UnregisterPICTImage), + STATICM("PIX",RegisterPIXImage,UnregisterPIXImage), + STATICM("PLASMA",RegisterPLASMAImage,UnregisterPLASMAImage), +#if defined(HasPNG) + STATICM("PNG",RegisterPNGImage,UnregisterPNGImage), +#endif + STATICM("PNM",RegisterPNMImage,UnregisterPNMImage), + STATICM("PREVIEW",RegisterPREVIEWImage,UnregisterPREVIEWImage), + STATICM("PS",RegisterPSImage,UnregisterPSImage), + STATICM("PS2",RegisterPS2Image,UnregisterPS2Image), + STATICM("PS3",RegisterPS3Image,UnregisterPS3Image), +#if defined(EnableBrokenCoders) && EnableBrokenCoders + STATICM("PSD",RegisterPSDImage,UnregisterPSDImage), +#endif /* defined(EnableBrokenCoders) && EnableBrokenCoders */ + STATICM("PWP",RegisterPWPImage,UnregisterPWPImage), + STATICM("RGB",RegisterRGBImage,UnregisterRGBImage), + STATICM("RLA",RegisterRLAImage,UnregisterRLAImage), + STATICM("RLE",RegisterRLEImage,UnregisterRLEImage), + STATICM("SCT",RegisterSCTImage,UnregisterSCTImage), + STATICM("SFW",RegisterSFWImage,UnregisterSFWImage), + STATICM("SGI",RegisterSGIImage,UnregisterSGIImage), + STATICM("STEGANO",RegisterSTEGANOImage,UnregisterSTEGANOImage), + STATICM("SUN",RegisterSUNImage,UnregisterSUNImage), + STATICM("SVG",RegisterSVGImage,UnregisterSVGImage), + STATICM("TGA",RegisterTGAImage,UnregisterTGAImage), +#if defined(HasTIFF) + STATICM("TIFF",RegisterTIFFImage,UnregisterTIFFImage), +#endif + STATICM("TILE",RegisterTILEImage,UnregisterTILEImage), + STATICM("TIM",RegisterTIMImage,UnregisterTIMImage), + STATICM("TOPOL",RegisterTOPOLImage,UnregisterTOPOLImage), + STATICM("TTF",RegisterTTFImage,UnregisterTTFImage), + STATICM("TXT",RegisterTXTImage,UnregisterTXTImage), + STATICM("UIL",RegisterUILImage,UnregisterUILImage), + STATICM("URL",RegisterURLImage,UnregisterURLImage), + STATICM("UYVY",RegisterUYVYImage,UnregisterUYVYImage), + STATICM("VICAR",RegisterVICARImage,UnregisterVICARImage), + STATICM("VID",RegisterVIDImage,UnregisterVIDImage), + STATICM("VIFF",RegisterVIFFImage,UnregisterVIFFImage), + STATICM("WBMP",RegisterWBMPImage,UnregisterWBMPImage), +#if defined(HasWEBP) + STATICM("WEBP",RegisterWEBPImage,UnregisterWEBPImage), +#endif + STATICM("WMF",RegisterWMFImage,UnregisterWMFImage), + STATICM("WPG",RegisterWPGImage,UnregisterWPGImage), +#if defined(HasX11) + STATICM("X",RegisterXImage,UnregisterXImage), +#endif /* defined(HasX11) */ + STATICM("XBM",RegisterXBMImage,UnregisterXBMImage), + STATICM("XC",RegisterXCImage,UnregisterXCImage), + STATICM("XCF",RegisterXCFImage,UnregisterXCFImage), + STATICM("XPM",RegisterXPMImage,UnregisterXPMImage), +#if defined(_VISUALC_) + STATICM("XTRN",RegisterXTRNImage,UnregisterXTRNImage), +#endif /* defined(_VISUALC_) */ +#if defined(HasX11) + STATICM("XWD",RegisterXWDImage,UnregisterXWDImage), +#endif /* defined(HasX11) */ + STATICM("YUV",RegisterYUVImage,UnregisterYUVImage) +}; + + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ D e s t r o y M a g i c k M o d u l e s % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DestroyMagickResources() destroys the resource environment. +% +% The format of the DestroyMagickResources() method is: +% +% DestroyMagickResources(void) +% +% +*/ +void +DestroyMagickModules(void) +{ + unsigned int index; + + for (index=0; index < sizeof(StaticModules)/sizeof(StaticModules[0]);index++) + { + if (StaticModules[index].loaded == MagickTrue) + { + (StaticModules[index].unregister_fn)(); + StaticModules[index].loaded = MagickFalse; + } + } +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ I n i t i a l i z e M a g i c k M o d u l e s % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% InitializeMagickModules() initializes the module loader. +% +% The format of the InitializeMagickModules() method is: +% +% InitializeMagickModules(void) +% +% +*/ +void +InitializeMagickModules(void) +{ +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% O p e n M o d u l e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% OpenModule() loads a module, and invokes its registration method. It +% returns MagickPass on success, and MagickFail if there is an error. +% +% The format of the OpenModule method is: +% +% MagickPassFail OpenModule(const char *module,ExceptionInfo *exception) +% +% A description of each parameter follows: +% +% o status: Method OpenModule returns MagickPass if the specified module is +% loaded, otherwise MagickFail. +% +% o module: a character string that indicates the module to load. +% +% o exception: Return any errors or warnings in this structure. +% +% +*/ +MagickPassFail +OpenModule(const char *module,ExceptionInfo *exception) +{ + char + module_name[MaxTextExtent]; + + size_t + name_length; + + unsigned int + index; + + MagickPassFail + status = MagickFail; + + (void) exception; + /* + Assign module name from alias. + */ + assert(module != (const char *) NULL); + name_length=strlcpy(module_name,module,MaxTextExtent); + LocaleUpper(module_name); + (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), + "Magick \"%s\"", module_name); + for (index=0; index < ArraySize(ModuleAliases);index++) + { + if (ModuleAliases[index].magick[0] > module[0]) + break; + if ((ModuleAliases[index].magick[0] == module[0]) && + (ModuleAliases[index].magick_len == name_length) && + (memcmp(ModuleAliases[index].magick,module,name_length) == 0)) + { + name_length=strlcpy(module_name,ModuleAliases[index].name,MaxTextExtent); + break; + } + } + + /* + Find module in list and load if not already loaded + */ + for (index=0; index < ArraySize(StaticModules);index++) + { + if (StaticModules[index].name[0] > module_name[0]) + break; + if ((StaticModules[index].name[0] == module_name[0]) && + (StaticModules[index].name_length == name_length) && + (memcmp(StaticModules[index].name,module_name,name_length) == 0)) + { + if (StaticModules[index].loaded == MagickFalse) + { + (StaticModules[index].register_fn)(); + StaticModules[index].loaded = MagickTrue; + (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), + "Loaded static module \"%s\"", module_name); + } + status=MagickPass; + break; + } + } + if (index == ArraySize(StaticModules)) + status=MagickFail; + + return status; +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% O p e n M o d u l e s % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Method OpenModules loads all available modules. +% +% The format of the OpenModules method is: +% +% MagickPassFail OpenModules(ExceptionInfo *exception) +% +% A description of each parameter follows: +% +% o status: Method OpenModules returns True if the modules are loaded, +% otherwise False. +% +% o exception: Return any errors or warnings in this structure. +% +*/ +MagickPassFail +OpenModules(ExceptionInfo *exception) +{ + unsigned int index; + (void) exception; + + for (index=0; index < ArraySize(StaticModules);index++) + { + if (StaticModules[index].loaded == MagickFalse) + { + (StaticModules[index].register_fn)(); + StaticModules[index].loaded = MagickTrue; + } + } + + return MagickPass; +} +#endif /* !defined(SupportMagickModules) */ + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % @@ -73,17 +428,17 @@ % */ #if defined(SupportMagickModules) -MagickExport unsigned int ExecuteStaticModuleProcess(const char *tag, +unsigned int ExecuteStaticModuleProcess(const char *tag, Image **image,const int argc,char **argv) #else -MagickExport unsigned int ExecuteModuleProcess(const char *tag, +unsigned int ExecuteModuleProcess(const char *tag, Image **image,const int argc,char **argv) #endif /* defined(SupportMagickModules) */ { unsigned int status = False; -#if !defined(BuildMagickModules) +#if !defined(SupportMagickModules) unsigned int (*method)(Image **,const int,char **) = 0; @@ -105,7 +460,7 @@ MagickExport unsigned int ExecuteModuleProcess(const char *tag, ARG_NOT_USED(image); ARG_NOT_USED(argc); ARG_NOT_USED(argv); -#endif /* !defined(BuildMagickModules) */ +#endif /* !defined(SupportMagickModules) */ return(status); } @@ -120,7 +475,7 @@ MagickExport unsigned int ExecuteModuleProcess(const char *tag, % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% +% RegisterStaticModules() statically registers all the available module % handlers. % @@ -130,143 +485,20 @@ RegisterStaticModules() statically registers all the available module % % */ -MagickExport void RegisterStaticModules(void) +void RegisterStaticModules(void) { -#if !defined(BuildMagickModules) - RegisterARTImage(); - RegisterAVSImage(); - RegisterBMPImage(); - RegisterCALSImage(); - RegisterCAPTIONImage(); - RegisterCINEONImage(); -#if defined(HasWINGDI32) - RegisterCLIPBOARDImage(); -#endif - RegisterCMYKImage(); - RegisterCUTImage(); - RegisterDCMImage(); - RegisterDCRAWImage(); - RegisterDIBImage(); -#if defined(HasDPS) - RegisterDPSImage(); -#endif - RegisterDPXImage(); -#if defined(HasWINGDI32) - RegisterEMFImage(); -#endif -#if defined(HasTIFF) - RegisterEPTImage(); -#endif - RegisterFAXImage(); - RegisterFITSImage(); -#if defined(HasFPX) - RegisterFPXImage(); -#endif - RegisterGIFImage(); - RegisterGRAYImage(); - RegisterGRADIENTImage(); - RegisterHISTOGRAMImage(); - RegisterHRZImage(); - RegisterHTMLImage(); - RegisterICONImage(); - RegisterIDENTITYImage(); - RegisterINFOImage(); -#if defined(HasJBIG) - RegisterJBIGImage(); -#endif -#if defined(HasJPEG) - RegisterJNXImage(); -#endif -#if defined(HasJPEG) - RegisterJPEGImage(); -#endif -#if defined(HasJP2) - RegisterJP2Image(); -#endif - RegisterLABELImage(); - RegisterLOCALEImage(); - RegisterLOGOImage(); - RegisterMACImage(); - RegisterMAPImage(); - RegisterMATImage(); - RegisterMATTEImage(); - RegisterMETAImage(); - RegisterMIFFImage(); - RegisterMONOImage(); - RegisterMPCImage(); - RegisterMPEGImage(); - RegisterMPRImage(); - RegisterMSLImage(); - RegisterMTVImage(); - RegisterMVGImage(); - RegisterNULLImage(); - RegisterOTBImage(); - RegisterPALMImage(); - RegisterPCDImage(); - RegisterPCLImage(); - RegisterPCXImage(); - RegisterPDBImage(); - RegisterPDFImage(); - RegisterPICTImage(); - RegisterPIXImage(); - RegisterPLASMAImage(); -#if defined(HasPNG) - RegisterPNGImage(); -#endif - RegisterPNMImage(); - RegisterPREVIEWImage(); - RegisterPSImage(); - RegisterPS2Image(); - RegisterPS3Image(); -#if defined(EnableBrokenCoders) && EnableBrokenCoders - RegisterPSDImage(); -#endif /* defined(EnableBrokenCoders) && EnableBrokenCoders */ - RegisterPWPImage(); - RegisterRGBImage(); - RegisterRLAImage(); - RegisterRLEImage(); - RegisterSCTImage(); - RegisterSFWImage(); - RegisterSGIImage(); - RegisterSTEGANOImage(); - RegisterSUNImage(); - RegisterSVGImage(); - RegisterTGAImage(); -#if defined(HasTIFF) - RegisterTIFFImage(); -#endif - RegisterTILEImage(); - RegisterTIMImage(); - RegisterTOPOLImage(); - RegisterTTFImage(); - RegisterTXTImage(); - RegisterUILImage(); - RegisterURLImage(); - RegisterUYVYImage(); - RegisterVICARImage(); - RegisterVIDImage(); - RegisterVIFFImage(); - RegisterWBMPImage(); -#if defined(HasWEBP) - RegisterWEBPImage(); -#endif - RegisterWMFImage(); - RegisterWPGImage(); -#if defined(HasX11) - RegisterXImage(); -#endif /* defined(HasX11) */ - RegisterXBMImage(); - RegisterXCImage(); - RegisterXCFImage(); - RegisterXPMImage(); -#if defined(_VISUALC_) - RegisterXTRNImage(); -#endif /* defined(_VISUALC_) */ -#if defined(HasX11) - RegisterXWDImage(); -#endif /* defined(HasX11) */ - RegisterYUVImage(); -#endif /* !defined(BuildMagickModules) */ +#if !defined(SupportMagickModules) + unsigned int index; + + for (index=0; index < ArraySize(StaticModules); index++) + { + if (StaticModules[index].loaded == MagickFalse) + { + (StaticModules[index].register_fn)(); + StaticModules[index].loaded = MagickTrue; + } + } +#endif /* !defined(SupportMagickModules) */ } /* @@ -289,141 +521,18 @@ MagickExport void RegisterStaticModules(void) % % */ -MagickExport void UnregisterStaticModules(void) +void UnregisterStaticModules(void) { -#if !defined(BuildMagickModules) - UnregisterARTImage(); - UnregisterAVSImage(); - UnregisterBMPImage(); - UnregisterCALSImage(); - UnregisterCAPTIONImage(); - UnregisterCINEONImage(); -#if defined(HasWINGDI32) - UnregisterCLIPBOARDImage(); -#endif - UnregisterCMYKImage(); - UnregisterCUTImage(); - UnregisterDCMImage(); - UnregisterDCRAWImage(); - UnregisterDIBImage(); -#if defined(HasDPS) - UnregisterDPSImage(); -#endif - UnregisterDPXImage(); -#if defined(HasWINGDI32) - UnregisterEMFImage(); -#endif -#if defined(HasTIFF) - UnregisterEPTImage(); -#endif - UnregisterFAXImage(); - UnregisterFITSImage(); -#if defined(HasFPX) - UnregisterFPXImage(); -#endif - UnregisterGIFImage(); - UnregisterGRAYImage(); - UnregisterGRADIENTImage(); - UnregisterHISTOGRAMImage(); - UnregisterHRZImage(); - UnregisterHTMLImage(); - UnregisterICONImage(); - UnregisterIDENTITYImage(); - UnregisterINFOImage(); -#if defined(HasJBIG) - UnregisterJBIGImage(); -#endif -#if defined(HasJPEG) - UnregisterJNXImage(); -#endif -#if defined(HasJPEG) - UnregisterJPEGImage(); -#endif -#if defined(HasJP2) - UnregisterJP2Image(); -#endif - UnregisterLABELImage(); - UnregisterLOCALEImage(); - UnregisterLOGOImage(); - UnregisterMACImage(); - UnregisterMAPImage(); - UnregisterMATImage(); - UnregisterMATTEImage(); - UnregisterMETAImage(); - UnregisterMIFFImage(); - UnregisterMONOImage(); - UnregisterMPCImage(); - UnregisterMPEGImage(); - UnregisterMPRImage(); - UnregisterMSLImage(); - UnregisterMTVImage(); - UnregisterMVGImage(); - UnregisterNULLImage(); - UnregisterOTBImage(); - UnregisterPALMImage(); - UnregisterPCDImage(); - UnregisterPCLImage(); - UnregisterPCXImage(); - UnregisterPDBImage(); - UnregisterPDFImage(); - UnregisterPICTImage(); - UnregisterPIXImage(); - UnregisterPLASMAImage(); -#if defined(HasPNG) - UnregisterPNGImage(); -#endif - UnregisterPNMImage(); - UnregisterPREVIEWImage(); - UnregisterPSImage(); - UnregisterPS2Image(); - UnregisterPS3Image(); -#if defined(EnableBrokenCoders) && EnableBrokenCoders - UnregisterPSDImage(); -#endif /* defined(EnableBrokenCoders) && EnableBrokenCoders */ - UnregisterPWPImage(); - UnregisterRGBImage(); - UnregisterRLAImage(); - UnregisterRLEImage(); - UnregisterSCTImage(); - UnregisterSFWImage(); - UnregisterSGIImage(); - UnregisterSTEGANOImage(); - UnregisterSUNImage(); - UnregisterSVGImage(); - UnregisterTGAImage(); -#if defined(HasTIFF) - UnregisterTIFFImage(); -#endif - UnregisterTILEImage(); - UnregisterTIMImage(); - UnregisterTOPOLImage(); - UnregisterTTFImage(); - UnregisterTXTImage(); - UnregisterUILImage(); - UnregisterURLImage(); - UnregisterUYVYImage(); - UnregisterVICARImage(); - UnregisterVIDImage(); - UnregisterVIFFImage(); - UnregisterWBMPImage(); -#if defined(HasWEBP) - UnregisterWEBPImage(); -#endif - UnregisterWMFImage(); - UnregisterWPGImage(); -#if defined(HasX11) - UnregisterXImage(); -#endif /* defined(HasX11) */ - UnregisterXBMImage(); - UnregisterXCImage(); - UnregisterXCFImage(); - UnregisterXPMImage(); -#if defined(_VISUALC_) - UnregisterXTRNImage(); -#endif /* defined(_VISUALC_) */ -#if defined(HasX11) - UnregisterXWDImage(); -#endif /* defined(HasX11) */ - UnregisterYUVImage(); -#endif /* !defined(BuildMagickModules) */ +#if !defined(SupportMagickModules) + unsigned int index; + + for (index=0; index < ArraySize(StaticModules);index++) + { + if (StaticModules[index].loaded == MagickTrue) + { + (StaticModules[index].unregister_fn)(); + StaticModules[index].loaded = MagickFalse; + } + } +#endif /* !defined(SupportMagickModules) */ } diff --git a/magick/static.h b/magick/static.h index 8de6d06..a01c75d 100644 --- a/magick/static.h +++ b/magick/static.h @@ -1,11 +1,11 @@ /* - Copyright (C) 2003-2010 GraphicsMagick Group + Copyright (C) 2003-2018 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + ImageMagick Coder Registration Methods. */ #ifndef _MAGICK_STATIC_H diff --git a/magick/statistics.c b/magick/statistics.c index a9b3d0c..30c6d2e 100644 --- a/magick/statistics.c +++ b/magick/statistics.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2014 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2003 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -58,18 +58,18 @@ typedef struct _StatisticsContext { } StatisticsContext; static MagickPassFail GetImageStatisticsMean(void *mutable_data, const void *immutable_data, - const Image *image, - const PixelPacket *pixel, - const IndexPacket *indexes, + const Image * restrict image, + const PixelPacket * restrict pixel, + const IndexPacket * restrict indexes, const long npixels, ExceptionInfo *exception) { ImageStatistics lstatistics, - *statistics=(ImageStatistics *) mutable_data; + * restrict statistics=(ImageStatistics *) mutable_data; const StatisticsContext - *context=(const StatisticsContext *) immutable_data; + * restrict context=(const StatisticsContext *) immutable_data; double normalized; @@ -162,18 +162,18 @@ static MagickPassFail GetImageStatisticsMean(void *mutable_data, #define Square(x) ((x)*(x)) static MagickPassFail GetImageStatisticsVariance(void *mutable_data, const void *immutable_data, - const Image *image, - const PixelPacket *pixel, - const IndexPacket *indexes, + const Image * restrict image, + const PixelPacket * restrict pixel, + const IndexPacket * restrict indexes, const long npixels, ExceptionInfo *exception) { ImageStatistics lstatistics, - *statistics=(ImageStatistics *) mutable_data; + * restrict statistics=(ImageStatistics *) mutable_data; const StatisticsContext - *context=(const StatisticsContext *) immutable_data; + * restrict context=(const StatisticsContext *) immutable_data; double normalized; @@ -204,15 +204,15 @@ static MagickPassFail GetImageStatisticsVariance(void *mutable_data, normalized=(double) pixel[i].red/MaxRGB; lstatistics.red.variance += Square(normalized-lstatistics.red.mean)/context->variance_divisor; - + normalized=(double) pixel[i].green/MaxRGB; lstatistics.green.variance += Square(normalized-lstatistics.green.mean)/context->variance_divisor; - + normalized=(double) pixel[i].blue/MaxRGB; lstatistics.blue.variance += Square(normalized-lstatistics.blue.mean)/context->variance_divisor; - + if (process_opacity) { normalized=(double) pixel[i].opacity/MaxRGB; @@ -239,7 +239,7 @@ MagickExport MagickPassFail GetImageStatistics(const Image *image, { StatisticsContext context; - + MagickPassFail status=MagickPass; @@ -260,7 +260,7 @@ MagickExport MagickPassFail GetImageStatistics(const Image *image, samples=(double) image->rows*image->columns; context.samples=samples; context.variance_divisor=samples-1; - + /* Compute Mean, Max, and Min */ @@ -292,4 +292,3 @@ MagickExport MagickPassFail GetImageStatistics(const Image *image, return status; } - diff --git a/magick/statistics.h b/magick/statistics.h index 7fea1bb..21b3fb7 100644 --- a/magick/statistics.h +++ b/magick/statistics.h @@ -2,11 +2,11 @@ Copyright (C) 2003 - 2009 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick Image Statistics Methods. */ #ifndef _MAGICK_STATISTICS_H @@ -46,7 +46,7 @@ typedef struct _ImageStatistics extern MagickExport MagickPassFail GetImageStatistics(const Image *image,ImageStatistics *statistics, - ExceptionInfo *exception); + ExceptionInfo *exception); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/magick/studio.h b/magick/studio.h index bf31c2f..ae181c0 100644 --- a/magick/studio.h +++ b/magick/studio.h @@ -1,11 +1,11 @@ /* - Copyright (C) 2003 - 2016 GraphicsMagick Group + Copyright (C) 2003 - 2017 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick Application Programming Interface declarations. */ #ifndef _MAGICK_STUDIO_H @@ -345,6 +345,7 @@ extern int vsnprintf(char *s, size_t n, const char *format, va_list ap); Define declarations. */ #define AbsoluteValue(x) ((x) < 0 ? -(x) : (x)) +#define ArraySize(a) (sizeof(a)/sizeof(a[0])) #define False 0 #define DegreesToRadians(x) (MagickPI*(x)/180.0) #define MagickIncarnate(x) InitializeMagick(x) @@ -356,12 +357,12 @@ extern int vsnprintf(char *s, size_t n, const char *format, va_list ap); #endif #define Max(x,y) (((x) > (y)) ? (x) : (y)) #define Min(x,y) (((x) < (y)) ? (x) : (y)) -#define NumberOfObjectsInArray(octets,size) ((octets+size-1)/size) +#define NumberOfObjectsInArray(octets,size) (octets/size) /* rounds down */ #define QuantumTick(i,span) \ ((((i) % ((Max(101,span)-1)/100)) == 0) || \ ((magick_int64_t) (i) == ((magick_int64_t) (span)-1))) #define RadiansToDegrees(x) (180.0*(x)/MagickPI) -#define RoundUpToAlignment(offset,alignment) \ +#define RoundUpToAlignment(offset,alignment) \ (((offset)+((alignment)-1)) & ~((alignment)-1)) #define AssertAlignment(offset,alignment) \ (assert((((size_t) offset) % (size_t) alignment) == (size_t) 0)) diff --git a/magick/symbols.h b/magick/symbols.h index d6f76c2..8868b62 100644 --- a/magick/symbols.h +++ b/magick/symbols.h @@ -1,18 +1,11 @@ /* - Copyright (C) 2003 - 2016 GraphicsMagick Group - + Copyright (C) 2012-2018 GraphicsMagick Group + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. Library symbol name-scoping support. - - Obtained via: - - nm -p magick/.libs/libGraphicsMagick.a | grep ' T ' | egrep -vi '(Gm)|(lt_)' | \ - egrep -v '(MagickError)|(MagickFatalError)|(MagickWarning)|(ThrowException)' | \ - awk '{ printf("#define %s Gm%s\n", $3, $3); }' | sort - */ #if !defined(_MAGICK_SYMBOLS_H) @@ -122,7 +115,9 @@ #define CompositeImage GmCompositeImage #define CompositeImageCommand GmCompositeImageCommand #define CompositeImageRegion GmCompositeImageRegion +#define CompositeMaskImage GmCompositeMaskImage #define CompositeOperatorToString GmCompositeOperatorToString +#define CompositePathImage GmCompositePathImage #define CompressImageColormap GmCompressImageColormap #define CompressionTypeToString GmCompressionTypeToString #define ConcatenateString GmConcatenateString @@ -138,7 +133,6 @@ #define CopyException GmCopyException #define CropImage GmCropImage #define CycleColormapImage GmCycleColormapImage -#define DCM_SetRescaling GmDCM_SetRescaling #define DeallocateImageProfileIterator GmDeallocateImageProfileIterator #define DeconstructImages GmDeconstructImages #define DefaultTileFrame GmDefaultTileFrame @@ -167,6 +161,8 @@ #define DestroyLogInfo GmDestroyLogInfo #define DestroyMagicInfo GmDestroyMagicInfo #define DestroyMagick GmDestroyMagick +#define DestroyMagickModules GmDestroyMagickModules +#define DestroyMagickMonitor GmDestroyMagickMonitor #define DestroyMagickRandomGenerator GmDestroyMagickRandomGenerator #define DestroyMagickRegistry GmDestroyMagickRegistry #define DestroyMagickResources GmDestroyMagickResources @@ -180,6 +176,7 @@ #define DestroyTypeInfo GmDestroyTypeInfo #define DetachBlob GmDetachBlob #define DifferenceImage GmDifferenceImage +#define DisassociateBlob GmDisassociateBlob #define DispatchImage GmDispatchImage #define DisplayImageCommand GmDisplayImageCommand #define DisplayImages GmDisplayImages @@ -194,6 +191,7 @@ #define DrawColor GmDrawColor #define DrawComment GmDrawComment #define DrawComposite GmDrawComposite +#define DrawCompositeMask GmDrawCompositeMask #define DrawDestroyContext GmDrawDestroyContext #define DrawEllipse GmDrawEllipse #define DrawGetClipPath GmDrawGetClipPath @@ -223,6 +221,8 @@ #define DrawGetTextEncoding GmDrawGetTextEncoding #define DrawGetTextUnderColor GmDrawGetTextUnderColor #define DrawImage GmDrawImage +#define DrawInfoGetClipPath GmDrawInfoGetClipPath +#define DrawInfoGetCompositePath GmDrawInfoGetCompositePath #define DrawLine GmDrawLine #define DrawMatte GmDrawMatte #define DrawPathClose GmDrawPathClose @@ -325,6 +325,7 @@ #define FormatString GmFormatString #define FormatStringList GmFormatStringList #define FrameImage GmFrameImage +#define FreeFunc GmFreeFunc #define FuzzyColorMatch GmFuzzyColorMatch #define GammaImage GmGammaImage #define GaussianBlurImage GmGaussianBlurImage @@ -332,6 +333,7 @@ #define GenerateDifferentialNoise GmGenerateDifferentialNoise #define GenerateNoise GmGenerateNoise #define GetBlobFileHandle GmGetBlobFileHandle +#define GetBlobFirstErrno GmGetBlobFirstErrno #define GetBlobInfo GmGetBlobInfo #define GetBlobIsOpen GmGetBlobIsOpen #define GetBlobSize GmGetBlobSize @@ -371,6 +373,7 @@ #define GetImageCharacteristics GmGetImageCharacteristics #define GetImageClipMask GmGetImageClipMask #define GetImageClippingPathAttribute GmGetImageClippingPathAttribute +#define GetImageCompositeMask GmGetImageCompositeMask #define GetImageDepth GmGetImageDepth #define GetImageDistortion GmGetImageDistortion #define GetImageException GmGetImageException @@ -437,6 +440,7 @@ #define HSLTransform GmHSLTransform #define HWBTransform GmHWBTransform #define HaldClutImage GmHaldClutImage +#define HighlightColor GmHighlightColor #define HighlightStyleToString GmHighlightStyleToString #define HuffmanDecodeImage GmHuffmanDecodeImage #define HuffmanEncode2Image GmHuffmanEncode2Image @@ -444,6 +448,8 @@ #define Hull GmHull #define IdentifyImageCommand GmIdentifyImageCommand #define IdentityAffine GmIdentityAffine +#define ImageGetClipMask GmImageGetClipMask +#define ImageGetCompositeMask GmImageGetCompositeMask #define ImageListToArray GmImageListToArray #define ImageToBlob GmImageToBlob #define ImageToFile GmImageToFile @@ -463,9 +469,12 @@ #define InitializeDifferenceImageOptions GmInitializeDifferenceImageOptions #define InitializeDifferenceStatistics GmInitializeDifferenceStatistics #define InitializeLogInfo GmInitializeLogInfo +#define InitializeLogInfoPost GmInitializeLogInfoPost #define InitializeMagicInfo GmInitializeMagicInfo #define InitializeMagick GmInitializeMagick #define InitializeMagickClientPathAndName GmInitializeMagickClientPathAndName +#define InitializeMagickModules GmInitializeMagickModules +#define InitializeMagickMonitor GmInitializeMagickMonitor #define InitializeMagickRandomGenerator GmInitializeMagickRandomGenerator #define InitializeMagickRandomKernel GmInitializeMagickRandomKernel #define InitializeMagickRegistry GmInitializeMagickRegistry @@ -518,13 +527,15 @@ #define LocaleNCompare GmLocaleNCompare #define LocaleUpper GmLocaleUpper #define LockSemaphoreInfo GmLockSemaphoreInfo -#define LogMagickEvent GmLogMagickEvent -#define LogMagickEventList GmLogMagickEventList -#define MatteColor GmMatteColor #define MSBOrderLong GmMSBOrderLong #define MSBOrderShort GmMSBOrderShort #define MagickAllocFunctions GmMagickAllocFunctions #define MagickArraySize GmMagickArraySize +#define MagickAtoFChk GmMagickAtoFChk +#define MagickAtoIChk GmMagickAtoIChk +#define MagickAtoLChk GmMagickAtoLChk +#define MagickAtoUIChk GmMagickAtoUIChk +#define MagickAtoULChk GmMagickAtoULChk #define MagickBitStreamInitializeRead GmMagickBitStreamInitializeRead #define MagickBitStreamInitializeWrite GmMagickBitStreamInitializeWrite #define MagickBitStreamMSBRead GmMagickBitStreamMSBRead @@ -537,16 +548,18 @@ #define MagickCreateDirectoryPath GmMagickCreateDirectoryPath #define MagickDestroyCommandInfo GmMagickDestroyCommandInfo #define MagickFindRawImageMinMax GmMagickFindRawImageMinMax +#define MagickFmax GmMagickFmax +#define MagickFmin GmMagickFmin #define MagickFormatString GmMagickFormatString #define MagickFormatStringList GmMagickFormatStringList #define MagickFree GmMagickFree #define MagickFreeAligned GmMagickFreeAligned -#define MagickFmin GmMagickFmin -#define MagickFmax GmMagickFmax #define MagickGetBitRevTable GmMagickGetBitRevTable +#define MagickGetFileAttributes GmMagickGetFileAttributes #define MagickGetFileSystemBlockSize GmMagickGetFileSystemBlockSize #define MagickGetMMUPageSize GmMagickGetMMUPageSize #define MagickGetQuantumSamplesPerPixel GmMagickGetQuantumSamplesPerPixel +#define MagickGetToken GmMagickGetToken #define MagickInitializeCommandInfo GmMagickInitializeCommandInfo #define MagickIsTrue GmMagickIsTrue #define MagickMalloc GmMagickMalloc @@ -582,6 +595,7 @@ #define MagickReverseBits GmMagickReverseBits #define MagickSceneFileName GmMagickSceneFileName #define MagickSetConfirmAccessHandler GmMagickSetConfirmAccessHandler +#define MagickSetFileAttributes GmMagickSetFileAttributes #define MagickSetFileSystemBlockSize GmMagickSetFileSystemBlockSize #define MagickSizeStrToInt64 GmMagickSizeStrToInt64 #define MagickSpawnVP GmMagickSpawnVP @@ -681,10 +695,12 @@ #define MagickXWindowByName GmMagickXWindowByName #define MagickXWindowByProperty GmMagickXWindowByProperty #define MagnifyImage GmMagnifyImage +#define MallocFunc GmMallocFunc #define MapBlob GmMapBlob #define MapImage GmMapImage #define MapImages GmMapImages #define MapModeToString GmMapModeToString +#define MatteColor GmMatteColor #define MatteFloodfillImage GmMatteFloodfillImage #define MedianFilterImage GmMedianFilterImage #define MetricTypeToString GmMetricTypeToString @@ -711,8 +727,12 @@ #define OpaqueImage GmOpaqueImage #define OpenBlob GmOpenBlob #define OpenCacheView GmOpenCacheView +#define OpenModule GmOpenModule +#define OpenModules GmOpenModules #define OrderedDitherImage GmOrderedDitherImage #define OrientationTypeToString GmOrientationTypeToString +#define PSDensityGeometry GmPSDensityGeometry +#define PSPageGeometry GmPSPageGeometry #define PackbitsEncode2Image GmPackbitsEncode2Image #define PackbitsEncodeImage GmPackbitsEncodeImage #define PanicDestroyMagick GmPanicDestroyMagick @@ -723,16 +743,14 @@ #define PixelIterateDualNew GmPixelIterateDualNew #define PixelIterateDualRead GmPixelIterateDualRead #define PixelIterateMonoModify GmPixelIterateMonoModify -#define PixelIterateMonoSet GmPixelIterateMonoSet #define PixelIterateMonoRead GmPixelIterateMonoRead +#define PixelIterateMonoSet GmPixelIterateMonoSet #define PixelIterateTripleModify GmPixelIterateTripleModify #define PixelIterateTripleNew GmPixelIterateTripleNew #define PlasmaImage GmPlasmaImage #define PopImagePixels GmPopImagePixels #define PrependImageToList GmPrependImageToList #define ProfileImage GmProfileImage -#define PSDensityGeometry GmPSDensityGeometry -#define PSPageGeometry GmPSPageGeometry #define PurgeTemporaryFiles GmPurgeTemporaryFiles #define PurgeTemporaryFilesAsyncSafe GmPurgeTemporaryFilesAsyncSafe #define PushImagePixels GmPushImagePixels @@ -762,6 +780,8 @@ #define ReadBlobLSBShort GmReadBlobLSBShort #define ReadBlobLSBShortFromBuffer GmReadBlobLSBShortFromBuffer #define ReadBlobLSBShorts GmReadBlobLSBShorts +#define ReadBlobLSBSignedLong GmReadBlobLSBSignedLong +#define ReadBlobLSBSignedShort GmReadBlobLSBSignedShort #define ReadBlobMSBDouble GmReadBlobMSBDouble #define ReadBlobMSBDoubles GmReadBlobMSBDoubles #define ReadBlobMSBFloat GmReadBlobMSBFloat @@ -770,16 +790,18 @@ #define ReadBlobMSBLongs GmReadBlobMSBLongs #define ReadBlobMSBShort GmReadBlobMSBShort #define ReadBlobMSBShorts GmReadBlobMSBShorts +#define ReadBlobMSBSignedLong GmReadBlobMSBSignedLong +#define ReadBlobMSBSignedShort GmReadBlobMSBSignedShort #define ReadBlobString GmReadBlobString #define ReadBlobZC GmReadBlobZC #define ReadImage GmReadImage #define ReadInlineImage GmReadInlineImage +#define ReallocFunc GmReallocFunc #define ReduceNoiseImage GmReduceNoiseImage #define ReferenceBlob GmReferenceBlob #define ReferenceCache GmReferenceCache #define ReferenceImage GmReferenceImage #define RegisterARTImage GmRegisterARTImage -#define RegisterAVIImage GmRegisterAVIImage #define RegisterAVSImage GmRegisterAVSImage #define RegisterBMPImage GmRegisterBMPImage #define RegisterCALSImage GmRegisterCALSImage @@ -866,6 +888,7 @@ #define RegisterVIDImage GmRegisterVIDImage #define RegisterVIFFImage GmRegisterVIFFImage #define RegisterWBMPImage GmRegisterWBMPImage +#define RegisterWEBPImage GmRegisterWEBPImage #define RegisterWMFImage GmRegisterWMFImage #define RegisterWPGImage GmRegisterWPGImage #define RegisterXBMImage GmRegisterXBMImage @@ -891,7 +914,6 @@ #define SampleImage GmSampleImage #define ScaleImage GmScaleImage #define SeekBlob GmSeekBlob -#define SegmentImage GmSegmentImage #define SetBlobClosable GmSetBlobClosable #define SetBlobTemporary GmSetBlobTemporary #define SetCacheView GmSetCacheView @@ -905,13 +927,14 @@ #define SetFatalErrorHandler GmSetFatalErrorHandler #define SetGeometry GmSetGeometry #define SetImage GmSetImage -#define SetImageEx GmSetImageEx #define SetImageAttribute GmSetImageAttribute #define SetImageChannelDepth GmSetImageChannelDepth #define SetImageClipMask GmSetImageClipMask #define SetImageColor GmSetImageColor #define SetImageColorRegion GmSetImageColorRegion +#define SetImageCompositeMask GmSetImageCompositeMask #define SetImageDepth GmSetImageDepth +#define SetImageEx GmSetImageEx #define SetImageInfo GmSetImageInfo #define SetImageOpacity GmSetImageOpacity #define SetImagePixels GmSetImagePixels @@ -921,7 +944,6 @@ #define SetImageVirtualPixelMethod GmSetImageVirtualPixelMethod #define SetLogEventMask GmSetLogEventMask #define SetLogFormat GmSetLogFormat -#define SetLogMethod GmSetLogMethod #define SetMagickInfo GmSetMagickInfo #define SetMagickRegistry GmSetMagickRegistry #define SetMagickResourceLimit GmSetMagickResourceLimit @@ -957,6 +979,7 @@ #define StringToList GmStringToList #define StringToMetricType GmStringToMetricType #define StringToNoiseType GmStringToNoiseType +#define StringToOrientationType GmStringToOrientationType #define StringToPreviewType GmStringToPreviewType #define StringToQuantumOperator GmStringToQuantumOperator #define StringToResolutionType GmStringToResolutionType @@ -993,7 +1016,6 @@ #define UnlockSemaphoreInfo GmUnlockSemaphoreInfo #define UnmapBlob GmUnmapBlob #define UnregisterARTImage GmUnregisterARTImage -#define UnregisterAVIImage GmUnregisterAVIImage #define UnregisterAVSImage GmUnregisterAVSImage #define UnregisterBMPImage GmUnregisterBMPImage #define UnregisterCALSImage GmUnregisterCALSImage @@ -1080,6 +1102,7 @@ #define UnregisterVIDImage GmUnregisterVIDImage #define UnregisterVIFFImage GmUnregisterVIFFImage #define UnregisterWBMPImage GmUnregisterWBMPImage +#define UnregisterWEBPImage GmUnregisterWEBPImage #define UnregisterWMFImage GmUnregisterWMFImage #define UnregisterWPGImage GmUnregisterWPGImage #define UnregisterXBMImage GmUnregisterXBMImage @@ -1099,8 +1122,12 @@ #define WriteBlobFile GmWriteBlobFile #define WriteBlobLSBLong GmWriteBlobLSBLong #define WriteBlobLSBShort GmWriteBlobLSBShort +#define WriteBlobLSBSignedLong GmWriteBlobLSBSignedLong +#define WriteBlobLSBSignedShort GmWriteBlobLSBSignedShort #define WriteBlobMSBLong GmWriteBlobMSBLong #define WriteBlobMSBShort GmWriteBlobMSBShort +#define WriteBlobMSBSignedLong GmWriteBlobMSBSignedLong +#define WriteBlobMSBSignedShort GmWriteBlobMSBSignedShort #define WriteBlobString GmWriteBlobString #define WriteBlobStringEOL GmWriteBlobStringEOL #define WriteBlobStringWithEOL GmWriteBlobStringWithEOL diff --git a/magick/tempfile.c b/magick/tempfile.c index 8ffd368..b4ef858 100644 --- a/magick/tempfile.c +++ b/magick/tempfile.c @@ -136,7 +136,7 @@ static void ComposeTemporaryFileName(char *name) for (c=name; *c; c++) { if (*c == 'X') - *c=SafeChars[MagickRandomInteger() % (sizeof(SafeChars)-1)]; + *c=SafeChars[MagickRandomInteger() % (sizeof(SafeChars)-1)]; } } @@ -312,10 +312,10 @@ MagickExport int AcquireTemporaryFileDescriptor(char *filename) { char tempname[16]; - + int tries=0; - + for (tries=0; tries < 256; tries++) { (void) strlcpy(tempname,"gmXXXXXX",sizeof(tempname)); diff --git a/magick/tempfile.h b/magick/tempfile.h index 4a8e386..c958cfe 100644 --- a/magick/tempfile.h +++ b/magick/tempfile.h @@ -1,10 +1,10 @@ /* Copyright (C) 2003, 2004 GraphicsMagick Group - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick Temporary File Management */ diff --git a/magick/texture.c b/magick/texture.c index e5f3298..7f5b56a 100644 --- a/magick/texture.c +++ b/magick/texture.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2009 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2003 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -67,6 +67,10 @@ MagickExport Image *ConstituteTextureImage(const unsigned long columns, MagickPassFail status=MagickPass; +#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) + int num_threads=Min(8,omp_get_max_threads()); +#endif /* defined(HAVE_OPENMP) */ + assert(texture_image != (Image *) NULL); assert(texture_image->signature == MagickSignature); @@ -75,18 +79,18 @@ MagickExport Image *ConstituteTextureImage(const unsigned long columns, return canvas_image; #if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) # if defined(TUNE_OPENMP) -# pragma omp parallel for schedule(runtime) shared(row_count, status) +# pragma omp parallel for if(num_threads > 1) num_threads(num_threads) schedule(runtime) shared(row_count, status) # else -# pragma omp parallel for schedule(static,16) shared(row_count, status) +# pragma omp parallel for if(num_threads > 1) num_threads(num_threads) schedule(guided) shared(row_count, status) # endif #endif for (y=0; y < (long) canvas_image->rows; y++) { const PixelPacket - *texture_pixels; + * restrict texture_pixels; PixelPacket - *canvas_pixels; + *restrict canvas_pixels; unsigned long x; @@ -94,9 +98,6 @@ MagickExport Image *ConstituteTextureImage(const unsigned long columns, MagickBool thread_status; -#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_ConstituteTextureImage) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -116,7 +117,7 @@ MagickExport Image *ConstituteTextureImage(const unsigned long columns, { const IndexPacket *texture_indexes=(const IndexPacket *) NULL; - + IndexPacket *canvas_indexes=(IndexPacket *) NULL;; @@ -147,20 +148,23 @@ MagickExport Image *ConstituteTextureImage(const unsigned long columns, if (!SyncImagePixelsEx(canvas_image,exception)) thread_status=MagickFail; } -#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_ConstituteTextureImage) +#if defined(HAVE_OPENMP) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,canvas_image->rows)) - if (!MagickMonitorFormatted(row_count,canvas_image->rows,exception, - ConstituteTextureImageText, - texture_image->filename)) - thread_status=MagickFail; + row_count++; + if (QuantumTick(row_count,canvas_image->rows)) + if (!MagickMonitorFormatted(row_count,canvas_image->rows,exception, + ConstituteTextureImageText, + texture_image->filename)) + thread_status=MagickFail; - if (thread_status == MagickFail) + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) +# pragma omp flush (status) +#endif + } } if (status == MagickFail) @@ -207,7 +211,7 @@ MagickExport Image *ConstituteTextureImage(const unsigned long columns, */ #define TextureImageText "[%s] Apply texture..." -MagickExport MagickPassFail TextureImage(Image *image,const Image *texture) +MagickExport MagickPassFail TextureImage(Image * restrict image,const Image * restrict texture) { MagickPassFail status=MagickPass; @@ -237,7 +241,7 @@ MagickExport MagickPassFail TextureImage(Image *image,const Image *texture) # if defined(TUNE_OPENMP) # pragma omp parallel for schedule(runtime) shared(row_count, status) # else -# pragma omp parallel for schedule(static,4) shared(row_count, status) +# pragma omp parallel for schedule(guided) shared(row_count, status) # endif #endif for (y=0; y < (long) image->rows; y++) @@ -252,10 +256,10 @@ MagickExport MagickPassFail TextureImage(Image *image,const Image *texture) z; register const PixelPacket - *p; + * restrict p; register PixelPacket - *q; + * restrict q; unsigned long width; @@ -263,9 +267,6 @@ MagickExport MagickPassFail TextureImage(Image *image,const Image *texture) MagickBool thread_status; -#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_TextureImage) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -322,18 +323,21 @@ MagickExport MagickPassFail TextureImage(Image *image,const Image *texture) thread_status=MagickFail; } #if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_TextureImage) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,image->rows)) - if (!MagickMonitorFormatted(row_count,image->rows,&image->exception, - TextureImageText,image->filename)) - thread_status=MagickFail; + row_count++; + if (QuantumTick(row_count,image->rows)) + if (!MagickMonitorFormatted(row_count,image->rows,&image->exception, + TextureImageText,image->filename)) + thread_status=MagickFail; - if (thread_status == MagickFail) + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) +# pragma omp flush (status) +#endif + } } if (image->matte) diff --git a/magick/texture.h b/magick/texture.h index 804c517..050a481 100644 --- a/magick/texture.h +++ b/magick/texture.h @@ -2,11 +2,11 @@ Copyright (C) 2003 - 2009 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick Texture Methods. */ #ifndef _MAGICK_TEXTURE_H @@ -24,7 +24,7 @@ extern "C" { extern MagickExport Image *ConstituteTextureImage(const unsigned long columns,const unsigned long rows, - const Image *texture,ExceptionInfo *exception); + const Image *texture,ExceptionInfo *exception); extern MagickExport MagickPassFail TextureImage(Image *,const Image *); diff --git a/magick/timer.h b/magick/timer.h index 3dd42c2..1ed1d20 100644 --- a/magick/timer.h +++ b/magick/timer.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + ImageMagick Timer Methods. */ #ifndef _MAGICK_TIMER_H diff --git a/magick/transform.c b/magick/transform.c index 04d1c20..b18d5b6 100644 --- a/magick/transform.c +++ b/magick/transform.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2015 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -148,25 +148,22 @@ MagickExport Image *ChopImage(const Image *image,const RectangleInfo *chop_info, { register const PixelPacket *p; - + register const IndexPacket *indexes; - + register IndexPacket *chop_indexes; - + register long x; - + register PixelPacket *q; MagickBool thread_status; -#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_ChopImage) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -196,18 +193,21 @@ MagickExport Image *ChopImage(const Image *image,const RectangleInfo *chop_info, thread_status=MagickFail; } #if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_ChopImage) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,chop_image->rows)) - if (!MagickMonitorFormatted(row_count,chop_image->rows,exception, - ChopImageText,image->filename)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,chop_image->rows)) + if (!MagickMonitorFormatted(row_count,chop_image->rows,exception, + ChopImageText,image->filename)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) +# pragma omp flush (status) +#endif + } } /* Extract chop image. @@ -223,25 +223,22 @@ MagickExport Image *ChopImage(const Image *image,const RectangleInfo *chop_info, { register const PixelPacket *p; - + register const IndexPacket *indexes; - + register IndexPacket *chop_indexes; - + register long x; - + register PixelPacket *q; MagickBool thread_status; -#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_ChopImage) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -271,18 +268,21 @@ MagickExport Image *ChopImage(const Image *image,const RectangleInfo *chop_info, thread_status=MagickFail; } #if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_ChopImage) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,chop_image->rows)) - if (!MagickMonitorFormatted(row_count,chop_image->rows,exception, - ChopImageText,image->filename)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,chop_image->rows)) + if (!MagickMonitorFormatted(row_count,chop_image->rows,exception, + ChopImageText,image->filename)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) +# pragma omp flush (status) +#endif + } } if (row_count < chop_image->rows) { @@ -333,7 +333,7 @@ MagickExport Image *CoalesceImages(const Image *image,ExceptionInfo *exception) register long i; - + MagickBool found_transparency=False; @@ -373,8 +373,8 @@ MagickExport Image *CoalesceImages(const Image *image,ExceptionInfo *exception) case BackgroundDispose: { /* - Fill image with transparent color, if one exists. - */ + Fill image with transparent color, if one exists. + */ coalesce_image->next=CloneImage(coalesce_image,0,0,True,exception); if (coalesce_image->next != (Image *) NULL) { for (i = 0; i < (long) coalesce_image->colors; i++) { @@ -560,9 +560,6 @@ MagickExport Image *CropImage(const Image *image,const RectangleInfo *geometry, MagickBool thread_status; -#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_CropImage) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -585,21 +582,24 @@ MagickExport Image *CropImage(const Image *image,const RectangleInfo *geometry, thread_status=MagickFail; } #if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_CropImage) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,crop_image->rows)) - if (!MagickMonitorFormatted(row_count,crop_image->rows,exception, - "[%s] Crop: %lux%lu+%ld+%ld...", - crop_image->filename, - crop_image->columns,crop_image->rows, - page.x,page.y)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,crop_image->rows)) + if (!MagickMonitorFormatted(row_count,crop_image->rows,exception, + "[%s] Crop: %lux%lu+%ld+%ld...", + crop_image->filename, + crop_image->columns,crop_image->rows, + page.x,page.y)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) +# pragma omp flush (status) +#endif + } } if (row_count < crop_image->rows) { @@ -838,7 +838,7 @@ MagickExport Image *DeconstructImages(const Image *image, % */ MagickExport Image *ExtentImage(const Image *image,const RectangleInfo *geometry, - ExceptionInfo *exception) + ExceptionInfo *exception) { Image *extent_image; @@ -853,7 +853,7 @@ MagickExport Image *ExtentImage(const Image *image,const RectangleInfo *geometry Allocate canvas image */ if ((extent_image=CloneImage(image,geometry->width,geometry->height, - MagickTrue,exception)) == (Image *) NULL) + MagickTrue,exception)) == (Image *) NULL) return((Image *) NULL); /* @@ -871,7 +871,7 @@ MagickExport Image *ExtentImage(const Image *image,const RectangleInfo *geometry operator. */ if ((CompositeImage(extent_image,image->compose,image,geometry->x, - geometry->y)) == MagickFail) + geometry->y)) == MagickFail) { CopyException(exception,&extent_image->exception); DestroyImage(extent_image); @@ -932,18 +932,18 @@ MagickExport Image *FlattenImages(const Image *image,ExceptionInfo *exception) */ if ((flatten_image != (Image *) NULL) && (flatten_image->matte)) (void) MagickCompositeImageUnderColor(flatten_image, - &flatten_image->background_color, - exception); + &flatten_image->background_color, + exception); if ((flatten_image != (Image *) NULL) && (image->next != (Image *) NULL)) { /* - Flatten remaining images onto canvas + Flatten remaining images onto canvas */ for (next=image->next; next != (Image *) NULL; next=next->next) - (void) CompositeImage(flatten_image,next->compose,next,next->page.x, - next->page.y); + (void) CompositeImage(flatten_image,next->compose,next,next->page.x, + next->page.y); } return(flatten_image); } @@ -1036,9 +1036,6 @@ MagickExport Image *FlipImage(const Image *image,ExceptionInfo *exception) MagickBool thread_status; -#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_FlipImage) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -1061,18 +1058,21 @@ MagickExport Image *FlipImage(const Image *image,ExceptionInfo *exception) thread_status=MagickFail; } #if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_FlipImage) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,flip_image->rows)) - if (!MagickMonitorFormatted(row_count,flip_image->rows,exception, - FlipImageText,image->filename)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,flip_image->rows)) + if (!MagickMonitorFormatted(row_count,flip_image->rows,exception, + FlipImageText,image->filename)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) +# pragma omp flush (status) +#endif + } } if (row_count < flip_image->rows) { @@ -1165,9 +1165,6 @@ MagickExport Image *FlopImage(const Image *image,ExceptionInfo *exception) MagickBool thread_status; -#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_FlopImage) -#endif thread_status=status; if (thread_status == MagickFail) continue; @@ -1195,18 +1192,21 @@ MagickExport Image *FlopImage(const Image *image,ExceptionInfo *exception) thread_status=MagickFail; } #if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) -# pragma omp critical (GM_FlopImage) +# pragma omp atomic #endif - { - row_count++; - if (QuantumTick(row_count,flop_image->rows)) - if (!MagickMonitorFormatted(row_count,flop_image->rows,exception, - FlopImageText,image->filename)) - thread_status=MagickFail; - - if (thread_status == MagickFail) + row_count++; + if (QuantumTick(row_count,flop_image->rows)) + if (!MagickMonitorFormatted(row_count,flop_image->rows,exception, + FlopImageText,image->filename)) + thread_status=MagickFail; + + if (thread_status == MagickFail) + { status=MagickFail; - } +#if defined(HAVE_OPENMP) && !defined(DisableSlowOpenMP) +# pragma omp flush (status) +#endif + } } if (row_count < flop_image->rows) { @@ -1330,11 +1330,16 @@ MagickExport Image *MosaicImages(const Image *image,ExceptionInfo *exception) MagickPassFail status; + size_t + image_list_length; + assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); + image_list_length=GetImageListLength(image); + /* Determine mosaic bounding box. */ @@ -1374,7 +1379,7 @@ MagickExport Image *MosaicImages(const Image *image,ExceptionInfo *exception) { (void) CompositeImage(mosaic_image,next->compose,next,next->page.x, next->page.y); - status=MagickMonitorFormatted(scene++,GetImageListLength(image), + status=MagickMonitorFormatted(scene++,image_list_length, exception,MosaicImageText,image->filename); if (status == MagickFail) break; @@ -1530,7 +1535,7 @@ MagickExport Image *ShaveImage(const Image *image, % T r a n s f o r m I m a g e % % % % % -% % +% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % TransformImage() is a convenience method that behaves like ResizeImage() or @@ -1556,7 +1561,7 @@ MagickExport Image *ShaveImage(const Image *image, % */ MagickExport void TransformImage(Image **image,const char *crop_geometry, - const char *image_geometry) + const char *image_geometry) { Image *previous, @@ -1585,9 +1590,9 @@ MagickExport void TransformImage(Image **image,const char *crop_geometry, if ((geometry.width == 0) || (geometry.height == 0) || ((flags & XValue) != 0) || ((flags & YValue) != 0) || (flags & PercentValue)) - { - crop_image=CropImage(transform_image,&geometry,&(*image)->exception); - } + { + crop_image=CropImage(transform_image,&geometry,&(*image)->exception); + } else if ((transform_image->columns > geometry.width) || (transform_image->rows > geometry.height)) @@ -1610,38 +1615,38 @@ MagickExport void TransformImage(Image **image,const char *crop_geometry, height=geometry.height; next=(Image *) NULL; for (y=0; y < (long) transform_image->rows; y+=height) - { - for (x=0; x < (long) transform_image->columns; x+=width) - { - geometry.width=width; - geometry.height=height; - geometry.x=x; - geometry.y=y; - next=CropImage(transform_image,&geometry,&(*image)->exception); - if (next == (Image *) NULL) - break; - if (crop_image == (Image *) NULL) - crop_image=next; - else - { - next->previous=crop_image; - crop_image->next=next; - crop_image=crop_image->next; - } - } - if (next == (Image *) NULL) - break; - } + { + for (x=0; x < (long) transform_image->columns; x+=width) + { + geometry.width=width; + geometry.height=height; + geometry.x=x; + geometry.y=y; + next=CropImage(transform_image,&geometry,&(*image)->exception); + if (next == (Image *) NULL) + break; + if (crop_image == (Image *) NULL) + crop_image=next; + else + { + next->previous=crop_image; + crop_image->next=next; + crop_image=crop_image->next; + } + } + if (next == (Image *) NULL) + break; + } } if (crop_image != (Image *) NULL) { - previous=transform_image->previous; - crop_image->next=transform_image->next; + previous=transform_image->previous; + crop_image->next=transform_image->next; DestroyImage(transform_image); - transform_image=(Image *) NULL; + transform_image=(Image *) NULL; while (crop_image->previous != (Image *) NULL) crop_image=crop_image->previous; - crop_image->previous=previous; + crop_image->previous=previous; transform_image=crop_image; } *image=transform_image; @@ -1654,16 +1659,16 @@ MagickExport void TransformImage(Image **image,const char *crop_geometry, */ SetGeometry(transform_image,&geometry); flags=GetMagickGeometry(image_geometry,&geometry.x,&geometry.y, - &geometry.width,&geometry.height); + &geometry.width,&geometry.height); if ((transform_image->columns == geometry.width) && (transform_image->rows == geometry.height)) return; - + /* Resize image. */ resize_image=ZoomImage(transform_image,geometry.width,geometry.height, - &(*image)->exception); + &(*image)->exception); if (resize_image == (Image *) NULL) return; diff --git a/magick/transform.h b/magick/transform.h index a7f477f..812f01d 100644 --- a/magick/transform.h +++ b/magick/transform.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003 - 2010 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + ImageMagick Image Transform Methods. */ #ifndef _MAGICK_TRANSFORM_H diff --git a/magick/tsd.c b/magick/tsd.c index 24ed438..773ac89 100644 --- a/magick/tsd.c +++ b/magick/tsd.c @@ -1,6 +1,6 @@ /* Copyright (C) 2005,2013,2014 GraphicsMagick Group - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. diff --git a/magick/tsd.h b/magick/tsd.h index 559fccf..e8a08d0 100644 --- a/magick/tsd.h +++ b/magick/tsd.h @@ -1,6 +1,6 @@ /* Copyright (C) 2005,2012 GraphicsMagick Group - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. diff --git a/magick/type.h b/magick/type.h index 4cbaa77..b55ee94 100644 --- a/magick/type.h +++ b/magick/type.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003 - 2009 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + Drawing methods. */ #ifndef _MAGICK_TYPE_H diff --git a/magick/unix_port.c b/magick/unix_port.c index 68c582b..aa533ee 100644 --- a/magick/unix_port.c +++ b/magick/unix_port.c @@ -78,10 +78,10 @@ MagickExport long MagickGetMMUPageSize(void) #endif /* defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) */ #if defined(HAVE_GETPAGESIZE) if (pagesize <= 0) - pagesize=getpagesize(); + pagesize=getpagesize(); #endif /* defined(HAVE_GETPAGESIZE) */ if (pagesize <= 0) - pagesize=16384; + pagesize=16384; } return pagesize; diff --git a/magick/unix_port.h b/magick/unix_port.h index e65ff4e..82842f8 100644 --- a/magick/unix_port.h +++ b/magick/unix_port.h @@ -1,12 +1,12 @@ /* Copyright (C) 2007-2016 GraphicsMagick Group - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. Interfaces specific to Unix. - + */ #ifndef _UNIX_PORT_H #define _UNIX_PORT_H diff --git a/magick/utility.c b/magick/utility.c index 7f18dff..16992ab 100644 --- a/magick/utility.c +++ b/magick/utility.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003 - 2016 GraphicsMagick Group +% Copyright (C) 2003 - 2018 GraphicsMagick Group % Copyright (c) 2000 Markus Friedl. All rights reserved. % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company @@ -61,24 +61,6 @@ #endif /* - Compute a value which is the next kilobyte power of 2 larger than - the requested value or MaxTextExtent, whichever is larger. - - The objective is to round up the size quickly (and in repeatable - steps) in order to reduce the number of memory copies due to realloc - for strings which grow rapidly, while producing a reasonable size - for smaller strings. -*/ -#define MagickRoundUpStringLength(size) \ -{ \ - size_t \ - _rounded; \ - \ - for (_rounded=256U; _rounded < (Max(size,256)); _rounded *= 2); \ - size=_rounded; \ -} - -/* Static declarations. */ static const char @@ -935,104 +917,104 @@ MagickExport MagickPassFail ExpandFilenames(int *argc,char ***argv) for (i=0; i < *argc; i++) { char - **filelist, - filename[MaxTextExtent], - magick[MaxTextExtent], - path[MaxTextExtent], - subimage[MaxTextExtent]; + **filelist, + filename[MaxTextExtent], + magick[MaxTextExtent], + path[MaxTextExtent], + subimage[MaxTextExtent]; option=(*argv)[i]; /* Never throw options away, so copy here, then perhaps modify later */ vector[count++]=AcquireString(option); /* - Don't expand or process any VID: argument since the VID coder - does its own expansion + Don't expand or process any VID: argument since the VID coder + does its own expansion */ if (LocaleNCompare("VID:",option,4) == 0) - continue; + continue; /* - Don't attempt to expand the argument to these options. + Don't attempt to expand the argument to these options. */ if ((LocaleNCompare("+define",option,7) == 0) || - (LocaleNCompare("+profile",option,8) == 0) || - (LocaleNCompare("-comment",option,8) == 0) || - (LocaleNCompare("-convolve",option,9) == 0) || - (LocaleNCompare("-draw",option,5) == 0) || - (LocaleNCompare("-font",option,5) == 0) || - (LocaleNCompare("-format",option,7) == 0) || - (LocaleNCompare("-label",option,6) == 0)) - { - i++; - if (i == *argc) + (LocaleNCompare("+profile",option,8) == 0) || + (LocaleNCompare("-comment",option,8) == 0) || + (LocaleNCompare("-convolve",option,9) == 0) || + (LocaleNCompare("-draw",option,5) == 0) || + (LocaleNCompare("-font",option,5) == 0) || + (LocaleNCompare("-format",option,7) == 0) || + (LocaleNCompare("-label",option,6) == 0)) + { + i++; + if (i == *argc) continue; - option=(*argv)[i]; - vector[count++]=AcquireString(option); - continue; - } + option=(*argv)[i]; + vector[count++]=AcquireString(option); + continue; + } /* Pass quotes through to the command-line parser */ if ((*option == '"') || (*option == '\'')) - continue; + continue; /* - Expand @filename to a list of arguments. + Expand @filename to a list of arguments. */ j=0; if (option[0] == '@') - { - FILE - *file; - - file=fopen(option+1,"r"); - if (file != (FILE *) NULL) - { - - first=MagickTrue; - number_files=0; - while (fgets(filename,sizeof(filename),file) != (char *) NULL) - { - for (j=0; filename[j] != '\0'; j++) - if (filename[j] == '\n') - filename[j] = '\0'; - - if (filename[0] != '\0') - { - if ((number_files % prealloc_entries) == 0) - { - MagickReallocMemory(char **,vector, - (*argc+count+prealloc_entries)* - sizeof(char *)); - if (vector == (char **) NULL) - { - fclose(file); - return(MagickFail); - } - } - - if (first) - { - /* Deallocate original option assigned above */ - --count; - MagickFreeMemory(vector[count]); - first=MagickFalse; - } - number_files++; - vector[count++]=AcquireString(filename); - } - } - - fclose(file); - } - } - - /* - Fast cycle options that are not expandable filename patterns. - ListFiles only expands patterns in the filename. We also check - if the full option resolves to a file since ListFiles() obtains - a list of all the files in the directory and is thus very slow - if there are thousands of files. + { + FILE + *file; + + file=fopen(option+1,"r"); + if (file != (FILE *) NULL) + { + + first=MagickTrue; + number_files=0; + while (fgets(filename,sizeof(filename),file) != (char *) NULL) + { + for (j=0; filename[j] != '\0'; j++) + if (filename[j] == '\n') + filename[j] = '\0'; + + if (filename[0] != '\0') + { + if ((number_files % prealloc_entries) == 0) + { + MagickReallocMemory(char **,vector, + (*argc+count+prealloc_entries)* + sizeof(char *)); + if (vector == (char **) NULL) + { + fclose(file); + return(MagickFail); + } + } + + if (first) + { + /* Deallocate original option assigned above */ + --count; + MagickFreeMemory(vector[count]); + first=MagickFalse; + } + number_files++; + vector[count++]=AcquireString(filename); + } + } + + fclose(file); + } + } + + /* + Fast cycle options that are not expandable filename patterns. + ListFiles only expands patterns in the filename. We also check + if the full option resolves to a file since ListFiles() obtains + a list of all the files in the directory and is thus very slow + if there are thousands of files. */ GetPathComponent(option,TailPath,filename); if ((!IsGlob(filename)) || IsAccessibleNoLogging(option)) @@ -1045,110 +1027,110 @@ MagickExport MagickPassFail ExpandFilenames(int *argc,char ***argv) /* GetPathComponent throws away the colon */ if (*magick != '\0') - (void) strlcat(magick,":",sizeof(magick)); + (void) strlcat(magick,":",sizeof(magick)); ExpandFilename(path); if ('\0' == current_directory[0]) - if (getcwd(current_directory,MaxTextExtent-1) == NULL) + if (getcwd(current_directory,MaxTextExtent-1) == NULL) MagickFatalError(ConfigureFatalError,UnableToGetCurrentDirectory, NULL); /* Get the list of matching file names. */ filelist=ListFiles(*path=='\0' ? current_directory : path, - filename,&number_files); + filename,&number_files); if (filelist != (char **) NULL) - for (j=0; j < number_files; j++) - if (IsDirectory(filelist[j]) <= 0) - break; + for (j=0; j < number_files; j++) + if (IsDirectory(filelist[j]) <= 0) + break; /* ListFiles() may change current directory without restoring. */ if ((strlen(current_directory) > 0) && (chdir(current_directory) != 0)) { for (j=0; j < number_files; j++) - MagickFreeMemory(filelist[j]); + MagickFreeMemory(filelist[j]); MagickFreeMemory(filelist); MagickFatalError(ConfigureFatalError,UnableToRestoreCurrentDirectory, NULL); } if (filelist == 0) - continue; + continue; if (j == number_files) - { - /* - Bourne/Bash shells passes through unchanged any glob patterns - not matching anything (abc* and there's no file starting with - abc). Do the same for behaviour consistent with that. - */ - for (j=0; j < number_files; j++) - MagickFreeMemory(filelist[j]); - MagickFreeMemory(filelist); - continue; - } + { + /* + Bourne/Bash shells passes through unchanged any glob patterns + not matching anything (abc* and there's no file starting with + abc). Do the same for behaviour consistent with that. + */ + for (j=0; j < number_files; j++) + MagickFreeMemory(filelist[j]); + MagickFreeMemory(filelist); + continue; + } /* - There's at least one matching filename. - Transfer file list to argument vector. + There's at least one matching filename. + Transfer file list to argument vector. */ MagickReallocMemory(char **,vector, - (*argc+count+number_files+prealloc_entries)*sizeof(char *)); + (*argc+count+number_files+prealloc_entries)*sizeof(char *)); if (vector == (char **) NULL) - return(MagickFail); + return(MagickFail); first=MagickTrue; for (j=0; j < number_files; j++) - { - char - filename_buffer[MaxTextExtent]; - - *filename_buffer='\0'; - if (strlcat(filename_buffer,path,sizeof(filename_buffer)) - >= sizeof(filename_buffer)) - MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", - filename_buffer); - if (*path != '\0') - { - if (strlcat(filename_buffer,DirectorySeparator,sizeof(filename_buffer)) - >= sizeof(filename_buffer)) - MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", - filename_buffer); - } - if (strlcat(filename_buffer,filelist[j],sizeof(filename_buffer)) - >= sizeof(filename_buffer)) - MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", - filename_buffer); - /* If it's a filename (not a directory) ... */ - if (IsDirectory(filename_buffer) == 0) - { - char - formatted_buffer[MaxTextExtent]; - - *formatted_buffer='\0'; - if (strlcat(formatted_buffer,magick,sizeof(formatted_buffer)) - >= sizeof(formatted_buffer)) - MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", - formatted_buffer); - if (strlcat(formatted_buffer,filename_buffer,sizeof(formatted_buffer)) - >= sizeof(formatted_buffer)) - MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", - formatted_buffer); - if (strlcat(formatted_buffer,subimage,sizeof(formatted_buffer)) - >= sizeof(formatted_buffer)) - MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", - formatted_buffer); - if (first) - { - /* Deallocate original option assigned above */ - --count; - MagickFreeMemory(vector[count]); - first=MagickFalse; - } - vector[count++]=AcquireString(formatted_buffer); - } - MagickFreeMemory(filelist[j]); - } + { + char + filename_buffer[MaxTextExtent]; + + *filename_buffer='\0'; + if (strlcat(filename_buffer,path,sizeof(filename_buffer)) + >= sizeof(filename_buffer)) + MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", + filename_buffer); + if (*path != '\0') + { + if (strlcat(filename_buffer,DirectorySeparator,sizeof(filename_buffer)) + >= sizeof(filename_buffer)) + MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", + filename_buffer); + } + if (strlcat(filename_buffer,filelist[j],sizeof(filename_buffer)) + >= sizeof(filename_buffer)) + MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", + filename_buffer); + /* If it's a filename (not a directory) ... */ + if (IsDirectory(filename_buffer) == 0) + { + char + formatted_buffer[MaxTextExtent]; + + *formatted_buffer='\0'; + if (strlcat(formatted_buffer,magick,sizeof(formatted_buffer)) + >= sizeof(formatted_buffer)) + MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", + formatted_buffer); + if (strlcat(formatted_buffer,filename_buffer,sizeof(formatted_buffer)) + >= sizeof(formatted_buffer)) + MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", + formatted_buffer); + if (strlcat(formatted_buffer,subimage,sizeof(formatted_buffer)) + >= sizeof(formatted_buffer)) + MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow", + formatted_buffer); + if (first) + { + /* Deallocate original option assigned above */ + --count; + MagickFreeMemory(vector[count]); + first=MagickFalse; + } + vector[count++]=AcquireString(formatted_buffer); + } + MagickFreeMemory(filelist[j]); + } MagickFreeMemory(filelist); } *argc=count; @@ -1239,7 +1221,7 @@ MagickExport void FormatSize(const magick_int64_t size,char *format) % % */ -MagickExport void FormatStringList(char *string,const char *format, +MagickExport void FormatStringList(char *string,const char *format, va_list operands) { #if defined(HAVE_VSNPRINTF) @@ -1334,7 +1316,7 @@ MagickExport MagickPassFail GetExecutionPath(char *path) char executable_path[PATH_MAX*2], real_path[PATH_MAX+1]; - + bufsize=sizeof(executable_path); if (_NSGetExecutablePath(executable_path,&bufsize) == 0) if (realpath(executable_path,real_path) != NULL) @@ -1357,7 +1339,7 @@ MagickExport MagickPassFail GetExecutionPath(char *path) long pid; - char + char link_path[MaxTextExtent], real_path[PATH_MAX+1]; @@ -1476,16 +1458,16 @@ MagickExport MagickPassFail GetExecutionPathUsingName(char *path) const char *end = NULL, *start = search_path; - + end=start+strlen(start); while ( start < end ) { const char *separator; - + int length; - + separator = strchr(start,DirectoryListSeparator); if (separator) length=separator-start; @@ -1850,9 +1832,9 @@ static int MagickStrToD(const char *start,char **end,double *value) int i, n=0; - + p=start; - + for (i=0; (*p != 0) && (*p != 'x') && (*p != ',') && (i < MaxTextExtent-2); i++) buff[i]=*p++; buff[i]=0; @@ -2450,7 +2432,7 @@ MagickExport void GetPathComponent(const char *path,PathType type, /* first locate the spot were the filename begins */ for (p=component+strlen(component); p > component; p--) - if (IsBasenameSeparator(*p)) + if (IsBasenameSeparator(*p)) /* Is directory delimiter like '/' or '\\' */ break; switch (type) @@ -2608,7 +2590,7 @@ MagickExport void GetToken(const char *start,char **end,char *token) % if the specification may be a subimage specification. If the pattern is % ultimately determined to be a subimage specification, then globbing is % not performed. -% +% % % The format of the GlobExpression function is: % @@ -3495,34 +3477,73 @@ MagickExport void LocaleUpper(char *string) MagickExport MagickPassFail MagickAtoFChk(const char *str, double *value) { + MagickPassFail status = MagickPass; char *estr=0; *value=strtod(str,&estr); if (str == estr) - *value=0.0; - return (str == estr ? MagickFail : MagickPass); + { + *value=0.0; + status=MagickFail; + } +#if defined(INFINITY) + else if ((*value == +INFINITY) || (*value == -INFINITY)) + { + *value=0.0; + status=MagickFail; + errno=ERANGE; + } +#endif + else if (isnan(*value)) + { + *value=0.0; + status=MagickFail; + errno=ERANGE; + } + return status; } MagickExport MagickPassFail MagickAtoIChk(const char *str, int *value) { + MagickPassFail status = MagickPass; char *estr=0; long lvalue; lvalue=strtol(str,&estr, 10); - if ((str == estr) || ((int) lvalue != lvalue)) - lvalue=0; + if (str == estr) + { + lvalue=0; + status=MagickFail; + errno=EINVAL; + } + else if ((int) lvalue != lvalue) + { + lvalue=0; + status=MagickFail; + errno=ERANGE; + } *value=(int) lvalue; - return (str == estr ? MagickFail : MagickPass); + return status; } MagickExport MagickPassFail MagickAtoUIChk(const char *str, unsigned int *value) { + MagickPassFail status = MagickPass; char *estr=0; long lvalue; lvalue=strtol(str,&estr, 10); - if ((str == estr) || ((long) ((unsigned int) lvalue) != lvalue)) - lvalue=0U; + if (str == estr) + { + lvalue=0U; + status=MagickFail; + errno=EINVAL; + } + else if ((long) ((unsigned int) lvalue) != lvalue) + { + lvalue=0U; + status=MagickFail; + errno=ERANGE; + } *value=(unsigned int) lvalue; - return (((str == estr) || ((long) ((unsigned int) lvalue) != lvalue)) - ? MagickFail : MagickPass); + return status; } MagickExport MagickPassFail MagickAtoLChk(const char *str, long *value) @@ -3536,14 +3557,24 @@ MagickExport MagickPassFail MagickAtoLChk(const char *str, long *value) MagickExport MagickPassFail MagickAtoULChk(const char *str, unsigned long *value) { + MagickPassFail status = MagickPass; char *estr=0; long lvalue; lvalue=strtol(str,&estr, 10); - if ((str == estr) || ((long) ((unsigned long) lvalue) != lvalue)) - lvalue=0L; + if (str == estr) + { + lvalue=0L; + status=MagickFail; + errno=EINVAL; + } + else if ((long) ((unsigned long) lvalue) != lvalue) + { + lvalue=0L; + status=MagickFail; + errno=ERANGE; + } *value=(unsigned long) lvalue; - return (((str == estr) || ((long) ((unsigned long) lvalue) != lvalue)) ? - MagickFail : MagickPass); + return status; } /* @@ -3648,7 +3679,7 @@ double MagickFmax(const double x, const double y) */ MagickExport void MagickFormatStringList(char *string, const size_t length, - const char *format, + const char *format, va_list operands) { #if defined(HAVE_VSNPRINTF) @@ -3827,7 +3858,7 @@ MagickExport size_t MagickGetToken(const char *start,char **end,char *token, ((r = strrchr(token,')')) != NULL)) { *r='\0'; - (void) memmove(token,token+5,r-token+1); + (void) memmove(token,token+5,r-token-4); } } if (end != (char **) NULL) @@ -4029,14 +4060,14 @@ MagickSpawnVP(const unsigned int verbose,const char *file, char *const argv[]) */ ExceptionInfo exception; - + GetExceptionInfo(&exception); if (MagickConfirmAccess(FileExecuteConfirmAccessMode,argv[0],&exception) - == MagickFail) + == MagickFail) { - errno=EPERM; - DestroyExceptionInfo(&exception); - return -1; + errno=EPERM; + DestroyExceptionInfo(&exception); + return -1; } } @@ -4053,47 +4084,47 @@ MagickSpawnVP(const unsigned int verbose,const char *file, char *const argv[]) child_pid = fork( ); if ( (pid_t)-1 == child_pid) { - /* Failed to fork, errno contains reason */ - status = -1; - FormatString(message,"fork failed: %.1024s", strerror(errno)); + /* Failed to fork, errno contains reason */ + status = -1; + FormatString(message,"fork failed: %.1024s", strerror(errno)); } else if ( 0 == child_pid ) { - /* We are the child process, exec program with arguments. */ - status = execvp(file, argv); + /* We are the child process, exec program with arguments. */ + status = execvp(file, argv); - /* If we get here, then execvp must have failed. */ - (void) fprintf(stderr, "execvp failed, errno = %d (%s)\n",errno,strerror(errno)); + /* If we get here, then execvp must have failed. */ + (void) fprintf(stderr, "execvp failed, errno = %d (%s)\n",errno,strerror(errno)); - /* If there is an execvp error, then call _exit() */ - _exit(1); + /* If there is an execvp error, then call _exit() */ + _exit(1); } else { - /* We are the parent process, wait for child. */ - pid_t waitpid_status; - int child_status = 0; - waitpid_status = waitpid(child_pid, &child_status, 0); - if ( (pid_t)-1 == waitpid_status ) - { - /* Waitpid error */ - status = -1; - FormatString(message, "waitpid failed: %.1024s", strerror(errno)); - } - else if ( waitpid_status == child_pid ) - { - /* Status is available for child process */ - if ( WIFEXITED( child_status ) ) - { - status = WEXITSTATUS( child_status ); - } - else if ( WIFSIGNALED( child_status ) ) - { - int sig_num = WTERMSIG( child_status ); - status = -1; - FormatString(message, "child process quit due to signal %d", sig_num); - } - } + /* We are the parent process, wait for child. */ + pid_t waitpid_status; + int child_status = 0; + waitpid_status = waitpid(child_pid, &child_status, 0); + if ( (pid_t)-1 == waitpid_status ) + { + /* Waitpid error */ + status = -1; + FormatString(message, "waitpid failed: %.1024s", strerror(errno)); + } + else if ( waitpid_status == child_pid ) + { + /* Status is available for child process */ + if ( WIFEXITED( child_status ) ) + { + status = WEXITSTATUS( child_status ); + } + else if ( WIFSIGNALED( child_status ) ) + { + int sig_num = WTERMSIG( child_status ); + status = -1; + FormatString(message, "child process quit due to signal %d", sig_num); + } + } } } #endif @@ -4105,29 +4136,29 @@ MagickSpawnVP(const unsigned int verbose,const char *file, char *const argv[]) if (verbose || (status != 0)) { const char - *message_p = (const char *) NULL; + *message_p = (const char *) NULL; char - *command; + *command; unsigned int - i; + i; command = AllocateString((const char*) NULL); for (i = 0; argv[i] != (const char*) NULL; i++) - { - char - buffer[MaxTextExtent]; + { + char + buffer[MaxTextExtent]; - FormatString(buffer,"\"%.1024s\"", argv[i]); + FormatString(buffer,"\"%.1024s\"", argv[i]); - if (0 != i) - (void) ConcatenateString(&command," "); + if (0 != i) + (void) ConcatenateString(&command," "); - (void) ConcatenateString(&command,buffer); - } + (void) ConcatenateString(&command,buffer); + } if (message[0] != '\0') - message_p = message; + message_p = message; MagickError2(DelegateError,command,message_p); MagickFreeMemory(command); } @@ -4483,13 +4514,13 @@ MagickExport size_t MagickStrlCat(char *dst, const char *src, const size_t size) if (size >= 1) { char - *p; + *p; for ( p = dst + length ; - (*q != 0) && (length < size - 1) ; - length++, p++, q++ ) - *p = *q; - + (*q != 0) && (length < size - 1) ; + length++, p++, q++ ) + *p = *q; + dst[length]='\0'; } @@ -4563,13 +4594,13 @@ MagickExport size_t MagickStrlCpy(char *dst, const char *src, const size_t size) if (size >= 1) { char - *p; + *p; for ( p=dst ; - (*q != 0) && (length < size-1) ; - length++, p++, q++ ) - *p = *q; - + (*q != 0) && (length < size-1) ; + length++, p++, q++ ) + *p = *q; + dst[length]='\0'; } @@ -4632,13 +4663,13 @@ MagickExport size_t MagickStrlCpyTrunc(char *dst, const char *src, const size_t if (size >= 1) { char - *p; + *p; for ( p=dst, q=src; - (*q != 0) && (length < size-1) ; - length++, p++, q++ ) - *p = *q; - + (*q != 0) && (length < size-1) ; + length++, p++, q++ ) + *p = *q; + dst[length]='\0'; } @@ -5058,7 +5089,7 @@ MagickExport char **StringToList(const char *text) register const char *p; - register long + register size_t i; size_t @@ -5078,26 +5109,21 @@ MagickExport char **StringToList(const char *text) for (p=text; *p != '\0'; p++) if (*p == '\n') lines++; - textlist=MagickAllocateMemory(char **,(lines+MaxTextExtent)*sizeof(char *)); + textlist=MagickAllocateMemory(char **,(lines+1)*sizeof(char *)); if (textlist == (char **) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, UnableToConvertText); p=text; - for (i=0; i < (long) lines; i++) + for (i=0; i < lines; i++) { for (q=(char *) p; *q != '\0'; q++) if ((*q == '\r') || (*q == '\n')) break; - textlist[i]=MagickAllocateMemory(char *,(size_t) (q-p+MaxTextExtent)); + textlist[i]=MagickAllocateMemory(char *,(size_t) (q-p+1)); if (textlist[i] == (char *) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, UnableToConvertText); - /* - Don't use strlcpy here because it spends too much time - looking for the trailing null in order to report the - characters not copied. - */ - (void) strncpy(textlist[i],p,q-p); + (void) memcpy(textlist[i],p,q-p); textlist[i][q-p]='\0'; if (*q == '\r') q++; @@ -5106,30 +5132,35 @@ MagickExport char **StringToList(const char *text) } else { + const size_t + chars_per_line = 0x14; + char hex_string[MaxTextExtent]; - register long + register size_t j; /* Convert string to a HEX list. */ - lines=(strlen(text)/0x14)+1; - textlist=MagickAllocateMemory(char **,(lines+MaxTextExtent)*sizeof(char *)); + lines=(strlen(text)/chars_per_line)+1; + textlist=MagickAllocateMemory(char **,(lines+1)*sizeof(char *)); if (textlist == (char **) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, UnableToConvertText); p=text; - for (i=0; i < (long) lines; i++) + for (i=0; i < lines; i++) { + /* FIXME: Allocation here is excessively large */ textlist[i]=MagickAllocateMemory(char *,2*MaxTextExtent); if (textlist[i] == (char *) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, UnableToConvertText); - FormatString(textlist[i],"0x%08lx: ",0x14*i); + FormatString(textlist[i],"0x%08" MAGICK_SIZE_T_F "x: ", + (MAGICK_SIZE_T) chars_per_line*i); q=textlist[i]+strlen(textlist[i]); - for (j=1; j <= (long) Min(strlen(p),0x14); j++) + for (j=1; j <= Min(strlen(p),chars_per_line); j++) { FormatString(hex_string,"%02x",*(p+j)); (void) strlcpy(q,hex_string,MaxTextExtent); @@ -5137,7 +5168,7 @@ MagickExport char **StringToList(const char *text) if ((j % 0x04) == 0) *q++=' '; } - for (; j <= 0x14; j++) + for (; j <= chars_per_line; j++) { *q++=' '; *q++=' '; @@ -5145,7 +5176,7 @@ MagickExport char **StringToList(const char *text) *q++=' '; } *q++=' '; - for (j=1; j <= (long) Min(strlen(p),0x14); j++) + for (j=1; j <= Min(strlen(p),chars_per_line); j++) { if (isprint((int)(unsigned char)(*p))) *q++=(*p); @@ -5262,30 +5293,30 @@ SubstituteString(char **buffer,const char *search,const char *replace) for (i=0; p[i] != '\0'; i++) { if ((p[i] == search[0]) && (strncmp(&p[i],search,search_len) == 0)) - { - if (0 == replace_len) - replace_len=strlen(replace); - if (replace_len > search_len) - { - size_t - allocation_len; - - allocation_len=strlen(p)+(replace_len-search_len)+1; - MagickRoundUpStringLength(allocation_len); - MagickReallocMemory(char *,p,allocation_len); - *buffer=p; - if (p == (char *) NULL) - MagickFatalError3(ResourceLimitFatalError, - MemoryAllocationFailed, - UnableToAllocateString); - } - if (search_len != replace_len) - (void) MagickCloneMemory(&p[i+replace_len],&p[i+search_len], - strlen(&p[i+search_len])+1); - (void) MagickCloneMemory(&p[i],replace,replace_len); - i += replace_len; - replaced=MagickTrue; - } + { + if (0 == replace_len) + replace_len=strlen(replace); + if (replace_len > search_len) + { + size_t + allocation_len; + + allocation_len=strlen(p)+(replace_len-search_len)+1; + MagickRoundUpStringLength(allocation_len); + MagickReallocMemory(char *,p,allocation_len); + *buffer=p; + if (p == (char *) NULL) + MagickFatalError3(ResourceLimitFatalError, + MemoryAllocationFailed, + UnableToAllocateString); + } + if (search_len != replace_len) + (void) MagickCloneMemory(&p[i+replace_len],&p[i+search_len], + strlen(&p[i+search_len])+1); + (void) MagickCloneMemory(&p[i],replace,replace_len); + i += replace_len; + replaced=MagickTrue; + } } return replaced; } @@ -5349,11 +5380,11 @@ MagickExport int SystemCommand(const unsigned int verbose,const char *command) program[0]='\0'; MagickGetToken(command,&end,program,MaxTextExtent); if (MagickConfirmAccess(FileExecuteConfirmAccessMode,program,&exception) - == MagickFail) + == MagickFail) { - errno=EPERM; - DestroyExceptionInfo(&exception); - return -1; + errno=EPERM; + DestroyExceptionInfo(&exception); + return -1; } } @@ -5550,6 +5581,8 @@ MagickExport int SystemCommand(const unsigned int verbose,const char *command) #define IN_QUOTE 2 #define IN_OZONE 3 +static long sindex(char c,char *string) MAGICK_FUNC_PURE; + static long sindex(char c,char *string) { register char @@ -6308,7 +6341,7 @@ MagickExport char *TranslateTextEx(const ImageInfo *image_info, /* Extract attribute key string. */ p++; - for (i=0; (i < MaxTextExtent) && (*p) && (*p != ']'); i++) + for (i=0; (i < MaxTextExtent-1) && (*p) && (*p != ']'); i++) { key[i]=(*p++); } diff --git a/magick/utility.h b/magick/utility.h index 1845d81..82b6cd9 100644 --- a/magick/utility.h +++ b/magick/utility.h @@ -1,12 +1,12 @@ /* - Copyright (C) 2003 - 2016 GraphicsMagick Group + Copyright (C) 2003 - 2018 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + GraphicsMagick Utility Methods. */ #ifndef _MAGICK_UTILITY_H @@ -78,9 +78,9 @@ extern MagickExport char *TranslateTextEx(const ImageInfo *,Image *,const char *,MagickTextTranslate); extern MagickExport const char - *GetClientFilename(void), - *GetClientName(void), - *GetClientPath(void), + *GetClientFilename(void) MAGICK_FUNC_CONST, + *GetClientName(void) MAGICK_FUNC_CONST, + *GetClientPath(void) MAGICK_FUNC_CONST, *SetClientFilename(const char *), *SetClientName(const char *), *SetClientPath(const char *); @@ -90,9 +90,9 @@ extern MagickExport double extern MagickExport int GetGeometry(const char *,long *,long *,unsigned long *,unsigned long *), - GlobExpression(const char *,const char *), - LocaleNCompare(const char *,const char *,const size_t), - LocaleCompare(const char *,const char *), + GlobExpression(const char *,const char *) MAGICK_FUNC_PURE, + LocaleNCompare(const char *,const char *,const size_t) MAGICK_FUNC_PURE, + LocaleCompare(const char *,const char *) MAGICK_FUNC_PURE, GetMagickDimension(const char *str,double *width,double *height,double *xoff,double *yoff), GetMagickGeometry(const char *geometry,long *x,long *y,unsigned long *width, unsigned long *height), @@ -121,14 +121,14 @@ extern MagickExport MagickBool IsAccessibleNoLogging(const char *), IsAccessibleAndNotEmpty(const char *), IsGeometry(const char *), - IsGlob(const char *), + IsGlob(const char *) MAGICK_FUNC_PURE, IsWriteable(const char *), MagickSceneFileName(char *filename,const char* filename_template, const char* scene_template,const MagickBool force,unsigned long scene), SubstituteString(char **buffer,const char *search,const char *replace); extern MagickExport unsigned long - MultilineCensus(const char *); + MultilineCensus(const char *) MAGICK_FUNC_PURE; extern MagickExport void AppendImageFormat(const char *,char *), @@ -145,9 +145,9 @@ extern MagickExport void extern MagickExport void FormatString(char *string,const char *format,...) MAGICK_ATTRIBUTE((__format__ (__printf__,2,3))), - FormatStringList(char *string,const char *format,va_list operands), + FormatStringList(char *string,const char *format,va_list operands) MAGICK_ATTRIBUTE((__format__ (__printf__,2,0))), MagickFormatString(char *string,const size_t length,const char *format,...) MAGICK_ATTRIBUTE((__format__ (__printf__,3,4))), - MagickFormatStringList(char *string,const size_t length,const char *format,va_list operands); + MagickFormatStringList(char *string,const size_t length,const char *format,va_list operands) MAGICK_ATTRIBUTE((__format__ (__printf__,3,0))); extern MagickExport magick_int64_t MagickSizeStrToInt64(const char *str,const unsigned int kilo); @@ -184,6 +184,24 @@ extern MagickExport MagickPassFail MagickAtoUIChk(const char *str, unsigned int extern MagickExport MagickPassFail MagickAtoLChk(const char *str, long *value); extern MagickExport MagickPassFail MagickAtoULChk(const char *str, unsigned long *value); +/* + Compute a value which is the next kilobyte power of 2 larger than + the requested value or MaxTextExtent, whichever is larger. + + The objective is to round up the size quickly (and in repeatable + steps) in order to reduce the number of memory copies due to realloc + for strings which grow rapidly, while producing a reasonable size + for smaller strings. +*/ +#define MagickRoundUpStringLength(size) \ +{ \ + size_t \ + _rounded; \ + \ + for (_rounded=256U; _rounded < (Max(size,256)); _rounded *= 2); \ + size=_rounded; \ +} + #endif /* defined(MAGICK_IMPLEMENTATION) */ #if defined(__cplusplus) || defined(c_plusplus) diff --git a/magick/version.h b/magick/version.h index f5f1155..c181d3e 100644 --- a/magick/version.h +++ b/magick/version.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2003 - 2016 GraphicsMagick Group + Copyright (C) 2003 - 2018 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company @@ -34,12 +34,12 @@ extern "C" { identifying the release. */ #define MagickPackageName "GraphicsMagick" -#define MagickCopyright "Copyright (C) 2002-2017 GraphicsMagick Group.\nAdditional copyrights and licenses apply to this software.\nSee http://www.GraphicsMagick.org/www/Copyright.html for details." -#define MagickLibVersion 0x191600 -#define MagickLibVersionText "1.3.26" -#define MagickLibVersionNumber 19,16,0 -#define MagickChangeDate "20170704" -#define MagickReleaseDate "2017-07-04" +#define MagickCopyright "Copyright (C) 2002-2018 GraphicsMagick Group.\nAdditional copyrights and licenses apply to this software.\nSee http://www.GraphicsMagick.org/www/Copyright.html for details." +#define MagickLibVersion 0x221900 +#define MagickLibVersionText "1.3.31" +#define MagickLibVersionNumber 22,19,0 +#define MagickChangeDate "20181117" +#define MagickReleaseDate "2018-11-17" /* The MagickLibInterfaceNewest and MagickLibInterfaceOldest defines @@ -54,7 +54,7 @@ extern "C" { MagickLibVersionNumber, but these are broken out and simplified so that they can be easily used in C pre-processor logic. */ -#define MagickLibInterfaceNewest 19 +#define MagickLibInterfaceNewest 22 #define MagickLibInterfaceOldest 3 #if (QuantumDepth == 8) @@ -75,9 +75,9 @@ extern "C" { Method declarations. */ extern MagickExport const char - *GetMagickCopyright(void), - *GetMagickVersion(unsigned long *), - *GetMagickWebSite(void); + *GetMagickCopyright(void) MAGICK_FUNC_CONST, + *GetMagickVersion(unsigned long *) MAGICK_FUNC_CONST, + *GetMagickWebSite(void) MAGICK_FUNC_CONST; #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/magick/version.h.in b/magick/version.h.in index ad4ce36..2c5dd82 100644 --- a/magick/version.h.in +++ b/magick/version.h.in @@ -1,5 +1,5 @@ /* - Copyright (C) 2003 - 2016 GraphicsMagick Group + Copyright (C) 2003 - 2018 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company @@ -34,7 +34,7 @@ extern "C" { identifying the release. */ #define MagickPackageName "@PACKAGE_NAME@" -#define MagickCopyright "Copyright (C) 2002-2017 GraphicsMagick Group.\nAdditional copyrights and licenses apply to this software.\nSee http://www.GraphicsMagick.org/www/Copyright.html for details." +#define MagickCopyright "Copyright (C) 2002-2018 GraphicsMagick Group.\nAdditional copyrights and licenses apply to this software.\nSee http://www.GraphicsMagick.org/www/Copyright.html for details." #define MagickLibVersion @MAGICK_LIB_VERSION@ #define MagickLibVersionText "@MAGICK_LIB_VERSION_TEXT@" #define MagickLibVersionNumber @MAGICK_LIB_VERSION_NUMBER@ @@ -75,9 +75,9 @@ extern "C" { Method declarations. */ extern MagickExport const char - *GetMagickCopyright(void), - *GetMagickVersion(unsigned long *), - *GetMagickWebSite(void); + *GetMagickCopyright(void) MAGICK_FUNC_CONST, + *GetMagickVersion(unsigned long *) MAGICK_FUNC_CONST, + *GetMagickWebSite(void) MAGICK_FUNC_CONST; #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/magick/widget.c b/magick/widget.c index 10a3049..0167e61 100644 --- a/magick/widget.c +++ b/magick/widget.c @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2015 GraphicsMagick Group +% Copyright (C) 2003-2017 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -1029,8 +1029,8 @@ static void XEditText(Display *display,MagickXWidgetInfo *text_info, (void) memmove(text_info->cursor,text_info->cursor+1, strlen(text_info->cursor+1)+1); text_info->highlight=False; - break; } + break; } case XK_Left: case XK_KP_Left: @@ -2706,80 +2706,80 @@ MagickExport int MagickXCommandWidget(Display *display,MagickXWindows *windows, #define tile_width 112 #define tile_height 64 static unsigned char tile_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, - 0x00, 0x1E, 0xF8, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE0, 0xC0, 0x87, 0x3F, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xE0, 0x8F, 0x73, 0xDC, 0xFC, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x8E, 0x03, 0xDC, 0x7C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x71, 0x80, 0x1F, 0xEC, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xC3, 0x71, 0x00, 0x7F, - 0x6E, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xC7, 0x73, - 0x18, 0x70, 0x6E, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, - 0x8F, 0x73, 0xDC, 0x71, 0xEE, 0x3B, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF8, 0x8F, 0xF3, 0x9F, 0x7F, 0xE7, 0x39, 0x3E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x78, 0x9C, 0xE7, 0x0F, 0x3F, 0xE7, 0x19, 0x7C, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1C, 0x87, 0x03, 0x00, 0xE6, 0x1C, - 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x38, 0x07, 0x00, 0x00, - 0xE0, 0x9C, 0xC7, 0x01, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE3, 0x38, 0x00, - 0x00, 0x00, 0x00, 0xCC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE7, - 0x39, 0x00, 0x00, 0x00, 0x00, 0xC8, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF8, 0xCF, 0x01, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x71, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3C, 0xCE, 0x03, 0x00, 0x81, 0x0D, 0x00, 0x80, 0x7F, 0x7C, - 0x00, 0x00, 0x00, 0x00, 0x3C, 0x9E, 0x00, 0x80, 0x87, 0x1E, 0x00, 0x00, - 0x3F, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1C, 0x00, 0xC0, 0xDC, 0x1F, - 0x00, 0x00, 0x38, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x40, - 0xF0, 0x38, 0x00, 0x00, 0x10, 0xC7, 0x01, 0x00, 0x00, 0x00, 0xF0, 0x0F, - 0x00, 0x40, 0x77, 0x30, 0x00, 0x00, 0x80, 0xC3, 0x03, 0x00, 0x00, 0xC0, - 0xE1, 0x01, 0x00, 0xC0, 0x2D, 0x30, 0x00, 0x00, 0xA0, 0xE3, 0x03, 0x00, - 0x00, 0xE0, 0xC7, 0x03, 0x00, 0xC0, 0x38, 0xF0, 0x00, 0x00, 0x30, 0xF7, - 0xC1, 0x00, 0x00, 0xF0, 0x8F, 0x07, 0x00, 0xC0, 0x18, 0xE0, 0x01, 0x00, - 0x70, 0xFE, 0xC0, 0x00, 0x00, 0x38, 0x3F, 0x0F, 0x00, 0x40, 0x10, 0x60, - 0x03, 0x00, 0x70, 0x7C, 0xD8, 0x01, 0x00, 0x98, 0x3D, 0x06, 0x00, 0x40, - 0x10, 0x74, 0x06, 0x00, 0xE0, 0x3E, 0x1E, 0x00, 0x00, 0xB8, 0x39, 0x02, - 0x00, 0xC0, 0x0C, 0x36, 0x04, 0x00, 0xC0, 0x0F, 0x3F, 0x00, 0x00, 0x98, - 0x08, 0x00, 0x00, 0xC0, 0x0C, 0x36, 0x0C, 0x00, 0x80, 0xC7, 0x0F, 0x00, - 0x00, 0xC0, 0x0D, 0x00, 0x00, 0xE0, 0x08, 0x1E, 0x08, 0x00, 0x00, 0xE0, - 0x03, 0x00, 0x00, 0xC2, 0x0F, 0x00, 0x00, 0xA0, 0x0C, 0x0C, 0x18, 0x00, - 0x00, 0xE0, 0x01, 0x00, 0x00, 0x87, 0x07, 0x00, 0x00, 0xD0, 0x1B, 0x04, - 0x30, 0x00, 0x00, 0x60, 0x78, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x78, - 0x10, 0x06, 0x60, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x38, 0xF0, 0x0F, 0x60, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x80, 0x07, - 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFC, 0xF1, 0x00, 0x00, 0x00, 0x8F, 0x01, - 0x80, 0x1F, 0x00, 0x00, 0x00, 0x06, 0x00, 0xC0, 0xE3, 0x00, 0x00, 0x00, - 0x87, 0x03, 0x80, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x70, 0x60, 0xA3, 0x03, - 0x00, 0x00, 0x83, 0x03, 0x00, 0xFC, 0x00, 0x00, 0x80, 0x01, 0x70, 0x30, - 0x00, 0x07, 0x00, 0x00, 0x87, 0x03, 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x0E, - 0x70, 0x18, 0x00, 0x06, 0x00, 0x00, 0x9F, 0x01, 0x10, 0x00, 0x00, 0x00, - 0x60, 0x0F, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x00, 0x1E, 0x00, 0x9C, 0x1F, - 0x00, 0x00, 0x20, 0x06, 0x00, 0x06, 0x60, 0x06, 0x00, 0x00, 0x1C, 0x00, - 0x9E, 0x1F, 0x00, 0x00, 0x20, 0x00, 0x38, 0x33, 0x60, 0x0C, 0x00, 0x00, - 0x00, 0x78, 0x9E, 0x3F, 0x00, 0x00, 0x60, 0x00, 0xB8, 0x71, 0x62, 0x08, - 0x02, 0x00, 0xF0, 0x7F, 0x8E, 0x39, 0x00, 0x00, 0xC0, 0x00, 0xE0, 0x30, - 0x0E, 0xFB, 0x0F, 0x00, 0xFC, 0x7F, 0xC6, 0x39, 0x00, 0x00, 0x80, 0x03, - 0x7C, 0x00, 0x1C, 0xFF, 0x18, 0x00, 0xFC, 0x07, 0x06, 0x38, 0x00, 0x00, - 0x00, 0xFF, 0x1F, 0x00, 0x72, 0x0E, 0x10, 0x00, 0xE8, 0x01, 0x0E, 0x38, - 0x00, 0x00, 0xC0, 0xFC, 0x01, 0x00, 0xC7, 0x00, 0x18, 0x00, 0xC0, 0x07, - 0x3E, 0x3C, 0x00, 0x00, 0xC0, 0x3E, 0x06, 0x03, 0xDC, 0x00, 0x18, 0x00, - 0xE0, 0x0F, 0xFE, 0x1F, 0x00, 0x00, 0x80, 0x63, 0x07, 0x87, 0x78, 0x00, - 0x0C, 0x00, 0xF8, 0x1D, 0xFC, 0x0F, 0x00, 0x00, 0x80, 0xC3, 0x07, 0xC7, - 0x69, 0x30, 0x06, 0x00, 0x78, 0x18, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x02, - 0x07, 0x80, 0x3D, 0x3C, 0x03, 0x00, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x06, 0x1C, 0x00, 0x94, 0x97, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF8, 0x0F, 0xF0, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1E, 0x38, 0xF0, 0xFF, 0x0F, 0xD8, 0x3F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xE0, 0xF8, 0x10, 0x0E, 0x6C, - 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xF8, 0xFC, 0xBF, - 0x3D, 0x06, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0E, - 0x60, 0xFC, 0xFC, 0x1D, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFC, 0x01, 0x00, 0x3C, 0xFF, 0x79, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xC0, 0x00, 0x00, 0xFC, 0x67, 0x80, 0x1D, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x1A, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, + 0x00, 0x1E, 0xF8, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE0, 0xC0, 0x87, 0x3F, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xE0, 0x8F, 0x73, 0xDC, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x8E, 0x03, 0xDC, 0x7C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x71, 0x80, 0x1F, 0xEC, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xC3, 0x71, 0x00, 0x7F, + 0x6E, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xC7, 0x73, + 0x18, 0x70, 0x6E, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, + 0x8F, 0x73, 0xDC, 0x71, 0xEE, 0x3B, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0x8F, 0xF3, 0x9F, 0x7F, 0xE7, 0x39, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x9C, 0xE7, 0x0F, 0x3F, 0xE7, 0x19, 0x7C, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1C, 0x87, 0x03, 0x00, 0xE6, 0x1C, + 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x38, 0x07, 0x00, 0x00, + 0xE0, 0x9C, 0xC7, 0x01, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE3, 0x38, 0x00, + 0x00, 0x00, 0x00, 0xCC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE7, + 0x39, 0x00, 0x00, 0x00, 0x00, 0xC8, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF8, 0xCF, 0x01, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x71, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0xCE, 0x03, 0x00, 0x81, 0x0D, 0x00, 0x80, 0x7F, 0x7C, + 0x00, 0x00, 0x00, 0x00, 0x3C, 0x9E, 0x00, 0x80, 0x87, 0x1E, 0x00, 0x00, + 0x3F, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1C, 0x00, 0xC0, 0xDC, 0x1F, + 0x00, 0x00, 0x38, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x40, + 0xF0, 0x38, 0x00, 0x00, 0x10, 0xC7, 0x01, 0x00, 0x00, 0x00, 0xF0, 0x0F, + 0x00, 0x40, 0x77, 0x30, 0x00, 0x00, 0x80, 0xC3, 0x03, 0x00, 0x00, 0xC0, + 0xE1, 0x01, 0x00, 0xC0, 0x2D, 0x30, 0x00, 0x00, 0xA0, 0xE3, 0x03, 0x00, + 0x00, 0xE0, 0xC7, 0x03, 0x00, 0xC0, 0x38, 0xF0, 0x00, 0x00, 0x30, 0xF7, + 0xC1, 0x00, 0x00, 0xF0, 0x8F, 0x07, 0x00, 0xC0, 0x18, 0xE0, 0x01, 0x00, + 0x70, 0xFE, 0xC0, 0x00, 0x00, 0x38, 0x3F, 0x0F, 0x00, 0x40, 0x10, 0x60, + 0x03, 0x00, 0x70, 0x7C, 0xD8, 0x01, 0x00, 0x98, 0x3D, 0x06, 0x00, 0x40, + 0x10, 0x74, 0x06, 0x00, 0xE0, 0x3E, 0x1E, 0x00, 0x00, 0xB8, 0x39, 0x02, + 0x00, 0xC0, 0x0C, 0x36, 0x04, 0x00, 0xC0, 0x0F, 0x3F, 0x00, 0x00, 0x98, + 0x08, 0x00, 0x00, 0xC0, 0x0C, 0x36, 0x0C, 0x00, 0x80, 0xC7, 0x0F, 0x00, + 0x00, 0xC0, 0x0D, 0x00, 0x00, 0xE0, 0x08, 0x1E, 0x08, 0x00, 0x00, 0xE0, + 0x03, 0x00, 0x00, 0xC2, 0x0F, 0x00, 0x00, 0xA0, 0x0C, 0x0C, 0x18, 0x00, + 0x00, 0xE0, 0x01, 0x00, 0x00, 0x87, 0x07, 0x00, 0x00, 0xD0, 0x1B, 0x04, + 0x30, 0x00, 0x00, 0x60, 0x78, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x78, + 0x10, 0x06, 0x60, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x38, 0xF0, 0x0F, 0x60, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x80, 0x07, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFC, 0xF1, 0x00, 0x00, 0x00, 0x8F, 0x01, + 0x80, 0x1F, 0x00, 0x00, 0x00, 0x06, 0x00, 0xC0, 0xE3, 0x00, 0x00, 0x00, + 0x87, 0x03, 0x80, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x70, 0x60, 0xA3, 0x03, + 0x00, 0x00, 0x83, 0x03, 0x00, 0xFC, 0x00, 0x00, 0x80, 0x01, 0x70, 0x30, + 0x00, 0x07, 0x00, 0x00, 0x87, 0x03, 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x0E, + 0x70, 0x18, 0x00, 0x06, 0x00, 0x00, 0x9F, 0x01, 0x10, 0x00, 0x00, 0x00, + 0x60, 0x0F, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x00, 0x1E, 0x00, 0x9C, 0x1F, + 0x00, 0x00, 0x20, 0x06, 0x00, 0x06, 0x60, 0x06, 0x00, 0x00, 0x1C, 0x00, + 0x9E, 0x1F, 0x00, 0x00, 0x20, 0x00, 0x38, 0x33, 0x60, 0x0C, 0x00, 0x00, + 0x00, 0x78, 0x9E, 0x3F, 0x00, 0x00, 0x60, 0x00, 0xB8, 0x71, 0x62, 0x08, + 0x02, 0x00, 0xF0, 0x7F, 0x8E, 0x39, 0x00, 0x00, 0xC0, 0x00, 0xE0, 0x30, + 0x0E, 0xFB, 0x0F, 0x00, 0xFC, 0x7F, 0xC6, 0x39, 0x00, 0x00, 0x80, 0x03, + 0x7C, 0x00, 0x1C, 0xFF, 0x18, 0x00, 0xFC, 0x07, 0x06, 0x38, 0x00, 0x00, + 0x00, 0xFF, 0x1F, 0x00, 0x72, 0x0E, 0x10, 0x00, 0xE8, 0x01, 0x0E, 0x38, + 0x00, 0x00, 0xC0, 0xFC, 0x01, 0x00, 0xC7, 0x00, 0x18, 0x00, 0xC0, 0x07, + 0x3E, 0x3C, 0x00, 0x00, 0xC0, 0x3E, 0x06, 0x03, 0xDC, 0x00, 0x18, 0x00, + 0xE0, 0x0F, 0xFE, 0x1F, 0x00, 0x00, 0x80, 0x63, 0x07, 0x87, 0x78, 0x00, + 0x0C, 0x00, 0xF8, 0x1D, 0xFC, 0x0F, 0x00, 0x00, 0x80, 0xC3, 0x07, 0xC7, + 0x69, 0x30, 0x06, 0x00, 0x78, 0x18, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x02, + 0x07, 0x80, 0x3D, 0x3C, 0x03, 0x00, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x1C, 0x00, 0x94, 0x97, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF8, 0x0F, 0xF0, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1E, 0x38, 0xF0, 0xFF, 0x0F, 0xD8, 0x3F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xE0, 0xF8, 0x10, 0x0E, 0x6C, + 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xF8, 0xFC, 0xBF, + 0x3D, 0x06, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0E, + 0x60, 0xFC, 0xFC, 0x1D, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFC, 0x01, 0x00, 0x3C, 0xFF, 0x79, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xFC, 0x67, 0x80, 0x1D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x1A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, }; int @@ -4829,10 +4829,15 @@ MagickExport void MagickXFileBrowserWidget(Display *display,MagickXWindows *wind GetExceptionInfo(&exception); magick_info=GetMagickInfo("*",&exception); DestroyExceptionInfo(&exception); + if (magick_info == (const MagickInfo *) NULL) + break; i=0; for (p=magick_info; p != (MagickInfo *) NULL; p=p->next) i++; - formats=MagickAllocateMemory(char **,(i+1)*sizeof(char *)); + formats=MagickAllocateArray(char **,(i+1),sizeof(char *)); + if (formats == (char **) NULL) + break; + (void) memset(formats,0,(i+1)*sizeof(char *)); i=0; for (p=magick_info; p != (MagickInfo *) NULL; p=p->next) { @@ -4840,8 +4845,10 @@ MagickExport void MagickXFileBrowserWidget(Display *display,MagickXWindows *wind continue; if (!p->encoder) continue; + /* AllocateString does a fatal exit on failed alloc */ formats[i]=AllocateString(p->name); - LocaleLower((char *) formats[i]); + if (formats[i] != NULL) + LocaleLower((char *) formats[i]); i++; } formats[i]=(char *) NULL; @@ -5309,6 +5316,8 @@ MagickExport void MagickXFileBrowserWidget(Display *display,MagickXWindows *wind extern "C" { #endif +static int FontCompare(const void *x,const void *y) MAGICK_FUNC_PURE; + static int FontCompare(const void *x,const void *y) { register char diff --git a/magick/widget.h b/magick/widget.h index 6b40cbb..c2f2a3d 100644 --- a/magick/widget.h +++ b/magick/widget.h @@ -2,11 +2,11 @@ Copyright (C) 2003 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + X11 User Interface Methods for ImageMagick. */ #ifndef _MAGICK_WIDGET_H diff --git a/magick/xwindow.c b/magick/xwindow.c index bfcb2c9..0d02b7f 100644 --- a/magick/xwindow.c +++ b/magick/xwindow.c @@ -160,14 +160,14 @@ MagickShmAt(int shmid, void *shmaddr, int shmflg) /* Shared memory control operations. */ -static int +static int MagickShmCtl(int shmid, int cmd, struct shmid_ds *buf) { int status; if ((status=shmctl(shmid, cmd, buf)) == -1) { (void) LogMagickEvent(X11Event,GetMagickModule(),"shm control id=%d cmd=%s failed (%s)", - shmid, ((cmd == IPC_STAT) ? "IPC_STAT" : + shmid, ((cmd == IPC_STAT) ? "IPC_STAT" : (cmd == IPC_SET) ? "IPC_SET" : (cmd == IPC_RMID) ? "IPC_RMID" : "Unknown"), strerror(errno)); @@ -175,7 +175,7 @@ MagickShmCtl(int shmid, int cmd, struct shmid_ds *buf) else { (void) LogMagickEvent(X11Event,GetMagickModule(),"shm control id=%d cmd=%s", - shmid, ((cmd == IPC_STAT) ? "IPC_STAT" : + shmid, ((cmd == IPC_STAT) ? "IPC_STAT" : (cmd == IPC_SET) ? "IPC_SET" : (cmd == IPC_RMID) ? "IPC_RMID" : "Unknown")); } @@ -184,7 +184,7 @@ MagickShmCtl(int shmid, int cmd, struct shmid_ds *buf) /* Detatch from shared memory. */ -static int +static int MagickShmDt(void *shmaddr) { int result; @@ -228,14 +228,14 @@ MagickShmDt(void *shmaddr) % % */ -MagickExport void +MagickExport void MagickXDestroyX11Resources(void) { MagickXWindows *windows = MagickXSetWindows((MagickXWindows *) ~0); if (windows != (MagickXWindows *) NULL) { MagickXDestroyXWindows(windows); - (void) MagickXSetWindows((MagickXWindows *) NULL); + (void) MagickXSetWindows((MagickXWindows *) NULL); } } @@ -261,7 +261,7 @@ MagickXDestroyX11Resources(void) % % */ -MagickExport void +MagickExport void MagickXDestroyXWindows(MagickXWindows *windows) { if (windows == (MagickXWindows *) NULL || @@ -375,7 +375,7 @@ MagickXDestroyXWindows(MagickXWindows *windows) % % o window: Pointer to MagickXWindowInfo structure to destroy. */ -MagickExport void +MagickExport void MagickXDestroyXWindowInfo(Display *display,MagickXWindowInfo *window) { if (window->mapped != False) @@ -447,7 +447,7 @@ MagickXDestroyXWindowInfo(Display *display,MagickXWindowInfo *window) #if defined(HasSharedMemory) XShmSegmentInfo *segment_info; - + segment_info=(XShmSegmentInfo *) window->segment_info; if (segment_info != (XShmSegmentInfo *) NULL) { @@ -492,7 +492,7 @@ MagickXDestroyXWindowInfo(Display *display,MagickXWindowInfo *window) % % */ -MagickExport unsigned int +MagickExport unsigned int MagickIsTrue(const char *reason) { if (reason == (char *) NULL) @@ -545,11 +545,11 @@ MagickIsTrue(const char *reason) % % */ -MagickExport unsigned int +MagickExport unsigned int MagickXAnnotateImage(Display *display, - const MagickXPixelInfo *pixel, - MagickXAnnotateInfo *annotate_info, - Image *image) + const MagickXPixelInfo *pixel, + MagickXAnnotateInfo *annotate_info, + Image *image) { GC annotate_context; @@ -640,7 +640,7 @@ MagickXAnnotateImage(Display *display, y=0; (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height); (void) AcquireOnePixelByReference(image,&annotate_image->background_color, - x,y,&image->exception); + x,y,&image->exception); annotate_image->matte=annotate_info->stencil == ForegroundStencil; for (y=0; y < (long) annotate_image->rows; y++) { @@ -857,8 +857,8 @@ MagickFontToList(char *font) MagickExport XFontStruct * MagickXBestFont(Display *display, - const MagickXResourceInfo *resource_info, - const unsigned int text_font) + const MagickXResourceInfo *resource_info, + const unsigned int text_font) { static const char *Fonts[]= @@ -1098,9 +1098,9 @@ MagickXBestIconSize(Display *display,MagickXWindowInfo *window, % % */ -MagickExport void +MagickExport void MagickXBestPixel(Display *display,const Colormap colormap, - XColor *colors,unsigned int number_colors,XColor *color) + XColor *colors,unsigned int number_colors,XColor *color) { double min_distance; @@ -1226,8 +1226,8 @@ MagickXBestPixel(Display *display,const Colormap colormap, MagickExport XVisualInfo * MagickXBestVisualInfo(Display *display, - XStandardColormap *map_info, - MagickXResourceInfo *resource_info) + XStandardColormap *map_info, + MagickXResourceInfo *resource_info) { char *map_type, @@ -1517,7 +1517,7 @@ MagickXBestVisualInfo(Display *display, % % */ -MagickExport void +MagickExport void MagickXCheckRefreshWindows(Display *display,MagickXWindows *windows) { XEvent @@ -1570,7 +1570,7 @@ MagickXCheckRefreshWindows(Display *display,MagickXWindows *windows) % % */ -MagickExport void +MagickExport void MagickXClientMessage(Display *display,const Window window, const Atom protocol,const Atom reason,const Time timestamp) { @@ -1578,6 +1578,7 @@ MagickXClientMessage(Display *display,const Window window, client_event; assert(display != (Display *) NULL); + (void) memset(&client_event,0,sizeof(client_event)); client_event.type=ClientMessage; client_event.window=window; client_event.message_type=protocol; @@ -1690,8 +1691,8 @@ MagickXClientWindow(Display *display,Window target_window) */ MagickExport void MagickXConfigureImageColormap(Display *display, - MagickXResourceInfo *resource_info, - MagickXWindows *windows,Image *image) + MagickXResourceInfo *resource_info, + MagickXWindows *windows,Image *image) { Colormap colormap; @@ -1746,7 +1747,7 @@ MagickXConfigureImageColormap(Display *display, */ MagickExport void MagickXConstrainWindowPosition(Display *display, - MagickXWindowInfo *window_info) + MagickXWindowInfo *window_info) { unsigned int limit; @@ -1970,9 +1971,9 @@ MagickXDestroyWindowColors(Display *display,Window window) */ MagickExport void MagickXDisplayImageInfo(Display *display, - const MagickXResourceInfo *resource_info, - MagickXWindows *windows,Image *undo_image, - Image *image) + const MagickXResourceInfo *resource_info, + MagickXWindows *windows,Image *undo_image, + Image *image) { char filename[MaxTextExtent], @@ -2184,7 +2185,7 @@ static void MagickXDitherImage(Image *image,XImage *ximage) { red_map[i][j]=MagickAllocateArray(unsigned char *,256,sizeof(unsigned char)); green_map[i][j]=MagickAllocateArray(unsigned char *, - 256,sizeof(unsigned char)); + 256,sizeof(unsigned char)); blue_map[i][j]=MagickAllocateArray(unsigned char *,256,sizeof(unsigned char)); if ((red_map[i][j] == (unsigned char *) NULL) || (green_map[i][j] == (unsigned char *) NULL) || @@ -2302,7 +2303,7 @@ static void MagickXDitherImage(Image *image,XImage *ximage) */ MagickExport unsigned int MagickXDrawImage(Display *display,const MagickXPixelInfo *pixel, - MagickXDrawInfo *draw_info,Image *image) + MagickXDrawInfo *draw_info,Image *image) { GC draw_context; @@ -2726,12 +2727,12 @@ MagickXError(Display *display,XErrorEvent *error) */ MagickExport void MagickXFreeResources(Display *display, - XVisualInfo *visual_info, - XStandardColormap *map_info, - MagickXPixelInfo *pixel, - XFontStruct *font_info, - MagickXResourceInfo *resource_info, - MagickXWindowInfo *window_info) + XVisualInfo *visual_info, + XStandardColormap *map_info, + MagickXPixelInfo *pixel, + XFontStruct *font_info, + MagickXResourceInfo *resource_info, + MagickXWindowInfo *window_info) { assert(display != (Display *) NULL); assert(resource_info != (MagickXResourceInfo *) NULL); @@ -2821,9 +2822,9 @@ MagickXFreeResources(Display *display, */ MagickExport void MagickXFreeStandardColormap(Display *display, - const XVisualInfo *visual_info, - XStandardColormap *map_info, - MagickXPixelInfo *pixel) + const XVisualInfo *visual_info, + XStandardColormap *map_info, + MagickXPixelInfo *pixel) { /* Free colormap. @@ -2928,7 +2929,7 @@ MagickXGetAnnotateInfo(MagickXAnnotateInfo *annotate_info) */ MagickExport void MagickXGetMapInfo(const XVisualInfo *visual_info, - const Colormap colormap,XStandardColormap *map_info) + const Colormap colormap,XStandardColormap *map_info) { /* Initialize map info. @@ -3039,11 +3040,11 @@ MagickXGetImportInfo(MagickXImportInfo *ximage_info) */ MagickExport void MagickXGetPixelPacket(Display *display, - const XVisualInfo *visual_info, - const XStandardColormap *map_info, - const MagickXResourceInfo *resource_info, - Image *image, - MagickXPixelInfo *pixel) + const XVisualInfo *visual_info, + const XStandardColormap *map_info, + const MagickXResourceInfo *resource_info, + Image *image, + MagickXPixelInfo *pixel) { static const char *PenColors[MaxNumberPens]= @@ -3292,8 +3293,8 @@ MagickXGetPixelPacket(Display *display, */ MagickExport char * MagickXGetResourceClass(XrmDatabase database, - const char *client_name,const char *keyword, - char *resource_default) + const char *client_name,const char *keyword, + char *resource_default) { char resource_class[MaxTextExtent], @@ -3384,7 +3385,7 @@ MagickXGetResourceClass(XrmDatabase database, */ MagickExport XrmDatabase MagickXGetResourceDatabase(Display *display, - const char *client_name) + const char *client_name) { char filename[MaxTextExtent]; @@ -3487,7 +3488,7 @@ MagickXGetResourceDatabase(Display *display, */ MagickExport void MagickXGetResourceInfo(XrmDatabase database,const char *client_name, - MagickXResourceInfo *resource_info) + MagickXResourceInfo *resource_info) { char *resource_value; @@ -3717,9 +3718,9 @@ MagickXGetResourceInfo(XrmDatabase database,const char *client_name, */ MagickExport char * MagickXGetResourceInstance(XrmDatabase database, - const char *client_name, - const char *keyword, - const char *resource_default) + const char *client_name, + const char *keyword, + const char *resource_default) { char *resource_type, @@ -4029,7 +4030,7 @@ MagickXGetWindowColor(Display *display,MagickXWindows *windows,char *name) */ static Image * MagickXGetWindowImage(Display *display,const Window window, - const unsigned int borders,const unsigned int level) + const unsigned int borders,const unsigned int level) { typedef struct _ColormapInfo { @@ -4156,7 +4157,7 @@ MagickXGetWindowImage(Display *display,const Window window, max_windows+=1024; if (window_info == (WindowInfo *) NULL) window_info=MagickAllocateArray(WindowInfo *, - max_windows,sizeof(WindowInfo)); + max_windows,sizeof(WindowInfo)); else MagickReallocMemory(WindowInfo *,window_info,max_windows*sizeof(WindowInfo)); } @@ -4618,12 +4619,12 @@ MagickXGetWindowImage(Display *display,const Window window, */ MagickExport void MagickXGetWindowInfo(Display *display, - XVisualInfo *visual_info, - XStandardColormap *map_info, - MagickXPixelInfo *pixel, - XFontStruct *font_info, - MagickXResourceInfo *resource_info, - MagickXWindowInfo *window) + XVisualInfo *visual_info, + XStandardColormap *map_info, + MagickXPixelInfo *pixel, + XFontStruct *font_info, + MagickXResourceInfo *resource_info, + MagickXWindowInfo *window) { /* Initialize window info. @@ -4763,8 +4764,8 @@ MagickXGetWindowInfo(Display *display, */ MagickExport void MagickXHighlightEllipse(Display *display,Window window, - GC annotate_context, - const RectangleInfo *highlight_info) + GC annotate_context, + const RectangleInfo *highlight_info) { assert(display != (Display *) NULL); assert(window != (Window) NULL); @@ -4813,9 +4814,9 @@ MagickXHighlightEllipse(Display *display,Window window, % % */ -MagickExport void +MagickExport void MagickXHighlightLine(Display *display,Window window, - GC annotate_context,const XSegment *highlight_info) + GC annotate_context,const XSegment *highlight_info) { assert(display != (Display *) NULL); assert(window != (Window) NULL); @@ -4860,8 +4861,8 @@ MagickXHighlightLine(Display *display,Window window, */ MagickExport void MagickXHighlightRectangle(Display *display,Window window, - GC annotate_context, - const RectangleInfo *highlight_info) + GC annotate_context, + const RectangleInfo *highlight_info) { assert(display != (Display *) NULL); assert(window != (Window) NULL); @@ -4905,7 +4906,7 @@ MagickXHighlightRectangle(Display *display,Window window, */ MagickExport Image * MagickXImportImage(const ImageInfo *image_info, - MagickXImportInfo *ximage_info) + MagickXImportInfo *ximage_info) { Colormap *colormaps; @@ -5173,7 +5174,7 @@ MagickXImportImage(const ImageInfo *image_info, */ MagickExport MagickXWindows * MagickXInitializeWindows(Display *display, - MagickXResourceInfo *resource_info) + MagickXResourceInfo *resource_info) { Window root_window; @@ -5373,8 +5374,8 @@ MagickXInitializeWindows(Display *display, */ MagickExport Cursor MagickXMakeCursor(Display *display,Window window, - Colormap colormap,char *background_color, - char *foreground_color) + Colormap colormap,char *background_color, + char *foreground_color) { #define scope_height 17 #define scope_x_hot 8 @@ -5481,13 +5482,13 @@ static const char * MagickXImageFormatToString(int xformat) { static const char - *formats[] = + *formats[] = { "XYBitmap", "XYPixmap", "ZPixmap" }; - + const char *format = "Unknown"; @@ -5505,7 +5506,7 @@ MagickXByteOrderToString(int xbyte_order) "LSBFirst", "MSBFirst" }; - + const char *byte_order = "Unknown"; @@ -5516,10 +5517,10 @@ MagickXByteOrderToString(int xbyte_order) } MagickExport unsigned int MagickXMakeImage(Display *display, - const MagickXResourceInfo *resource_info, - MagickXWindowInfo *window, - Image *image, - unsigned int width,unsigned int height) + const MagickXResourceInfo *resource_info, + MagickXWindowInfo *window, + Image *image, + unsigned int width,unsigned int height) { int depth, @@ -5552,7 +5553,7 @@ MagickXMakeImage(Display *display, if (window->image != (Image *) NULL) { MonitorHandler - handler=(MonitorHandler) NULL; + handler=(MonitorHandler) NULL; handler=SetMonitorHandler((MonitorHandler) NULL); if (window->crop_geometry) @@ -5617,8 +5618,8 @@ MagickXMakeImage(Display *display, } } if ((window->image->matte != MagickFalse) && - (window->pixel_info->colors == 0) - /* && (window->immutable == MagickFalse) */) + (window->pixel_info->colors == 0) + /* && (window->immutable == MagickFalse) */) { Image *texture; @@ -5627,7 +5628,7 @@ MagickXMakeImage(Display *display, Tile background with texture according to opacity */ strlcpy(resource_info->image_info->filename,"image:checkerboard", - sizeof(resource_info->image_info->filename)); + sizeof(resource_info->image_info->filename)); texture=ReadImage(resource_info->image_info,&window->image->exception); if (texture != (Image *) NULL) { @@ -5635,20 +5636,20 @@ MagickXMakeImage(Display *display, *textured_image; textured_image=CloneImage(window->image,0,0,MagickTrue, - &window->image->exception); + &window->image->exception); if (textured_image != (Image *) NULL) { if (TextureImage(textured_image,texture) != MagickFail) - { - if (window->image != image) - DestroyImage(window->image); - window->image=textured_image; - window->destroy=MagickTrue; - } - else - { - DestroyImage(textured_image); - } + { + if (window->image != image) + DestroyImage(window->image); + window->image=textured_image; + window->destroy=MagickTrue; + } + else + { + DestroyImage(textured_image); + } } DestroyImage(texture); texture=(Image *) NULL; @@ -5673,13 +5674,14 @@ MagickXMakeImage(Display *display, *segment_info; size_t - shm_extent; + shm_extent; segment_info=(XShmSegmentInfo *) window->segment_info; segment_info[1].shmid=(-1); segment_info[1].shmaddr=NULL; + shm_extent=0; ximage=XShmCreateImage(display,window->visual,depth,format,(char *) NULL, - &segment_info[1],width,height); + &segment_info[1],width,height); window->shared_memory &= (ximage != (XImage *) NULL); if (window->shared_memory) @@ -5779,9 +5781,9 @@ MagickXMakeImage(Display *display, (void) LogMagickEvent(X11Event,GetMagickModule()," width x height: %dx%d", ximage->width,ximage->height); (void) LogMagickEvent(X11Event,GetMagickModule()," format: %s", - MagickXImageFormatToString(ximage->format)); + MagickXImageFormatToString(ximage->format)); (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %s", - MagickXByteOrderToString(ximage->byte_order)); + MagickXByteOrderToString(ximage->byte_order)); (void) LogMagickEvent(X11Event,GetMagickModule(), " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit, ximage->bitmap_bit_order,ximage->bitmap_pad); @@ -5798,13 +5800,25 @@ MagickXMakeImage(Display *display, if (!window->shared_memory) { if (ximage->format == XYBitmap) - ximage->data= - MagickAllocateArray(char *, - MagickArraySize(ximage->height,ximage->bytes_per_line), - ximage->depth); + { + ximage->data= + MagickAllocateArray(char *, + MagickArraySize(ximage->height, + ximage->bytes_per_line), + ximage->depth); + if (ximage->data != (char *) NULL) + (void) memset(ximage->data,0, + (size_t) ximage->height*ximage->bytes_per_line* + ximage->depth); + } else - ximage->data= - MagickAllocateArray(char *,ximage->height,ximage->bytes_per_line); + { + ximage->data= + MagickAllocateArray(char *,ximage->height,ximage->bytes_per_line); + if (ximage->data != (char *) NULL) + (void) memset(ximage->data,0, + (size_t) ximage->height*ximage->bytes_per_line); + } } if (ximage->data == (char *) NULL) { @@ -5852,7 +5866,7 @@ MagickXMakeImage(Display *display, { XShmSegmentInfo *segment_info; - + segment_info=(XShmSegmentInfo *) window->segment_info; segment_info[0]=segment_info[1]; } @@ -5881,8 +5895,8 @@ MagickXMakeImage(Display *display, Allocate matte image pixel data. */ length=MagickArraySize(MagickArraySize(matte_image->bytes_per_line, - matte_image->height), - matte_image->depth); + matte_image->height), + matte_image->depth); matte_image->data=MagickAllocateMemory(char *,length); if (matte_image->data == (char *) NULL) { @@ -6002,8 +6016,8 @@ MagickXMakeImage(Display *display, */ static void MagickXMakeImageLSBFirst(const MagickXResourceInfo *resource_info, - const MagickXWindowInfo *window,Image *image, - XImage *ximage,XImage *matte_image) + const MagickXWindowInfo *window,Image *image, + XImage *ximage,XImage *matte_image) { int y; @@ -6560,8 +6574,8 @@ MagickXMakeImageLSBFirst(const MagickXResourceInfo *resource_info, */ static void MagickXMakeImageMSBFirst(const MagickXResourceInfo *resource_info, - const MagickXWindowInfo *window,Image *image, - XImage *ximage,XImage *matte_image) + const MagickXWindowInfo *window,Image *image, + XImage *ximage,XImage *matte_image) { int y; @@ -7111,7 +7125,7 @@ MagickXMakeImageMSBFirst(const MagickXResourceInfo *resource_info, % % */ -MagickExport void +MagickExport void MagickXMakeMagnifyImage(Display *display,MagickXWindows *windows) { char @@ -7561,8 +7575,8 @@ MagickXMakeMagnifyImage(Display *display,MagickXWindows *windows) */ static unsigned int MagickXMakePixmap(Display *display, - const MagickXResourceInfo *resource_info, - MagickXWindowInfo *window) + const MagickXResourceInfo *resource_info, + MagickXWindowInfo *window) { unsigned int height, @@ -7698,11 +7712,11 @@ static int PopularityCompare(const void *x,const void *y) MagickExport void MagickXMakeStandardColormap(Display *display, - XVisualInfo *visual_info, - MagickXResourceInfo *resource_info, - Image *image, - XStandardColormap *map_info, - MagickXPixelInfo *pixel) + XVisualInfo *visual_info, + MagickXResourceInfo *resource_info, + Image *image, + XStandardColormap *map_info, + MagickXPixelInfo *pixel) { Colormap colormap; @@ -7853,7 +7867,7 @@ MagickXMakeStandardColormap(Display *display, */ number_colors=image->colors; colors=MagickAllocateArray(XColor *, - visual_info->colormap_size,sizeof(XColor)); + visual_info->colormap_size,sizeof(XColor)); if (colors == (XColor *) NULL) MagickFatalError3(ResourceLimitError,MemoryAllocationFailed, UnableToCreateColormap); @@ -7893,7 +7907,7 @@ MagickXMakeStandardColormap(Display *display, */ number_colors=image->colors; colors=MagickAllocateArray(XColor *, - visual_info->colormap_size,sizeof(XColor)); + visual_info->colormap_size,sizeof(XColor)); if (colors == (XColor *) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, UnableToCreateColormap); @@ -7939,7 +7953,7 @@ MagickXMakeStandardColormap(Display *display, Define Standard colormap for shared GrayScale or PseudoColor visual. */ diversity=MagickAllocateArray(DiversityPacket *, - image->colors,sizeof(DiversityPacket)); + image->colors,sizeof(DiversityPacket)); if (diversity == (DiversityPacket *) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, UnableToCreateColormap); @@ -8001,8 +8015,8 @@ MagickXMakeStandardColormap(Display *display, Read X server colormap. */ server_colors=MagickAllocateArray(XColor *, - visual_info->colormap_size, - sizeof(XColor)); + visual_info->colormap_size, + sizeof(XColor)); if (server_colors == (XColor *) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, UnableToCreateColormap); @@ -8289,8 +8303,8 @@ MagickXMakeStandardColormap(Display *display, */ MagickExport void MagickXMakeWindow(Display *display,Window parent,char **argv, - int argc,XClassHint *class_hint,XWMHints *manager_hints, - MagickXWindowInfo *window_info) + int argc,XClassHint *class_hint,XWMHints *manager_hints, + MagickXWindowInfo *window_info) { #define MinWindowSize 64 @@ -8536,8 +8550,8 @@ MagickXMakeWindow(Display *display,Window parent,char **argv, */ MagickExport unsigned int MagickXMagickMonitor(const char *task, - const magick_int64_t quantum,const magick_uint64_t span, - ExceptionInfo *exception) + const magick_int64_t quantum,const magick_uint64_t span, + ExceptionInfo *exception) { MagickXWindows *windows; @@ -8663,7 +8677,7 @@ MagickXQueryColorDatabase(const char *target,XColor *color) % % */ -MagickExport void +MagickExport void MagickXQueryPosition(Display *display,const Window window,int *x,int *y) { int @@ -8716,7 +8730,7 @@ MagickXQueryPosition(Display *display,const Window window,int *x,int *y) */ MagickExport void MagickXRefreshWindow(Display *display,const MagickXWindowInfo *window, - const XEvent *event) + const XEvent *event) { int x, @@ -8822,7 +8836,7 @@ MagickXRefreshWindow(Display *display,const MagickXWindowInfo *window, */ MagickExport unsigned int MagickXRemoteCommand(Display *display,const char *window, - const char *filename) + const char *filename) { Atom remote_atom; @@ -9175,8 +9189,8 @@ MagickXSignalHandler(int status) */ MagickExport void MagickXSetCursorState(Display *display, - MagickXWindows *windows, - const unsigned int state) + MagickXWindows *windows, + const unsigned int state) { assert(display != (Display *) NULL); assert(windows != (MagickXWindows *) NULL); @@ -9393,7 +9407,7 @@ MagickXVisualClassName(const int visual_class) */ MagickExport void MagickXWarning(const ExceptionType warning, - const char *reason,const char *description) + const char *reason,const char *description) { char text[MaxTextExtent]; @@ -9443,7 +9457,7 @@ MagickXWarning(const ExceptionType warning, */ MagickExport Window MagickXWindowByID(Display *display,const Window root_window, - const unsigned long id) + const unsigned long id) { RectangleInfo rectangle_info; @@ -9517,7 +9531,7 @@ MagickXWindowByID(Display *display,const Window root_window, */ MagickExport Window MagickXWindowByName(Display *display,const Window root_window, - const char *name) + const char *name) { register int i; @@ -9590,7 +9604,7 @@ MagickXWindowByName(Display *display,const Window root_window, */ MagickExport Window MagickXWindowByProperty(Display *display,const Window window, - const Atom property) + const Atom property) { Atom type; diff --git a/magick/xwindow.h b/magick/xwindow.h index b66ff97..ab0e072 100644 --- a/magick/xwindow.h +++ b/magick/xwindow.h @@ -1,11 +1,11 @@ /* Copyright (C) 2003 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio - + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - + X11 Utility Methods for ImageMagick. */ #ifndef _MAGICK_XWINDOW_H @@ -534,7 +534,7 @@ extern MagickExport int MagickXError(Display *,XErrorEvent *); extern MagickExport unsigned int - MagickIsTrue(const char *), + MagickIsTrue(const char *) MAGICK_FUNC_PURE, MagickXAnnotateImage(Display *,const MagickXPixelInfo *,MagickXAnnotateInfo *,Image *), MagickXDisplayBackgroundImage(Display *,MagickXResourceInfo *,Image *), MagickXDrawImage(Display *,const MagickXPixelInfo *,MagickXDrawInfo *,Image *), diff --git a/scripts/gmsymbols.sh b/scripts/gmsymbols.sh new file mode 100755 index 0000000..cbb6140 --- /dev/null +++ b/scripts/gmsymbols.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# Execute like +# gmsymbols.sh magick/.libs/libGraphicsMagick.a MAGICK + +LIB=$1 +SYM=$2 + +cat < """ diff --git a/tests/rwblob.c b/tests/rwblob.c index 9dd30a5..4db481b 100644 --- a/tests/rwblob.c +++ b/tests/rwblob.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2013 GraphicsMagick Group + * Copyright (C) 2003 - 2018 GraphicsMagick Group * Copyright (C) 2003 ImageMagick Studio * Copyright 1991-1999 E. I. du Pont de Nemours and Company * @@ -19,6 +19,7 @@ */ #include +#include #include #include @@ -74,32 +75,14 @@ int main ( int argc, char **argv ) { char *option = argv[arg]; - + if (*option == '-') { if (LocaleCompare("compress",option+1) == 0) { arg++; option=argv[arg]; - imageInfo->compression=UndefinedCompression; - if (LocaleCompare("None",option) == 0) - imageInfo->compression=NoCompression; - if (LocaleCompare("BZip",option) == 0) - imageInfo->compression=BZipCompression; - if (LocaleCompare("Fax",option) == 0) - imageInfo->compression=FaxCompression; - if (LocaleCompare("Group4",option) == 0) - imageInfo->compression=Group4Compression; - if (LocaleCompare("JPEG",option) == 0) - imageInfo->compression=JPEGCompression; - if (LocaleCompare("Lossless",option) == 0) - imageInfo->compression=LosslessJPEGCompression; - if (LocaleCompare("LZW",option) == 0) - imageInfo->compression=LZWCompression; - if (LocaleCompare("RLE",option) == 0) - imageInfo->compression=RLECompression; - if (LocaleCompare("Zip",option) == 0) - imageInfo->compression=ZipCompression; + imageInfo->compression=StringToCompressionType(option); } else if (LocaleCompare("debug",option+1) == 0) { @@ -117,10 +100,10 @@ int main ( int argc, char **argv ) goto program_exit; } if(imageInfo->depth != 8 && imageInfo->depth != 16 && - imageInfo->depth != 32) + imageInfo->depth != 32) { (void) printf("-depth (%ld) not 8, 16, or 32\n", - imageInfo->depth); + imageInfo->depth); (void) fflush(stdout); exit_status = 1; goto program_exit; @@ -184,9 +167,9 @@ int main ( int argc, char **argv ) { (void) printf("arg=%d, argc=%d\n", arg, argc); (void) printf ( "Usage: %s [-compress algorithm -debug events -depth " - "integer -define value -log format -nocheck -quality quality " + "integer -define value -log format -nocheck -quality quality " "-size geometry -verbose] " - "infile format\n", argv[0] ); + "infile format\n", argv[0] ); (void) fflush(stdout); exit_status = 1; goto program_exit; @@ -231,6 +214,8 @@ int main ( int argc, char **argv ) original = ReadImage ( imageInfo, &exception ); if (exception.severity != UndefinedException) { + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); CatchException(&exception); exit_status = 1; goto program_exit; @@ -238,7 +223,7 @@ int main ( int argc, char **argv ) if ( original == (Image *)NULL ) { (void) printf ( "Failed to read original image %s\n", - imageInfo->filename ); + imageInfo->filename ); (void) fflush(stdout); exit_status = 1; goto program_exit; @@ -270,14 +255,24 @@ int main ( int argc, char **argv ) blob =(char *) ImageToBlob ( imageInfo, original, &blob_length, &exception ); if (exception.severity != UndefinedException) { + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); CatchException(&exception); exit_status = 1; goto program_exit; } if ( blob == NULL ) { - (void) printf ( "Failed to write BLOB in format %s\n", - imageInfo->magick ); + (void) printf ( "Failed to write BLOB in format %s (blob is NULL!)\n", + imageInfo->magick ); + (void) fflush(stdout); + exit_status = 1; + goto program_exit; + } + if ( blob_length == 0) + { + (void) printf ( "Failed to write BLOB in format %s (blob length is 0!)\n", + imageInfo->magick ); (void) fflush(stdout); exit_status = 1; goto program_exit; @@ -303,28 +298,30 @@ int main ( int argc, char **argv ) ping_image = PingBlob(imageInfo, blob, blob_length, &exception ); if (exception.severity != UndefinedException) { - CatchException(&exception); - (void) fflush(stderr); - ping_error = MagickTrue; + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); + CatchException(&exception); + (void) fflush(stderr); + ping_error = MagickTrue; } if ( ping_image == (Image *)NULL ) { - (void) printf ( "Failed to ping image from BLOB in format %s\n", - imageInfo->magick ); - (void) fflush(stdout); - ping_error = MagickTrue; + (void) printf ( "Failed to ping image from BLOB in format %s\n", + imageInfo->magick ); + (void) fflush(stdout); + ping_error = MagickTrue; } else { - /* Print a short description of the image to stdout */ - DescribeImage( ping_image, stdout, MagickFalse ); - (void) fflush(stdout); - DestroyImageList( ping_image ); + /* Print a short description of the image to stdout */ + DescribeImage( ping_image, stdout, MagickFalse ); + (void) fflush(stdout); + DestroyImageList( ping_image ); } if (ping_error) { - exit_status = 1; - goto program_exit; + exit_status = 1; + goto program_exit; } } @@ -338,6 +335,8 @@ int main ( int argc, char **argv ) original = BlobToImage( imageInfo, blob, blob_length, &exception ); if (exception.severity != UndefinedException) { + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); CatchException(&exception); exit_status = 1; goto program_exit; @@ -345,7 +344,7 @@ int main ( int argc, char **argv ) if ( original == (Image *)NULL ) { (void) printf ( "Failed to read image from BLOB in format %s\n", - imageInfo->magick ); + imageInfo->magick ); (void) fflush(stdout); exit_status = 1; goto program_exit; @@ -361,9 +360,11 @@ int main ( int argc, char **argv ) (void) strcpy( imageInfo->filename, "" ); original->delay = 10; blob = (char *) ImageToBlob ( imageInfo, original, &blob_length, - &exception ); + &exception ); if (exception.severity != UndefinedException) { + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); CatchException(&exception); exit_status = 1; goto program_exit; @@ -372,7 +373,7 @@ int main ( int argc, char **argv ) if ( blob == NULL ) { (void) printf ( "Failed to write BLOB in format %s\n", - imageInfo->magick ); + imageInfo->magick ); (void) fflush(stdout); exit_status = 1; goto program_exit; @@ -390,6 +391,8 @@ int main ( int argc, char **argv ) final = BlobToImage( imageInfo, blob, blob_length, &exception ); if (exception.severity != UndefinedException) { + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); CatchException(&exception); exit_status = 1; goto program_exit; @@ -397,7 +400,7 @@ int main ( int argc, char **argv ) if ( final == (Image *)NULL ) { (void) printf ( "Failed to read image from BLOB in format %s\n", - imageInfo->magick ); + imageInfo->magick ); (void) fflush(stdout); exit_status = 1; goto program_exit; @@ -411,10 +414,10 @@ int main ( int argc, char **argv ) * Check final output */ double - fuzz_factor = 0; + fuzz_factor = 0; /* - Some formats are lossy. + Some formats are lossy. */ if ((!strcmp( "CIN", format ) && (QuantumDepth == 8)) || (!strcmp( "CMYK", format )) || @@ -433,76 +436,90 @@ int main ( int argc, char **argv ) (final->compression == JPEGCompression)) fuzz_factor = 0.06; + switch(imageInfo->compression) + { + case JPEGCompression: + case JPEG2000Compression: + case WebPCompression: + { + fuzz_factor = 0.06; + break; + } + default: + { + } + } + { - Image - *o, - *f; - - unsigned long - frame=0; - - /* - Verify that frame pixels are identical (or close enough). - */ - for (o=original, f=final, frame=0; - ((o != (Image *) NULL) && (f != (Image *) NULL)) ; - o = o->next, f = f->next, frame++) - { - printf("Checking frame %ld...\n",frame); - if ( !IsImagesEqual(o, f ) && - (original->error.normalized_mean_error > fuzz_factor) ) - { - (void) printf( "R/W file check for format \"%s\" failed " - "(frame = %ld): %.6f/%.6f/%.6fe\n", - format,frame, - original->error.mean_error_per_pixel, - original->error.normalized_mean_error, - original->error.normalized_maximum_error); - (void) fflush(stdout); - exit_status = 1; - goto program_exit; - } - } - - if (check_for_added_frames) - { - /* - Verify that reads from BLOB R/W #1 and BLOB R/W #2 did - return the same number of frames. - */ - if ((o != (Image *) NULL) && (f != (Image *) NULL)) - { - (void) printf("R/W file check for format \"%s\" failed due to " - "differing number of returned frames (%ld vs %ld)\n", - format, - GetImageListLength(original), - GetImageListLength(final)); - exit_status = 1; - goto program_exit; - } - - /* - If format supports multiple frames, then we should expect - that frames are not lost (or spuriously added) due to - read/write of format. - */ - if (magick_info->adjoin) - { - unsigned long - final_frames; - - final_frames=GetImageListLength(final); - if (original_frames != final_frames) - { - (void) printf("R/W file check for format \"%s\" failed due " - "to differing number of returned frames (%ld " - "vs %ld) from original file\n", - format,original_frames,final_frames); - exit_status = 1; - goto program_exit; - } - } - } + Image + *o, + *f; + + unsigned long + frame=0; + + /* + Verify that frame pixels are identical (or close enough). + */ + for (o=original, f=final, frame=0; + ((o != (Image *) NULL) && (f != (Image *) NULL)) ; + o = o->next, f = f->next, frame++) + { + printf("Checking frame %ld...\n",frame); + if ( !IsImagesEqual(o, f ) && + (original->error.normalized_mean_error > fuzz_factor) ) + { + (void) printf( "R/W file check for format \"%s\" failed " + "(frame = %ld): %.6f/%.6f/%.6fe\n", + format,frame, + original->error.mean_error_per_pixel, + original->error.normalized_mean_error, + original->error.normalized_maximum_error); + (void) fflush(stdout); + exit_status = 1; + goto program_exit; + } + } + + if (check_for_added_frames) + { + /* + Verify that reads from BLOB R/W #1 and BLOB R/W #2 did + return the same number of frames. + */ + if ((o != (Image *) NULL) && (f != (Image *) NULL)) + { + (void) printf("R/W file check for format \"%s\" failed due to " + "differing number of returned frames (%ld vs %ld)\n", + format, + GetImageListLength(original), + GetImageListLength(final)); + exit_status = 1; + goto program_exit; + } + + /* + If format supports multiple frames, then we should expect + that frames are not lost (or spuriously added) due to + read/write of format. + */ + if (magick_info->adjoin) + { + unsigned long + final_frames; + + final_frames=GetImageListLength(final); + if (original_frames != final_frames) + { + (void) printf("R/W file check for format \"%s\" failed due " + "to differing number of returned frames (%ld " + "vs %ld) from original file\n", + format,original_frames,final_frames); + exit_status = 1; + goto program_exit; + } + } + } } } diff --git a/tests/rwblob.tap b/tests/rwblob.tap index c78429a..8292c67 100755 --- a/tests/rwblob.tap +++ b/tests/rwblob.tap @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (C) 2004-2015 GraphicsMagick Group +# Copyright (C) 2004-2018 GraphicsMagick Group . ./common.shi . ${top_srcdir}/tests/common.shi @@ -10,7 +10,7 @@ rwblob=./rwblob check_types='bilevel gray pallette truecolor' # Number of tests we plan to run -test_plan_fn 204 +test_plan_fn 209 # ART format for type in ${check_types} @@ -29,6 +29,8 @@ for type in ${check_types} do test_command_fn "BMP ${type}" ${MEMCHECK} ${rwblob} "${SRCDIR}/input_${type}.miff" BMP done +# Special test to verify that lower-case magick works +test_command_fn "BMP truecolor" ${MEMCHECK} ${rwblob} "${SRCDIR}/input_${type}.miff" bmp # BMP2 format for type in ${check_types} @@ -222,6 +224,12 @@ do test_command_fn "PPM ${type}" ${MEMCHECK} ${rwblob} "${SRCDIR}/input_${type}.miff" PPM done +# PTIF format +for type in ${check_types} +do + test_command_fn "PTIF ${type}" -F TIFF ${MEMCHECK} ${rwblob} "${SRCDIR}/input_${type}.miff" PTIF +done + # RAS format for type in ${check_types} do diff --git a/tests/rwfile.c b/tests/rwfile.c index 946688e..9bb151a 100644 --- a/tests/rwfile.c +++ b/tests/rwfile.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2013 GraphicsMagick Group + * Copyright (C) 2003 - 2018 GraphicsMagick Group * Copyright (C) 2003 ImageMagick Studio * Copyright 1991-1999 E. I. du Pont de Nemours and Company * @@ -19,6 +19,7 @@ * */ #include +#include #include #include @@ -81,34 +82,14 @@ int main ( int argc, char **argv ) { char *option = argv[arg]; - + if (*option == '-') { if (LocaleCompare("compress",option+1) == 0) { arg++; option=argv[arg]; - imageInfo->compression=UndefinedCompression; - if (LocaleCompare("Undefined",option) == 0) - imageInfo->compression=UndefinedCompression; - if (LocaleCompare("None",option) == 0) - imageInfo->compression=NoCompression; - if (LocaleCompare("BZip",option) == 0) - imageInfo->compression=BZipCompression; - if (LocaleCompare("Fax",option) == 0) - imageInfo->compression=FaxCompression; - if (LocaleCompare("Group4",option) == 0) - imageInfo->compression=Group4Compression; - if (LocaleCompare("JPEG",option) == 0) - imageInfo->compression=JPEGCompression; - if (LocaleCompare("Lossless",option) == 0) - imageInfo->compression=LosslessJPEGCompression; - if (LocaleCompare("LZW",option) == 0) - imageInfo->compression=LZWCompression; - if (LocaleCompare("RLE",option) == 0) - imageInfo->compression=RLECompression; - if (LocaleCompare("Zip",option) == 0) - imageInfo->compression=ZipCompression; + imageInfo->compression=StringToCompressionType(option); } else if (LocaleCompare("debug",option+1) == 0) { @@ -142,19 +123,19 @@ int main ( int argc, char **argv ) goto program_exit; } if(imageInfo->depth != 8 && imageInfo->depth != 16 && - imageInfo->depth != 32) + imageInfo->depth != 32) { (void) printf("-depth (%ld) not 8, 16, or 32\n", - imageInfo->depth); + imageInfo->depth); (void) fflush(stdout); exit_status = 1; goto program_exit; } } - else if (LocaleCompare("filespec",option+1) == 0) - { - (void) strcpy(basefilespec,argv[++arg]); - } + else if (LocaleCompare("filespec",option+1) == 0) + { + (void) strcpy(basefilespec,argv[++arg]); + } else if (LocaleCompare("log",option+1) == 0) { (void) SetLogFormat(argv[++arg]); @@ -183,7 +164,7 @@ int main ( int argc, char **argv ) } (void) CloneString(&imageInfo->size,argv[arg]); } - else if (LocaleCompare("stdio",option+1) == 0) + else if (LocaleCompare("stdio",option+1) == 0) { use_stdio=MagickTrue; } @@ -209,7 +190,7 @@ int main ( int argc, char **argv ) exit_status = 1; goto program_exit; } - + (void) strncpy(infile, argv[arg], MaxTextExtent-1 ); arg++; (void) strncpy( format, argv[arg], MaxTextExtent-1 ); @@ -242,16 +223,16 @@ int main ( int argc, char **argv ) if (use_stdio) { (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Reading stdio image %s", infile); + "Reading stdio image %s", infile); imageInfo->file=fopen(infile,"rb"); } else { (void) strncpy( imageInfo->filename, infile, MaxTextExtent-1 ); if (!magick_info->adjoin || !check_for_added_frames) - (void) strcat( imageInfo->filename, "[0]" ); + (void) strcat( imageInfo->filename, "[0]" ); (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Reading image %s", imageInfo->filename); + "Reading image %s", imageInfo->filename); } original = ReadImage ( imageInfo, &exception ); if (use_stdio) @@ -261,6 +242,8 @@ int main ( int argc, char **argv ) } if (exception.severity != UndefinedException) { + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); CatchException(&exception); exit_status = 1; goto program_exit; @@ -268,7 +251,7 @@ int main ( int argc, char **argv ) if ( original == (Image *)NULL ) { (void) printf ( "Failed to read original image %s\n", - imageInfo->filename ); + imageInfo->filename ); (void) fflush(stdout); exit_status = 1; goto program_exit; @@ -295,7 +278,7 @@ int main ( int argc, char **argv ) if (IgnoreExtensionTreatment == magick_info->extension_treatment) { /* - Prepend magic specifier if extension will be ignored. + Prepend magic specifier if extension will be ignored. */ (void) strcpy(filespec,format); (void) strcat(filespec,":"); @@ -320,18 +303,20 @@ int main ( int argc, char **argv ) if (use_stdio) { (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Writing stdio image %s", filename); + "Writing stdio image %s", filename); imageInfo->file=fopen(filename,"wb+"); } else { (void) strncpy( original->filename, filename, MaxTextExtent-1 ); (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Writing image %s", original->filename); + "Writing image %s", original->filename); } original->delay = 10; if (!WriteImage ( imageInfo, original )) { + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); CatchException(&original->exception); exit_status = 1; goto program_exit; @@ -359,11 +344,11 @@ int main ( int argc, char **argv ) (void) strncpy( imageInfo->magick, format, MaxTextExtent-1 ); if (use_stdio) { - imageInfo->file=fopen(filename,"rb"); + imageInfo->file=fopen(filename,"rb"); } else { - strncpy( imageInfo->filename, filename, MaxTextExtent-1 ); + strncpy( imageInfo->filename, filename, MaxTextExtent-1 ); } if ( size[0] != '\0' ) (void) CloneString( &imageInfo->size, size ); @@ -371,32 +356,34 @@ int main ( int argc, char **argv ) ping_image = PingImage(imageInfo, &exception ); if (use_stdio) { - (void) fclose(imageInfo->file); - imageInfo->file = (FILE *) NULL; + (void) fclose(imageInfo->file); + imageInfo->file = (FILE *) NULL; } if (exception.severity != UndefinedException) { - CatchException(&exception); - (void) fflush(stderr); - ping_error = MagickTrue; + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); + CatchException(&exception); + (void) fflush(stderr); + ping_error = MagickTrue; } if ( ping_image == (Image *)NULL ) { - (void) printf ( "Failed to ping image from file \"%s\" in format %s\n", - filename, imageInfo->magick ); - (void) fflush(stdout); - ping_error = MagickTrue; + (void) printf ( "Failed to ping image from file \"%s\" in format %s\n", + filename, imageInfo->magick ); + (void) fflush(stdout); + ping_error = MagickTrue; } else { - /* Print a short description of the image to stdout */ - DescribeImage( ping_image, stdout, MagickFalse ); - DestroyImageList( ping_image ); + /* Print a short description of the image to stdout */ + DescribeImage( ping_image, stdout, MagickFalse ); + DestroyImageList( ping_image ); } if (ping_error) { - exit_status = 1; - goto program_exit; + exit_status = 1; + goto program_exit; } } @@ -424,6 +411,8 @@ int main ( int argc, char **argv ) } if (exception.severity != UndefinedException) { + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); CatchException(&exception); exit_status = 1; goto program_exit; @@ -449,19 +438,21 @@ int main ( int argc, char **argv ) if (use_stdio) { (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Writing stdio image %s", filename); + "Writing stdio image %s", filename); imageInfo->file=fopen(filename,"wb+"); } else { (void) strncpy( original->filename, filename, MaxTextExtent-1 ); (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Writing stdio image %s", original->filename); + "Writing stdio image %s", original->filename); } original->delay = 10; (void) fflush(stdout); if(!WriteImage (imageInfo,original)) { + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); CatchException(&original->exception); exit_status = 1; goto program_exit; @@ -493,6 +484,8 @@ int main ( int argc, char **argv ) final = ReadImage ( imageInfo, &exception ); if (exception.severity != UndefinedException) { + if (exception.reason) + (void) printf(" reason:%s\n",exception.reason); CatchException(&exception); exit_status = 1; goto program_exit; @@ -512,10 +505,10 @@ int main ( int argc, char **argv ) * Check final output */ double - fuzz_factor = 0; + fuzz_factor = 0; /* - Some formats are lossy. + Some formats are lossy. */ if ((!strcmp( "CIN", format ) && (QuantumDepth == 8)) || (!strcmp( "CMYK", format )) || @@ -534,76 +527,90 @@ int main ( int argc, char **argv ) (final->compression == JPEGCompression)) fuzz_factor = 0.06; + switch(imageInfo->compression) + { + case JPEGCompression: + case JPEG2000Compression: + case WebPCompression: + { + fuzz_factor = 0.06; + break; + } + default: + { + } + } + { - Image - *o, - *f; - - unsigned long - frame=0; - - /* - Verify that frame pixels are identical (or close enough). - */ - for (o=original, f=final, frame=0; - ((o != (Image *) NULL) && (f != (Image *) NULL)) ; - o = o->next, f = f->next, frame++) - { - printf("Checking frame %ld...\n",frame); - if ( !IsImagesEqual(o, f ) && - (original->error.normalized_mean_error > fuzz_factor) ) - { - (void) printf( "R/W file check for format \"%s\" failed " - "(frame = %ld): %.6f/%.6f/%.6fe\n", - format,frame, - original->error.mean_error_per_pixel, - original->error.normalized_mean_error, - original->error.normalized_maximum_error); - (void) fflush(stdout); - exit_status = 1; - goto program_exit; - } - } - - if (check_for_added_frames) - { - /* - Verify that reads from file R/W #1 and file R/W #2 did - return the same number of frames. - */ - if ((o != (Image *) NULL) && (f != (Image *) NULL)) - { - (void) printf("R/W file check for format \"%s\" failed due to " - "differing number of returned frames (%ld vs %ld)\n", - format, - GetImageListLength(original), - GetImageListLength(final)); - exit_status = 1; - goto program_exit; - } - - /* - If format supports multiple frames, then we should expect - that frames are not lost (or spuriously added) due to - read/write of format. - */ - if (magick_info->adjoin) - { - unsigned long - final_frames; - - final_frames=GetImageListLength(final); - if (original_frames != final_frames) - { - (void) printf("R/W file check for format \"%s\" failed due " - "to differing number of returned frames (%ld " - "vs %ld) from original file\n", - format,original_frames,final_frames); - exit_status = 1; - goto program_exit; - } - } - } + Image + *o, + *f; + + unsigned long + frame=0; + + /* + Verify that frame pixels are identical (or close enough). + */ + for (o=original, f=final, frame=0; + ((o != (Image *) NULL) && (f != (Image *) NULL)) ; + o = o->next, f = f->next, frame++) + { + printf("Checking frame %ld...\n",frame); + if ( !IsImagesEqual(o, f ) && + (original->error.normalized_mean_error > fuzz_factor) ) + { + (void) printf( "R/W file check for format \"%s\" failed " + "(frame = %ld): %.6f/%.6f/%.6fe\n", + format,frame, + original->error.mean_error_per_pixel, + original->error.normalized_mean_error, + original->error.normalized_maximum_error); + (void) fflush(stdout); + exit_status = 1; + goto program_exit; + } + } + + if (check_for_added_frames) + { + /* + Verify that reads from file R/W #1 and file R/W #2 did + return the same number of frames. + */ + if ((o != (Image *) NULL) && (f != (Image *) NULL)) + { + (void) printf("R/W file check for format \"%s\" failed due to " + "differing number of returned frames (%ld vs %ld)\n", + format, + GetImageListLength(original), + GetImageListLength(final)); + exit_status = 1; + goto program_exit; + } + + /* + If format supports multiple frames, then we should expect + that frames are not lost (or spuriously added) due to + read/write of format. + */ + if (magick_info->adjoin) + { + unsigned long + final_frames; + + final_frames=GetImageListLength(final); + if (original_frames != final_frames) + { + (void) printf("R/W file check for format \"%s\" failed due " + "to differing number of returned frames (%ld " + "vs %ld) from original file\n", + format,original_frames,final_frames); + exit_status = 1; + goto program_exit; + } + } + } } } diff --git a/tests/rwfile.tap b/tests/rwfile.tap index f86c3a0..b26dee7 100755 --- a/tests/rwfile.tap +++ b/tests/rwfile.tap @@ -1,6 +1,6 @@ #!/bin/sh # -*- shell-script -*- -# Copyright (C) 2004-2015 GraphicsMagick Group +# Copyright (C) 2004-2017 GraphicsMagick Group . ./common.shi . ${top_srcdir}/tests/common.shi @@ -11,7 +11,7 @@ rwfile=./rwfile check_types='bilevel gray pallette truecolor' # Number of tests we plan to run -test_plan_fn 564 +test_plan_fn 648 # ART format for type in ${check_types} @@ -202,6 +202,27 @@ do test_command_fn "MIFF ${type} (stdio)" ${MEMCHECK} ${rwfile} -stdio -filespec "out_${type}_stdio_%d" "${SRCDIR}/input_${type}.miff" MIFF done +for type in ${check_types} +do + test_command_fn "MIFF RLE compressed ${type}" ${MEMCHECK} ${rwfile} -compress RLE -filespec "out_${type}_rle_%d" "${SRCDIR}/input_${type}.miff" MIFF +done + +# Normally one would expect that -F BZLIB is required, but bzip +# compression is silently translated to no compression if not +# available. +for type in ${check_types} +do + test_command_fn "MIFF BZIP compressed ${type}" ${MEMCHECK} ${rwfile} -compress BZIP -filespec "out_${type}_bzip_%d" "${SRCDIR}/input_${type}.miff" MIFF +done + +# Normally one would expect that -F ZLIB is required, but zip +# compression is silently translated to no compression if not +# available. +for type in ${check_types} +do + test_command_fn "MIFF ZIP compressed ${type}" ${rwfile} -compress ZIP -filespec "out_${type}_zip_%d" "${SRCDIR}/input_${type}.miff" MIFF +done + # MNG format for type in ${check_types} do @@ -406,10 +427,13 @@ do done # TIFF format -for type in ${check_types} +for compress in None Fax Group4 JPEG LZW RLE Zip LZMA WebP ZSTD do - test_command_fn "TIFF ${type}" -F TIFF ${MEMCHECK} ${rwfile} -filespec "out_${type}_%d" "${SRCDIR}/input_${type}.miff" TIFF - test_command_fn "TIFF ${type} (stdio)" -F TIFF ${MEMCHECK} ${rwfile} -stdio -filespec "out_${type}_stdio_%d" "${SRCDIR}/input_${type}.miff" TIFF + for type in ${check_types} + do + test_command_fn "TIFF ${type} compress=${compress}" -F TIFF ${MEMCHECK} ${rwfile} -compress ${compress} -filespec "out_${type}_${compress}_%d" "${SRCDIR}/input_${type}.miff" TIFF + test_command_fn "TIFF ${type} compress=${compress} (stdio)" -F TIFF ${MEMCHECK} ${rwfile} -stdio -compress ${compress} -filespec "out_${type}_${compress}_stdio_%d" "${SRCDIR}/input_${type}.miff" TIFF + done done # VDA format diff --git a/utilities/Makefile.am b/utilities/Makefile.am index 8b6178c..47e01c3 100644 --- a/utilities/Makefile.am +++ b/utilities/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2012 GraphicsMagick Group +# Copyright (C) 2004-2018 GraphicsMagick Group # # This program is covered by multiple licenses, which are described in # Copyright.txt. You should have received a copy of Copyright.txt with this @@ -16,7 +16,7 @@ utilities_gm_LDFLAGS = $(LDFLAGS) utilities_gm_SOURCES = utilities/gm.c -UTILITIES_XFAIL_TESTS = +UTILITIES_XFAIL_TESTS = # Tests to run UTILITIES_TESTS = \ @@ -32,7 +32,7 @@ UTILITIES_TESTS = \ utilities/tests/preview.tap utilities/tests/montage.log : \ - utilities/tests/effects.tap + utilities/tests/effects.log UTILITIES_MANS = \ utilities/gm.1 \ diff --git a/utilities/gm.1 b/utilities/gm.1 index 889c3a1..3525e0b 100644 --- a/utilities/gm.1 +++ b/utilities/gm.1 @@ -1,4 +1,4 @@ -.TH gm 1 "2017/01/29" "GraphicsMagick" +.TH gm 1 "2018/10/14" "GraphicsMagick" .TP .in 15 .in 15 @@ -1040,9 +1040,10 @@ space, then the change-image pixel intensities are used. \fRthe type of image compression Choices are: \fINone\fP, \fIBZip\fP, \fIFax\fP, -\fIGroup4\fP, +\fIGroup3\fP, \fIGroup4\fP, \fIJPEG\fP, \fILossless\fP, -\fILZW\fP, \fIRLE\fP, \fIZip\fP, or \fILZMA\fP. +\fILZW\fP, \fIRLE\fP, \fIZip\fP, \fILZMA\fP, \fIJPEG2000\fP, +\fIJPEG2000\fP, \fIJBIG\fP, \fIJBIG2\fP, \fIWebP\fP, or \fIZSTD\fP. Specify \fB+compress\fP to store the binary image in an uncompressed format. @@ -1052,10 +1053,11 @@ The default is the compression type of the specified image file. the JPEG library has been patched to support it. Use of lossless JPEG is generally not recommended. -Use the \fB-quality\fP option to set the compression level to be used by -JPEG, PNG, MIFF, and MPEG encoders. Use the \fB-sampling-factor\fP -option to set the sampling factor to be used by the DPX, JPEG, MPEG, and -YUV encoders for downsampling the chroma channels. +Use the \fB-quality\fP option to set the compression level to be used +by the JPEG, JPEG-2000, PNG, MIFF, MPEG, and TIFF encoders. Use the +\fB-sampling-factor\fP option to set the sampling factor to be used +by the DPX, JPEG, MPEG, and YUV encoders for downsampling the chroma +channels. .TP .B "-contrast" \fRenhance or reduce the image contrast @@ -1220,7 +1222,7 @@ type implied by the DPX header (if any). .in 20 DPX samples are output within 32-bit words. They may be tightly packed end-to-end within the words ("packed"), padded with null bits to -the right of the sample ("a" or "lsbpad), or padded with null bits to the +the right of the sample ("a" or "lsbpad"), or padded with null bits to the left of the sample ("b" or "msbpad"). This option only has an effect for sample sizes of 10 or 12 bits. If samples are not packed, the DPX standard recommends type A padding. Many DPX readers demand a sample size @@ -1297,11 +1299,31 @@ Enables or disables fancy upsampling when reading a JPEG file .in 15 .in 15 -.B "jpeg:optimize-coding={true|false}" +.B "jpeg:max-scan-number=" +.in 20 + \fR +.in 20 +Specifies an integer value for the maximum number of progressive +scans allowed in a JPEG file. The default maximum is 100 scans. This +limit is imposed due to a weakness in the JPEG standard which allows +small JPEG files to take many minutes or hours to be read. + +.in 15 +.in 15 +.B "jpeg:max-warnings=" .in 20 \fR .in 20 +Specifies an integer value for how many warnings are allowed for +any given error type before being promoted to a hard error. JPEG +files producing excessive warnings indicate a problem with the file. +.in 15 +.in 15 +.B "jpeg:optimize-coding={true|false}" +.in 20 + \fR +.in 20 Selects if huffman encoding should be used. Huffman encoding is enabled by default, but may be disabled for very large images since it encoding requires that the entire image be buffered in memory. Huffman encoding @@ -1333,6 +1355,17 @@ requested to scale the image to fit the page size (width and/or height). .in 15 .in 15 +.B "mng:maximum-loops=" +.in 20 + \fR +.in 20 +mng:maximum-loops specifies the maximum number of loops allowed to +be specified by a MNG LOOP chunk. Without an imposed limit, a MNG file +could request up to 2147483647 loops, which could run for a very long +time. The current default limit is 512 loops. + +.in 15 +.in 15 .B "pdf:use-cropbox={true|false}" .in 20 \fR @@ -1363,6 +1396,17 @@ imagemask operator instead of the image operator. .in 15 .in 15 +.B "ptif:minimum-geometry=" +.in 20 + \fR +.in 20 +If the ptif:minimum-geometry key is defined, GraphicsMagick will +use it to determine the minimum frame size to output when writing a +pyramid TIFF file (a TIFF file containing a succession of reduced +versions of the first frame). The default minimum geometry is 32x32. + +.in 15 +.in 15 .B "tiff:alpha={unspecified|associated|unassociated}" .in 20 \fR @@ -1568,6 +1612,30 @@ Enables tiled TIFF if it has not already been enabled. .in 15 .in 15 +.B "tiff:webp-lossless={TRUE|FALSE}" +.in 20 + \fR +.in 20 +Specify a value of \fBTRUE\fP to enable lossless mode while +writing WebP-compressed TIFF files. The WebP \fBwebp:lossless\fP +option may also be used. The quality factor set by the +\fB-quality\fP option may be used to influence the level of effort +expended while compressing. + +.in 15 +.in 15 +.B "tiff:zstd-compress-level=" +.in 20 + \fR +.in 20 +Specify the compression level to use while writing Zstd-compressed +TIFF files. The valid range is 1 to 22. If this define is not +specified, then the 'quality' value is used such that the default +quality setting of 75 is translated to a compress level of 9 such that +\'quality' has a useful range of 10-184 if used for this purpose. + +.in 15 +.in 15 .B "webp:lossless={true|false}" .in 20 \fR @@ -3512,12 +3580,21 @@ first, e.g., with the "-gamma 0.45455" option. \fRoutput files to directory Use -output-directory to specify a directory under which to write the -output files. Normally mogrify overwrites the input files but with this -option the output files may be written to a different directory so that -the input files are preserved. The algorithm used preserves all of the -input path specification in the output path so that the user-specified -input path (including any directory part) is appended to the output path. -The user is responsible for creating the output directory. +output files. Normally mogrify overwrites the input files, but with +this option the output files may be written to a different directory +tree so that the input files are preserved. The algorithm used +preserves all of the input path specification in the output path so +that the user-specified input path (including any sub-directory part) +is appended to the output path. If the input file lacks an extension, +then a suitable extension is automatically added to the output file. +The user is responsible for creating the output directory specified as +an argument, but subdirectories will be created as needed if the +\fB-create-directories\fP option is supplied. This option may be +used to apply transformations on files from one directory and write +the transformed files to a different directory. In conjunction with +\fB-create-directories\fP, this option is designed to support +transforming whole directory trees of files provided that the relative +path of the input file is included as part the list of filenames. .TP .B "-orient \fI"\fP \fRSet the image orientation attribute @@ -3819,7 +3896,7 @@ When writing a JNG image with transparency, two quality values are required, one for the main image and one for the grayscale image that conveys the opacity channel. These are written as a single integer equal to the main image quality plus 1000 times the opacity quality. For example, if you -want to use quality 75 for the main image and quality 90 to compress +want to use quality 75 for the main image and quality 90 to compress the opacity data, use -quality 90075. For the PNM family of formats (PNM, PGM, and PPM) specify a quality @@ -3827,6 +3904,14 @@ factor of zero in order to obtain the ASCII variant of the format. Note that -compress \fInone\fP used to be used to trigger ASCII output but provided the opposite result of what was expected as compared with other formats. + +For the TIFF format, the JPEG, WebP, Zip, and Zstd compression +algorithms are influenced by the quality value. JPEG and WebP provide +lossy compression so higher quality produces a larger file with less +degradation. The Zip and Zstd compression algorithms (and WebP in +lossless mode) are lossless and for these algorithms a higher +\'quality' means to work harder to produce a smaller file, but with no +difference in image quality. .TP .B "-raise \fIx"\fP \fRlighten or darken image edges @@ -10430,35 +10515,35 @@ software was configured and the host system. .SH EXAMPLES To display the version information: - % gm -version - GraphicsMagick 1.3.19 2013-12-31 Q16 http://www.GraphicsMagick.org/ - Copyright (C) 2002-2013 GraphicsMagick Group. + GraphicsMagick 1.3.27a 2017-12-11 Q16 http://www.GraphicsMagick.org/ + Copyright (C) 2002-2017 GraphicsMagick Group. Additional copyrights and licenses apply to this software. See http://www.GraphicsMagick.org/www/Copyright.html for details. Feature Support: - Thread Safe yes + Native Thread Safe yes Large Files (> 32 bit) yes - Large Memory (> 32 bit) no + Large Memory (> 32 bit) yes BZIP yes DPS no FlashPix no FreeType yes Ghostscript (Library) no - JBIG no + JBIG yes JPEG-2000 yes JPEG yes Little CMS yes Loadable Modules no - OpenMP yes (201107) + OpenMP yes (201307) PNG yes TIFF yes TRIO no - UMEM yes - WMF no + UMEM no + WebP yes + WMF yes X11 yes XML yes ZLIB yes - Host type: i386-pc-solaris2.11 + Host type: x86_64-unknown-linux-gnu Configured using the command: ./configure ... Final Build Parameters: diff --git a/version.sh b/version.sh index 4ff58a6..b9ffa0c 100755 --- a/version.sh +++ b/version.sh @@ -17,7 +17,7 @@ PACKAGE_BUGREPORT='graphicsmagick-bugs@lists.sourceforge.net' # Package base version. This is is the numeric version suffix applied to # PACKAGE_NAME (e.g. "1.2"). -PACKAGE_VERSION='1.3.26' +PACKAGE_VERSION='1.3.31' # # Package name plus version string. @@ -27,7 +27,7 @@ PACKAGE_STRING="$PACKAGE_NAME $PACKAGE_VERSION" # # Formal Package release date # Set to string "unreleased" if package is not a formal release. -PACKAGE_RELEASE_DATE="2017-07-04" +PACKAGE_RELEASE_DATE="2018-11-17" #PACKAGE_RELEASE_DATE="unreleased" # @@ -50,7 +50,7 @@ fi # # Mercurial branch that this release is on. # -HG_BRANCH_TAG=default +HG_BRANCH_TAG=GraphicsMagick-1_3 # # Libtool library revision control info @@ -86,21 +86,20 @@ HG_BRANCH_TAG=default # # Magick library versioning # -MAGICK_LIBRARY_CURRENT=19 - +MAGICK_LIBRARY_CURRENT=22 MAGICK_LIBRARY_REVISION=0 -MAGICK_LIBRARY_AGE=16 +MAGICK_LIBRARY_AGE=19 # # Magick++ library versioning # -MAGICK_PLUS_PLUS_LIBRARY_CURRENT=14 +MAGICK_PLUS_PLUS_LIBRARY_CURRENT=16 MAGICK_PLUS_PLUS_LIBRARY_REVISION=0 -MAGICK_PLUS_PLUS_LIBRARY_AGE=2 +MAGICK_PLUS_PLUS_LIBRARY_AGE=4 # # Magick Wand library versioning # -MAGICK_WAND_LIBRARY_CURRENT=10 -MAGICK_WAND_LIBRARY_REVISION=0 -MAGICK_WAND_LIBRARY_AGE=8 +MAGICK_WAND_LIBRARY_CURRENT=11 +MAGICK_WAND_LIBRARY_REVISION=1 +MAGICK_WAND_LIBRARY_AGE=9 diff --git a/wand/GraphicsMagickWand-config.1 b/wand/GraphicsMagickWand-config.1 index aded420..a0fcb4e 100644 --- a/wand/GraphicsMagickWand-config.1 +++ b/wand/GraphicsMagickWand-config.1 @@ -4,7 +4,7 @@ .SH NAME GraphicsMagickWand-config \- get information about the installed version of GraphicsMagick .SH SYNOPSIS -.B GraphicsMagickWand-config +.B GraphicsMagickWand-config .B [--cflags] .B [--cppflags] .B [--exec-prefix] @@ -26,8 +26,8 @@ use: .nf GraphicsMagickWand-config --version .fi - -To compile a program that calls the + +To compile a program that calls the .B GraphicsMagick Wand Application Programmer Interface, use: @@ -38,7 +38,7 @@ Application Programmer Interface, use: .SH OPTIONS .TP .B --cflags -Print the compiler flags that were used to compile +Print the compiler flags that were used to compile .BR libGraphicsMagick . .TP .B --cppflags diff --git a/wand/drawing_wand.c b/wand/drawing_wand.c index 55a1347..b4d82fa 100644 --- a/wand/drawing_wand.c +++ b/wand/drawing_wand.c @@ -246,33 +246,33 @@ static int MvgPrintf(DrawingWand *drawing_wand,const char *format,...) */ { size_t - space_available; - + space_available; + space_available=drawing_wand->mvg_alloc-drawing_wand->mvg_length-1; formatted_length = -1; if (space_available > 0) - { - - va_start(argp, format); + { + + va_start(argp, format); #if defined(HAVE_VSNPRINTF) - formatted_length=vsnprintf(drawing_wand->mvg+drawing_wand->mvg_length, - (size_t) space_available,format,argp); + formatted_length=vsnprintf(drawing_wand->mvg+drawing_wand->mvg_length, + (size_t) space_available,format,argp); #else - formatted_length=vsprintf(drawing_wand->mvg+drawing_wand->mvg_length, - format,argp); + formatted_length=vsprintf(drawing_wand->mvg+drawing_wand->mvg_length, + format,argp); #endif - va_end(argp); - } + va_end(argp); + } if ((formatted_length < 0) || ((size_t) formatted_length > space_available)) - { - ThrowException(&drawing_wand->exception,DrawError, - UnableToPrint,format); - } + { + ThrowException(&drawing_wand->exception,DrawError, + UnableToPrint,format); + } else - { - drawing_wand->mvg_length+=formatted_length; - drawing_wand->mvg_width+=formatted_length; - } + { + drawing_wand->mvg_length+=formatted_length; + drawing_wand->mvg_width+=formatted_length; + } } drawing_wand->mvg[drawing_wand->mvg_length]=0; if ((drawing_wand->mvg_length > 1) && @@ -305,7 +305,7 @@ static int MvgAutoWrapPrintf(DrawingWand *drawing_wand,const char *format,...) if (formatted_length < 0) { ThrowException(&drawing_wand->exception,DrawError, - UnableToPrint,format); + UnableToPrint,format); } else { @@ -396,20 +396,20 @@ static void AdjustAffine(DrawingWand *drawing_wand,const AffineMatrix *affine) % */ WandExport DrawingWand *CloneDrawingWand(const DrawingWand *drawing_wand) -{ +{ DrawingWand *clone_wand; ExceptionInfo exeption_info; - + assert(drawing_wand != (DrawingWand *) NULL); assert(drawing_wand->signature == MagickSignature); - + clone_wand=MagickAllocateMemory(DrawingWand *,sizeof(*clone_wand)); if (clone_wand == (DrawingWand *) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, - UnableToAllocateDrawingWand); + UnableToAllocateDrawingWand); GetExceptionInfo(&exeption_info); (void) memcpy(clone_wand,drawing_wand,sizeof(*clone_wand)); @@ -418,25 +418,25 @@ WandExport DrawingWand *CloneDrawingWand(const DrawingWand *drawing_wand) clone_wand->mvg=(char *) NULL; clone_wand->pattern_id=(char *) NULL; clone_wand->graphic_context=(DrawInfo **) NULL; - + clone_wand->own_image=MagickTrue; if (drawing_wand->image != (Image *) NULL) { clone_wand->image=CloneImage(drawing_wand->image,0,0,MagickTrue, - &exeption_info); + &exeption_info); if (clone_wand->image == (Image *) NULL) - goto clone_drawing_wand_fail; + goto clone_drawing_wand_fail; } - + if (drawing_wand->mvg) { clone_wand->mvg=MagickAllocateMemory(char *,drawing_wand->mvg_alloc); if (clone_wand->mvg == (char *) NULL) - { - ThrowException3(&exeption_info,ResourceLimitError, - MemoryAllocationFailed,UnableToCloneDrawingWand); - goto clone_drawing_wand_fail; - } + { + ThrowException3(&exeption_info,ResourceLimitError, + MemoryAllocationFailed,UnableToCloneDrawingWand); + goto clone_drawing_wand_fail; + } (void) memcpy(clone_wand->mvg,drawing_wand->mvg,drawing_wand->mvg_length+1); } @@ -446,28 +446,28 @@ WandExport DrawingWand *CloneDrawingWand(const DrawingWand *drawing_wand) if (drawing_wand->graphic_context != (DrawInfo **) NULL) { clone_wand->graphic_context=MagickAllocateArray(DrawInfo **, - drawing_wand->index+1, - sizeof(DrawInfo *)); + drawing_wand->index+1, + sizeof(DrawInfo *)); if (clone_wand->graphic_context == (DrawInfo **) NULL) - { - ThrowException3(&exeption_info,ResourceLimitError, - MemoryAllocationFailed,UnableToCloneDrawingWand); - goto clone_drawing_wand_fail; - } + { + ThrowException3(&exeption_info,ResourceLimitError, + MemoryAllocationFailed,UnableToCloneDrawingWand); + goto clone_drawing_wand_fail; + } (void) memset(clone_wand->graphic_context,0, - (drawing_wand->index+1)*sizeof(DrawInfo *)); + (drawing_wand->index+1)*sizeof(DrawInfo *)); for (clone_wand->index=0; clone_wand->index <= drawing_wand->index; clone_wand->index++) - { - clone_wand->graphic_context[clone_wand->index]= - CloneDrawInfo((ImageInfo*)NULL,drawing_wand->graphic_context[clone_wand->index]); - if (clone_wand->graphic_context[clone_wand->index] == (DrawInfo*) NULL) - { - ThrowException3(&exeption_info,ResourceLimitError, - MemoryAllocationFailed,UnableToCloneDrawingWand); - goto clone_drawing_wand_fail; - } - } + { + clone_wand->graphic_context[clone_wand->index]= + CloneDrawInfo((ImageInfo*)NULL,drawing_wand->graphic_context[clone_wand->index]); + if (clone_wand->graphic_context[clone_wand->index] == (DrawInfo*) NULL) + { + ThrowException3(&exeption_info,ResourceLimitError, + MemoryAllocationFailed,UnableToCloneDrawingWand); + goto clone_drawing_wand_fail; + } + } clone_wand->index=drawing_wand->index; } @@ -482,11 +482,11 @@ clone_drawing_wand_fail: if (clone_wand->graphic_context != (DrawInfo **) NULL) { for ( ; clone_wand->index >= 0; clone_wand->index--) - { - if (clone_wand->graphic_context[clone_wand->index] != (DrawInfo*) NULL) - DestroyDrawInfo(clone_wand->graphic_context[clone_wand->index]); - clone_wand->graphic_context[clone_wand->index]=(DrawInfo*) NULL; - } + { + if (clone_wand->graphic_context[clone_wand->index] != (DrawInfo*) NULL) + DestroyDrawInfo(clone_wand->graphic_context[clone_wand->index]); + clone_wand->graphic_context[clone_wand->index]=(DrawInfo*) NULL; + } MagickFreeMemory(clone_wand->graphic_context); } (void) memset(clone_wand,0,sizeof(*clone_wand)); @@ -538,11 +538,11 @@ WandExport void DestroyDrawingWand(DrawingWand *drawing_wand) if (drawing_wand->graphic_context != (DrawInfo **) NULL) { for ( ; drawing_wand->index >= 0; drawing_wand->index--) - { - if (drawing_wand->graphic_context[drawing_wand->index] != (DrawInfo*) NULL) - DestroyDrawInfo(drawing_wand->graphic_context[drawing_wand->index]); - drawing_wand->graphic_context[drawing_wand->index]=(DrawInfo*) NULL; - } + { + if (drawing_wand->graphic_context[drawing_wand->index] != (DrawInfo*) NULL) + DestroyDrawInfo(drawing_wand->graphic_context[drawing_wand->index]); + drawing_wand->graphic_context[drawing_wand->index]=(DrawInfo*) NULL; + } MagickFreeMemory(drawing_wand->graphic_context); } @@ -851,10 +851,12 @@ WandExport MagickBool DrawClearException(DrawingWand *drawing_wand) */ WandExport char *DrawGetClipPath(const DrawingWand *drawing_wand) { + char * pClipPath ; assert(drawing_wand != (const DrawingWand *) NULL); assert(drawing_wand->signature == MagickSignature); - if (CurrentContext->clip_path != (char *) NULL) - return((char *) AcquireString(CurrentContext->clip_path)); + pClipPath = *DrawInfoGetClipPath(CurrentContext); + if (pClipPath != (char *) NULL) + return((char *) AcquireString(pClipPath)); return((char *) NULL); } @@ -887,14 +889,16 @@ WandExport char *DrawGetClipPath(const DrawingWand *drawing_wand) WandExport void DrawSetClipPath(DrawingWand *drawing_wand, const char *clip_path) { + char **ppClipPath,*pClipPath; assert(drawing_wand != (DrawingWand *) NULL); assert(drawing_wand->signature == MagickSignature); assert(clip_path != (const char *) NULL); - if ((CurrentContext->clip_path == NULL) || drawing_wand->filter_off || - LocaleCompare(CurrentContext->clip_path,clip_path) != 0) + pClipPath = *(ppClipPath = DrawInfoGetClipPath(CurrentContext)); + if ((pClipPath == NULL) || drawing_wand->filter_off || + LocaleCompare(pClipPath,clip_path) != 0) { - (void) CloneString(&CurrentContext->clip_path,clip_path); - if (CurrentContext->clip_path == (char*)NULL) + (void) CloneString(ppClipPath,clip_path); + if (*ppClipPath == (char*)NULL) ThrowException3(&drawing_wand->exception,ResourceLimitError, MemoryAllocationFailed,UnableToDrawOnImage); (void) MvgPrintf(drawing_wand,"clip-path url(#%s)\n",clip_path); @@ -1040,12 +1044,12 @@ WandExport ClipPathUnits DrawGetClipUnits(const DrawingWand *drawing_wand) % */ WandExport char *DrawGetException(const DrawingWand *drawing_wand, - ExceptionType *severity) + ExceptionType *severity) { char buffer[MaxTextExtent], *description; - + assert(drawing_wand != (const DrawingWand *) NULL); assert(drawing_wand->signature == MagickSignature); assert(drawing_wand->exception.signature == MagickSignature); @@ -1056,12 +1060,12 @@ WandExport char *DrawGetException(const DrawingWand *drawing_wand, if (drawing_wand->exception.severity != UndefinedException) { if (drawing_wand->exception.description) - FormatString(buffer,"%.1024s (%.1024s)", - drawing_wand->exception.reason, - drawing_wand->exception.description); + FormatString(buffer,"%.1024s (%.1024s)", + drawing_wand->exception.reason, + drawing_wand->exception.description); else - FormatString(buffer,"%.1024s", - drawing_wand->exception.reason); + FormatString(buffer,"%.1024s", + drawing_wand->exception.reason); CloneString(&description,buffer); } diff --git a/wand/drawing_wand.h b/wand/drawing_wand.h index 9d37135..ffedbad 100644 --- a/wand/drawing_wand.h +++ b/wand/drawing_wand.h @@ -250,18 +250,18 @@ extern WandExport char *DrawGetTextEncoding(const DrawingWand *); extern WandExport ClipPathUnits - DrawGetClipUnits(const DrawingWand *); + DrawGetClipUnits(const DrawingWand *) MAGICK_FUNC_PURE; extern WandExport DecorationType - DrawGetTextDecoration(const DrawingWand *); + DrawGetTextDecoration(const DrawingWand *) MAGICK_FUNC_PURE; extern WandExport double - DrawGetFillOpacity(const DrawingWand *), - DrawGetFontSize(const DrawingWand *), + DrawGetFillOpacity(const DrawingWand *) MAGICK_FUNC_PURE, + DrawGetFontSize(const DrawingWand *) MAGICK_FUNC_PURE, *DrawGetStrokeDashArray(const DrawingWand *,unsigned long *), - DrawGetStrokeDashOffset(const DrawingWand *), - DrawGetStrokeOpacity(const DrawingWand *), - DrawGetStrokeWidth(const DrawingWand *); + DrawGetStrokeDashOffset(const DrawingWand *) MAGICK_FUNC_PURE, + DrawGetStrokeOpacity(const DrawingWand *) MAGICK_FUNC_PURE, + DrawGetStrokeWidth(const DrawingWand *) MAGICK_FUNC_PURE; extern WandExport DrawInfo *DrawPeekGraphicContext(const DrawingWand *); @@ -272,33 +272,33 @@ extern WandExport DrawingWand *NewDrawingWand(void); extern WandExport FillRule - DrawGetClipRule(const DrawingWand *), - DrawGetFillRule(const DrawingWand *); + DrawGetClipRule(const DrawingWand *) MAGICK_FUNC_PURE, + DrawGetFillRule(const DrawingWand *) MAGICK_FUNC_PURE; extern WandExport GravityType - DrawGetGravity(const DrawingWand *); + DrawGetGravity(const DrawingWand *) MAGICK_FUNC_PURE; extern WandExport LineCap - DrawGetStrokeLineCap(const DrawingWand *); + DrawGetStrokeLineCap(const DrawingWand *) MAGICK_FUNC_PURE; extern WandExport LineJoin - DrawGetStrokeLineJoin(const DrawingWand *); + DrawGetStrokeLineJoin(const DrawingWand *) MAGICK_FUNC_PURE; extern WandExport StretchType - DrawGetFontStretch(const DrawingWand *); + DrawGetFontStretch(const DrawingWand *) MAGICK_FUNC_PURE; extern WandExport StyleType - DrawGetFontStyle(const DrawingWand *); + DrawGetFontStyle(const DrawingWand *) MAGICK_FUNC_PURE; extern WandExport unsigned int DrawClearException(DrawingWand *), - DrawGetStrokeAntialias(const DrawingWand *), - DrawGetTextAntialias(const DrawingWand *), + DrawGetStrokeAntialias(const DrawingWand *) MAGICK_FUNC_PURE, + DrawGetTextAntialias(const DrawingWand *) MAGICK_FUNC_PURE, DrawRender(const DrawingWand *) MAGICK_ATTRIBUTE ((deprecated)); /* Use MagickDrawImage() instead */ extern WandExport unsigned long - DrawGetFontWeight(const DrawingWand *), - DrawGetStrokeMiterLimit(const DrawingWand *); + DrawGetFontWeight(const DrawingWand *) MAGICK_FUNC_PURE, + DrawGetStrokeMiterLimit(const DrawingWand *) MAGICK_FUNC_PURE; extern WandExport void DrawAffine(DrawingWand *,const AffineMatrix *), diff --git a/wand/drawtest.c b/wand/drawtest.c index 3e824d6..b181abc 100644 --- a/wand/drawtest.c +++ b/wand/drawtest.c @@ -30,7 +30,7 @@ ScribbleImage (MagickWand *canvas) DrawPushGraphicContext(draw_wand); { DrawSetViewbox(draw_wand,0,0,MagickGetImageWidth(canvas), - MagickGetImageHeight(canvas)); + MagickGetImageHeight(canvas)); DrawScale(draw_wand,1.101,1.08); DrawTranslate(draw_wand,-23.69,-22.97); DrawRotate(draw_wand,0); @@ -59,11 +59,11 @@ ScribbleImage (MagickWand *canvas) DrawPopClipPath(draw_wand); } DrawPopDefs(draw_wand); - + DrawPushGraphicContext(draw_wand); { DrawSetClipPath(draw_wand, "url(#clip_1)"); - + DrawPushGraphicContext(draw_wand); { DrawSetStrokeAntialias(draw_wand,MagickTrue); @@ -79,7 +79,7 @@ ScribbleImage (MagickWand *canvas) DrawRectangle(draw_wand,72,72,144,144); } DrawPopGraphicContext(draw_wand); - + DrawPushGraphicContext(draw_wand); { DrawSetStrokeAntialias(draw_wand,MagickTrue); @@ -95,7 +95,7 @@ ScribbleImage (MagickWand *canvas) DrawRoundRectangle(draw_wand,72,216,360,432,9,9); } DrawPopGraphicContext(draw_wand); - + DrawPushGraphicContext(draw_wand); { const PointInfo points[37] = @@ -111,7 +111,7 @@ ScribbleImage (MagickWand *canvas) { 346,114.8 }, { 347.1,111.5 }, { 348.9,108.5 }, { 351.4,105.8 }, { 378.1,81.72 } }; - + DrawSetStrokeAntialias(draw_wand,MagickTrue); DrawSetStrokeWidth(draw_wand,2.016); DrawSetStrokeLineCap(draw_wand,RoundCap); @@ -125,7 +125,7 @@ ScribbleImage (MagickWand *canvas) DrawPolygon(draw_wand,37,points); } DrawPopGraphicContext(draw_wand); - + DrawPushGraphicContext(draw_wand); { DrawSetStrokeAntialias(draw_wand,MagickTrue); @@ -141,7 +141,7 @@ ScribbleImage (MagickWand *canvas) DrawEllipse(draw_wand,489.6,424.8,72,129.6,0,360); } DrawPopGraphicContext(draw_wand); - + DrawPushGraphicContext(draw_wand); { const PointInfo points[48] = @@ -159,7 +159,7 @@ ScribbleImage (MagickWand *canvas) { 204,55.3 }, { 204.3,44.35 }, { 204.9,39.6 }, { 205.9,35.42 }, { 207.4,31.82 }, { 209.2,28.87 }, { 211.3,26.64}, { 213.8,25.13 } }; - + DrawSetStrokeAntialias(draw_wand,MagickTrue); DrawSetStrokeWidth(draw_wand,3.024); DrawSetStrokeLineCap(draw_wand,RoundCap); @@ -173,7 +173,7 @@ ScribbleImage (MagickWand *canvas) DrawPolygon(draw_wand,48,points); } DrawPopGraphicContext(draw_wand); - + DrawPushGraphicContext(draw_wand); { DrawSetStrokeAntialias(draw_wand,MagickTrue); @@ -212,7 +212,7 @@ ScribbleImage (MagickWand *canvas) { 180,504 }, { 282.7,578.6 }, { 243.5,699.4 }, { 116.5,699.4 }, { 77.26,578.6 }, { 180,504 } }; - + DrawSetStrokeAntialias(draw_wand,MagickTrue); DrawSetStrokeWidth(draw_wand,9); DrawSetStrokeLineCap(draw_wand,RoundCap); @@ -226,7 +226,7 @@ ScribbleImage (MagickWand *canvas) DrawPolygon(draw_wand,6,points); } DrawPopGraphicContext(draw_wand); - + DrawPushGraphicContext(draw_wand); { const PointInfo points[11] = @@ -235,7 +235,7 @@ ScribbleImage (MagickWand *canvas) { 243.5,699.4 }, { 180,666 }, { 116.5,699.4 }, { 128.7,628.7 }, { 77.26,578.6 }, { 148.2,568.3 }, { 180,504 } }; - + DrawSetStrokeAntialias(draw_wand,MagickTrue); DrawSetStrokeWidth(draw_wand,9); DrawSetStrokeLineCap(draw_wand,RoundCap); @@ -249,7 +249,7 @@ ScribbleImage (MagickWand *canvas) DrawPolygon(draw_wand,11,points); } DrawPopGraphicContext(draw_wand); - + DrawPushGraphicContext(draw_wand); { const PointInfo points[15] = @@ -259,7 +259,7 @@ ScribbleImage (MagickWand *canvas) { 525.6,93.6 }, { 496.8,158.4 }, { 532.8,136.8 }, { 518.4,180 }, { 540,172.8 }, { 540,223.2 }, { 540,288 } }; - + DrawSetStrokeAntialias(draw_wand,MagickTrue); DrawSetStrokeWidth(draw_wand,5.976); DrawSetStrokeLineCap(draw_wand,RoundCap); @@ -273,7 +273,7 @@ ScribbleImage (MagickWand *canvas) DrawPolygon(draw_wand,15,points); } DrawPopGraphicContext(draw_wand); - + DrawPushGraphicContext(draw_wand); { const PointInfo points[7] = @@ -281,7 +281,7 @@ ScribbleImage (MagickWand *canvas) { 57.6,640.8 }, { 57.6,784.8 }, { 194.4,799.2 }, { 259.2,777.6 }, { 151.2,756 }, { 86.4,748.8 }, { 57.6,640.8 } }; - + DrawSetStrokeAntialias(draw_wand,MagickTrue); DrawSetStrokeWidth(draw_wand,5.976); DrawSetStrokeLineCap(draw_wand,RoundCap); @@ -295,7 +295,7 @@ ScribbleImage (MagickWand *canvas) DrawPolygon(draw_wand,7,points); } DrawPopGraphicContext(draw_wand); - + DrawPushGraphicContext(draw_wand); { const PointInfo points[193] = @@ -314,7 +314,7 @@ ScribbleImage (MagickWand *canvas) { 428,531.2 }, { 434.6,532.9 }, { 436.7,533.8 }, { 437.8,534.9 }, { 437.8,536.2 }, { 436.8,537.8 }, { 434.5,539.6 }, { 430.9,541.8 }, { 419.3,547.6 }, { 401.3,555.2 }, { 342.4,577.9 }, {325.2,584.9 }, - { 311,591.3 }, { 300,597.3 }, { 291.6,602.8 }, { 285.8,607.8 }, + { 311,591.3 }, { 300,597.3 }, { 291.6,602.8 }, { 285.8,607.8 }, { 282.3,612.3 }, { 281.4,614.4 }, { 280.9,616.2 }, { 281.2,619.6 }, { 282.1,621.2 }, { 283.3,622.6 }, { 286.8,624.9 }, { 291.5,626.6 }, { 297.1,627.8 }, { 303.6,628.3 }, { 310.5,628.3 }, { 317.9,627.6 }, @@ -350,7 +350,7 @@ ScribbleImage (MagickWand *canvas) { 27.86,597.4 }, { 27.29,595.2 }, { 26.64,588.7 }, { 26.86,578.8 }, { 27.86,565.3 } }; - + DrawSetStrokeAntialias(draw_wand,MagickTrue); DrawSetStrokeWidth(draw_wand,5.904); DrawSetStrokeLineCap(draw_wand,RoundCap); @@ -410,7 +410,7 @@ int main ( int argc, char **argv ) if (MagickPass == status) if ((status = MagickReadImage( canvas, "xc:white" )) == MagickFail) printf ( "Failed to read canvas image %s\n", MagickGetFilename(canvas) ); - + /* * Scribble on image */ @@ -436,7 +436,7 @@ int main ( int argc, char **argv ) if (MagickPass == status) if ((status = MagickWriteImage ( canvas, outfile )) == MagickFail) printf ( "Failed to write image file %s\n", outfile ); - + DestroyMagickWand( canvas ); DestroyMagick(); diff --git a/wand/magick_compat.c b/wand/magick_compat.c index 9e6893a..b077568 100644 --- a/wand/magick_compat.c +++ b/wand/magick_compat.c @@ -193,6 +193,9 @@ WandExport size_t CopyMagickString(char *destination,const char *source, */ WandExport int FormatMagickStringList(char *string,const size_t length, const char *format,va_list operands) + MAGICK_ATTRIBUTE((__format__ (__printf__,3,0))); +WandExport int FormatMagickStringList(char *string,const size_t length, + const char *format,va_list operands) { int count; @@ -506,7 +509,7 @@ WandExport unsigned int ParseGeometry(const char *geometry, */ GetExceptionInfo(&exception); image_info=CloneImageInfo((ImageInfo *) NULL); - (void) strlcpy(image_info->filename,geometry,sizeof(image_info->filename)); + (void) strlcpy(image_info->filename,geometry,sizeof(image_info->filename)); image=PingImage(image_info,&exception); if (image != (Image *) NULL) { diff --git a/wand/magick_wand.c b/wand/magick_wand.c index e3df549..5dcc76f 100644 --- a/wand/magick_wand.c +++ b/wand/magick_wand.c @@ -219,7 +219,7 @@ static MagickWand *CloneMagickWandWithImages(const MagickWand *wand, clone_wand=MagickAllocateMemory(MagickWand *,sizeof(MagickWand)); if (clone_wand == (MagickWand *) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, - UnableToAllocateWand); + UnableToAllocateWand); (void) memset(clone_wand,0,sizeof(MagickWand)); (void) MagickFormatString(clone_wand->id,MaxTextExtent,"MagickWand-%lu", GetMagickWandId()); @@ -1829,7 +1829,7 @@ WandExport char *MagickDescribeImage(MagickWand *wand) if ((file = AcquireTemporaryFileStream(filename, TextFileIOMode)) == (FILE *) NULL) { ThrowException(&wand->exception,FileOpenError, - UnableToCreateTemporaryFile,filename); + UnableToCreateTemporaryFile,filename); } else { @@ -2227,9 +2227,9 @@ WandExport unsigned int MagickEqualizeImage(MagickWand *wand) % on the new image. % */ -WandExport unsigned int +WandExport unsigned int MagickExtentImage(MagickWand *wand,const size_t width,const size_t height, - const ssize_t x,const ssize_t y) + const ssize_t x,const ssize_t y) { Image *extent_image; @@ -2865,7 +2865,7 @@ WandExport MagickWand *MagickGetImage(MagickWand *wand) WandExport char *MagickGetImageAttribute(MagickWand *wand, const char *name) { const ImageAttribute - *attribute; + *attribute; assert(wand != (MagickWand *) NULL); assert(wand->signature == MagickSignature); @@ -3031,8 +3031,8 @@ WandExport unsigned int MagickGetImageBorderColor(MagickWand *wand, */ WandExport unsigned int MagickGetImageBoundingBox(MagickWand *wand,const double fuzz, - unsigned long *width, unsigned long *height, - long *x, long *y) + unsigned long *width, unsigned long *height, + long *x, long *y) { RectangleInfo rectangle; @@ -3282,7 +3282,7 @@ WandExport unsigned int MagickGetImageChannelMean(MagickWand *wand, } deviation *= MaxRGBDouble; *standard_deviation = RoundDoubleToQuantum(deviation); - + meanf *= MaxRGBDouble; *mean = RoundDoubleToQuantum(meanf); @@ -4303,10 +4303,10 @@ WandExport unsigned char *MagickGetImageProfile(MagickWand *wand, const unsigned char *profile=0; - + unsigned char *result=0; - + assert(wand != (MagickWand *) NULL); assert(wand->signature == MagickSignature); *length=0; @@ -5090,6 +5090,46 @@ WandExport MagickPassFail MagickHaldClutImage(MagickWand *wand,const MagickWand % % % % % % +% M a g i c k H a s C o l o r M a p % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MagickHasColormap() returns True if the check was successful with the +% colormap parameter set to a boolean value indicating whether the current +% wand image uses a color map or not. Returns False if there are no wand +% images available. +% +% The format of the MagickHasColormap method is: +% +% unsigned int MagickHasColormap(MagickWand *wand, +% unsigned int *colormap) +% +% A description of each parameter follows: +% +% o wand: The magick wand. +% +% o colormap: Set to True if current image uses a color map, False if not. +% +*/ +WandExport unsigned int MagickHasColormap(MagickWand *wand, + unsigned int *colormap) +{ + assert(wand != (MagickWand *) NULL); + assert(wand->signature == MagickSignature); + if (wand->images == (Image *) NULL) + ThrowWandException(WandError,WandContainsNoImages,wand->id); + + *colormap = (wand->image->storage_class == PseudoClass ? True : False); + return(True); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % % M a g i c k H a s N e x t I m a g e % % % % % @@ -5202,6 +5242,177 @@ WandExport unsigned int MagickImplodeImage(MagickWand *wand,const double amount) % % % % % % +% M a g i c k I s G r a y I m a g e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MagickIsGrayImage() returns True if the check was successful with the +% grayimage parameter set to a boolean value indicating whether the current +% wand image is a gray-scale image or not. Returns False if there was +% an error. +% +% The format of the MagickIsGrayImage method is: +% +% unsigned int MagickIsGrayImage(MagickWand *wand, +% unsigned int *grayimage) +% +% A description of each parameter follows: +% +% o wand: The magick wand. +% +% o grayimage: Set to True if current image is a gray-scale image, +% False if not. +% +*/ +WandExport unsigned int MagickIsGrayImage(MagickWand *wand, + unsigned int *grayimage) +{ + assert(wand != (MagickWand *) NULL); + assert(wand->signature == MagickSignature); + assert(grayimage != (unsigned int *) NULL); + if (wand->images == (Image *) NULL) + ThrowWandException(WandError,WandContainsNoImages,wand->id); + MagickClearException(wand); + *grayimage = IsGrayImage(wand->image, &wand->exception); + return (wand->exception.severity == UndefinedException); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% M a g i c k I s M o n o c h r o m e I m a g e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MagickIsMonochromeImage() returns True if the check was successful with the +% monochrome parameter set to a boolean value indicating whether the current +% wand image is a monochrome image or not. Returns False if there was +% an error. +% +% The format of the MagickIsMonochromeImage method is: +% +% unsigned int MagickIsMonochromeImage(MagickWand *wand, +% unsigned int *monochrome) +% +% A description of each parameter follows: +% +% o wand: The magick wand. +% +% o monochrome: Set to True if current image is a monochrome image, +% False if not. +% +*/ +WandExport unsigned int MagickIsMonochromeImage(MagickWand *wand, + unsigned int *monochrome) +{ + assert(wand != (MagickWand *) NULL); + assert(wand->signature == MagickSignature); + assert(monochrome != (unsigned int *) NULL); + if (wand->images == (Image *) NULL) + ThrowWandException(WandError,WandContainsNoImages,wand->id); + MagickClearException(wand); + *monochrome = IsMonochromeImage(wand->image, &wand->exception); + return (wand->exception.severity == UndefinedException); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% M a g i c k I s O p a q u e I m a g e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MagickIsOpaqueImage() returns True if the check was successful with the +% opaque parameter set to a boolean value indicating whether the current +% wand image is entirely opaque or not. Returns False if there was +% an error. +% +% The format of the MagickIsOpaqueImage method is: +% +% unsigned int MagickIsOpaqueImage(MagickWand *wand, +% unsigned int *opaque) +% +% A description of each parameter follows: +% +% o wand: The magick wand. +% +% o opaque: Set to True if current image is entirely opaque, +% False if not. +% +*/ +WandExport unsigned int MagickIsOpaqueImage(MagickWand *wand, + unsigned int *opaque) +{ + assert(wand != (MagickWand *) NULL); + assert(wand->signature == MagickSignature); + assert(opaque != (unsigned int *) NULL); + if (wand->images == (Image *) NULL) + ThrowWandException(WandError,WandContainsNoImages,wand->id); + MagickClearException(wand); + *opaque = IsOpaqueImage(wand->image, &wand->exception); + return (wand->exception.severity == UndefinedException); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% M a g i c k I s P a l e t t e I m a g e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MagickIsPaletteImage() returns True if the check was successful with the +% palette parameter set to a boolean value indicating whether the current +% wand image is an image with 256 unique colors or less. Returns False if +% there was an error. Note that a palette image does not necessarily use a +% colormap. See MagickHasColormap() if needing to determine whether a +% colormap is in use. +% +% +% The format of the MagickIsPaletteImage method is: +% +% unsigned int MagickIsPaletteImage(MagickWand *wand, +% unsigned int *palette) +% +% A description of each parameter follows: +% +% o wand: The magick wand. +% +% o palette: Set to True if current image is 256 colors or less, +% False if not. +% +*/ +WandExport unsigned int MagickIsPaletteImage(MagickWand *wand, + unsigned int *palette) +{ + assert(wand != (MagickWand *) NULL); + assert(wand->signature == MagickSignature); + assert(palette != (unsigned int *) NULL); + if (wand->images == (Image *) NULL) + ThrowWandException(WandError,WandContainsNoImages,wand->id); + MagickClearException(wand); + *palette = IsPaletteImage(wand->image, &wand->exception); + return (wand->exception.severity == UndefinedException); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % % M a g i c k L a b e l I m a g e % % % % % @@ -6977,7 +7188,7 @@ WandExport unsigned int MagickReadImageBlob(MagickWand *wand, % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% MagickReadImageFile() reads an image or image sequence from an open file +% MagickReadImageFile() reads an image or image sequence from an open file % descriptor. % % The format of the MagickReadImageFile method is: @@ -7648,20 +7859,20 @@ WandExport unsigned int MagickSeparateImageChannel(MagickWand *wand, % -sampling-factor option to specify the factors for chroma % downsampling. To use the same quality value as that found by the % JPEG decoder, use the -define jpeg:preserve-settings flag. -% +% % For the MIFF image format, and the TIFF format while using ZIP % compression, quality/10 is the zlib compres- sion level, which is 0 % (worst but fastest compression) to 9 (best but slowest). It has no % effect on the image appearance, since the compression is always % lossless. -% +% % For the JPEG-2000 image format, quality is mapped using a non-linear % equation to the compression ratio required by the Jasper library. % This non-linear equation is intended to loosely approximate the % quality provided by the JPEG v1 format. The default quality value 75 % results in a request for 16:1 compression. The quality value 100 % results in a request for non-lossy compres- sion. -% +% % For the MNG and PNG image formats, the quality value sets the zlib % compression level (quality / 10) and filter-type (quality % 10). % Compression levels range from 0 (fastest compression) to 100 (best @@ -7669,38 +7880,38 @@ WandExport unsigned int MagickSeparateImageChannel(MagickWand *wand, % used, which is fastest but not necessarily the worst compression. If % filter-type is 4 or less, the specified filter-type is used for all % scanlines: -% +% % 0) none % 1) sub % 2) up % 3) average % 4) Paeth -% +% % If filter-type is 5, adaptive filtering is used when quality is % greater than 50 and the image does not have a color map, otherwise no % filtering is used. -% +% % If filter-type is 6, adaptive filtering with minimum- % sum-of-absolute-values is used. -% +% % Only if the output is MNG, if filter-type is 7, the LOCO color % transformation and adaptive filtering with % minimum-sum-of-absolute-values are used. -% +% % The default is quality is 75, which means nearly the best compression % with adaptive filtering. The quality setting has no effect on the % appearance of PNG and MNG images, since the compression is always % lossless. -% +% % For further information, see the PNG specification. -% +% % When writing a JNG image with transparency, two quality values are % required, one for the main image and one for the grayscale image that % conveys the opacity channel. These are written as a single integer % equal to the main image quality plus 1000 times the opacity quality. % For example, if you want to use quality 75 for the main image and % quality 90 to compress the opacity data, use -quality 90075. -% +% % For the PNM family of formats (PNM, PGM, and PPM) specify a quality % factor of zero in order to obtain the ASCII variant of the % format. Note that -compress none used to be used to trigger ASCII @@ -7903,11 +8114,11 @@ WandExport unsigned int MagickSetImage(MagickWand *wand, % o value: The value of the attribute % */ -WandExport unsigned int MagickSetImageAttribute(MagickWand *wand, const char *name, +WandExport unsigned int MagickSetImageAttribute(MagickWand *wand, const char *name, const char *value) { unsigned int status; - + assert(wand != (MagickWand *) NULL); assert(wand->signature == MagickSignature); if (wand->images == (Image *) NULL) @@ -8496,7 +8707,7 @@ WandExport unsigned int MagickSetImageGamma(MagickWand *wand,const double gamma) % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % - % MagickSetImageGeometry() sets the image geometry string. + % MagickSetImageGeometry() sets the image geometry string. % % The format of the MagickSetImageGeometry method is: % @@ -9470,7 +9681,7 @@ WandExport unsigned int MagickSetInterlaceScheme(MagickWand *wand, */ WandExport unsigned int MagickSetResolution(MagickWand *wand, - const double x_resolution,const double y_resolution) + const double x_resolution,const double y_resolution) { char geometry[MaxTextExtent]; @@ -10736,7 +10947,7 @@ WandExport unsigned int MagickWriteImage(MagickWand *wand,const char *filename) % */ WandExport unsigned int MagickWriteImagesFile(MagickWand *wand,FILE * file, - const unsigned int adjoin) + const unsigned int adjoin) { ImageInfo *write_info; @@ -10941,7 +11152,7 @@ WandExport MagickWand *NewMagickWand(void) wand=MagickAllocateMemory(MagickWand *,sizeof(MagickWand)); if (wand == (MagickWand *) NULL) MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed, - UnableToAllocateWand); + UnableToAllocateWand); (void) memset(wand,0,sizeof(MagickWand)); (void) MagickFormatString(wand->id,MaxTextExtent,"MagickWand-%lu", GetMagickWandId()); diff --git a/wand/magick_wand.h b/wand/magick_wand.h index 41877d6..4277605 100644 --- a/wand/magick_wand.h +++ b/wand/magick_wand.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2016 GraphicsMagick Group */ +/* Copyright (C) 2003-2018 GraphicsMagick Group */ /* ImageMagick MagickWand interface. @@ -54,7 +54,7 @@ typedef struct _MagickWand extern WandExport char *MagickDescribeImage(MagickWand *), - *MagickGetConfigureInfo(MagickWand *,const char *), + *MagickGetConfigureInfo(MagickWand *,const char *) MAGICK_FUNC_CONST, *MagickGetException(const MagickWand *,ExceptionType *), *MagickGetFilename(const MagickWand *), *MagickGetImageAttribute(MagickWand *, const char *), @@ -74,13 +74,13 @@ extern WandExport CompressionType MagickGetImageCompression(MagickWand *); extern WandExport const char - *MagickGetCopyright(void), - *MagickGetHomeURL(void), + *MagickGetCopyright(void) MAGICK_FUNC_CONST, + *MagickGetHomeURL(void) MAGICK_FUNC_CONST, *MagickGetImageGeometry(MagickWand *), - *MagickGetPackageName(void), + *MagickGetPackageName(void) MAGICK_FUNC_CONST, *MagickGetQuantumDepth(unsigned long *), - *MagickGetReleaseDate(void), - *MagickGetVersion(unsigned long *); + *MagickGetReleaseDate(void) MAGICK_FUNC_CONST, + *MagickGetVersion(unsigned long *) MAGICK_FUNC_CONST; extern WandExport DisposeType MagickGetImageDispose(MagickWand *); @@ -98,7 +98,7 @@ extern WandExport ImageType MagickGetImageType(MagickWand *); extern WandExport ImageType - MagickGetImageSavedType(MagickWand *); + MagickGetImageSavedType(MagickWand *) MAGICK_FUNC_CONST; extern WandExport InterlaceType MagickGetImageInterlaceScheme(MagickWand *); @@ -215,9 +215,14 @@ extern WandExport unsigned int MagickGetImageWhitePoint(MagickWand *,double *,double *), MagickGetSize(const MagickWand *,unsigned long *,unsigned long *), MagickHaldClutImage(MagickWand *wand,const MagickWand *clut_wand), + MagickHasColormap(MagickWand *,unsigned int *), MagickHasNextImage(MagickWand *), MagickHasPreviousImage(MagickWand *), MagickImplodeImage(MagickWand *,const double), + MagickIsGrayImage(MagickWand *,unsigned int *), + MagickIsMonochromeImage(MagickWand *,unsigned int *), + MagickIsOpaqueImage(MagickWand *,unsigned int *), + MagickIsPaletteImage(MagickWand *,unsigned int *), MagickLabelImage(MagickWand *,const char *), MagickLevelImage(MagickWand *,const double,const double,const double), MagickLevelImageChannel(MagickWand *,const ChannelType,const double, diff --git a/wand/pixel_wand.h b/wand/pixel_wand.h index 5c4841e..6dce09c 100644 --- a/wand/pixel_wand.h +++ b/wand/pixel_wand.h @@ -23,14 +23,14 @@ extern WandExport char *PixelGetColorAsString(const PixelWand *); extern WandExport double - PixelGetBlack(const PixelWand *), - PixelGetBlue(const PixelWand *), - PixelGetCyan(const PixelWand *), - PixelGetGreen(const PixelWand *), - PixelGetMagenta(const PixelWand *), - PixelGetOpacity(const PixelWand *), - PixelGetRed(const PixelWand *), - PixelGetYellow(const PixelWand *); + PixelGetBlack(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetBlue(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetCyan(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetGreen(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetMagenta(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetOpacity(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetRed(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetYellow(const PixelWand *) MAGICK_FUNC_PURE; extern WandExport PixelWand *ClonePixelWand(const PixelWand *), @@ -39,20 +39,20 @@ extern WandExport PixelWand **NewPixelWands(const unsigned long); extern WandExport Quantum - PixelGetBlackQuantum(const PixelWand *), - PixelGetBlueQuantum(const PixelWand *), - PixelGetCyanQuantum(const PixelWand *), - PixelGetGreenQuantum(const PixelWand *), - PixelGetMagentaQuantum(const PixelWand *), - PixelGetOpacityQuantum(const PixelWand *), - PixelGetRedQuantum(const PixelWand *), - PixelGetYellowQuantum(const PixelWand *); + PixelGetBlackQuantum(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetBlueQuantum(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetCyanQuantum(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetGreenQuantum(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetMagentaQuantum(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetOpacityQuantum(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetRedQuantum(const PixelWand *) MAGICK_FUNC_PURE, + PixelGetYellowQuantum(const PixelWand *) MAGICK_FUNC_PURE; extern WandExport unsigned int PixelSetColor(PixelWand *,const char *); extern WandExport unsigned long - PixelGetColorCount(const PixelWand *); + PixelGetColorCount(const PixelWand *) MAGICK_FUNC_PURE; extern WandExport void DestroyPixelWand(PixelWand *), diff --git a/wand/wand_api.h b/wand/wand_api.h index 954ed10..5784254 100644 --- a/wand/wand_api.h +++ b/wand/wand_api.h @@ -20,7 +20,7 @@ extern "C" { * mutli-threaded DLLs using the multithreaded runtime DLLs. **/ # if defined(_MT) && defined(_DLL) && !defined(_LIB) -# pragma warning( disable: 4273 ) /* Disable the stupid dll linkage warnings */ +# pragma warning( disable: 4273 ) /* Disable the stupid dll linkage warnings */ # if !defined(_WANDLIB_) # define WandExport __declspec(dllimport) # else diff --git a/wand/wand_symbols.h b/wand/wand_symbols.h index 387292e..5e4d095 100644 --- a/wand/wand_symbols.h +++ b/wand/wand_symbols.h @@ -1,17 +1,11 @@ /* - Copyright (C) 2012-2014 GraphicsMagick Group - + Copyright (C) 2012-2018 GraphicsMagick Group + This program is covered by multiple licenses, which are described in Copyright.txt. You should have received a copy of Copyright.txt with this package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. - Library symbol name-scoping support. - - Obtained via: - - nm -p wand/.libs/libGraphicsMagickWand.a | grep ' T ' | egrep -vi '(Gm)|(lt_)' | \ - awk '{ printf("#define %s Gm%s\n", $3, $3); }' | sort > wand/wand_symbols.h - + Library symbol name-scoping support. */ #if !defined(_MAGICK_WAND_SYMBOLS_H) @@ -34,6 +28,7 @@ #define MagickAnimateImages GmMagickAnimateImages #define MagickAnnotateImage GmMagickAnnotateImage #define MagickAppendImages GmMagickAppendImages +#define MagickAutoOrientImage GmMagickAutoOrientImage #define MagickAverageImages GmMagickAverageImages #define MagickBlackThresholdImage GmMagickBlackThresholdImage #define MagickBlurImage GmMagickBlurImage @@ -41,6 +36,7 @@ #define MagickCdlImage GmMagickCdlImage #define MagickCharcoalImage GmMagickCharcoalImage #define MagickChopImage GmMagickChopImage +#define MagickClearException GmMagickClearException #define MagickClipImage GmMagickClipImage #define MagickClipPathImage GmMagickClipPathImage #define MagickCloneDrawingWand GmMagickCloneDrawingWand @@ -79,8 +75,8 @@ #define MagickDrawGetFillColor GmMagickDrawGetFillColor #define MagickDrawGetFillOpacity GmMagickDrawGetFillOpacity #define MagickDrawGetFillRule GmMagickDrawGetFillRule -#define MagickDrawGetFontFamily GmMagickDrawGetFontFamily #define MagickDrawGetFont GmMagickDrawGetFont +#define MagickDrawGetFontFamily GmMagickDrawGetFontFamily #define MagickDrawGetFontSize GmMagickDrawGetFontSize #define MagickDrawGetFontStretch GmMagickDrawGetFontStretch #define MagickDrawGetFontStyle GmMagickDrawGetFontStyle @@ -147,8 +143,8 @@ #define MagickDrawSetFillOpacity GmMagickDrawSetFillOpacity #define MagickDrawSetFillPatternURL GmMagickDrawSetFillPatternURL #define MagickDrawSetFillRule GmMagickDrawSetFillRule -#define MagickDrawSetFontFamily GmMagickDrawSetFontFamily #define MagickDrawSetFont GmMagickDrawSetFont +#define MagickDrawSetFontFamily GmMagickDrawSetFontFamily #define MagickDrawSetFontSize GmMagickDrawSetFontSize #define MagickDrawSetFontStretch GmMagickDrawSetFontStretch #define MagickDrawSetFontStyle GmMagickDrawSetFontStyle @@ -181,15 +177,16 @@ #define MagickFlipImage GmMagickFlipImage #define MagickFlopImage GmMagickFlopImage #define MagickFrameImage GmMagickFrameImage -#define MagickFxImageChannel GmMagickFxImageChannel #define MagickFxImage GmMagickFxImage -#define MagickGammaImageChannel GmMagickGammaImageChannel +#define MagickFxImageChannel GmMagickFxImageChannel #define MagickGammaImage GmMagickGammaImage +#define MagickGammaImageChannel GmMagickGammaImageChannel #define MagickGetConfigureInfo GmMagickGetConfigureInfo #define MagickGetCopyright GmMagickGetCopyright #define MagickGetException GmMagickGetException #define MagickGetFilename GmMagickGetFilename #define MagickGetHomeURL GmMagickGetHomeURL +#define MagickGetImage GmMagickGetImage #define MagickGetImageAttribute GmMagickGetImageAttribute #define MagickGetImageBackgroundColor GmMagickGetImageBackgroundColor #define MagickGetImageBluePrimary GmMagickGetImageBluePrimary @@ -213,7 +210,6 @@ #define MagickGetImageGamma GmMagickGetImageGamma #define MagickGetImageGeometry GmMagickGetImageGeometry #define MagickGetImageGravity GmMagickGetImageGravity -#define MagickGetImage GmMagickGetImage #define MagickGetImageGreenPrimary GmMagickGetImageGreenPrimary #define MagickGetImageHeight GmMagickGetImageHeight #define MagickGetImageHistogram GmMagickGetImageHistogram @@ -222,6 +218,7 @@ #define MagickGetImageIterations GmMagickGetImageIterations #define MagickGetImageMatte GmMagickGetImageMatte #define MagickGetImageMatteColor GmMagickGetImageMatteColor +#define MagickGetImageOrientation GmMagickGetImageOrientation #define MagickGetImagePage GmMagickGetImagePage #define MagickGetImagePixels GmMagickGetImagePixels #define MagickGetImageProfile GmMagickGetImageProfile @@ -246,12 +243,17 @@ #define MagickGetSize GmMagickGetSize #define MagickGetVersion GmMagickGetVersion #define MagickHaldClutImage GmMagickHaldClutImage +#define MagickHasColormap GmMagickHasColormap #define MagickHasNextImage GmMagickHasNextImage #define MagickHasPreviousImage GmMagickHasPreviousImage #define MagickImplodeImage GmMagickImplodeImage +#define MagickIsGrayImage GmMagickIsGrayImage +#define MagickIsMonochromeImage GmMagickIsMonochromeImage +#define MagickIsOpaqueImage GmMagickIsOpaqueImage +#define MagickIsPaletteImage GmMagickIsPaletteImage #define MagickLabelImage GmMagickLabelImage -#define MagickLevelImageChannel GmMagickLevelImageChannel #define MagickLevelImage GmMagickLevelImage +#define MagickLevelImageChannel GmMagickLevelImageChannel #define MagickMagnifyImage GmMagickMagnifyImage #define MagickMapImage GmMagickMapImage #define MagickMatteFloodfillImage GmMagickMatteFloodfillImage @@ -262,13 +264,14 @@ #define MagickMorphImages GmMagickMorphImages #define MagickMosaicImages GmMagickMosaicImages #define MagickMotionBlurImage GmMagickMotionBlurImage -#define MagickNegateImageChannel GmMagickNegateImageChannel #define MagickNegateImage GmMagickNegateImage +#define MagickNegateImageChannel GmMagickNegateImageChannel #define MagickNewDrawingWand GmMagickNewDrawingWand #define MagickNextImage GmMagickNextImage #define MagickNormalizeImage GmMagickNormalizeImage #define MagickOilPaintImage GmMagickOilPaintImage #define MagickOpaqueImage GmMagickOpaqueImage +#define MagickOperatorImageChannel GmMagickOperatorImageChannel #define MagickPingImage GmMagickPingImage #define MagickPreviewImages GmMagickPreviewImages #define MagickPreviousImage GmMagickPreviousImage @@ -280,12 +283,13 @@ #define MagickQueryFormats GmMagickQueryFormats #define MagickRadialBlurImage GmMagickRadialBlurImage #define MagickRaiseImage GmMagickRaiseImage +#define MagickReadImage GmMagickReadImage #define MagickReadImageBlob GmMagickReadImageBlob #define MagickReadImageFile GmMagickReadImageFile -#define MagickReadImage GmMagickReadImage #define MagickReduceNoiseImage GmMagickReduceNoiseImage #define MagickRelinquishMemory GmMagickRelinquishMemory #define MagickRemoveImage GmMagickRemoveImage +#define MagickRemoveImageOption GmMagickRemoveImageOption #define MagickRemoveImageProfile GmMagickRemoveImageProfile #define MagickResampleImage GmMagickResampleImage #define MagickResetIterator GmMagickResetIterator @@ -299,6 +303,7 @@ #define MagickSetDepth GmMagickSetDepth #define MagickSetFilename GmMagickSetFilename #define MagickSetFormat GmMagickSetFormat +#define MagickSetImage GmMagickSetImage #define MagickSetImageAttribute GmMagickSetImageAttribute #define MagickSetImageBackgroundColor GmMagickSetImageBackgroundColor #define MagickSetImageBluePrimary GmMagickSetImageBluePrimary @@ -315,8 +320,8 @@ #define MagickSetImageFormat GmMagickSetImageFormat #define MagickSetImageFuzz GmMagickSetImageFuzz #define MagickSetImageGamma GmMagickSetImageGamma +#define MagickSetImageGeometry GmMagickSetImageGeometry #define MagickSetImageGravity GmMagickSetImageGravity -#define MagickSetImage GmMagickSetImage #define MagickSetImageGreenPrimary GmMagickSetImageGreenPrimary #define MagickSetImageIndex GmMagickSetImageIndex #define MagickSetImageInterlaceScheme GmMagickSetImageInterlaceScheme @@ -324,6 +329,7 @@ #define MagickSetImageMatte GmMagickSetImageMatte #define MagickSetImageMatteColor GmMagickSetImageMatteColor #define MagickSetImageOption GmMagickSetImageOption +#define MagickSetImageOrientation GmMagickSetImageOrientation #define MagickSetImagePage GmMagickSetImagePage #define MagickSetImagePixels GmMagickSetImagePixels #define MagickSetImageProfile GmMagickSetImageProfile @@ -353,8 +359,8 @@ #define MagickStripImage GmMagickStripImage #define MagickSwirlImage GmMagickSwirlImage #define MagickTextureImage GmMagickTextureImage -#define MagickThresholdImageChannel GmMagickThresholdImageChannel #define MagickThresholdImage GmMagickThresholdImage +#define MagickThresholdImageChannel GmMagickThresholdImageChannel #define MagickTintImage GmMagickTintImage #define MagickTransformImage GmMagickTransformImage #define MagickTransparentImage GmMagickTransparentImage @@ -362,11 +368,11 @@ #define MagickUnsharpMaskImage GmMagickUnsharpMaskImage #define MagickWaveImage GmMagickWaveImage #define MagickWhiteThresholdImage GmMagickWhiteThresholdImage +#define MagickWriteImage GmMagickWriteImage #define MagickWriteImageBlob GmMagickWriteImageBlob #define MagickWriteImageFile GmMagickWriteImageFile -#define MagickWriteImage GmMagickWriteImage -#define MagickWriteImagesFile GmMagickWriteImagesFile #define MagickWriteImages GmMagickWriteImages +#define MagickWriteImagesFile GmMagickWriteImagesFile #define NewMagickWand GmNewMagickWand #define NewPixelWand GmNewPixelWand #define NewPixelWands GmNewPixelWands @@ -394,8 +400,8 @@ #define PixelSetBlackQuantum GmPixelSetBlackQuantum #define PixelSetBlue GmPixelSetBlue #define PixelSetBlueQuantum GmPixelSetBlueQuantum -#define PixelSetColorCount GmPixelSetColorCount #define PixelSetColor GmPixelSetColor +#define PixelSetColorCount GmPixelSetColorCount #define PixelSetCyan GmPixelSetCyan #define PixelSetCyanQuantum GmPixelSetCyanQuantum #define PixelSetGreen GmPixelSetGreen @@ -413,3 +419,11 @@ #endif /* defined(PREFIX_MAGICK_SYMBOLS) */ #endif /* defined(_MAGICK_WAND_SYMBOLS_H) */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 2 + * fill-column: 78 + * End: + */ diff --git a/wand/wandtest.c b/wand/wandtest.c index 105cf18..28c8919 100644 --- a/wand/wandtest.c +++ b/wand/wandtest.c @@ -101,7 +101,7 @@ int main(int argc,char **argv) MagickWand *clone_wand, *magick_wand; - + PixelWand *background, *fill; @@ -132,7 +132,7 @@ int main(int argc,char **argv) char *p, path[MaxTextExtent]; - + path[0]=0; p=getenv("SRCDIR"); if (p) @@ -142,7 +142,7 @@ int main(int argc,char **argv) strcat(path,"/"); } strcat(path,"sequence.miff"); - + status=MagickReadImage(magick_wand,path); } if (status == False) diff --git a/www/ChangeLog-2017.html b/www/ChangeLog-2017.html new file mode 100644 index 0000000..8ad6c1d --- /dev/null +++ b/www/ChangeLog-2017.html @@ -0,0 +1,1283 @@ + + + + + + + + + + + + + + +
+ + +

2017-12-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • tests/rwfile.tap: Add tests for MIFF compressed sub-formats.
  • +
+
+

2017-12-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/blob.c (OpenBlob): Zlib 1.2.8 does not accept an open +mode of "w+b" or "wb+". It seems to be allergic to '+'. As a +result, writing to ".gz" files was not working with Zlib 1.2.8. +Note that "w+b" must be used in the normal case since the test +suite fails otherwise!
  • +
+
+

2017-12-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadMNGImage): Fix SourceForge issue #535 +"heap-buffer-overflow in ReadMNGImage". Problem was caused by +accessing byte before testing that limit has been reached, rather +than testing for limit before accessing the byte. This means that +it could only ever read one past the buffer allocation size.
  • +
  • coders/webp.c (WriteWEBPImage): Fix SourceForge issue #536 +"stack-buffer-overflow in WriteWEBPImage". Due to a change to use +WebPMemoryWriter as part of the EXIF and ICC profile support +addition (enabled with libwebp 0.5.0), the progress indicator +callback is now passed a pointer to a wrong structure. This is +quite unfortunate since the progress indication is useful. The +progress indication is temporarily disabled when the +WebPMemoryWriter is in use until a solution is implemented. +(ProgressCallback): Re-implement progress callback so that image +pointer is stored/retrieved as thread-specific data.
  • +
  • coders/png.c (ReadMNGImage): Fix SourceForge issue #537 "null +pointer dereference in ReadMNGImage". DEFI chunk must be at least +2 bytes long.
  • +
  • coders/tiff.c (ReadNewsProfile): Fix SourceForge issue #533 +"heap-buffer-overflow on LocaleNCompare". LocaleNCompare() was +being allowed to read heap data beyond the allocated region.
  • +
+
+

2017-12-17 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/shear.c (IntegralRotateImage): Assure that reported error +in rotate by 270 case does immediately terminate processing. +Return a NULL Image pointer if there is a problem rather than a +corrupted image. Fix is related to SourceForge issue #532 +"heap-buffer-overflow bug in ReadWPGImage".
  • +
  • magick/pixel_cache.c (AcquireCacheNexus): Add a check that the +pixel cache is compatible with the image dimensions. Fix is +related to SourceForge issue #532 "heap-buffer-overflow bug in +ReadWPGImage".
  • +
+
+

2017-12-16 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Fix SourceForge issue #530 +"heap-buffer-overflow in ReadOneJNGImage". In this case there is +a read one byte beyond the oFFs chunk allocation size due to an +error in specifying an offset into the chunk.
  • +
  • coders/palm.c (ReadPALMImage): Fix SourceForge issue #529 +"global-buffer-overflow in ReadPALMImage". This issue only +occured in builds with QuantumDepth=8 due to the small range of +IndexPacket.
  • +
+
+

2017-12-13 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • PerlMagick/{Magick.pm, Magick.pm.in, Makefile.PL.in}: Only base +PerlMagick version on numeric portion of PACKAGE_VERSION.
  • +
+
+

2017-12-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • www/index.rst: Update to 1.3.27.
  • +
  • www/Changes.rst: Add 1.3.27
  • +
  • version.sh: Update library versioning.
  • +
  • NEWS.txt: Update NEWS in preparation for releasing 1.3.27.
  • +
+
+

2017-12-08 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dcm.c (DCM_ReadElement): Change size checks addressing +CVE-2017-12140 to be based on size_t rather than magick_off_t due +to apparent instability of the previous check across compilers.
  • +
+
+

2017-12-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (WriteOnePNGImage): Fix heap read access outside of +allocated PixelPacket array while testing pixels for opacity. +Resolves SourceForge issue #526 "heap-buffer-overflow in +WriteOnePNGImage".
  • +
+
+

2017-12-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pnm.c (WritePNMImage): Fix SourceForge bug #525 +"heap-buffer-overflow in MagickBitStreamMSBWrite".
  • +
+
+

2017-12-05 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dcm.c (DCM_ReadElement): Eliminate huge memory allocation +based on bogus length value. Addresses CVE-2017-12140. Problem was +reported via email from Petr Gajdos on Tue, 5 Dec 2017.
  • +
+
+

2017-12-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • Magick++/lib/Image.cpp (colorMap): Try to eliminate Coverity CID +172796 "Dereference after null check" which seems to be bogus.
  • +
  • coders/png.c (WriteOnePNGImage): Fix Coverity CID 168053 +"Dereference after null check". The check for null and the error +report which attempted to use the null value was not needed at +all.
  • +
  • coders/cut.c (GetCutColors): Fix Coverity CID 10181: "Null +pointer dereferences". SetImagePixels() may return NULL.
  • +
  • coders/rgb.c (ReadRGBImage): Fix SourceForge issue #523 +"heap-buffer-overflow". Similar issue to cmyk.c.
  • +
  • coders/gray.c (ReadGRAYImage): Fix SourceForge issue #522 +"heap-buffer-overflow". Similar issue to cmyk.c.
  • +
  • coders/cmyk.c (ReadCMYKImage): Fix SourceForge issue #521 +"heap-buffer-overflow". The requested tile must be within the +bounds of the image. As it happens, 'montage' passes size and +tile information which is useless for reading a raw image so it is +not possible to read raw CMYK using 'montage'.
  • +
+
+

2017-12-02 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pwp.c (ReadPWPImage): Eliminate dereference of null image +pointer. Addresses CVE-2017-11640. Also address access to +uninitialized memory. Problem was reported via email from Petr +Gajdos on Wed, 29 Nov 2017.
  • +
+
+

2017-11-22 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/wpg.c Additional check for wrong bpp CVE-2017-14342.
  • +
+
+

2017-11-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • Magick++/lib/Image.cpp (autoOrient): Add method to auto-orient +an image so it looks right-side up by default. Based on patch by +Przemysław Sobala submitted as SourceForge patch #53 "Add +Magick::Image::autoOrient() method to Magick++ library".
  • +
  • www/download.rst: Change "Czechoslovakian ftp mirror" to "Czech +ftp mirror". Resolves SourceForge bug #520 "[web] Download sites: +non-existent country".
  • +
+
+

2017-11-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/wpg.c (ReadWPGImage): Fix excessive use of disk resources +due to unreasonable record length. Addresses CVE-2017-14341. +Notified of this issue (with suggested patch) via email by Petr +Gajdos on Tue, 21 Nov 2017.
  • +
+
+

2017-11-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • README.txt: Comprehensive white-space clean-up across +GraphicsMagick core source files. Hard TAB character is converted +to spaces. Trailing white-space garbage is stripped.
  • +
  • magick/colormap.c (MagickConstrainColormapIndex): Deprecate use +of MagickConstrainColormapIndex() and prefer use of +VerifyColormapIndex() and VerifyColormapIndexWithColors() due to +avoiding dependence on index type, allowing provision of colors +other than image->colors, and capturing more useful source file +and line information.
  • +
  • coders/{rle.c, mat.c, xbm.c, sgi.c, png.c}: Eliminate size_t vs +unsigned 32 conversion warnings in WIN64 build.
  • +
+
+

2017-11-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • tiff: Import libtiff 4.0.9.
  • +
+
+

2017-11-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/bmp.c (DecodeImage): "Right-size" and "Right-type" +DecodeImage() variables and check for EOF at every point of the +way. Pass buffer size as an argument.
  • +
  • coders/dib.c (DecodeImage): "Right-size" and "Right-type" +DecodeImage() variables and check for EOF at every point of the +way. Pass buffer size as an argument.
  • +
  • coders/bmp.c (_BMPInfo): "Right-size" BMPInfo members. The +'long' type is promoted to 64-bit on LP64 systems and the large +size is not needed.
  • +
+
+

2017-11-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/webp.c: Incorporate patch by Jan Spitalnik to add EXIF +and ICC metadata support to the WebP coder. While WebP is still +supported back to libwebp 0.1.99, the metadata support requires at +least libwebp 0.5.0. Resolves SourceForge patch #52 "Add EXIF/ICC +metadata support to WebP coder".
  • +
  • coders/png.c (ReadOneJNGImage): Fix JNG memory leaks when JPEG +image fails to be read. +(WriteOnePNGImage): Promotion of indexed PNG to RGBA lacked +setting of image matte, resulting in undersized buffer allocation +and heap overflow. Fixes SourceForge bug #453 "Heap overflow in +source-gra/coders/png.c".
  • +
+
+

2017-11-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/sfw.c (SFWScan): Fix heap buffer overflow +(CVE-2017-13134). Notified of problem via email (including a +patch) from Petr Gajdos on Mon, 6 Nov 2017.
  • +
+
+

2017-11-05 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/wpg.c Wrong MaxMap check condition - fixed.
  • +
+
+

2017-11-04 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/wpg.c Check for InsertRow() return value.
  • +
+
+

2017-11-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/export.c: Add not-null check for indexes pointer where +needed.
  • +
  • magick/import.c: Add not-null check for indexes pointer with +associated exception report where the indexes pointer is needed. +(ImportCMYKQuantumType): Was wrongly importing an opacity channel +in some cases. Would have crashed if these cases were ever used.
  • +
  • coders/wpg.c (ReadWPGImage): Assure that colormapped image is a +PseudoClass type with valid colormapped indexes. Fixes +SourceForge bug 519 "Null Pointer Dereference (Write) with +malformed WPG Image".
  • +
  • coders/sfw.c (ReadSFWImage): Avoid possible heap overflow while +copying JFIF magic into buffer. Reject runt files. Fixes +CVE-2017-12983. Notified of problem via email from Petr Gajdos on +Thu, 2 Nov 2017.
  • +
+
+

2017-10-28 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/render.c (DrawImage): Fix SourceForge bug #517 "Push +operations in DrawImage can lead to negative strncpy when looking +for pop". Interestingly, valgrind and ASAN only detected a +problem with one of the test cases since exercised code which +updated an array using the index. It appears that Linux strncpy() +simply ignores the bad request.
  • +
+
+

2017-10-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Make sure that a reasonable +exception is reported to the user when there is a read failure.
  • +
+
+

2017-10-26 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Reject JNG files with +unreasonable dimensions given the file size.
  • +
+
+

2017-10-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Fix SourceForge bug #518 "Null +pointer in". Also make sure that errors are reported properly due +to problems with transferring JPEG scanlines. +(ReadOneJNGImage): Add more checks for null value returned from +SetImagePixels().
  • +
+
+

2017-10-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/describe.c (DescribeImage): Fix possible heap read +overflow while accessing heap data, and possible information +disclosure while describing the IPTC profile. Report was provided +via email from Maor Shwartz to the graphicsmagick-security mail +alias on Thu, 19 Oct 2017. Independent security researchers, +Jeremy Heng (@nn_amon) and Terry Chia (Ayrx), reported this +vulnerability to Beyond Security’s SecuriTeam Secure Disclosure +program. Please note that this interface is usually (but not +exclusively) used from within the command-line utility program, in +which case there is not much useful information which might be +disclosed. +(DescribeImage): Fix possible heap write overflow when describing +visual image directory. Report was provided via email from Maor +Shwartz to the graphicsmagick-security mail alias on Thu, 19 Oct +2017. Independent security researchers, Jeremy Heng (@nn_amon) +and Terry Chia (Ayrx), reported this vulnerability to Beyond +Security’s SecuriTeam Secure Disclosure program. Please note that +this interface is usually (but not exclusively) used from within +the command-line utility program, in which case the only harm +would be a program crash.
  • +
  • magick/constitute.c (WriteImage): Assure that the errno present +when the blob error status first occured is reported to the user.
  • +
  • magick/blob.c (GetBlobStatus): Blob error status is now updated +immediately upon the first error reported. +(GetBlobFirstErrno): Returns errno value when the first blob error +was reported. This is useful for error reporting.
  • +
+
+

2017-10-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/constitute.c (WriteImage): Restore use of GetBlobStatus() +to test if an I/O error was encountered while writing output file. +This assures that I/O failure in writers which do not themselves +verify writes is assured to be reported.
  • +
+
+

2017-10-17 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/webp.c (WriterCallback): WebP writer now detects partial +write to output file. Patch by Przemysław Sobala from a posting +on Mon, 16 Oct 2017 via the graphicsmagick-help mailing list.
  • +
+
+

2017-10-14 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/command.c (MontageImageCommand): Fix memory leaks in +error return path. Only people doing leak testing or the few who +execute MontageImageCommand() as a function will care about this.
  • +
  • magick/studio.h (NumberOfObjectsInArray): The +NumberOfObjectsInArray() macro is used to compute the number of +whole objects in an array. Instead it was rounding up, resulting +in scrambling the heap beyond the allocation. Fixes +CVE-2017-13737 "There is an invalid free in the MagickFree +function in magick/memory.c in GraphicsMagick 1.3.26 that will +lead to a remote denial of service attack."
  • +
+
+

2017-10-09 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOnePNGImage): Suppress "comparison between +signed and unsigned integer expressions" warning.
  • +
  • coders/png.c (ReadJNGImage): Fix memory leak in SourceForge +Issue #469 "use after free in ReadJNGImage".
  • +
  • coders/png.c (ReadJNGImage): Fix memory leak in SourceForge +Issue #470 "Assert failure in writeblob".
  • +
+
+

2017-10-08 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • doc/options.imdoc: Fix SourceForge issue #444 "gm mogrify: Wrong +documentation for option -output-directory".
  • +
+
+

2017-10-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/module.c (InitializeModuleSearchPath): Verify that any +component paths specified in MAGICK_CODER_MODULE_PATH and +MAGICK_FILTER_MODULE_PATH exist before adding them to search paths +actually used, and convert to real paths if possible. This avoids +possible use of relative paths to load modules (a possible +security issue) and may improve efficiency by removing +non-existent paths.
  • +
  • coders/yuv.c (ReadYUVImage): Fix leak of scanline upon Image +allocation failure. Patch submitted by Petr Gajdos via email on +Fri, 6 Oct 2017.
  • +
+
+

2017-09-13 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Attempt to fix SourceForge Issue #469 "use after +free in ReadJNGImage". Note that this change was found to replace +a use after free with a memory leak so the problem is not solved +yet.
  • +
+
+

2017-10-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dcm.c (DCM_ReadNonNativeImages): Additional fix +(improvement) for SourceForge issue #512 "NULL Pointer Dereference +in DICOM Decoder".
  • +
+
+

2017-10-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dcm.c (ReadDCMImage): Fix SourceForge issue #512 "NULL +Pointer Dereference in DICOM Decoder".
  • +
  • coders/pict.c (ReadPICTImage): Fix SourceForge issue #511 +"Memory Allocation error due to malformed image file".
  • +
  • coders/pnm.c (WritePNMImage): Fix SourceForge issue #503 "memory +leak in WritePNMImage".
  • +
  • coders/png.c (ReadMNGImage): Fix SourceForge issue #501 "memory +leak in ReadMNGImage".
  • +
  • magick/segment.c (InitializeIntervalTree): Fix SourceForge issue +#507 "null pointer in segment.c" and issue #508 "null pointer in +segment.c".
  • +
  • coders/topol.c (ReadTOPOLImage): Fix SourceForge issue #510 +"null pointer and meory leak in topol.c".
  • +
  • magick/widget.c (MagickXFileBrowserWidget): Fix SourceForge +issue #506 "null pointer in widget.c".
  • +
  • coders/tiff.c (WriteTIFFImage): Fix SourceForge issue #509 +"Memory leak in tiff.c".
  • +
  • magick/module.c (FindMagickModule): Fix SourceForge issue #502 +"null pointer in module.c".
  • +
  • coders/avs.c (ReadAVSImage): Fix Coverity CID 184115 "Control +flow issues (DEADCODE)".
  • +
+
+

2017-09-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/avs.c (ReadAVSImage): Fix SourceForge issue #499 "memory +leak in avs.c".
  • +
  • coders/cmyk.c (ReadCMYKImage): Fix SourceForge issue #498 +"memory leak in cmyk.c".
  • +
  • coders/cut.c (ReadCUTImage): Fix SourceForge issue #497 "memory +leak in cut.c".
  • +
  • coders/dpx.c (ReadDPXImage): Fix SourceForge issue #496 "memory +leak in dpx.c".
  • +
  • coders/hdf.c (ReadHDFImage): Fix SourceForge issue #495 "memory +leak in hdf.c".
  • +
  • coders/pcx.c (ReadPCXImage): Fix SourceForge issue #494 "memory +leak in pcx.c".
  • +
  • coders/pcd.c (ReadPCDImage): Fix SourceForge issue #493 "memory +leak in ReadPCDImage".
  • +
  • coders/histogram.c (WriteHISTOGRAMImage): Fix SourceForge issue +#492 "memory leak in WriteHISTOGRAMImage".
  • +
  • coders/gif.c (WriteGIFImage): Fix SourceForge issue #491 "memory +leak in WriteGIFImage".
  • +
  • coders/fits.c (WriteFITSImage): Fix SourceForge issue #490 +"memory leak in WriteFITSImage".
  • +
  • coders/palm.c (WritePALMImage): Fix SourceForge issue #489 +"memory leak in WritePALMImage".
  • +
  • coders/rgb.c (ReadRGBImage): Fix SourceForge issue #488 "Memory +leak in rgb.c".
  • +
  • coders/palm.c (ReadPALMImage): Fix SourceForge issue #487 "NULL +pointer dereference in ReadPALMImage".
  • +
  • Magick++/lib/Options.cpp (strokeDashArray): Fix SourceForge +issue #486 "NULL pointer dereference in +Magick::Options::strokeDashArray".
  • +
  • magick/nt_feature.c (NTGetTypeList): Fix SourceForge issue #485 +"NULL pointer dereference in NTGetTypeList".
  • +
  • coders/sun.c (ReadSUNImage): Fix SourceForge issue #484 "Memory +leak in sun.c".
  • +
  • coders/tim.c (ReadTIMImage): Fix SourceForge issue #483 "Memory +leak in tim.c".
  • +
  • magick/nt_base.c (NTRegistryKeyLookup): Fix SourceForge issue +#482 "NULL pointer dereference in NTRegistryKeyLookup".
  • +
  • coders/viff.c (ReadVIFFImage): Fix SourceForge issue #481 +"Memory leak in viff.c".
  • +
  • magick/profile.c (SetImageProfile): Fix SourceForge issue #480 +"assertion failure in MagickMapAllocateMap".
  • +
  • coders/yuv.c (ReadYUVImage): Fix SourceForge issue #478 "Memory +leak in yuv.c".
  • +
  • magick/map.c (MagickMapCloneMap): Fix SourceForge issue #477 +"assertion failure in MagickMapIterateNext".
  • +
  • coders/emf.c (ReadEnhMetaFile): Fix SourceForge issue #475 "NULL +pointer dereference in ReadEnhMetaFile".
  • +
  • coders/cineon.c (ReadCINEONImage): Fix SourceForge issue #473 +"NULL pointer dereference in ReadCINEONImage"
  • +
  • coders/tiff.c (TIFFIgnoreTags): Fix SourceForge issue #476 "NULL +Pointer in tiff.c".
  • +
+
+

2017-09-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/blob.c (GetConfigureBlob): Fix SourceForge issue #472 +"NULL Pointer in GetConfigureBlob".
  • +
+
+

2017-09-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/rle.c (ReadRLEImage): Fix SourceForge issue #458 "Heap +out of bounds read in ReadRLEImage()".
  • +
+
+

2017-09-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/sgi.c (ReadSGIImage): Check for EOF while reading SGI +file header. Issue was brought to our attention by Petr Gajdos +via email on Fri, 1 Sep 2017.
  • +
+
+

2017-09-17 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tiff.c (ReadTIFFImage): Allow a single scanline, strip, +tile, to be 1000X larger than the input file in order to not cause +problems for extremely compressible images or tile sizes much +larger than the pixel dimensions.
  • +
+
+

2017-09-16 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/symbols.h, wand/wand_symbols.h: Update C library symbols +which should be prefixed with 'Gm'. However, GM will not move +Magick++ namespace because of the ImageMagick version. Resolves +SourceForge issue #468 "--enable-symbol-prefix does not prevent +clashes with libMagick++ or libMagickWand?"
  • +
  • coders/png.c (DestroyJNG): DestroyJNG should be a static +function. Was wrongly exposed as DestroyJNGInfo in 1.3.26. This +is not a public function and was not intended to be part of the +ABI.
  • +
  • coders/tiff.c (ReadTIFFImage): Limit scanline, strip, and tile +memory allocations based on file size multiplied by a maximum +compression ratio. Fixes SourceForge issues #460, #461, #462, +#463, #464 "allocation failure in ReadTIFFImage".
  • +
  • coders/pnm.c (ReadPNMImage): Require that XV 332 format have 256 +colors. Fixes SourceForge issue #465 "NULL Pointer Dereference +triggered by malformed file". In our own testing the test case +produced an assertion failure because assertions were enabled.
  • +
  • magick/colormap.c (AllocateImageColormap): Use unsigned array +index.
  • +
+
+

2017-09-14 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/mat.c (ReadMATImage): Fix CVE-2016-10070, which is a heap +overflow in the MAT reader due to an under-sized memory +allocation. Based on private email from Petr Gajdos on Mon, 11 +Sep 2017.
  • +
+
+

2017-09-13 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Check MemoryResource before allocating +ping_pixel array.
  • +
+
+

2017-09-11 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • +
    magick/shear.c: Possible evil loop might waste CPU for long time
    +
    without any reason.
    +
    +
  • +
+
+

2017-09-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/render.c (DrawImage): Fix SourceForge issue #448 "Heap +out of bounds read in DrawDashPolygon()". Problem was reported by +Kamil Frankowicz on August 28, 2017.
  • +
  • coders/uil.c (WriteUILImage): Fix crash in UIL writer when +writing image containing transparency. Issue was reported by +LCatro via email on 18 Jul 2017.
  • +
  • coders/wpg.c (InsertRow): Fix crash which occurs if image is not +PseudoClass but a PseudoColor scanline is needed. Resolves +SourceForge issue #449 "Null pointer dereference in InsertRow()".
  • +
  • coders/rle.c (ReadRLEImage): Impose image dimension limits +according to Utah RLE specification. Cap number of planes handled +internally at 4. Remove non-standard multi-frame extension, which +did not work anyway.
  • +
+
+

2017-09-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadJNGImage): Complete fixing CVE-2017-8350 crash +while reading a malformed JNG file.
  • +
  • coders/{html.c, map.c, plasma.c, png.c, psd.c, rle.c, stegano.c, +uil.c}: Downgrade claimed coder stability level for HTML, SHTML, +MAP, FRACTAL, PLASMA, JNG, MNG, RLE, STEGANO, and UIL formats.
  • +
+
+

2017-09-08 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadJNGImage): More efforts toward fixing +CVE-2017-8350 while reading a malformed JNG file.
  • +
+
+

2017-09-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/error.c (ThrowLoggedException): Capture the first +exception at ErrorException level or greater, or only capture +exception if it is more severe than an already reported exception. +This should help lead to better error reports since the first +error is usually the most significant.
  • +
  • coders/png.c (ReadJNGImage): Add "improper header" exception +reporting.
  • +
+
+

2017-09-01 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadJNGImage): Efforts toward fixing CVE-2017-8350 +while reading a malformed JNG file.
  • +
+
+

2017-08-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/wpg.c (ReadWPGImage): Patch submitted by Petr Gajdos to +check that .Width and .Height are greater than zero before they +are assigned to image->columns and image->rows respectively +(CVE-2014-9815). +(ReadWPGImage): Do more validations on WPG_Palette.StartIndex and +WPG_Palette.NumOfEntries.
  • +
+
+

2017-08-29 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Fix for SourceForge issue #440 +"use-after-free in CloseBlob (blob.c) (INCOMPLETE FIX FOR +CVE-2017-11403)" and SourceForge issue #438 "heap use after free +in CloseBlob".
  • +
  • coders/png.c (ReadOneJNGImage): Fix for SourceForge issue #439 +"assertion failure in magick/pixel_cache.c"
  • +
+
+

2017-08-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/mpeg.c (WriteMPEGImage): Fix MPEG writer memory leak. +Only the first image in the coalesce image list was being freed. +Problem was reported by LCatro via email on July 15, 2017.
  • +
  • magick/attribute.c (TracePSClippingPath, TraceSVGClippingPath): +Fix SourceForge bug #447 "Heap out of bounds read in +ReadMSBShort()".
  • +
+
+

2017-08-26 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/xbm.c (ReadXBMImage): Fix two denial of service (DOS) +issues in ReadXBMImage() which result in the reader not +returning. Problem was reported via email on Wed Aug 23 2017 by +Xiaohei and Wangchu from Alibaba Security Team.
  • +
  • coders/jnx.c (ReadJNXImage): Fix denial of service (DOS) issue +in ReadJNXImage() whereby large amounts of CPU and memory +resources may be consumed although the file itself does not +support the requests. Problem was reported via email on Wed Aug +23 2017 by Xiaohei and Wangchu from Alibaba Security Team.
  • +
+
+

2017-08-14 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneMNGImage): Deal with invalid (too large) +length of MNG chunks (bug #446).
  • +
+
+

2017-08-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pnm.c (ReadPNMImage): Verify that sufficient file data +exists to support what the file header requires before allocating +memory for it. Fixes problem reported by Agostino Sarubbo via +email on Wed, 12 Jul 2017 and reported yet again via SourceForge +bug #441 "memory allocation failure in MagickRealloc".
  • +
+
+

2017-08-20 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c: Fix SourceForge bug #433 "memory leak in +ReadMATImage". Credit for discovering and reporting the problem +is "ADLab of Venustech".
  • +
  • coders/sun.c (ReadSUNImage): Fix failure to allocate memory due +to inadequate file data to support claimed image width and height. +First notified by email from Agostino Sarubbo on 14 Jul 2017 and +then again as SourceForge bug #442 "memory allocation failure in +magickmalloc".
  • +
+
+

2017-08-16 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/svg.c (GetStyleTokens): Fix SourceForge bugs 434 "heap +buffer overflow in GetStyleTokens", 435 "null pointer +dereference_in_SVGStartElement", and 436 "heap buffer overflow in +GetStyleTokens" which all originated from a heap buffer overflow +in GetStyleStokens(), or inconsistent initialization. Now the +implementation truncates parsing for poorly-formed input (to avoid +buffer overflow) while still correctly parsing well-formed input. +The reproducers and problem reports are attributed to "ADLab of +Venustech".
  • +
+
+

2017-08-14 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Fixed double-free after +reading a malformed JNG (Issue #438).
  • +
+
+

2017-08-14 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pcd.c (ReadPCDImage): Fix memory leak on return path due +to corrupted header. Patch included in email on 14 Aug 2017 by +Petr Gajdos (ImageMagick CVE CVE-2017-8351).
  • +
+
+

2017-08-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/gif.c (ReadGIFImage): Assure that global colormap is +initialized.
  • +
  • coders/pict.c (ReadPICTImage): Fix memory leaks in error return +path. ImageMagick CVE CVE-2017-8353. Patch by Petr Gajdos.
  • +
+
+

2017-08-11 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • tests/rwblob.c and rwfile.c: Write the reason for FAIL in +test-suite.log.
  • +
  • magick/image.h: Revised table of image orientations to show +Exif ImageOrientation values (which happen to be the same as +the enum values 1 to 8).
  • +
  • coders/png.c: ReadJNGIMage(): fix memory leak (Issue 431).
  • +
+
+

2017-08-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/mtv.c (ReadMTVImage): Fix memory leak in error return +path upon unexpected EOF (ImageMagick CVE-2017-9142). Problem was +brought to our attention via email from Petr Gajdos on Wed, 9 Aug +2017. Also changed pixel cache access functions used to assure +delivery of exception to the user.
  • +
+
+

2017-08-05 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • configure.ac (SETJMP_IS_THREAD_SAFE): Decide if setjmp/longjmp +are thread safe based on host OS. Assume that these interfaces +are thread safe by default. Declared not to be thread safe under +Solaris. Declaring these interfaces to be thread safe increases +available concurrency for coders which use setjmp/longjmp for +error recovery (e.g. PNG and JPEG).
  • +
+
+

2017-08-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/jpeg.c (RegisterJPEGImage): Add support for the +SETJMP_IS_THREAD_SAFE preprocessor definition (already used by +coders/png.c) to indicate if setjmp/longjmp are thread safe on +this platform and that it is safe for multiple encoders/decoders +to be active at one time.
  • +
+
+

2017-07-31 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/sun.c: Fix heap read overflow while indexing into +colormap. Problem was reported via email on 17 Jul 2017 by +Agostino Sarubbo.
  • +
+
+

2017-07-31 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadMNGImage): Stop a leak when rejecting a +MNG image with dimensions that are too large.
  • +
+
+

2017-07-26 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/wmf.c (ReadWMFImage): Eliminate use of already freed heap +data in error reporting path. Problem was reported via email by +Agostino Sarubbo on Fri, 14 Jul 2017
  • +
+
+

2017-07-25 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadMNGImage) Free chunk allocation that remains +after attempting to read a truncated file.
  • +
  • coders/png.c: Removed some redundant checks for chunk length +before MagickFreeMemory(chunk), which is safe to call with a +NULL argument.
  • +
  • coders/png.c: Fixed writer bug due to missing brackets; a Log +statement should have been inside the "i" loop but instead was +using i++ left over from the loop. Bug report by L. Catro.
  • +
  • coders/png.c: Reject a MNG with dimensions greater than 65k +by 65k.
  • +
  • coders/png.c (WriteOnePNGImage): Return without crashing if +WriteOnePNGImage is passed a NULL image. Fixes CVE-2017-11522.
  • +
+
+

2017-07-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pcl.c (WritePCLImage): Fix null pointer dereference in +PCL writer when writing monochrome images. Problem was reported +by LCatro via email on July 18.
  • +
  • magick/pixel_cache.c (PersistCache): Fix memory leak while +writing a MPC file. Problem was reported by LCatro via email on +July 18.
  • +
  • coders/map.c (WriteMAPImage): Fix null pointer dereference or +segmentation violation in the MAP writer if the input image is not +already colormapped. Problem was reported by LCatro via email on +July 18.
  • +
  • coders/gray.c (WriteGRAYImage): Improve tracing and tidy up.
  • +
  • coders/rgb.c (WriteRGBImage): Fix heap overwrite in raw RGB +writer (all output subformats) given a multiframe sequence using +different widths. Problem was reported by LCatro via email on +July 18.
  • +
  • coders/cmyk.c (WriteCMYKImage): Fix heap overwrite in raw CMYK +writer (all output subformats) given a multiframe sequence using +different widths. Also fix wrong output of CMYKA (and vice-versa) +when CMYK was intended. Problem was reported by LCatro via email +on July 18.
  • +
  • coders/palm.c: Disable the PALM writer since the writer is a +work in progress and still has implementation problems. Perhaps +no one in the world remains who cares about the undocumented PALM +format. Resolves heap overflow and assertion issues reported by +LCatro via emails on July 11th, and 12th, 2017.
  • +
  • magick/colormap.c (ReplaceImageColormap): Throw an exception +rather than assertion if the input image is not colormapped.
  • +
+
+

2017-07-13 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Implemented eXIf chunk support.
  • +
+
+

2017-07-12 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Fix typecast of left shifts (patch by Bob F)
  • +
+
+

2017-07-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/ps.c (ReadPSImage): Fix reference to constant NULL image +argument which is dereferenced to pass an exception to +MagickMonitorFormatted(). Problem was reported by Agostino +Sarubbo via email on Wed, 12 Jul 2017.
  • +
+
+

2017-07-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/blob.c: Add casts to fix undefined behavior in left +shifts. Issue was reported by Agostino Sarubbo via email on Mon, +10 Jul 2017.
  • +
+
+

2017-07-10 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Ignore out-of-bounds MOVE +and CLIP object_id's.
  • +
  • coders/png.c (ReadMNGImage): Fix apparent off-by-one error +in MNG FRAM change_clipping processing.
  • +
  • coders/png.c (ReadMNGImage): Fix out-of-order CloseBlob() +and DestroyImageList() that caused a use-after-free crash. +Fixes CVE-2017-11403. This bug was discovered by Agostino Sarubbo.
  • +
+
+

2017-07-08 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJngImage): Revised double-free fix.
  • +
+
+

2017-07-08 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Fix double-frees caused by +commit on 2017-07-06.
  • +
  • coders/jpeg.c (ReadJPEGImage): Defer creating pixel cache until +after successfully reading first scanline. Classify some serious +libjpeg reported "warnings" as errors and quit processing +scanlines immediately upon first error so that corrupt JPEG does +not consume excessive resources. Resolves excessive resource +consumption issue reported for two JPEG files provided via email +by LCatro on Tue, 4 Jul 2017.
  • +
+
+

2017-07-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Remove spurious 'n' from log +statement.
  • +
+
+

2017-07-06 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Consolidate JNG cleanup into a new DestroyJNG() +function.
  • +
+
+

2017-07-05 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: prevent a crash due to zero-length color_image +while reading a JNG image. (CVE-2017-11102)
  • +
+
+

2017-07-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • NEWS.txt: Make sure is up to date.
  • +
  • www/index.rst: Update for 1.3.26 release.
  • +
  • version.sh: Update library versioning for 1.3.26 release.
  • +
  • magick/command.c (BatchCommand): Add ferror() checks around +batch input loop.
  • +
+
+

2017-07-03 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Reject a PNG file if the file size is too small +(less than 61 bytes). Reject a JNG file if it is too small (less +than 147 bytes).
  • +
  • coders/jpeg.c: Reject a JPEG file if the file size is too small +(less than 107 bytes).
  • +
+
+

2017-07-02 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dpx.c (ReadDPXImage): Compute required file size and +verify that sufficient data exists in file before allocating +memory to decode the image data. Resolves problem with DPX file +with valid header (but a huge claimed image width) provided +provided via email on Thu, 29 Jun 2017 by LCatro. This issue has +been assigned CVE-2017-10799.
  • +
+
+

2016-07-02 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Check whether reported object size overflows file size.
  • +
+
+

2016-07-01 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Safety check for forged and or corrupted data. +This issue has been assigned CVE-2017-10800.
  • +
+
+

2017-07-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tiff.c ("QuantumTransferMode"): Use a generalized method +to enforce that buffer overflow can not happen while importing +pixels. Resolves problem with RGB TIFF claiming only one sample +per pixel provided via email on Thu, 29 Jun 2017 by LCatro. This +issue has been assigned CVE-2017-10794.
  • +
+
+

2017-06-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/command.c: Convert bare 'unsigned int' to MagickPassFail +where suitable to make intentions clear. Convert True/False to +MagickTrue/MagickFalse or MagickPass/MagickFail according to +purpose. This is a continuation of a gradual migration and does +not represent an API change.
  • +
+
+

2017-06-25 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+ +
+

2017-06-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • NEWS.txt: Update NEWS with changes since the previous release.
  • +
  • www/programming.rst: Switch the Lua link to +https://github.com/arcapos/luagraphicsmagick, which is a more +complete and direct interface from Lua to GraphicsMagick's Wand +API.
  • +
+
+

2017-06-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • VisualMagick/installer/gm-foo-dll.iss: Remove PerlMagick from +the slim Inno Setup installer builder and remove mention of +PerlMagick from the installer documentation.
  • +
  • TclMagick/generic/TclMagick.c (magickCmd): Resolve SourceForge +patch #51 "TclMagick: memory access error; possible segfault". +(newMagickObj): Fix formatting of pointer value so it is 64-bit +safe. Resolves SourceForge patch #50 "TclMagick: 64-bit +portability issue".
  • +
  • coders/pict.c (ReadPICTImage): Avoid possible use of negative +value when indexing array, which would cause buffer overflow. +Resolves SourceForge issue #427 "One possible buffer overflow +vulnerability in +GraphicsMagick-1.3.25/coders/pict.c:ReadPICTImage()".
  • +
+
+

2017-06-22 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Stop memory leak when reading invalid JNG image. +Fixes CVE-2017-8350.
  • +
+
+

2017-06-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Fix lcms2.h inclusion logic.
  • +
  • wand/magick_wand.c (MagickSetImageOrientation): Eliminate use of +snprintf, which is not supported by older Visual Studio.
  • +
+
+

2017-06-09 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Accept exIf chunks whose data segment +erroneously begins with "Exif00".
  • +
+
+

2017-06-01 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Removed experimental zxIF chunk support. That +proposal is dead.
  • +
+
+

2017-05-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • config/log.mgk: Added documentation suggested by SourceForge +issue #419 "Consider a small patch to log.mgk".
  • +
  • www/Changes.rst: Add missing link to most recent changes.
  • +
+
+

2017-05-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • www/Magick++/Image.rst: Improve documentation for Magick++ +Image::iccColorProfile() and Image::renderingIntent().
  • +
+
+

2017-05-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • tiff: Update to libtiff 4.0.8.
  • +
+
+

2017-03-19 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Quieted a new Coverity complaint about a potential +text buffer overrun.
  • +
+
+

2017-03-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/image.c (SetImageInfo): Ignore empty magic prefix +specification and do not remove colon character from start of +filename. Resolves SourceForge bug #415 "Inconsistent Behavior w/ +input_file Parameter".
  • +
+
+

2017-03-18 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Added new private orNT PNG chunk, to +preserve image->orientation when it is defined and not +the default TopLeft.
  • +
  • coders/jpeg.c: Mention image->orientation in the log when +writing a JPEG.
  • +
+
+

2017-03-15 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (WriteOnePNGImage): Add version info about +gm, libpng, zlib, and lcms to the PNG debug log.
  • +
+
+

2017-03-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/command.c (ImportImageCommand): Fix handling of -frame +options. Option handling was incorrect due to option checking the +frame option after it had been freed. Checking the frame dash +option before freeing the argument solves the problem. From patch +provided by Victor Ananjevsky as SourceForge patch #49 "-frame +doesn't work in gm import".
  • +
  • Magick++/lib/Image.cpp (attribute): Added Image attribute method +which accepts a 'char *' argument, and will remove the attribute +if the value argument is NULL. From patch provided by "Gints" as +SourceForge patch #46 "C++ api - method to clear/remove +attribute".
  • +
  • VisualMagick/configure/configure.cpp (InitInstance): Applied +patch by Paul McConkey to allow the quantum command line argument +to set the default value in the wizard drop list. This allows +setting the quantum depth when the /nowizard argument was +supplied. Resolves SourceForge patch #48 "When running from the +command line configure.exe does not use the quantum argument". +The provided configure.exe still needs to be rebuilt to +incorporate this change.
  • +
  • magick/command.c (MogrifyImage): The -orient command now also +updates the orientation in the EXIF profile, if it exists.
  • +
  • Magick++/lib/Image.cpp (orientation): Update orientation in EXIF +profile, if it exists.
  • +
+
+

2017-03-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/jp2.c: Support PGX JPEG 2000 format for reading and +writing (within the bounds of what JasPer supports).
  • +
+
+

2017-02-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tiff.c (QuantumTransferMode): Fix out of bounds read when +reading CMYKA TIFF which claims to have only 2 samples per pixel. +Problem was reported via email on February 15, 2017 by Valon +Chu. This issue was assigned CVE-2017-6335.
  • +
+
+

2017-01-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • doc/options.imdoc (-geometry): Geometry documentation changes +suggested by Jon Wong.
  • +
+
+

2017-01-26 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Added support for a proposed new PNG chunk +(zxIf, read-only) that is currently being discussed on the +png-mng-misc at lists.sourceforge.net mailing list. Enable +exIf and zxIf with CPPFLAGS="-DexIf_SUPPORTED -DxzIf_SUPPORTED". +If exIf is enabled, only the uncompressed exIF chunk will be +written and the hex-encoded zTXt chunk containing the raw Exif +profile won't be written.
  • +
+
+

2017-01-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/msl.c (MSLStartElement): Change test for NULL image +pointer to before it is used rather than after it is used. +Problem reported by Petr Gajdos on 2017-01-25.
  • +
+
+

2017-01-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • TclMagick/unix/m4/tcl.m4: Update tcl.m4 to TEA 3.10. File +supplied by Massimo Manghi.
  • +
+
+

2017-01-21 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Added support for a proposed new PNG +chunk (exIf read-write, eXIf read-only) that is currently +being discussed on the png-mng-misc at lists.sourceforge.net +mailing list.
  • +
+
+

2017-01-21 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+
+
    +
  • coders/png.c: Added read_user_chunk_callback() function +and used it to implement a private PNG caNv (canvas) chunk +for remembering the original dimensions and offsets when an +image is cropped. Previously we used the oFFs chunk for this +purpose, but this had potential conflicts with other applications +that also use the oFFs chunk.
  • +
+
+

2017-01-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • TclMagick/Makefile.am (AM_DISTCHECK_CONFIGURE_FLAGS): Applied +patch by Massimo Manghi to set AM_DISTCHECK_CONFIGURE_FLAGS so +that 'make distcheck' remembers configuration options, and also to +uninstall pkgIndex.tcl.
  • +
  • magick/image.c (SetImageEx): Use PixelIterateMonoSet() for +possibly improved efficiency.
  • +
  • magick/pixel_iterator.c (PixelIterateMonoSet): New pixel +iterator intended for use when initializing image pixels, without +regard to existing values.
  • +
+
+

2017-01-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • Copyright.txt: Bump copyright years and rotate ChangeLog.
  • +
+
+
+ + diff --git a/www/ChangeLog-2017.rst b/www/ChangeLog-2017.rst new file mode 100644 index 0000000..8a34df7 --- /dev/null +++ b/www/ChangeLog-2017.rst @@ -0,0 +1,1108 @@ +2017-12-25 Bob Friesenhahn + + - tests/rwfile.tap: Add tests for MIFF compressed sub-formats. + +2017-12-24 Bob Friesenhahn + + - magick/blob.c (OpenBlob): Zlib 1.2.8 does not accept an open + mode of "w+b" or "wb+". It seems to be allergic to '+'. As a + result, writing to ".gz" files was not working with Zlib 1.2.8. + Note that "w+b" must be used in the normal case since the test + suite fails otherwise! + +2017-12-22 Bob Friesenhahn + + - coders/png.c (ReadMNGImage): Fix SourceForge issue #535 + "heap-buffer-overflow in ReadMNGImage". Problem was caused by + accessing byte before testing that limit has been reached, rather + than testing for limit before accessing the byte. This means that + it could only ever read one past the buffer allocation size. + + - coders/webp.c (WriteWEBPImage): Fix SourceForge issue #536 + "stack-buffer-overflow in WriteWEBPImage". Due to a change to use + WebPMemoryWriter as part of the EXIF and ICC profile support + addition (enabled with libwebp 0.5.0), the progress indicator + callback is now passed a pointer to a wrong structure. This is + quite unfortunate since the progress indication is useful. The + progress indication is temporarily disabled when the + WebPMemoryWriter is in use until a solution is implemented. + (ProgressCallback): Re-implement progress callback so that image + pointer is stored/retrieved as thread-specific data. + + - coders/png.c (ReadMNGImage): Fix SourceForge issue #537 "null + pointer dereference in ReadMNGImage". DEFI chunk must be at least + 2 bytes long. + + - coders/tiff.c (ReadNewsProfile): Fix SourceForge issue #533 + "heap-buffer-overflow on LocaleNCompare". LocaleNCompare() was + being allowed to read heap data beyond the allocated region. + +2017-12-17 Bob Friesenhahn + + - magick/shear.c (IntegralRotateImage): Assure that reported error + in rotate by 270 case does immediately terminate processing. + Return a NULL Image pointer if there is a problem rather than a + corrupted image. Fix is related to SourceForge issue #532 + "heap-buffer-overflow bug in ReadWPGImage". + + - magick/pixel\_cache.c (AcquireCacheNexus): Add a check that the + pixel cache is compatible with the image dimensions. Fix is + related to SourceForge issue #532 "heap-buffer-overflow bug in + ReadWPGImage". + +2017-12-16 Bob Friesenhahn + + - coders/png.c (ReadOneJNGImage): Fix SourceForge issue #530 + "heap-buffer-overflow in ReadOneJNGImage". In this case there is + a read one byte beyond the oFFs chunk allocation size due to an + error in specifying an offset into the chunk. + + - coders/palm.c (ReadPALMImage): Fix SourceForge issue #529 + "global-buffer-overflow in ReadPALMImage". This issue only + occured in builds with QuantumDepth=8 due to the small range of + IndexPacket. + +2017-12-13 Bob Friesenhahn + + - PerlMagick/{Magick.pm, Magick.pm.in, Makefile.PL.in}: Only base + PerlMagick version on numeric portion of PACKAGE\_VERSION. + +2017-12-09 Bob Friesenhahn + + - www/index.rst: Update to 1.3.27. + + - www/Changes.rst: Add 1.3.27 + + - version.sh: Update library versioning. + + - NEWS.txt: Update NEWS in preparation for releasing 1.3.27. + +2017-12-08 Bob Friesenhahn + + - coders/dcm.c (DCM\_ReadElement): Change size checks addressing + CVE-2017-12140 to be based on size\_t rather than magick\_off\_t due + to apparent instability of the previous check across compilers. + +2017-12-07 Bob Friesenhahn + + - coders/png.c (WriteOnePNGImage): Fix heap read access outside of + allocated PixelPacket array while testing pixels for opacity. + Resolves SourceForge issue #526 "heap-buffer-overflow in + WriteOnePNGImage". + +2017-12-06 Bob Friesenhahn + + - coders/pnm.c (WritePNMImage): Fix SourceForge bug #525 + "heap-buffer-overflow in MagickBitStreamMSBWrite". + +2017-12-05 Bob Friesenhahn + + - coders/dcm.c (DCM\_ReadElement): Eliminate huge memory allocation + based on bogus length value. Addresses CVE-2017-12140. Problem was + reported via email from Petr Gajdos on Tue, 5 Dec 2017. + +2017-12-03 Bob Friesenhahn + + - Magick++/lib/Image.cpp (colorMap): Try to eliminate Coverity CID + 172796 "Dereference after null check" which seems to be bogus. + + - coders/png.c (WriteOnePNGImage): Fix Coverity CID 168053 + "Dereference after null check". The check for null and the error + report which attempted to use the null value was not needed at + all. + + - coders/cut.c (GetCutColors): Fix Coverity CID 10181: "Null + pointer dereferences". SetImagePixels() may return NULL. + + - coders/rgb.c (ReadRGBImage): Fix SourceForge issue #523 + "heap-buffer-overflow". Similar issue to cmyk.c. + + - coders/gray.c (ReadGRAYImage): Fix SourceForge issue #522 + "heap-buffer-overflow". Similar issue to cmyk.c. + + - coders/cmyk.c (ReadCMYKImage): Fix SourceForge issue #521 + "heap-buffer-overflow". The requested tile must be within the + bounds of the image. As it happens, 'montage' passes size and + tile information which is useless for reading a raw image so it is + not possible to read raw CMYK using 'montage'. + +2017-12-02 Bob Friesenhahn + + - coders/pwp.c (ReadPWPImage): Eliminate dereference of null image + pointer. Addresses CVE-2017-11640. Also address access to + uninitialized memory. Problem was reported via email from Petr + Gajdos on Wed, 29 Nov 2017. + +2017-11-22 Fojtik Jaroslav + + - coders/wpg.c Additional check for wrong bpp CVE-2017-14342. + + +2017-11-22 Bob Friesenhahn + + - Magick++/lib/Image.cpp (autoOrient): Add method to auto-orient + an image so it looks right-side up by default. Based on patch by + Przemysław Sobala submitted as SourceForge patch #53 "Add + Magick::Image::autoOrient() method to Magick++ library". + + - www/download.rst: Change "Czechoslovakian ftp mirror" to "Czech + ftp mirror". Resolves SourceForge bug #520 "[web] Download sites: + non-existent country". + +2017-11-21 Bob Friesenhahn + + - coders/wpg.c (ReadWPGImage): Fix excessive use of disk resources + due to unreasonable record length. Addresses CVE-2017-14341. + Notified of this issue (with suggested patch) via email by Petr + Gajdos on Tue, 21 Nov 2017. + +2017-11-19 Bob Friesenhahn + + - README.txt: Comprehensive white-space clean-up across + GraphicsMagick core source files. Hard TAB character is converted + to spaces. Trailing white-space garbage is stripped. + + - magick/colormap.c (MagickConstrainColormapIndex): Deprecate use + of MagickConstrainColormapIndex() and prefer use of + VerifyColormapIndex() and VerifyColormapIndexWithColors() due to + avoiding dependence on index type, allowing provision of colors + other than image->colors, and capturing more useful source file + and line information. + + - coders/{rle.c, mat.c, xbm.c, sgi.c, png.c}: Eliminate size\_t vs + unsigned 32 conversion warnings in WIN64 build. + +2017-11-18 Bob Friesenhahn + + - tiff: Import libtiff 4.0.9. + +2017-11-12 Bob Friesenhahn + + - coders/bmp.c (DecodeImage): "Right-size" and "Right-type" + DecodeImage() variables and check for EOF at every point of the + way. Pass buffer size as an argument. + + - coders/dib.c (DecodeImage): "Right-size" and "Right-type" + DecodeImage() variables and check for EOF at every point of the + way. Pass buffer size as an argument. + + - coders/bmp.c (\_BMPInfo): "Right-size" BMPInfo members. The + 'long' type is promoted to 64-bit on LP64 systems and the large + size is not needed. + +2017-11-11 Bob Friesenhahn + + - coders/webp.c: Incorporate patch by Jan Spitalnik to add EXIF + and ICC metadata support to the WebP coder. While WebP is still + supported back to libwebp 0.1.99, the metadata support requires at + least libwebp 0.5.0. Resolves SourceForge patch #52 "Add EXIF/ICC + metadata support to WebP coder". + + - coders/png.c (ReadOneJNGImage): Fix JNG memory leaks when JPEG + image fails to be read. + (WriteOnePNGImage): Promotion of indexed PNG to RGBA lacked + setting of image matte, resulting in undersized buffer allocation + and heap overflow. Fixes SourceForge bug #453 "Heap overflow in + source-gra/coders/png.c". + +2017-11-06 Bob Friesenhahn + + - coders/sfw.c (SFWScan): Fix heap buffer overflow + (CVE-2017-13134). Notified of problem via email (including a + patch) from Petr Gajdos on Mon, 6 Nov 2017. + +2017-11-05 Fojtik Jaroslav + + - coders/wpg.c Wrong MaxMap check condition - fixed. + +2017-11-04 Fojtik Jaroslav + + - coders/wpg.c Check for InsertRow() return value. + +2017-11-04 Bob Friesenhahn + + - magick/export.c: Add not-null check for indexes pointer where + needed. + + - magick/import.c: Add not-null check for indexes pointer with + associated exception report where the indexes pointer is needed. + (ImportCMYKQuantumType): Was wrongly importing an opacity channel + in some cases. Would have crashed if these cases were ever used. + + - coders/wpg.c (ReadWPGImage): Assure that colormapped image is a + PseudoClass type with valid colormapped indexes. Fixes + SourceForge bug 519 "Null Pointer Dereference (Write) with + malformed WPG Image". + + - coders/sfw.c (ReadSFWImage): Avoid possible heap overflow while + copying JFIF magic into buffer. Reject runt files. Fixes + CVE-2017-12983. Notified of problem via email from Petr Gajdos on + Thu, 2 Nov 2017. + +2017-10-28 Bob Friesenhahn + + - magick/render.c (DrawImage): Fix SourceForge bug #517 "Push + operations in DrawImage can lead to negative strncpy when looking + for pop". Interestingly, valgrind and ASAN only detected a + problem with one of the test cases since exercised code which + updated an array using the index. It appears that Linux strncpy() + simply ignores the bad request. + +2017-10-27 Bob Friesenhahn + + - coders/png.c (ReadOneJNGImage): Make sure that a reasonable + exception is reported to the user when there is a read failure. + +2017-10-26 Bob Friesenhahn + + - coders/png.c (ReadOneJNGImage): Reject JNG files with + unreasonable dimensions given the file size. + +2017-10-25 Bob Friesenhahn + + - coders/png.c (ReadOneJNGImage): Fix SourceForge bug #518 "Null + pointer in". Also make sure that errors are reported properly due + to problems with transferring JPEG scanlines. + (ReadOneJNGImage): Add more checks for null value returned from + SetImagePixels(). + +2017-10-22 Bob Friesenhahn + + - magick/describe.c (DescribeImage): Fix possible heap read + overflow while accessing heap data, and possible information + disclosure while describing the IPTC profile. Report was provided + via email from Maor Shwartz to the graphicsmagick-security mail + alias on Thu, 19 Oct 2017. Independent security researchers, + Jeremy Heng (@nn\_amon) and Terry Chia (Ayrx), reported this + vulnerability to Beyond Security’s SecuriTeam Secure Disclosure + program. Please note that this interface is usually (but not + exclusively) used from within the command-line utility program, in + which case there is not much useful information which might be + disclosed. + (DescribeImage): Fix possible heap write overflow when describing + visual image directory. Report was provided via email from Maor + Shwartz to the graphicsmagick-security mail alias on Thu, 19 Oct + 2017. Independent security researchers, Jeremy Heng (@nn\_amon) + and Terry Chia (Ayrx), reported this vulnerability to Beyond + Security’s SecuriTeam Secure Disclosure program. Please note that + this interface is usually (but not exclusively) used from within + the command-line utility program, in which case the only harm + would be a program crash. + + - magick/constitute.c (WriteImage): Assure that the errno present + when the blob error status first occured is reported to the user. + + - magick/blob.c (GetBlobStatus): Blob error status is now updated + immediately upon the first error reported. + (GetBlobFirstErrno): Returns errno value when the first blob error + was reported. This is useful for error reporting. + +2017-10-21 Bob Friesenhahn + + - magick/constitute.c (WriteImage): Restore use of GetBlobStatus() + to test if an I/O error was encountered while writing output file. + This assures that I/O failure in writers which do not themselves + verify writes is assured to be reported. + +2017-10-17 Bob Friesenhahn + + - coders/webp.c (WriterCallback): WebP writer now detects partial + write to output file. Patch by Przemysław Sobala from a posting + on Mon, 16 Oct 2017 via the graphicsmagick-help mailing list. + +2017-10-14 Bob Friesenhahn + + - magick/command.c (MontageImageCommand): Fix memory leaks in + error return path. Only people doing leak testing or the few who + execute MontageImageCommand() as a function will care about this. + + - magick/studio.h (NumberOfObjectsInArray): The + NumberOfObjectsInArray() macro is used to compute the number of + whole objects in an array. Instead it was rounding up, resulting + in scrambling the heap beyond the allocation. Fixes + CVE-2017-13737 "There is an invalid free in the MagickFree + function in magick/memory.c in GraphicsMagick 1.3.26 that will + lead to a remote denial of service attack." + +2017-10-09 Glenn Randers-Pehrson + + - coders/png.c (ReadOnePNGImage): Suppress "comparison between + signed and unsigned integer expressions" warning. + - coders/png.c (ReadJNGImage): Fix memory leak in SourceForge + Issue #469 "use after free in ReadJNGImage". + - coders/png.c (ReadJNGImage): Fix memory leak in SourceForge + Issue #470 "Assert failure in writeblob". + +2017-10-08 Bob Friesenhahn + + - doc/options.imdoc: Fix SourceForge issue #444 "gm mogrify: Wrong + documentation for option -output-directory". + +2017-10-07 Bob Friesenhahn + + - magick/module.c (InitializeModuleSearchPath): Verify that any + component paths specified in MAGICK\_CODER\_MODULE\_PATH and + MAGICK\_FILTER\_MODULE\_PATH exist before adding them to search paths + actually used, and convert to real paths if possible. This avoids + possible use of relative paths to load modules (a possible + security issue) and may improve efficiency by removing + non-existent paths. + + - coders/yuv.c (ReadYUVImage): Fix leak of scanline upon Image + allocation failure. Patch submitted by Petr Gajdos via email on + Fri, 6 Oct 2017. + +2017-09-13 Glenn Randers-Pehrson + + - coders/png.c: Attempt to fix SourceForge Issue #469 "use after + free in ReadJNGImage". Note that this change was found to replace + a use after free with a memory leak so the problem is not solved + yet. + +2017-10-03 Bob Friesenhahn + + - coders/dcm.c (DCM\_ReadNonNativeImages): Additional fix + (improvement) for SourceForge issue #512 "NULL Pointer Dereference + in DICOM Decoder". + +2017-10-01 Bob Friesenhahn + + - coders/dcm.c (ReadDCMImage): Fix SourceForge issue #512 "NULL + Pointer Dereference in DICOM Decoder". + + - coders/pict.c (ReadPICTImage): Fix SourceForge issue #511 + "Memory Allocation error due to malformed image file". + + - coders/pnm.c (WritePNMImage): Fix SourceForge issue #503 "memory + leak in WritePNMImage". + + - coders/png.c (ReadMNGImage): Fix SourceForge issue #501 "memory + leak in ReadMNGImage". + + - magick/segment.c (InitializeIntervalTree): Fix SourceForge issue + #507 "null pointer in segment.c" and issue #508 "null pointer in + segment.c". + + - coders/topol.c (ReadTOPOLImage): Fix SourceForge issue #510 + "null pointer and meory leak in topol.c". + + - magick/widget.c (MagickXFileBrowserWidget): Fix SourceForge + issue #506 "null pointer in widget.c". + + - coders/tiff.c (WriteTIFFImage): Fix SourceForge issue #509 + "Memory leak in tiff.c". + + - magick/module.c (FindMagickModule): Fix SourceForge issue #502 + "null pointer in module.c". + + - coders/avs.c (ReadAVSImage): Fix Coverity CID 184115 "Control + flow issues (DEADCODE)". + +2017-09-30 Bob Friesenhahn + + - coders/avs.c (ReadAVSImage): Fix SourceForge issue #499 "memory + leak in avs.c". + + - coders/cmyk.c (ReadCMYKImage): Fix SourceForge issue #498 + "memory leak in cmyk.c". + + - coders/cut.c (ReadCUTImage): Fix SourceForge issue #497 "memory + leak in cut.c". + + - coders/dpx.c (ReadDPXImage): Fix SourceForge issue #496 "memory + leak in dpx.c". + + - coders/hdf.c (ReadHDFImage): Fix SourceForge issue #495 "memory + leak in hdf.c". + + - coders/pcx.c (ReadPCXImage): Fix SourceForge issue #494 "memory + leak in pcx.c". + + - coders/pcd.c (ReadPCDImage): Fix SourceForge issue #493 "memory + leak in ReadPCDImage". + + - coders/histogram.c (WriteHISTOGRAMImage): Fix SourceForge issue + #492 "memory leak in WriteHISTOGRAMImage". + + - coders/gif.c (WriteGIFImage): Fix SourceForge issue #491 "memory + leak in WriteGIFImage". + + - coders/fits.c (WriteFITSImage): Fix SourceForge issue #490 + "memory leak in WriteFITSImage". + + - coders/palm.c (WritePALMImage): Fix SourceForge issue #489 + "memory leak in WritePALMImage". + + - coders/rgb.c (ReadRGBImage): Fix SourceForge issue #488 "Memory + leak in rgb.c". + + - coders/palm.c (ReadPALMImage): Fix SourceForge issue #487 "NULL + pointer dereference in ReadPALMImage". + + - Magick++/lib/Options.cpp (strokeDashArray): Fix SourceForge + issue #486 "NULL pointer dereference in + Magick::Options::strokeDashArray". + + - magick/nt\_feature.c (NTGetTypeList): Fix SourceForge issue #485 + "NULL pointer dereference in NTGetTypeList". + + - coders/sun.c (ReadSUNImage): Fix SourceForge issue #484 "Memory + leak in sun.c". + + - coders/tim.c (ReadTIMImage): Fix SourceForge issue #483 "Memory + leak in tim.c". + + - magick/nt\_base.c (NTRegistryKeyLookup): Fix SourceForge issue + #482 "NULL pointer dereference in NTRegistryKeyLookup". + + - coders/viff.c (ReadVIFFImage): Fix SourceForge issue #481 + "Memory leak in viff.c". + + - magick/profile.c (SetImageProfile): Fix SourceForge issue #480 + "assertion failure in MagickMapAllocateMap". + + - coders/yuv.c (ReadYUVImage): Fix SourceForge issue #478 "Memory + leak in yuv.c". + + - magick/map.c (MagickMapCloneMap): Fix SourceForge issue #477 + "assertion failure in MagickMapIterateNext". + + - coders/emf.c (ReadEnhMetaFile): Fix SourceForge issue #475 "NULL + pointer dereference in ReadEnhMetaFile". + + - coders/cineon.c (ReadCINEONImage): Fix SourceForge issue #473 + "NULL pointer dereference in ReadCINEONImage" + + - coders/tiff.c (TIFFIgnoreTags): Fix SourceForge issue #476 "NULL + Pointer in tiff.c". + +2017-09-25 Bob Friesenhahn + + - magick/blob.c (GetConfigureBlob): Fix SourceForge issue #472 + "NULL Pointer in GetConfigureBlob". + +2017-09-24 Bob Friesenhahn + + - coders/rle.c (ReadRLEImage): Fix SourceForge issue #458 "Heap + out of bounds read in ReadRLEImage()". + +2017-09-19 Bob Friesenhahn + + - coders/sgi.c (ReadSGIImage): Check for EOF while reading SGI + file header. Issue was brought to our attention by Petr Gajdos + via email on Fri, 1 Sep 2017. + +2017-09-17 Bob Friesenhahn + + - coders/tiff.c (ReadTIFFImage): Allow a single scanline, strip, + tile, to be 1000X larger than the input file in order to not cause + problems for extremely compressible images or tile sizes much + larger than the pixel dimensions. + +2017-09-16 Bob Friesenhahn + + - magick/symbols.h, wand/wand\_symbols.h: Update C library symbols + which should be prefixed with 'Gm'. However, GM will not move + Magick++ namespace because of the ImageMagick version. Resolves + SourceForge issue #468 "--enable-symbol-prefix does not prevent + clashes with libMagick++ or libMagickWand?" + + - coders/png.c (DestroyJNG): DestroyJNG should be a static + function. Was wrongly exposed as DestroyJNGInfo in 1.3.26. This + is not a public function and was not intended to be part of the + ABI. + + - coders/tiff.c (ReadTIFFImage): Limit scanline, strip, and tile + memory allocations based on file size multiplied by a maximum + compression ratio. Fixes SourceForge issues #460, #461, #462, + #463, #464 "allocation failure in ReadTIFFImage". + + - coders/pnm.c (ReadPNMImage): Require that XV 332 format have 256 + colors. Fixes SourceForge issue #465 "NULL Pointer Dereference + triggered by malformed file". In our own testing the test case + produced an assertion failure because assertions were enabled. + + - magick/colormap.c (AllocateImageColormap): Use unsigned array + index. + +2017-09-14 Bob Friesenhahn + + - coders/mat.c (ReadMATImage): Fix CVE-2016-10070, which is a heap + overflow in the MAT reader due to an under-sized memory + allocation. Based on private email from Petr Gajdos on Mon, 11 + Sep 2017. + +2017-09-13 Glenn Randers-Pehrson + + - coders/png.c: Check MemoryResource before allocating + ping\_pixel array. + +2017-09-11 Fojtik Jaroslav + + - magick/shear.c: Possible evil loop might waste CPU for long time + without any reason. + +2017-09-10 Bob Friesenhahn + + - magick/render.c (DrawImage): Fix SourceForge issue #448 "Heap + out of bounds read in DrawDashPolygon()". Problem was reported by + Kamil Frankowicz on August 28, 2017. + + - coders/uil.c (WriteUILImage): Fix crash in UIL writer when + writing image containing transparency. Issue was reported by + LCatro via email on 18 Jul 2017. + + - coders/wpg.c (InsertRow): Fix crash which occurs if image is not + PseudoClass but a PseudoColor scanline is needed. Resolves + SourceForge issue #449 "Null pointer dereference in InsertRow()". + + - coders/rle.c (ReadRLEImage): Impose image dimension limits + according to Utah RLE specification. Cap number of planes handled + internally at 4. Remove non-standard multi-frame extension, which + did not work anyway. + +2017-09-09 Bob Friesenhahn + + - coders/png.c (ReadJNGImage): Complete fixing CVE-2017-8350 crash + while reading a malformed JNG file. + + - coders/{html.c, map.c, plasma.c, png.c, psd.c, rle.c, stegano.c, + uil.c}: Downgrade claimed coder stability level for HTML, SHTML, + MAP, FRACTAL, PLASMA, JNG, MNG, RLE, STEGANO, and UIL formats. + +2017-09-08 Glenn Randers-Pehrson + + - coders/png.c (ReadJNGImage): More efforts toward fixing + CVE-2017-8350 while reading a malformed JNG file. + +2017-09-01 Bob Friesenhahn + + - magick/error.c (ThrowLoggedException): Capture the first + exception at ErrorException level or greater, or only capture + exception if it is more severe than an already reported exception. + This should help lead to better error reports since the first + error is usually the most significant. + + - coders/png.c (ReadJNGImage): Add "improper header" exception + reporting. + +2017-09-01 Glenn Randers-Pehrson + + - coders/png.c (ReadJNGImage): Efforts toward fixing CVE-2017-8350 + while reading a malformed JNG file. + +2017-08-30 Bob Friesenhahn + + - coders/wpg.c (ReadWPGImage): Patch submitted by Petr Gajdos to + check that .Width and .Height are greater than zero before they + are assigned to image->columns and image->rows respectively + (CVE-2014-9815). + (ReadWPGImage): Do more validations on WPG\_Palette.StartIndex and + WPG\_Palette.NumOfEntries. + +2017-08-29 Glenn Randers-Pehrson + + - coders/png.c (ReadOneJNGImage): Fix for SourceForge issue #440 + "use-after-free in CloseBlob (blob.c) (INCOMPLETE FIX FOR + CVE-2017-11403)" and SourceForge issue #438 "heap use after free + in CloseBlob". + - coders/png.c (ReadOneJNGImage): Fix for SourceForge issue #439 + "assertion failure in magick/pixel\_cache.c" + +2017-08-27 Bob Friesenhahn + + - coders/mpeg.c (WriteMPEGImage): Fix MPEG writer memory leak. + Only the first image in the coalesce image list was being freed. + Problem was reported by LCatro via email on July 15, 2017. + + - magick/attribute.c (TracePSClippingPath, TraceSVGClippingPath): + Fix SourceForge bug #447 "Heap out of bounds read in + ReadMSBShort()". + +2017-08-26 Bob Friesenhahn + + - coders/xbm.c (ReadXBMImage): Fix two denial of service (DOS) + issues in ReadXBMImage() which result in the reader not + returning. Problem was reported via email on Wed Aug 23 2017 by + Xiaohei and Wangchu from Alibaba Security Team. + + - coders/jnx.c (ReadJNXImage): Fix denial of service (DOS) issue + in ReadJNXImage() whereby large amounts of CPU and memory + resources may be consumed although the file itself does not + support the requests. Problem was reported via email on Wed Aug + 23 2017 by Xiaohei and Wangchu from Alibaba Security Team. + +2017-08-14 Glenn Randers-Pehrson + + - coders/png.c (ReadOneMNGImage): Deal with invalid (too large) + length of MNG chunks (bug #446). + +2017-08-20 Bob Friesenhahn + + - coders/pnm.c (ReadPNMImage): Verify that sufficient file data + exists to support what the file header requires before allocating + memory for it. Fixes problem reported by Agostino Sarubbo via + email on Wed, 12 Jul 2017 and reported yet again via SourceForge + bug #441 "memory allocation failure in MagickRealloc". + +2017-08-20 Fojtik Jaroslav + + - coders/mat.c: Fix SourceForge bug #433 "memory leak in + ReadMATImage". Credit for discovering and reporting the problem + is "ADLab of Venustech". + + - coders/sun.c (ReadSUNImage): Fix failure to allocate memory due + to inadequate file data to support claimed image width and height. + First notified by email from Agostino Sarubbo on 14 Jul 2017 and + then again as SourceForge bug #442 "memory allocation failure in + magickmalloc". + +2017-08-16 Bob Friesenhahn + + - coders/svg.c (GetStyleTokens): Fix SourceForge bugs 434 "heap + buffer overflow in GetStyleTokens", 435 "null pointer + dereference\_in\_SVGStartElement", and 436 "heap buffer overflow in + GetStyleTokens" which all originated from a heap buffer overflow + in GetStyleStokens(), or inconsistent initialization. Now the + implementation truncates parsing for poorly-formed input (to avoid + buffer overflow) while still correctly parsing well-formed input. + The reproducers and problem reports are attributed to "ADLab of + Venustech". + +2017-08-14 Glenn Randers-Pehrson + + - coders/png.c (ReadOneJNGImage): Fixed double-free after + reading a malformed JNG (Issue #438). + +2017-08-14 Bob Friesenhahn + + - coders/pcd.c (ReadPCDImage): Fix memory leak on return path due + to corrupted header. Patch included in email on 14 Aug 2017 by + Petr Gajdos (ImageMagick CVE CVE-2017-8351). + +2017-08-11 Bob Friesenhahn + + - coders/gif.c (ReadGIFImage): Assure that global colormap is + initialized. + + - coders/pict.c (ReadPICTImage): Fix memory leaks in error return + path. ImageMagick CVE CVE-2017-8353. Patch by Petr Gajdos. + +2017-08-11 Glenn Randers-Pehrson + + - tests/rwblob.c and rwfile.c: Write the reason for FAIL in + test-suite.log. + - magick/image.h: Revised table of image orientations to show + Exif ImageOrientation values (which happen to be the same as + the enum values 1 to 8). + - coders/png.c: ReadJNGIMage(): fix memory leak (Issue 431). + +2017-08-09 Bob Friesenhahn + + - coders/mtv.c (ReadMTVImage): Fix memory leak in error return + path upon unexpected EOF (ImageMagick CVE-2017-9142). Problem was + brought to our attention via email from Petr Gajdos on Wed, 9 Aug + 2017. Also changed pixel cache access functions used to assure + delivery of exception to the user. + +2017-08-05 Bob Friesenhahn + + - configure.ac (SETJMP\_IS\_THREAD\_SAFE): Decide if setjmp/longjmp + are thread safe based on host OS. Assume that these interfaces + are thread safe by default. Declared not to be thread safe under + Solaris. Declaring these interfaces to be thread safe increases + available concurrency for coders which use setjmp/longjmp for + error recovery (e.g. PNG and JPEG). + +2017-08-01 Bob Friesenhahn + + - coders/jpeg.c (RegisterJPEGImage): Add support for the + SETJMP\_IS\_THREAD\_SAFE preprocessor definition (already used by + coders/png.c) to indicate if setjmp/longjmp are thread safe on + this platform and that it is safe for multiple encoders/decoders + to be active at one time. + +2017-07-31 Bob Friesenhahn + + - coders/sun.c: Fix heap read overflow while indexing into + colormap. Problem was reported via email on 17 Jul 2017 by + Agostino Sarubbo. + +2017-07-31 Glenn Randers-Pehrson + + - coders/png.c (ReadMNGImage): Stop a leak when rejecting a + MNG image with dimensions that are too large. + +2017-07-26 Bob Friesenhahn + + - coders/wmf.c (ReadWMFImage): Eliminate use of already freed heap + data in error reporting path. Problem was reported via email by + Agostino Sarubbo on Fri, 14 Jul 2017 + +2017-07-25 Glenn Randers-Pehrson + + - coders/png.c (ReadMNGImage) Free chunk allocation that remains + after attempting to read a truncated file. + - coders/png.c: Removed some redundant checks for chunk length + before MagickFreeMemory(chunk), which is safe to call with a + NULL argument. + - coders/png.c: Fixed writer bug due to missing brackets; a Log + statement should have been inside the "i" loop but instead was + using i++ left over from the loop. Bug report by L. Catro. + - coders/png.c: Reject a MNG with dimensions greater than 65k + by 65k. + - coders/png.c (WriteOnePNGImage): Return without crashing if + WriteOnePNGImage is passed a NULL image. Fixes CVE-2017-11522. + +2017-07-22 Bob Friesenhahn + + - coders/pcl.c (WritePCLImage): Fix null pointer dereference in + PCL writer when writing monochrome images. Problem was reported + by LCatro via email on July 18. + + - magick/pixel\_cache.c (PersistCache): Fix memory leak while + writing a MPC file. Problem was reported by LCatro via email on + July 18. + + - coders/map.c (WriteMAPImage): Fix null pointer dereference or + segmentation violation in the MAP writer if the input image is not + already colormapped. Problem was reported by LCatro via email on + July 18. + + - coders/gray.c (WriteGRAYImage): Improve tracing and tidy up. + + - coders/rgb.c (WriteRGBImage): Fix heap overwrite in raw RGB + writer (all output subformats) given a multiframe sequence using + different widths. Problem was reported by LCatro via email on + July 18. + + - coders/cmyk.c (WriteCMYKImage): Fix heap overwrite in raw CMYK + writer (all output subformats) given a multiframe sequence using + different widths. Also fix wrong output of CMYKA (and vice-versa) + when CMYK was intended. Problem was reported by LCatro via email + on July 18. + + - coders/palm.c: Disable the PALM writer since the writer is a + work in progress and still has implementation problems. Perhaps + no one in the world remains who cares about the undocumented PALM + format. Resolves heap overflow and assertion issues reported by + LCatro via emails on July 11th, and 12th, 2017. + + - magick/colormap.c (ReplaceImageColormap): Throw an exception + rather than assertion if the input image is not colormapped. + +2017-07-13 Glenn Randers-Pehrson + + - coders/png.c: Implemented eXIf chunk support. + +2017-07-12 Glenn Randers-Pehrson + + - coders/png.c: Fix typecast of left shifts (patch by Bob F) + +2017-07-12 Bob Friesenhahn + + - coders/ps.c (ReadPSImage): Fix reference to constant NULL image + argument which is dereferenced to pass an exception to + MagickMonitorFormatted(). Problem was reported by Agostino + Sarubbo via email on Wed, 12 Jul 2017. + +2017-07-10 Bob Friesenhahn + + - magick/blob.c: Add casts to fix undefined behavior in left + shifts. Issue was reported by Agostino Sarubbo via email on Mon, + 10 Jul 2017. + +2017-07-10 Glenn Randers-Pehrson + + - coders/png.c (ReadOneJNGImage): Ignore out-of-bounds MOVE + and CLIP object\_id's. + - coders/png.c (ReadMNGImage): Fix apparent off-by-one error + in MNG FRAM change\_clipping processing. + - coders/png.c (ReadMNGImage): Fix out-of-order CloseBlob() + and DestroyImageList() that caused a use-after-free crash. + Fixes CVE-2017-11403. This bug was discovered by Agostino Sarubbo. + +2017-07-08 Glenn Randers-Pehrson + + - coders/png.c (ReadOneJngImage): Revised double-free fix. + +2017-07-08 Bob Friesenhahn + + - coders/png.c (ReadOneJNGImage): Fix double-frees caused by + commit on 2017-07-06. + + - coders/jpeg.c (ReadJPEGImage): Defer creating pixel cache until + after successfully reading first scanline. Classify some serious + libjpeg reported "warnings" as errors and quit processing + scanlines immediately upon first error so that corrupt JPEG does + not consume excessive resources. Resolves excessive resource + consumption issue reported for two JPEG files provided via email + by LCatro on Tue, 4 Jul 2017. + +2017-07-06 Bob Friesenhahn + + - coders/png.c (ReadOneJNGImage): Remove spurious '\n' from log + statement. + +2017-07-06 Glenn Randers-Pehrson + + - coders/png.c: Consolidate JNG cleanup into a new DestroyJNG() + function. + +2017-07-05 Glenn Randers-Pehrson + + - coders/png.c: prevent a crash due to zero-length color\_image + while reading a JNG image. (CVE-2017-11102) + +2017-07-04 Bob Friesenhahn + + - NEWS.txt: Make sure is up to date. + + - www/index.rst: Update for 1.3.26 release. + + - version.sh: Update library versioning for 1.3.26 release. + + - magick/command.c (BatchCommand): Add ferror() checks around + batch input loop. + +2017-07-03 Glenn Randers-Pehrson + + - coders/png.c: Reject a PNG file if the file size is too small + (less than 61 bytes). Reject a JNG file if it is too small (less + than 147 bytes). + - coders/jpeg.c: Reject a JPEG file if the file size is too small + (less than 107 bytes). + +2017-07-02 Bob Friesenhahn + + - coders/dpx.c (ReadDPXImage): Compute required file size and + verify that sufficient data exists in file before allocating + memory to decode the image data. Resolves problem with DPX file + with valid header (but a huge claimed image width) provided + provided via email on Thu, 29 Jun 2017 by LCatro. This issue has + been assigned CVE-2017-10799. + +2016-07-02 Fojtik Jaroslav + + - coders/mat.c Check whether reported object size overflows file size. + +2016-07-01 Fojtik Jaroslav + + - coders/mat.c Safety check for forged and or corrupted data. + This issue has been assigned CVE-2017-10800. + +2017-07-01 Bob Friesenhahn + + - coders/tiff.c ("QuantumTransferMode"): Use a generalized method + to enforce that buffer overflow can not happen while importing + pixels. Resolves problem with RGB TIFF claiming only one sample + per pixel provided via email on Thu, 29 Jun 2017 by LCatro. This + issue has been assigned CVE-2017-10794. + +2017-06-29 Bob Friesenhahn + + - magick/command.c: Convert bare 'unsigned int' to MagickPassFail + where suitable to make intentions clear. Convert True/False to + MagickTrue/MagickFalse or MagickPass/MagickFail according to + purpose. This is a continuation of a gradual migration and does + not represent an API change. + +2017-06-25 Glenn Randers-Pehrson + + - coders/png.c: Avoid NULL dereference when MAGN chunk processing + fails (https://sourceforge.net/p/graphicsmagick/bugs/426/). Expand + TABs. + +2017-06-25 Bob Friesenhahn + + - NEWS.txt: Update NEWS with changes since the previous release. + + - www/programming.rst: Switch the Lua link to + https://github.com/arcapos/luagraphicsmagick, which is a more + complete and direct interface from Lua to GraphicsMagick's Wand + API. + +2017-06-24 Bob Friesenhahn + + - VisualMagick/installer/gm-foo-dll.iss: Remove PerlMagick from + the slim Inno Setup installer builder and remove mention of + PerlMagick from the installer documentation. + + - TclMagick/generic/TclMagick.c (magickCmd): Resolve SourceForge + patch #51 "TclMagick: memory access error; possible segfault". + (newMagickObj): Fix formatting of pointer value so it is 64-bit + safe. Resolves SourceForge patch #50 "TclMagick: 64-bit + portability issue". + + - coders/pict.c (ReadPICTImage): Avoid possible use of negative + value when indexing array, which would cause buffer overflow. + Resolves SourceForge issue #427 "One possible buffer overflow + vulnerability in + GraphicsMagick-1.3.25/coders/pict.c:ReadPICTImage()". + +2017-06-22 Glenn Randers-Pehrson + + - coders/png.c: Stop memory leak when reading invalid JNG image. + Fixes CVE-2017-8350. + +2017-06-18 Bob Friesenhahn + + - coders/png.c: Fix lcms2.h inclusion logic. + + - wand/magick\_wand.c (MagickSetImageOrientation): Eliminate use of + snprintf, which is not supported by older Visual Studio. + +2017-06-09 Glenn Randers-Pehrson + + - coders/png.c: Accept exIf chunks whose data segment + erroneously begins with "Exif\0\0". + +2017-06-01 Glenn Randers-Pehrson + + - coders/png.c: Removed experimental zxIF chunk support. That + proposal is dead. + +2017-05-27 Bob Friesenhahn + + - config/log.mgk: Added documentation suggested by SourceForge + issue #419 "Consider a small patch to log.mgk". + + - www/Changes.rst: Add missing link to most recent changes. + +2017-05-24 Bob Friesenhahn + + - www/Magick++/Image.rst: Improve documentation for Magick++ + Image::iccColorProfile() and Image::renderingIntent(). + +2017-05-21 Bob Friesenhahn + + - tiff: Update to libtiff 4.0.8. + +2017-03-19 Glenn Randers-Pehrson + + - coders/png.c: Quieted a new Coverity complaint about a potential + text buffer overrun. + +2017-03-19 Bob Friesenhahn + + - magick/image.c (SetImageInfo): Ignore empty magic prefix + specification and do not remove colon character from start of + filename. Resolves SourceForge bug #415 "Inconsistent Behavior w/ + input\_file Parameter". + +2017-03-18 Glenn Randers-Pehrson + + - coders/png.c: Added new private orNT PNG chunk, to + preserve image->orientation when it is defined and not + the default TopLeft. + - coders/jpeg.c: Mention image->orientation in the log when + writing a JPEG. + +2017-03-15 Glenn Randers-Pehrson + + - coders/png.c (WriteOnePNGImage): Add version info about + gm, libpng, zlib, and lcms to the PNG debug log. + +2017-03-04 Bob Friesenhahn + + - magick/command.c (ImportImageCommand): Fix handling of -frame + options. Option handling was incorrect due to option checking the + frame option after it had been freed. Checking the frame dash + option before freeing the argument solves the problem. From patch + provided by Victor Ananjevsky as SourceForge patch #49 "-frame + doesn't work in gm import". + + - Magick++/lib/Image.cpp (attribute): Added Image attribute method + which accepts a 'char \*' argument, and will remove the attribute + if the value argument is NULL. From patch provided by "Gints" as + SourceForge patch #46 "C++ api - method to clear/remove + attribute". + + - VisualMagick/configure/configure.cpp (InitInstance): Applied + patch by Paul McConkey to allow the quantum command line argument + to set the default value in the wizard drop list. This allows + setting the quantum depth when the /nowizard argument was + supplied. Resolves SourceForge patch #48 "When running from the + command line configure.exe does not use the quantum argument". + The provided configure.exe still needs to be rebuilt to + incorporate this change. + + - magick/command.c (MogrifyImage): The -orient command now also + updates the orientation in the EXIF profile, if it exists. + + - Magick++/lib/Image.cpp (orientation): Update orientation in EXIF + profile, if it exists. + +2017-03-03 Bob Friesenhahn + + - coders/jp2.c: Support PGX JPEG 2000 format for reading and + writing (within the bounds of what JasPer supports). + +2017-02-23 Bob Friesenhahn + + - coders/tiff.c (QuantumTransferMode): Fix out of bounds read when + reading CMYKA TIFF which claims to have only 2 samples per pixel. + Problem was reported via email on February 15, 2017 by Valon + Chu. This issue was assigned CVE-2017-6335. + +2017-01-29 Bob Friesenhahn + + - doc/options.imdoc (-geometry): Geometry documentation changes + suggested by Jon Wong. + +2017-01-26 Glenn Randers-Pehrson + + - coders/png.c: Added support for a proposed new PNG chunk + (zxIf, read-only) that is currently being discussed on the + png-mng-misc at lists.sourceforge.net mailing list. Enable + exIf and zxIf with CPPFLAGS="-DexIf\_SUPPORTED -DxzIf\_SUPPORTED". + If exIf is enabled, only the uncompressed exIF chunk will be + written and the hex-encoded zTXt chunk containing the raw Exif + profile won't be written. + +2017-01-25 Bob Friesenhahn + + - coders/msl.c (MSLStartElement): Change test for NULL image + pointer to before it is used rather than after it is used. + Problem reported by Petr Gajdos on 2017-01-25. + +2017-01-22 Bob Friesenhahn + + - TclMagick/unix/m4/tcl.m4: Update tcl.m4 to TEA 3.10. File + supplied by Massimo Manghi. + +2017-01-21 Glenn Randers-Pehrson + + - coders/png.c: Added support for a proposed new PNG + chunk (exIf read-write, eXIf read-only) that is currently + being discussed on the png-mng-misc at lists.sourceforge.net + mailing list. + +2017-01-21 Glenn Randers-Pehrson + + - coders/png.c: Added read\_user\_chunk\_callback() function + and used it to implement a private PNG caNv (canvas) chunk + for remembering the original dimensions and offsets when an + image is cropped. Previously we used the oFFs chunk for this + purpose, but this had potential conflicts with other applications + that also use the oFFs chunk. + +2017-01-07 Bob Friesenhahn + + - TclMagick/Makefile.am (AM\_DISTCHECK\_CONFIGURE\_FLAGS): Applied + patch by Massimo Manghi to set AM\_DISTCHECK\_CONFIGURE\_FLAGS so + that 'make distcheck' remembers configuration options, and also to + uninstall pkgIndex.tcl. + + - magick/image.c (SetImageEx): Use PixelIterateMonoSet() for + possibly improved efficiency. + + - magick/pixel\_iterator.c (PixelIterateMonoSet): New pixel + iterator intended for use when initializing image pixels, without + regard to existing values. + +2017-01-01 Bob Friesenhahn + + - Copyright.txt: Bump copyright years and rotate ChangeLog. + + diff --git a/www/Changelog.html b/www/Changelog.html index f98b69b..ec73f11 100644 --- a/www/Changelog.html +++ b/www/Changelog.html @@ -35,302 +35,2821 @@
-

2017-07-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-11-17 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • NEWS.txt: Make sure is up to date.
  • -
  • www/index.rst: Update for 1.3.26 release.
  • -
  • version.sh: Update library versioning for 1.3.26 release.
  • -
  • magick/command.c (BatchCommand): Add ferror() checks around -batch input loop.
  • +
  • www/index.rst: Update in preparation for 1.3.31 release.
  • +
  • version.sh: Update library versioning in preparation for +1.3.31 release.
  • +
  • NEWS.txt: Update news in preparation for 1.3.31 release.
-

2017-07-03 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-11-15 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c: Reject a PNG file if the file size is too small -(less than 61 bytes). Reject a JNG file if it is too small (less -than 147 bytes).
  • -
  • coders/jpeg.c: Reject a JPEG file if the file size is too small -(less than 107 bytes).
  • +
  • magick/command.c (BenchmarkUsage): Document the benchmark +command better.
-

2017-07-02 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-11-14 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/dpx.c (ReadDPXImage): Compute required file size and -verify that sufficient data exists in file before allocating -memory to decode the image data. Resolves problem with DPX file -with valid header (but a huge claimed image width) provided -provided via email on Thu, 29 Jun 2017 by LCatro. This issue has -been assigned CVE-2017-10799.
  • +
  • magick/resize.c (HorizontalFilter, VerticalFilter): quantum is a +pointer so it's value can not be usefully flushed. Use a local +variable and then update quantum pointer when done.
-

2016-07-02 Fojtik Jaroslav <JaFojtik@seznam.cz>

+

2018-11-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/mat.c Check whether reported object size overflows file size.
  • +
  • magick/*: Changed row_count tallying to use 'omp atomic' and +status update to use 'omp flush' for progress and error +indication. This replaces most use of 'omp critical' for this +purpose. Changed some lumpy algorithms which were using 'static' +scheduling to 'guided' scheduling due to observing better results. +Also added prolific 'restrict' annotations where they were +missing.
  • +
  • www/security.rst: Documented a PGP private key for file signing +or private correspondence.
-

2016-07-01 Fojtik Jaroslav <JaFojtik@seznam.cz>

+

2018-11-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/mat.c Safety check for forged and or corrupted data. -This issue has been assigned CVE-2017-10800.
  • +
  • www/authors.rst: Moved "Glenn Randers-Pehrson" and "Gregory J +Wolfe" to the "Former Contributor" category.
-

2017-07-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-11-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/tiff.c ("QuantumTransferMode"): Use a generalized method -to enforce that buffer overflow can not happen while importing -pixels. Resolves problem with RGB TIFF claiming only one sample -per pixel provided via email on Thu, 29 Jun 2017 by LCatro. This -issue has been assigned CVE-2017-10794.
  • +
  • Added many GCC function annotations in the libraries and coders.
-

2017-06-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-11-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • magick/command.c: Convert bare 'unsigned int' to MagickPassFail -where suitable to make intentions clear. Convert True/False to -MagickTrue/MagickFalse or MagickPass/MagickFail according to -purpose. This is a continuation of a gradual migration and does -not represent an API change.
  • +
  • configure.ac: Use printf rather than echo to portably expand tab +requests in configuration summary.
-

2017-06-25 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-11-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c: Avoid NULL dereference when MAGN chunk processing -fails (https://sourceforge.net/p/graphicsmagick/bugs/426/). Expand -TABs.
  • +
  • configure.ac: Use pkg-config data as the initial choice when +configuring for FreeType 2.0 and libxml-2.0. Only fall back to +invoking an external script (and then traditional methods) if +pkg-config fails.
  • +
  • coders/msl.c (ProcessMSLScript): Release msl_image if OpenBlob +fails. Similar to ImageMagick CVE-2018-18544. Problem was +reported to us via email from Petr Gajdos on Thu, 1 Nov 2018.
-

2017-06-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-10-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • NEWS.txt: Update NEWS with changes since the previous release.
  • -
  • www/programming.rst: Switch the Lua link to -https://github.com/arcapos/luagraphicsmagick, which is a more -complete and direct interface from Lua to GraphicsMagick's Wand -API.
  • +
  • coders/miff.c (WriteMIFFImage): Only run +strlen(attribute->value) once per attribute since the length won't +change. May address oss-fuzz 11158 +"graphicsmagick/coder_MIFF_fuzzer: Timeout in +graphicsmagick_coder_MIFF_fuzzer". (Credit to OSS-Fuzz)
  • +
  • Fix compilation warnings observed with GCC 8.2.0.
-

2017-06-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-10-26 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • VisualMagick/installer/gm-foo-dll.iss: Remove PerlMagick from -the slim Inno Setup installer builder and remove mention of -PerlMagick from the installer documentation.
  • -
  • TclMagick/generic/TclMagick.c (magickCmd): Resolve SourceForge -patch #51 "TclMagick: memory access error; possible segfault". -(newMagickObj): Fix formatting of pointer value so it is 64-bit -safe. Resolves SourceForge patch #50 "TclMagick: 64-bit -portability issue".
  • -
  • coders/pict.c (ReadPICTImage): Avoid possible use of negative -value when indexing array, which would cause buffer overflow. -Resolves SourceForge issue #427 "One possible buffer overflow -vulnerability in -GraphicsMagick-1.3.25/coders/pict.c:ReadPICTImage()".
  • +
  • magick/pixel_iterator.c (PixelIterateMonoModifyImplementation): +Use atomic and flush rather than critical construct for a small +speedup.
  • +
  • magick/monitor.c (MagickMonitorFormatted): Serialize calls to +the progress monitor so that the caller does not need to perform +this serialization. +(MagickMonitor): Serialize calls to the progress monitor so that +the caller does not need to perform this serialization. This +function is now marked as deprecated. +(InitializeMagickMonitor): New private function to initialize +monitor functionality. +(DestroyMagickMonitor): New private function to destroy monitor +functionality.
-

2017-06-22 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-10-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c: Stop memory leak when reading invalid JNG image. -Fixes CVE-2017-8350.
  • +
  • coders/gif.c (ReadGIFImage): Improve the efficiency of storing a +GIF comment in order to avoid a DOS opportunity. Fixes oss-fuzz +11096 "graphicsmagick/coder_GIF_fuzzer: Timeout in +graphicsmagick_coder_GIF_fuzzer". (Credit to OSS-Fuzz)
-

2017-06-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-10-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c: Fix lcms2.h inclusion logic.
  • -
  • wand/magick_wand.c (MagickSetImageOrientation): Eliminate use of -snprintf, which is not supported by older Visual Studio.
  • +
  • PerlMagick/Makefile.PL.in: Use MAGICK_API_LIBS to obtain the +list of libraries to use when linking.
  • +
  • configure.ac: OpenMP library is normally supplied due to a +CFLAGS option so only supply it in cases where the CFLAGS option +may be lost or it might not be used. Otherwise the compiler may +apply the library twice when linking.
-

2017-06-09 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-10-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c: Accept exIf chunks whose data segment -erroneously begins with "Exif00".
  • +
  • configure.ac: Remove Ghostscript library support (--with-gslib) +from configure script. The 'HasGS' pre-processor defines which +were enabled by this remain in the source code so it is still +possible to use this library if absolutely necessary +(e.g. CPPFLAGS=-DHasGS LIBS=-lgs).
  • +
  • tests/rwfile.tap: Test TIFF format with all supported +compression options.
  • +
  • tests/{rwblob.c, rwfile.c} (main): Use StringToCompressionType() +to parse compression option. Also consider requested compression +algorithm when deciding if format is lossy.
  • +
  • coders/tiff.c (WriteTIFFImage): WebP compression needs +PHOTOMETRIC_RGB. Fix wrong rows-per-strip calculation when using +LZMA compression.
  • +
  • tests/rwblob.tap: Added a rwblob test to verify that lower-case +magick works.
  • +
  • magick/static.c (OpenModule): Upper case magick string before +searching static modules list. Fixes Debian bug 911386 +"libgraphicsmagick-q16-3: graphicsmagick 1.3.30 has made formats +case-sensitive at the API level".
  • +
  • filters/analyze.c (AnalyzeImage): X and y should be unsigned +long to match image rows/columns type. Calculate total pixels by +simple multiplication rather than counting.
-

2017-06-01 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-10-14 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c: Removed experimental zxIF chunk support. That -proposal is dead.
  • +
  • coders/tiff.c (WriteTIFFImage): Support WebP compression in +TIFF. This requires a libtiff release after 4.0.9.
  • +
  • magick/image.h ("C"): WebPCompression added to CompressionType +enumeration.
-

2017-05-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-10-13 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • config/log.mgk: Added documentation suggested by SourceForge -issue #419 "Consider a small patch to log.mgk".
  • -
  • www/Changes.rst: Add missing link to most recent changes.
  • +
  • configure.ac: Configure for the Zstd library. Use +--without-zstd to disable searching for this library. Libtiff may +require this library to successfully link so static linkage could +fail if searching for libzstd is disabled.
  • +
  • magick/image.h ("C"): ZSTDCompression added to CompressionType +enumeration.
  • +
  • coders/tiff.c (WriteTIFFImage): Support Zstd compression in +TIFF. This requires a libtiff release after 4.0.9.
-

2017-05-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-10-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • www/Magick++/Image.rst: Improve documentation for Magick++ -Image::iccColorProfile() and Image::renderingIntent().
  • +
  • magick/command.c (GMCommandSingle): Add 'compare' to the list of +command names that gm will support as a command if copied to or +linked from that name. There was already a 'compare' link +installed when the '--enable-magick-compat' configure option is +used, but it could not possibly function without being blessed by +this list. Related to Debian bug #910652 +"graphicsmagick-imagemagick-compat: Doesn't ship a compare tool".
-

2017-05-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-09-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • tiff: Update to libtiff 4.0.8.
  • +
  • Magick++/lib/Magick++/Drawable.h: Block unused-private-field +warnings from Clang due to _dummy members which were intentionally +included in some parent class definitions.
  • +
  • magick/widget.c (XEditText): Fix compilation warnings about +cases which fall-through.
  • +
  • magick/display.c (MagickXAnnotateEditImage): Fix compilation +warnings about cases which fall-through.
  • +
  • coders/pict.c (WritePICTImage): Add more checks to memory +allocation calculations.
  • +
  • magick/pixel_cache.c (DestroyCacheInfo): Eliminate intentional +fall-through logic in switch statement which results in compiler +warnings. Eliminate switch statements entirely and split +unrelated logic.
  • +
  • coders/txt.c (ReadTXTImage): Fix comparison between pointer and +'0' rather than NULL as was obviously intended.
  • +
  • coders/msl.c (MSLStartElement): Add missing 'break' statements +after ThrowException() calls. Otherwise execution falls through +into unrelated switch cases and throws a redundant exception.
-

2017-03-19 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-09-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c: Quieted a new Coverity complaint about a potential -text buffer overrun.
  • +
  • coders/meta.c (parse8BIM): Eliminate repeated use of strlen() +which scans the entire remaining string on each cycle. Fixes +oss-fuzz 10667 "graphicsmagick/coder_IPTCTEXT_fuzzer: Timeout in +graphicsmagick_coder_IPTCTEXT_fuzzer". (Credit to OSS-Fuzz)
-

2017-03-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-09-26 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • magick/image.c (SetImageInfo): Ignore empty magic prefix -specification and do not remove colon character from start of -filename. Resolves SourceForge bug #415 "Inconsistent Behavior w/ -input_file Parameter".
  • +
  • magick/utility.c (MagickGetToken): Fix possible read up to four +bytes beyond end of stack allocated token buffer. Fixes oss-fuzz +10653 "graphicsmagick/coder_MVG_fuzzer: Stack-buffer-overflow in +MagickGetToken". (Credit to OSS-Fuzz)
-

2017-03-18 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-09-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c: Added new private orNT PNG chunk, to -preserve image->orientation when it is defined and not -the default TopLeft.
  • -
  • coders/jpeg.c: Mention image->orientation in the log when -writing a JPEG.
  • +
  • fuzzing/coder_fuzzer.cc (LLVMFuzzerTestOneInput): Limit the +maximum number of JPEG progressive scans to 50.
  • +
  • coders/jpeg.c (ReadJPEGImage): Apply a default limit of 100 +progressive scans before the reader quits with an error. This +limit may be adjusted using the -define mechanism like -define +JPEG:max-scan-number=500. Also respond more quickly to files +which exceed the maximum image dimensions. Fixes oss-fuzz 10258 +"graphicsmagick/coder_JPEG_fuzzer: Timeout in +graphicsmagick_coder_JPEG_fuzzer". (Credit to OSS-Fuzz)
-

2017-03-15 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-09-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c (WriteOnePNGImage): Add version info about -gm, libpng, zlib, and lcms to the PNG debug log.
  • +
  • coders/png.c (ReadMNGImage): mng_LOOP chunk must be at least 5 +bytes long. Fixes oss-fuzz 10455 +"graphicsmagick/coder_MNG_fuzzer: Use-of-uninitialized-value in +ReadMNGImage". (Credit to OSS-Fuzz)
-

2017-03-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-09-15 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • magick/command.c (ImportImageCommand): Fix handling of -frame -options. Option handling was incorrect due to option checking the -frame option after it had been freed. Checking the frame dash -option before freeing the argument solves the problem. From patch -provided by Victor Ananjevsky as SourceForge patch #49 "-frame -doesn't work in gm import".
  • -
  • Magick++/lib/Image.cpp (attribute): Added Image attribute method -which accepts a 'char *' argument, and will remove the attribute -if the value argument is NULL. From patch provided by "Gints" as -SourceForge patch #46 "C++ api - method to clear/remove -attribute".
  • -
  • VisualMagick/configure/configure.cpp (InitInstance): Applied -patch by Paul McConkey to allow the quantum command line argument -to set the default value in the wizard drop list. This allows -setting the quantum depth when the /nowizard argument was -supplied. Resolves SourceForge patch #48 "When running from the -command line configure.exe does not use the quantum argument". -The provided configure.exe still needs to be rebuilt to -incorporate this change.
  • -
  • magick/command.c (MogrifyImage): The -orient command now also -updates the orientation in the EXIF profile, if it exists.
  • -
  • Magick++/lib/Image.cpp (orientation): Update orientation in EXIF -profile, if it exists.
  • +
  • magick/render.c (TraceEllipse): Detect arithmetic overflow when +computing the number of points to allocate for an ellipse. Fixes +oss-fuzz 10306 "graphicsmagick/coder_MVG_fuzzer: +Heap-buffer-overflow in TracePoint". (Credit to OSS-Fuzz)
-

2017-03-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-09-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/jp2.c: Support PGX JPEG 2000 format for reading and -writing (within the bounds of what JasPer supports).
  • +
  • magick/attribute.c (GenerateEXIFAttribute): Eliminate undefined +shift. Also right-sized involved data types. Fixes oss-fuzz +10309 "graphicsmagick/coder_JPG_fuzzer: Undefined-shift in +Read32s". (Credit to OSS-Fuzz)
-

2017-02-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-09-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/tiff.c (QuantumTransferMode): Fix out of bounds read when -reading CMYKA TIFF which claims to have only 2 samples per pixel. -Problem was reported via email on February 15, 2017 by Valon -Chu. This issue was assigned CVE-2017-6335.
  • +
  • magick/render.c (DrawClipPath): Fix Coverity 319663 "Null +pointer dereferences". Totally insignificant.
  • +
  • coders/wpg.c (ReadWPGImage): Mask/fix Coverity 319664 "Error +handling issues".
  • +
  • magick/attribute.c (FindEXIFAttribute): Change size types from +signed to unsigned and check for unsigned overflow. +(GenerateEXIFAttribute): Change size types from signed to unsigned +and check for unsigned overflow. Fixes oss-fuzz 10283 +"graphicsmagick/coder_JPG_fuzzer: Integer-overflow in +GenerateEXIFAttribute". (Credit to OSS-Fuzz)
  • +
  • coders/sfw.c (ReadSFWImage): Enforce that file is read using the +JPEG reader. (Credit to OSS-Fuzz)
  • +
  • coders/miff.c (ReadMIFFImage): Fix leak of 'values' buffer due +to change made yesterday.
  • +
  • coders/mpc.c (ReadMPCImage): Fix leak of 'values' buffer due to +change made yesterday. Fixes oss-fuzz 10277 +"graphicsmagick/coder_MPC_fuzzer: Direct-leak in +ReadMPCImage". (Credit to OSS-Fuzz)
-

2017-01-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-09-08 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • doc/options.imdoc (-geometry): Geometry documentation changes -suggested by Jon Wong.
  • +
  • coders/miff.c (ReadMIFFImage): Support legacy keyword +'color-profile' for ICC color profile as was used by ImageMagick +4.2.9.
  • +
  • coders/mpc.c (ReadMPCImage): Require that first keyword/value be +id=MagickCache
  • +
  • coders/miff.c (ReadMIFFImage): Require that first keyword/value +be id=ImageMagick.
-

2017-01-26 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-09-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c: Added support for a proposed new PNG chunk -(zxIf, read-only) that is currently being discussed on the -png-mng-misc at lists.sourceforge.net mailing list. Enable -exIf and zxIf with CPPFLAGS="-DexIf_SUPPORTED -DxzIf_SUPPORTED". -If exIf is enabled, only the uncompressed exIF chunk will be -written and the hex-encoded zTXt chunk containing the raw Exif -profile won't be written.
  • +
  • coders/dcm.c (DCM_ReadElement): Add more size checks.
  • +
  • coders/jnx.c (ExtractTileJPG): Enforce that JPEG tiles are read +by the JPEG coder. Fixes oss-fuzz 10147 +"graphicsmagick/coder_JNX_fuzzer: Use-of-uninitialized-value in +funcDCM_PhotometricInterpretation". (Credit to OSS-Fuzz)
-

2017-01-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-09-10 Fojtik Jaroslav <JaFojtik@seznam.cz>

    -
  • coders/msl.c (MSLStartElement): Change test for NULL image -pointer to before it is used rather than after it is used. -Problem reported by Petr Gajdos on 2017-01-25.
  • +
  • coders/wpg.c Zero fill raster error recovery.
-

2017-01-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-08-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • TclMagick/unix/m4/tcl.m4: Update tcl.m4 to TEA 3.10. File -supplied by Massimo Manghi.
  • +
  • magick/render.c (ConvertPrimitiveToPath): Second attempt to +prevent heap write overflow of PathInfo array. Fixes oss-fuzz +10096 "Heap-buffer-overflow in ConvertPrimitiveToPath". (Credit to +OSS-Fuzz)
-

2017-01-21 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-08-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • coders/png.c: Added support for a proposed new PNG -chunk (exIf read-write, eXIf read-only) that is currently -being discussed on the png-mng-misc at lists.sourceforge.net -mailing list.
  • +
  • coders/tiff.c ("QuantumTransferMode"): CIE Log images with an +alpha channel are not supported. Fixes oss-fuzz 10013 +"graphicsmagick/coder_TIFF_fuzzer: Use-of-uninitialized-value in +DisassociateAlphaRegion". (Credit to OSS-Fuzz)
  • +
  • magick/render.c (DrawImage): SetImageAttribute() appends new +text to any existing value, leading to every increasing memory +consumption if the existing value is not deleted first by the +unwary. Fixes oss-fuzz 9983 "graphicsmagick/coder_MVG_fuzzer: +Timeout in graphicsmagick_coder_MVG_fuzzer" and oss-fuzz 10016 +"graphicsmagick/coder_MVG_fuzzer: Out-of-memory in +graphicsmagick_coder_MVG_fuzzer". (Credit to OSS-Fuzz)
  • +
  • magick/utility.c (TranslateTextEx): Fix off-by-one in loop +bounds check which allowed a one-byte stack write overflow. Fixes +oss-fuzz 10055 "graphicsmagick/coder_MVG_fuzzer: +Stack-buffer-overflow in TranslateTextEx". (Credit to OSS-Fuzz)
  • +
  • magick/render.c (DrawImage): Be more precise about error +detection and reporting, and return from an error more quickly. +Also added MAX_DRAWIMAGE_RECURSION pre-processor definition to +allow adjusting the drawing recursion limit. The drawing +recursion limit is still 100, which seems exceptionally generous.
  • +
  • magick/constitute.c (WriteImage): Produce a more useful error +message if an encoding delegate is not available.
  • +
  • magick/nt_base.h (isnan): Try adding a MSVC replacement for +missing isnan() function. Not yet tested.
-

2017-01-21 Glenn Randers-Pehrson <glennrp@simple.dallas.tx.us>

+

2018-08-25 Fojtik Jaroslav <JaFojtik@seznam.cz>

    -
  • coders/png.c: Added read_user_chunk_callback() function -and used it to implement a private PNG caNv (canvas) chunk -for remembering the original dimensions and offsets when an -image is cropped. Previously we used the oFFs chunk for this -purpose, but this had potential conflicts with other applications -that also use the oFFs chunk.
  • +
  • coders/wpg.c This should fix intentional 64 bit file offset +overflow as depictedin OSS-fuzz-9936. Thanks to OSS-Fuzz.
-

2017-01-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-08-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

    -
  • TclMagick/Makefile.am (AM_DISTCHECK_CONFIGURE_FLAGS): Applied -patch by Massimo Manghi to set AM_DISTCHECK_CONFIGURE_FLAGS so -that 'make distcheck' remembers configuration options, and also to -uninstall pkgIndex.tcl.
  • -
  • magick/image.c (SetImageEx): Use PixelIterateMonoSet() for -possibly improved efficiency.
  • -
  • magick/pixel_iterator.c (PixelIterateMonoSet): New pixel -iterator intended for use when initializing image pixels, without -regard to existing values.
  • +
  • magick/render.c (ConvertPrimitiveToPath): Need to enlarge +PathInfo array allocation to avoid possible heap write overflow. +Fixes oss-fuzz 9651 "graphicsmagick/coder_MVG_fuzzer: +Heap-buffer-overflow in ConvertPrimitiveToPath". (Credit to +OSS-Fuzz)
-

2017-01-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+

2018-08-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/mpc.c (ReadMPCImage): Insist that the format be +identified prior to any comment, and that there is only one +comment.
  • +
  • coders/miff.c (ReadMIFFImage): Insist that the format be +identified prior to any comment, and that there is only one +comment. Fixes oss-fuzz 9979 "graphicsmagick/coder_MIFF_fuzzer: +Timeout in graphicsmagick_coder_MIFF_fuzzer". This is not a +serious issue, but the code runs slowly under UBSAN. (Credit to +OSS-Fuzz)
  • +
+
+

2018-08-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/utility.c (MagickAtoFChk): Add additional validation +checks for floating point values. NAN and +/- INFINITY values +also map to 0.0. Fixes oss-fuzz 9630 +"graphicsmagick/coder_MVG_fuzzer: Integer-overflow in +IsNexusInCore" and oss-fuzz 9612 "graphicsmagick/coder_MVG_fuzzer: +Integer-overflow in SetCacheNexus". (Credit to OSS-Fuzz)
  • +
  • magick/render.c (DrawImage): Add missing error-reporting logic +to return immediately upon memory reallocation failure. Apply +memory resource limits to PrimitiveInfo array allocation. Fixes +oss-fuzz 9576 "graphicsmagick/coder_MVG_fuzzer: Null-dereference +READ in DrawImage", oss-fuzz 9593 +"graphicsmagick/coder_MVG_fuzzer: Out-of-memory in +graphicsmagick_coder_MVG_fuzzer", oss-fuzz 9648 +"graphicsmagick/coder_MVG_fuzzer: Unknown signal in +DrawImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-08-16 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coder/mat.c Explicitly reject non-seekable streams.
  • +
+
+

2018-08-15 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coder/mat.c Correctly check GetBlobSize(image) even for zipstreams.
  • +
+
+

2018-08-14 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c More aggresive data corruption checking.
  • +
+
+

2018-08-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/xbm.c (XBMInteger): Limit the number of hex digits parsed +to avoid signed integer overflow. Fixes oss-fuzz 9746 +"graphicsmagick/coder_XBM_fuzzer: Undefined-shift in +XBMInteger". (Credit to OSS-Fuzz)
  • +
+
+

2018-08-07 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Typecast difference to quantum.
  • +
+
+

2018-08-05 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/mat.c (InsertComplexFloatRow): Avoid signed +overflow. Fixes oss-fuzz 9667 "graphicsmagick/coder_MAT_fuzzer: +Integer-overflow in InsertComplexFloatRow". (Credit to OSS-Fuzz)
  • +
  • coders/xbm.c (ReadXBMImage): Add validations for row and column +dimensions. Fixes oss-fuzz 9736 "graphicsmagick/coder_XBM_fuzzer: +Out-of-memory in graphicsmagick_coder_XBM_fuzzer". (Credit to +OSS-Fuzz)
  • +
+
+

2018-08-04 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/wpg.c Add mechanism to approve embedded subformats in +WPG. This should mute oss-fuzz 9559. (Credit to OSS-Fuzz)
  • +
+
+

2018-07-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/mvg.c (ReadMVGImage): Fix memory leak added on +2018-07-21. Fixes oss-fuzz 9548 "graphicsmagick/coder_MVG_fuzzer: +Direct-leak in CloneDrawInfo". (Credit to OSS-Fuzz)
  • +
+
+

2018-07-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/cineon.c (ReadCINEONImage): Fix SourceForge issue 571 +"Unexpected hang on a crafted Cineon image" by detecting and +quitting on EOF appropriately, and verifying that file size is +sufficient for claimed pixel dimensions when possible.
  • +
  • fuzzing/oss-fuzz-build.sh, fuzzing/dictionaries/MVG.dict: Added +MVG fuzzing dictionary by Alex Gaynor.
  • +
+
+

2018-07-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/pixel_cache.c (SetNexus): For requests one pixel tall, +SetNexus() was wrongly using pixels in-core rather than using a +staging area for the case where the nexus rows extend beyond the +image raster boundary, leading to heap overflow. This can happen +when virtual pixels outside the image bounds are accessed. Fixes +oss-fuzz 9512 "graphicsmagick/graphicsmagick_coder_MVG_fuzzer: +Heap-buffer-overflow in AcquireCacheNexus". (Credit to OSS-Fuzz)
  • +
  • magick/render.c (ExtractTokensBetweenPushPop): +ExtractTokensBetweenPushPop() needs to always return a valid +pointer into the primitive string. Fixes oss-fuzz 9511 +"graphicsmagick/graphicsmagick_coder_MVG_fuzzer: Null-dereference +READ in DrawImage". (Credit to OSS-Fuzz) +(DrawPolygonPrimitive): Fix leak of polygon set when object is +completely outside image. Fixes oss-fuzz 9513 +"graphicsmagick/graphicsmagick_coder_MVG_fuzzer: Direct-leak in +AllocateThreadViewDataSet". (Credit to OSS-Fuzz)
  • +
+
+

2018-07-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/blob.c (FileToBlob): Use confirm access APIs to verify +that read access to this path is allowed by policy. Check that +file is a regular file before proceeding to open and read from it.
  • +
  • coders/mvg.c (ReadMVGImage): Don't allow MVG files to side-load +a file as the drawing primitive using '@' syntax. Fixes oss-fuzz +9494 "graphicsmagick/coder_MVG_fuzzer: Sanitizer CHECK failure in +"((0)) != (0)" (0x0, 0x0)". (Credit to OSS-Fuzz)
  • +
+
+

2018-07-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/mvg.c (ReadMVGImage): Don't assume that in-memory MVG +blob is a null-terminated C string. Fixes oss-fuzz 9469 +"graphicsmagick/coder_MVG_fuzzer: Heap-buffer-overflow in +AllocateString". (Credit to OSS-Fuzz)
  • +
+
+

2018-07-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/miff.c (ReadMIFFImage): Detect EOF when reading using +ReadBlobZC() and avoid subsequent heap read overflow. Fixes +oss-fuzz 9357 "graphicsmagick/coder_MIFF_fuzzer: +Heap-buffer-overflow in ImportRGBQuantumType". (Credit to +OSS-Fuzz)
  • +
+
+

2018-07-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • fuzzing/oss-fuzz-build.sh (CFLAGS): Try disabling SIMD +instructions in libjpeg-turbo build.
  • +
+
+

2018-07-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (WriteOnePNGImage): Free png_pixels as soon as +possible. This might help with oss-fuzz 9334 +"graphicsmagick/coder_PNG8_fuzzer: Direct-leak in +WriteOnePNGImage", which we have yet to reproduce. It is not +clear if png_pixels is being clobbered by longjmp or if something +else is going on.
  • +
+
+

2018-06-26 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/jpeg.c (ReadJPEGImage): Provide a memory resource limit +(of 1/5th the memory resource limit for Graphicsmagick) to libjpeg +to limit how much memory it might consume for itself while reading +a file. Fixes oss-fuzz 9096 "graphicsmagick/coder_JPEG_fuzzer: +Timeout in graphicsmagick_coder_JPEG_fuzzer". (Credit to +OSS-Fuzz) +(ReadJPEGImage): Make sure that JPEG pixels array is initialized +in case libjpeg fails to completely initialize it. May fix +oss-fuzz 9115 "graphicsmagick/coder_JPEG_fuzzer: +Use-of-uninitialized-value in ReadJPEGImage". We are not sure +since the problem was not reproduced. (Credit to OSS-Fuzz)
  • +
+
+

2018-06-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • version.sh: Update library versioning for 1.3.30 release.
  • +
  • NEWS.txt: Update news for 1.3.30 release.
  • +
+
+

2018-06-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dpx.c (ReadDPXImage): Report exception on EOF file +reading DPX pixel data. Fixes oss-fuzz 8104 +"graphicsmagick/coder_DPX_fuzzer: Use-of-uninitialized-value in +WriteDPXImage", oss-fuzz 8297 "graphicsmagick/enhance_fuzzer: +Use-of-uninitialized-value in EnhanceImage", and oss-fuzz 8133 +"graphicsmagick/coder_DPX_fuzzer: Use-of-uninitialized-value in +RGBTransformPackets". (Credit to OSS-Fuzz)
  • +
+
+

2018-06-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/cmyk.c (ReadCMYKImage): Free scanline buffer in error +path. Fixes SourceForge issue #567 "small memory leak in rgb.c, +gray.c and cmyk.c" reported by Petr Gajdos.
  • +
  • coders/gray.c (ReadGRAYImage): Free scanline buffer in error +path. Fixes SourceForge issue #567 "small memory leak in rgb.c, +gray.c and cmyk.c" reported by Petr Gajdos.
  • +
  • coders/rgb.c (ReadRGBImage): Free scanline buffer in error +path. Fixes SourceForge issue #567 "small memory leak in rgb.c, +gray.c and cmyk.c" reported by Petr Gajdos.
  • +
  • coders/jpeg.c (ReadJPEGImage): Avoid memory leak of profile +buffer when longjmp-based exception is thrown while reading a +profile. Fixes oss-fuzz 8957 "graphicsmagick/enhance_fuzzer: +Direct-leak in ReadGenericProfile". (Credit to OSS-Fuzz)
  • +
+
+

2018-06-17 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/xcf.c (load_level): Make sure to free 'tile_image' before +returning exception. Fixes oss-fuzz 8935 +"graphicsmagick/coder_XCF_fuzzer: Indirect-leak in +CloneImage". (Credit to OSS-Fuzz)
  • +
  • coders/jpeg.c (ReadJPEGImage): Allow three warnings of any given +type before promoting the next warning of the same type to a hard +error. The warning limit may be adjusted by the user using +-define jpeg:max-warnings=<value>. Fixes oss-fuzz 8704 +"graphicsmagick/coder_JPG_fuzzer: Out-of-memory in +graphicsmagick_coder_JPG_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/png.c (ReadPNGImage): Detect EOF when reading +magic_number. Fixes oss-fuzz 8944 +"graphicsmagick/coder_PNG_fuzzer: Use-of-uninitialized-value in +ReadPNGImage". (Credit to OSS-Fuzz) +(ReadPNGImage, ReadJNGImage): Makes sure that return value of +ReadBlob() is always checked to detect EOF.
  • +
+
+

2018-06-16 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tiff.c (ReadTIFFImage): Re-structure exception reporting +so that QuantumTransferMode() exceptions thrown for +PLANARCONFIG_SEPARATE images are handled immediately. Fixes +oss-fuzz 8896 "graphicsmagick/coder_BIGTIFF_fuzzer: +Use-of-uninitialized-value in DisassociateAlphaRegion". (Credit to +OSS-Fuzz) +(ReadTIFFImage): tsize_t is a signed type so be prepared for +unexpected negative values produced by libtiff size functions. +Fixes oss-fuzz 8934 "graphicsmagick/coder_TIFF_fuzzer: Sanitizer +CHECK failure in "((0)) != (0)" (0x0, 0x0)". (Credit to OSS-Fuzz)
  • +
+
+

2018-06-16 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/wpg.c Fix oss-fuzz 7735 "graphicsmagick/coder_WPG_fuzzer: +Use-of-uninitialized-value in ReadWPGImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-06-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadMNGImage): ENDL chunk must be at least one +byte in size. Fixes oss-fuzz 8832 +"graphicsmagick/coder_MNG_fuzzer: Null-dereference READ in +ReadMNGImage". (Credit to OSS-Fuzz) +(ReadMNGImage): Length of DISC chunk must be evenly divisible by +2. Fixes oss-fuzz 8834 "graphicsmagick/coder_MNG_fuzzer: +Heap-buffer-overflow in ReadMNGImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-06-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/mpc.c (ReadMPCImage): Detect end of file while reading +image directory. Similar to MIFF fixes for ImageMagick +CVE-2017-18272. +(RegisterMPCImage): Require seekable stream since MPC is strictly +a file-based format and so GetBlobSize() is assured to work. +Similar to MIFF behavior. Claimed to be part of the resolution +for ImageMagick CVE CVE-2017-11449. Suggested by Petr Gajdos via +email on January 3, 2018.
  • +
+
+

2018-06-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/miff.c (ReadMIFFImage): Detect end of file while reading +image directory. Fixes SourceForge issue 565 "ImageMagick +CVE-2017-18272 applies to GraphicsMagick". Thanks to Petr Gajdos +for reporting this issue to us.
  • +
  • magick/import.c (ImportViewPixelArea): Use appropriate +bits_per_sample validations for FloatQuantumSampleType. Fixes +oss-fuzz 8780 "graphicsmagick/coder_PTIF_fuzzer: +Use-of-uninitialized-value in HorizontalFilter". (Credit to +OSS-Fuzz)
  • +
+
+

2018-06-09 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c More than 4GiB are not supported in MAT!
  • +
+
+

2018-06-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/mat.c (ReadMATImage): Add casts to avoid arithmetic +overflow when computing size and offsets. Fixes oss-fuzz 8801 +"graphicsmagick/coder_MAT_fuzzer: Timeout in +graphicsmagick_coder_MAT_fuzzer". (Credit to OSS-Fuzz)
  • +
  • magick/blob.c (ReadBlobLSBDoubles, ReadBlobMSBDoubles): Only +byte-swap doubles or test doubles for NAN if we have read enough +bytes for at least one double value. +(ReadBlob): Add an assertion to enforce that ReadBlob() will never +report reading more bytes than requested due to some +implementation issue.
  • +
+
+

2018-06-08 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/blob.c (ReadBlob, WriteBlob): gzread(), BZ2_bzread(), +gzwrite(), BZ2_bzwrite() return type 'int' rather than 'size_t' +like their stdio equivalents. Use correct signed type to avoid +returning a negative value into an unsigned type, forming a huge +positive value. Fixes oss-fuzz 8600 +"graphicsmagick/coder_MAT_fuzzer: Heap-buffer-overflow in +ReadBlobLSBDoubles". (Credit to OSS-Fuzz)
  • +
+
+

2018-06-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (png_read_raw_profile): Try to shore up parsing of +raw profile reading to avoid heap read overruns. Fixes oss-fuzz +8763 "graphicsmagick/coder_PNG32_fuzzer: Heap-buffer-overflow in +png_read_raw_profile". (Credit to OSS-Fuzz)
  • +
+
+

2018-06-07 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Reduce stack usage for 64 bit architecture.
  • +
+
+

2018-06-06 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/wpg.c Check return values of SeekBlob for more safety.
  • +
+
+

2018-06-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Use DestroyImageList() rather +than DestroyImage() on returned Image from supposed read of JPEG +data, in case multiple frames were unexpectedly returned. Also +add "JPEG:" prefix to filename when reading from temporary file to +force that it can only be read as a JPEG file, disabling format +auto-detection based on file header. Fixes oss-fuzz 8755 +"graphicsmagick/coder_JNG_fuzzer: Indirect-leak in +AllocateImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-06-05 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/blob.c (EOFBlob): Implement EOF detection for ZipStream. +Does some archaic zlib not provide gzeof()? Fixes oss-fuzz 8550 +"graphicsmagick/coder_MAT_fuzzer: Timeout in +graphicsmagick_coder_MAT_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-06-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOnePNGImage): Skip adding empty raw profile. +Fixes oss-fuzz "graphicsmagick/coder_PNG_fuzzer: +Heap-buffer-overflow in png_read_raw_profile". (Credit to +OSS-Fuzz)
  • +
+
+

2018-06-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • NEWS.txt: Update NEWS with latest changes.
  • +
  • coders/dcm.c (DCM_ReadRGBImage): Force the image to DirectClass +to avoid later use of uninitialized indexes. Fixes oss-fuzz 8602 +"graphicsmagick/coder_DCM_fuzzer: Use-of-uninitialized-value in +DCM_PostRescaleImage". (Credit to OSS-Fuzz) +(DCM_ReadPlanarRGBImage): Force the image to DirectClass to avoid +later use of uninitialized indexes.
  • +
  • coders/png.c (ReadMNGImage): Free chunk memory in error +reporting path to avoid leak. Fixes oss-fuzz 8721 +"graphicsmagick/coder_MNG_fuzzer: Direct-leak in +ReadMNGImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-06-02 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/constitute.c (ReadImage): Assure that an error exception +is thrown if coder returns null without properly reporting an +exception.
  • +
  • magick/blob.c (BlobToImage): Assure that an error exception is +thrown if coder returns null without properly reporting an +exception.
  • +
  • coders/png.c (ReadMNGImage): Disable mystery "linked list is +corrupted" code. Assure that exceptions are reported to the +correct place so they are not lost. Fixes oss-fuzz 8710 +"graphicsmagick/coder_MNG_fuzzer: Indirect-leak in +AllocateImage". (Credit to OSS-Fuzz)
  • +
  • coders/tiff.c (ReadTIFFImage): Initialize allocated scanline, +strip, or tile to zero in order to avoid complaint about use of +uninitialized data if libtiff fails to write all the bytes. Fixes +oss-fuzz 8551 "graphicsmagick/coder_TIFF_fuzzer: +Use-of-uninitialized-value in ImportGrayQuantumType". (Credit to +OSS-Fuzz)
  • +
  • magick/annotate.c (RenderFreetype): Throw an exception if +DrawInfo font is null. Should fix oss-fuzz 8557 +"graphicsmagick/coder_PCD_fuzzer: Unknown signal in +RenderFreetype" and may fix oss-fuzz 8544 +"graphicsmagick/coder_PCD_fuzzer: Null-dereference READ in +RenderFreetype". (Credit to OSS-Fuzz)
  • +
  • coders/jpeg.c (ReadGenericProfile): Add/improve tracing for +profile size and when JPEG header is being read.
  • +
+
+

2018-06-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Report a useful exception for +the case when the JNG file fails to provide the necessary image +chunks to allocate the color image. Inspired by oss-fuzz 8666 +"graphicsmagick/coder_JNG_fuzzer: ASSERT: data != (const char *) +NULL" although the reported issue was not reproduced.
  • +
+
+

2018-05-31 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadMNGImage): Fix off-by-one in length validation +for TERM chunk which allowed one byte heap read overflow. Fixes +oss-fuzz 8615 "graphicsmagick/coder_MNG_fuzzer: +Heap-buffer-overflow in mng_get_long". (Credit to OSS-Fuzz) +(ReadMNGImage): Fix leak of MngInfo in error reporting path. +Fixes oss-fuzz 8604 "graphicsmagick/coder_MNG_fuzzer: Direct-leak +in ReadMNGImage". (Credit to OSS-Fuzz) +(ReadMNGImage): Verify that claimed chunk size does not exceed +input size. Fixes oss-fuzz 8564 "graphicsmagick/coder_MNG_fuzzer: +Out-of-memory in graphicsmagick_coder_MNG_fuzzer". (Credit to +OSS-Fuzz)
  • +
  • coders/tiff.c (ReadTIFFImage): Reject files with excessive +samples-per-pixel or extra-samples. Avoids potential issues +observed in oss-fuzz 8634 "graphicsmagick/coder_BIGTIFF_fuzzer: +Undefined-shift in ImportAlphaQuantumType". (Credit to OSS-Fuzz)
  • +
+
+

2018-05-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadMNGImage): Assure that object id index is +always less than MNG_MAX_OBJECTS to avoid overflow. Fixes +oss-fuzz 8596 "graphicsmagick/coder_MNG_fuzzer: +Index-out-of-bounds in ReadMNGImage" and likely other issues yet +to be reported. (Credit to OSS-Fuzz)
  • +
+
+

2018-05-30 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (CompareEdges): Per ticket #562, +function CompareEdges() did not conform to the qsort() +requirement that if CompareEdges(edge0,edge1) returns +-1 (i.e., edge0 "less than" edge1), then +CompareEdges(edge1,edge0) should return 1 (edge1 +"greater than" edge0). This has been fixed.
  • +
+
+

2018-05-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Deal with JDAA JNG chunk with +length zero. Fixes oss-fuzz 8562 +"graphicsmagick/coder_JNG_fuzzer: ASSERT: data != (const char *) +NULL". (Credit to OSS-Fuzz)
  • +
  • coders/tiff.c (ReadTIFFImage): Check that the bits-per-sample is +supported by the implementation before attempting to decode the +image. Fixes oss-fuzz 8554 "graphicsmagick/coder_BIGTIFF_fuzzer: +Undefined-shift in MagickBitStreamMSBWrite". (Credit to OSS-Fuzz)
  • +
  • coders/png.c (ReadMNGImage): Eliminate use of uninitialized +header magic data by checking for EOF first. Fixes oss-fuzz 8597 +"graphicsmagick/coder_MNG_fuzzer: Use-of-uninitialized-value in +ReadMNGImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-05-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • fuzzing/oss-fuzz-build.sh: More fixes based on what is observed +in oss-fuzz build log.
  • +
+
+

2018-05-24 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/jnx.c The attribute should belong to only one scene and +not to whole image list.
  • +
+
+

2018-05-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • fuzzing/oss-fuzz-build.sh: Changes to add CPPFLAGS to configure +executions to hopefully get oss-fuzz build closer to success.
  • +
+
+

2018-05-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • PerlMagick/t/jpeg/read.t: Add a JNX reader test case.
  • +
  • coders/jnx.c (ReadJNXImage): JNX image depth should be 8.
  • +
  • fuzzing/oss-fuzz-build.sh: Apply patch from Alex Gaynor to +switch libpng to autotools build system, as well as configure +GraphicsMagick with '--with-quantum-depth=16'.
  • +
+
+

2018-05-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tiff.c (ReadTIFFImage): Validate tile memory requests for +the TIFFReadRGBATile() case in the same way as the TIFFReadTile() +case. Fixes oss-fuzz 8434 "graphicsmagick/coder_BIGTIFF_fuzzer: +Out-of-memory in graphicsmagick_coder_BIGTIFF_fuzzer". (Credit to +OSS-Fuzz)
  • +
+
+

2018-05-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tile.c (ReadTILEImage): Remove any existing size request +when while image to tile. This avoids size being used for both +the input image size and the tile image size. Fixes SourceForge +issue #563 "tile:<image> appears to blow image up by 100% before +applying tiling".
  • +
+
+

2018-05-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • fuzzing/oss-fuzz-build.sh: Patch from Paul Kehrer to disable +libpng test programs and binaries while building libpng in support +of oss-fuzz testing.
  • +
  • coders/dcm.c (DCM_ReadGrayscaleImage): If a palette was +provided, the image may be in PseudoClass but we need DirectClass +for gray image when GRAYSCALE_USES_PALETTE is not defined. Fixes +oss-fuzz 7550 "graphicsmagick/coder_DCM_fuzzer: +Use-of-uninitialized-value in SyncImageCallBack". (Credit to +OSS-Fuzz) +(ReadDCMImage): Restore use of DCM_PostRescaleImage() in order to +obtain suitably scaled DICOM again. Hopefully it is more robust +now. +(DCM_ReadPaletteImage): Assure that DirectClass pixels are +initialized.
  • +
+
+

2018-05-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tiff.c (ReadTIFFImage): Remove strange addition of +image->columns to pixel buffer offsets which now causes a heap +overflow since the buffer has been right-sized. Perhaps the extra +offset plus the over-sized allocation was some attempt to avoid +buffer over/underflows due to bugs in libtiff. Fixes oss-fuzz 8384 +"graphicsmagick/coder_BIGTIFF_fuzzer: Heap-buffer-overflow in +put1bitbwtile" which is described to be a regression. (Credit to +OSS-Fuzz)
  • +
  • magick/render.c (DrawImage): Fix wrong range checks which caused +spurious "Parsing of SVG images fail with "Non-conforming drawing +primitive definition (push)" failure. Fixes SourceForge issue 561 +"Parsing of SVG images fail with "Non-conforming drawing primitive +definition (push)"" which is due to problems caused by the fix for +SourceForge issue 517.
  • +
  • coders/tiff.c (WritePTIFImage): Use '-define +ptif:minimum-geometry=<geometry>' to specify the smallest +subresolution frame which is produced by the PTIF (Pyramid TIFF) +writer.
  • +
+
+

2018-05-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tiff.c (WritePTIFImage): Allow 1x1 input image to be +supported.
  • +
  • coders/png.c (ReadOneJNGImage): Unconditionally free JDAT chunk +memory. Fixes oss-fuzz 8366 "graphicsmagick/coder_JNG_fuzzer: +Direct-leak in ReadOneJNGImage". (Credit to OSS-Fuzz)
  • +
  • coders/tiff.c (WritePTIFImage): Fix leak of pyramid Image list +if ResizeImage() fails. Fixes oss-fuzz 8364 +"graphicsmagick/coder_PTIF_fuzzer: Indirect-leak in +CloneImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-05-17 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tiff.c (WriteTIFFImage): Add and use +ThrowTIFFWriterException() macro to consistently clean-up when +throwing writer exception. May fix oss-fuzz 8321 +"graphicsmagick/coder_EPT_fuzzer: Direct-leak in +TIFFClientOpen". (Credit to OSS-Fuzz) +(ReadTIFFImage): Add and use ThrowTIFFReaderException() macro to +consistently clean-up when throwing reader exception.
  • +
+
+

2018-05-16 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/alpha_composite.h (AlphaCompositePixel): The +macro definition for MagickAlphaCompositeQuantum in +alpha_composite.h computes an expression of the form:

    +

    a * b + c * d * e

    +

    Code in function AlphaCompositePixel() (also in +alpha_composite.h) multiplies the result of this macro +by variable "delta" as follows:

    +

    delta * a * b + c * d * e

    +

    However, the intended result is actually:

    +

    delta * ( a * b + c * d * e )

    +

    The macro definition has been modified to enclose the +entire expression in parentheses.

    +

    The effects of this bug were particularly evident at the +boundary between a stroked polygon and a transparent +black region. More generally, an incorrect composited +pixel value was being computed by AlphaCompositePixel() +whenever the output alpha value was not 100% opaque.

    +
  • +
+
+

2018-05-16 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • tests/rwblob.tap: Add a test for PTIF format.
  • +
  • coders/tiff.c (WritePTIFImage): Fix Image blob referencing in +order to avoid double-free when writing PTIF to memory BLOB. Fixes +oss-fuzz 8280 "graphicsmagick/coder_PTIF_fuzzer: Heap-double-free +in Magick::BlobRef::~BlobRef". (Credit to OSS-Fuzz)
  • +
+
+

2018-05-14 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tiff.c (WriteTIFFImage): Use libtiff's +TIFFDefaultStripSize() function rather than an old porting macro +required by some defunct libtiff version. Expected to fix +oss-fuzz 8248 "graphicsmagick/coder_EPT_fuzzer: +Floating-point-exception in WriteTIFFImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-05-13 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Fix potentional leak when compressed object is +corrupted. Fixes oss-fuzz 8251 (Credit to OSS-Fuzz)
  • +
+
+

2018-05-13 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tiff.c (ReadTIFFImage): Fix leak of Image when +TIFFReadRGBAImage() reports failure. Also harden buffer +allocation calculation. Fixes oss-fuzz 8275 +"graphicsmagick/coder_BIGTIFF_fuzzer: Indirect-leak in +AllocateImage". (Credit to OSS-Fuzz)
  • +
  • coders/ept.c (ReadEPTImage): Add validations of 'count' and +'filesize' read from EPT file. In response to oss-fuzz 8248 +"graphicsmagick/coder_EPT_fuzzer: Floating-point-exception in +WriteTIFFImage" but we are unable to recreate the oss-fuzz issue +since the EPT reader already immediately reports an EOF exception.
  • +
+
+

2018-05-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • fuzzing/oss-fuzz-build.sh: Apply SourceForge patch #57 "Add +fuzzing support for jpeg + freetype delegates" by Alex Gaynor.
  • +
  • coders/png.c (read_user_chunk_callback): Fix memory leak and use +of uninitialized memory when handling eXIf chunk. Fixes oss-fuzz +8247 "graphicsmagick/coder_PNG24_fuzzer: Direct-leak in +png_malloc". (Credit to OSS-Fuzz)
  • +
+
+

2018-05-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • fuzzing/oss-fuzz-build.sh: Apply SourceForge patch #56 "Use a +few delegate libraries in fuzzing" by Alex Gaynor.
  • +
+
+

2018-05-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • tests/rwfile.tap: MIFF zip and bzip compression tests do not +fail if zlib and bzlib are not available because the compression +request is silently changed to no compression.
  • +
+
+

2018-05-07 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (DrawImage, InsertAttributeIntoInputStream): +For a reference such as 'class="classname"', the "classname" +is now allowed to be undefined.
  • +
  • coders.svg.c (ProcessStyleClassDefs): Class definitions +defined within a <style> block may now be empty.
  • +
  • These relaxed conditions are not specifically called out in +the SVG spec as being either acceptable or unacceptable, but +other SVG renderers (e.g., Chrome) handle them this way. These +changes do not resolve, but are related to, ticket #307.
  • +
+
+

2018-05-05 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • utilities/Makefile.am (utilities/tests/montage.log): Fix +dependency rule so that effects.tap is fully executed before +execution of montage.tap starts.
  • +
+
+

2018-05-04 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (DrawImage, TraceXXX): The PrimitiveInfo +array used to store points generated by TraceEllipse(), the +other TraceXXX() functions, and DrawImage() was not always +being expanded when needed, resulting in writes beyond the +end of the currently allocated storage. To fix this problem, +a new data structure PrimitiveInfoMgr, and an associated +function, PrimtiveInfoRealloc(), were written to handle +expanding the PrimitiveInfo array as needed. DrawImage() and +the TraceXXX() functions were modified to prevent the out of +bounds writes to memory. This fixes ticket #516.
  • +
+
+

2018-05-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOneJNGImage): Add more JNG chunk +validations. Fixes an issue reported by "Trace Probe" via a +follow-up post to SourceForge issue 437 "assertion failure in +WriteBlob", although the issue described was not reproduced.
  • +
  • coders/meta.c (ReadMETAImage): Detect and report 8BIMTEXT and +8BIMWTEXT decoding problems. Fixes oss-fuzz 8125 +"graphicsmagick/coder_8BIMTEXT_fuzzer: Use-of-uninitialized-value +in format8BIM". (Credit to OSS-Fuzz)
  • +
+
+

2018-05-02 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (TraceStrokePolygon): Excessively +large values of stroke-width were cascading through +other computations, causing the function to write beyond +the end of it's array of points when the stroke-linejoin +attribute value was "round". Code was added to reallocate +the array of points as needed, and to limit the size of +stroke-width (for computational purposes) to no more than +approximately twice the diagonal size of the output image. +Fixes ticket #515.
  • +
  • The same limit on stroke-width was applied to all other +instances of the same computation in render.c.
  • +
+
+

2018-05-01 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • This change set fixes ticket #471.
  • +
  • magick/render.c (DrawImage): Polylines with fewer +than two points were being flagged as an error. The +SVG spec has no such restriction (fixed).
  • +
  • coders/svg.c (SVGStartElement) Inner <svg> elements +could modify the output image dimensions if a geometry +string was supplied. Now the output image dimensions +are determined by the outermost <svg> only.
  • +
+
+

2018-05-01 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (TraceEllipse, TraceRectangle, +TraceRoundRectangle): Per the SVG spec, rectangles and +round rectangles having a width or height of zero are +not rendered. Also per the spec, ellipses having an x +or y radius of zero are not rendered. Fixes ticket #457.
  • +
+
+

2018-04-30 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.h, (PrimitiveInfo), magick/render.c: Added +member "flags" to PrimitiveInfo to support indicating closed +shapes (e.g., rectangle, circle, path closed using 'z' or 'Z'). +Updated code in render.c (functions TraceXXX) to indicate +closed shapes. This replaces the previous policy of detecing +closed shapes by comparing the first and last points to see if +they are identical (within MagickEpsilon). The old policy +prevented open subpaths with the same first and last point from +being rendered properly (per the SVG spec) when round or square +endcaps were enabled. Part of the fix for ticket #322.
  • +
  • magick/render.c (ConvertPrimitiveToPath): Modified duplicate +point elimination code so that the first and last points of +a subpath are always preserved. Consequences: (1) Allows +for the correct rendering of the sequence "move x1 y1 line +x1 y1" with round or square endcaps. Part of the fix for +ticket #322. (2) Fixes a bug in which eliminating the last +point as a duplicate caused a closed shape to no longer be +closed. This would manifest itself, for example, as a small +"nub" on the boundary of a filled circle.
  • +
  • magick/render.c (GetPixelOpacity): Fixed a bug in the +code that computed the distance between a point and a +segment (polygon edge). Prior to this fix, for zero length +segments this code would generate a divide-by-zero and +incorrect output. Part of the fix for ticket #322.
  • +
  • magick/render.c (DrawPolygonPrimitive): Polygons/paths with +zero or one points are no longer rendered per the SVG spec.
  • +
  • magick/render.c (DrawStrokePolygon): Per the SVG spec, a +polygon consisting of a single move-to command is not stroked.
  • +
  • magick/render.c (TracePath): Per the SVG spec, if the +endpoints (x1, y1) and (x2, y2) of an arc subpath are identical, +then this is equivalent to omitting the elliptical arc segment +entirely. For rendering purposes the zero length arc is +treated like a zero length "line to" command to the current +point.
  • +
  • magick/render.c (TraceStrokePolygon): Added code to detect +zero length open subpaths and return a stroked polygon containing +no points when round or square endcaps are not enabled. This +satisfies the SVG spec requirement that zero length subpaths are +only stroked if the 'stroke-linecap' property has a value of +round or square.
  • +
  • magick/render.c (TracePath): Fixed a bug in which if a "move to" +command was followed by additional pairs of points, indicating +implied "line to" commands, each point was added twice.
  • +
+
+

2018-04-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pcx.c (ReadPCXImage): Colormap from PCX header is only +used if colors <= 16. Determination of DirectClass image was +wrong. Fixes oss-fuzz 8093 "graphicsmagick/coder_PCX_fuzzer: +Use-of-uninitialized-value in IsMonochromeImage". (Credit to +OSS-Fuzz)
  • +
+
+

2018-04-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • version.sh: Updates to prepare for the 1.3.29 release.
  • +
  • coders/pict.c (DecodeImage): Assure that scanline is initialized +to avoid use of uninitialized data. Fixes oss-fuzz 8063 +"graphicsmagick/coder_WPG_fuzzer: Use-of-uninitialized-value in +ReadPICTImage". (Credit to OSS-Fuzz)
  • +
  • coders/dpx.c (ReadDPXImage): Assure that NULL pixels is not +used. Fixes oss-fuzz 8078 "graphicsmagick/coder_DPX_fuzzer: +Null-dereference WRITE in ReadDPXImage". (Credit to OSS-Fuzz)
  • +
  • NEWS.txt: Update NEWS file with information about changes since +last release.
  • +
+
+

2018-04-28 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dib.c (ReadDIBImage): Disable EOF tests for "ICODIB" +subformat due to icon file provided by SourceForge issue #557 +"ErrorCorruptImage: Magick: Unexpected end-of-file ()" where an +EOF error was reported due to no mask data being supplied.
  • +
  • coders/png.c (ReadOneJNGImage): The embedded JPEG image is +required to have the same dimensions as the JNG image as provided +by JHDR. Fixes SourceForge bug 555 "heap-buffer-overflow in +AcquireCacheNexus when processing jng file". It is likely that +this issue is precipitated by using 'montage' which seems to set a +default non-zero image size. +(ReadMNGImage): By default limit the maximum loops specifiable by +the MNG LOOP chunk to 512 loops, but allow this to be modified by +'-define mng:maximum-loops=value'. Also assure that the value is +in the range of 0-2147483647 as per the MNG specification. This +is to address the denial of service issue described by +CVE-2018-10177. This problem was reported to us by Petr Gajdos +via email on Fri, 20 Apr 2018.
  • +
  • coders/dpx.c (ReadDPXImage): Move misplaced channel validation +code. Fixes oss-fuzz 8041 "graphicsmagick/coder_DPX_fuzzer: +Use-of-uninitialized-value in WriteDPXImage" and oss-fuzz 8055 +"graphicsmagick/enhance_fuzzer: Use-of-uninitialized-value in +EnhanceImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/xpm.c (StringToListMod): Algorithm fixes to fix use of +uninitialized data. Fixes oss-fuzz 8046 +"graphicsmagick/coder_XPM_fuzzer: Use-of-uninitialized-value in +StringToListMod". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-26 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/xpm.c (ReadXPMImage): Reduce memory consumption further. +Hopefully fixes oss-fuzz 8013 "graphicsmagick/coder_XPM_fuzzer: +Out-of-memory in graphicsmagick_coder_XPM_fuzzer". (Credit to +OSS-Fuzz)
  • +
  • magick/utility.c (StringToList): Only allocate the memory +required when converting string to an ASCII list. May or may not +fix oss-fuzz 8013 "graphicsmagick/coder_XPM_fuzzer: Out-of-memory +in graphicsmagick_coder_XPM_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/bmp.c (ReadBMPImage): Fix benign use of uninitialized +data when testing header magick. Fixes oss-fuzz 7980 +"graphicsmagick/coder_BMP_fuzzer: Use-of-uninitialized-value in +LocaleNCompare". (Credit to OSS-Fuzz)
  • +
  • coders/dpx.c (ReadDPXImage): ColorDifferenceCbCr does require +even image width. Fixes oss-fuzz 7966 +"graphicsmagick/coder_DPX_fuzzer: Unknown signal in +TentUpsampleChroma". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dpx.c (ReadDPXImage): ColorDifferenceCbCr element +requires two samples/pixel, not one. Fixes oss-fuzz 7951 +"graphicsmagick/coder_DPX_fuzzer: Heap-buffer-overflow in +ReadDPXImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pdb.c (ReadPDBImage): Assure that pixels buffer is +initialized. Fixes oss-fuzz 7937 +"graphicsmagick/coder_PDB_fuzzer: Use-of-uninitialized-value in +ReadPDBImage". (Credit to OSS-Fuzz)
  • +
  • coders/mvg.c (ReadMVGImage): Assure that MVG viewbox parameters +were supplied. Fixes oss-fuzz 7936 +"graphicsmagick/coder_MVG_fuzzer: Use-of-uninitialized-value in +ReadMVGImage". (Credit to OSS-Fuzz)
  • +
  • coders/dpx.c (ReadDPXImage): Element descriptors CbYCrY422 and +CbYACrYA4224 require that the image width be evenly divisible by 2 +so enforce that. Fixes oss-fuzz 7935 +"graphicsmagick/coder_DPX_fuzzer: Heap-buffer-overflow in +ReadDPXImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dpx.c (ReadDPXImage): Reject DPX files which claim to use +signed data. Fixes oss-fuzz 7758 +"graphicsmagick/coder_DPX_fuzzer: Use-of-uninitialized-value in +WriteDPXImage". (Credit to OSS-Fuzz) +(ReadDPXImage): Validate that the image elements do update all of +the channels, including the alpha channel. Now report an error if +a color channel is missing. Fixes oss-fuzz 7758 +"graphicsmagick/coder_DPX_fuzzer: Use-of-uninitialized-value in +WriteDPXImage".
  • +
  • coders/gif.c (DecodeImage): Finally fix oss-fuzz 7732 +"graphicsmagick/coder_GIF_fuzzer: Heap-buffer-overflow in +DecodeImage" which was not actually fixed with previous +changes. (Credit to OSS-Fuzz)
  • +
+
+

2018-04-21 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • +
    coders/topol.c Emit error when tile storage overflows image data;
    +
    fixes oss-fuzz 7769 thanks to oss-fuzz.
    +
    +
  • +
+
+

2018-04-20 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (ConvertPrimitiveToPath): Fixed a bug +in which SVG paths containing multiple open subpaths were +not being processed correctly, resulting in incorrect +output. This fixes ticket #94.
  • +
+
+

2018-04-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/gif.c (DecodeImage): Fix use of uninitialized memory +during error condition in decoder. Fixes oss-fuzz 7732 +"graphicsmagick/coder_GIF_fuzzer: Heap-buffer-overflow in +DecodeImage". (Credit to OSS-Fuzz)
  • +
  • coders/txt.c (ReadTXTImage): Assure that all image pixels are +initialized to black.
  • +
  • Magick++/demo/zoom.cpp (main): Add a -read-blob option to read +input file into a Blob so that it is read by the Blob reader +rather than the file reader. Default the output Geometry to the +input image geometry in case the user does not specify a resize +resolution or geometry.
  • +
  • Magick++/tests/readWriteBlob.cpp (main): Improve the quality of +code which reads a file into memory for Blob testing.
  • +
  • magick/blob.c (BlobToImage): Add exception reports for the cases +where 'magick' was not set and the file format could not be +deduced from its header. Previously a null Image pointer was +being returned without any exception being thrown.
  • +
+
+

2018-04-15 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dpx.c (ReadDPXImage): Assure that CbCr layer initializes +all channels if it is the first element of a planar DPX. Fixes +oss-fuzz 7703 "graphicsmagick/coder_DPX_fuzzer: +Use-of-uninitialized-value in WriteDPXImage". (Credit to OSS-Fuzz)
  • +
  • coders/pict.c (ReadPICTImage): Don't refer to filename member of +ImageInfo which was just destroyed. Much thanks to Alex Gaynor for +finding this. Should fix oss-fuzz 6867 +"graphicsmagick/coder_PCT_fuzzer: Heap-use-after-free in +GetLocaleExceptionMessage". (Credit to OSS-Fuzz).
  • +
+
+

2018-04-14 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/sgi.c (ReadSGIImage): Assure that iris pixels are fully +initialized. Fixes oss-fuzz 7543 +"graphicsmagick/coder_SGI_fuzzer: Use-of-uninitialized-value in +SGIEncode". (Credit to OSS-Fuzz).
  • +
  • coders/xcf.c (ReadXCFImage): Restore SetImage() which was +previously commented out. This is needed to assure initialized +pixels. Fixes oss-fuzz 7430 "graphicsmagick/coder_XCF_fuzzer: +Use-of-uninitialized-value in AlphaCompositePixel". (Credit to +OSS-Fuzz).
  • +
  • coders/pict.c (ReadPICTImage): Properly initialize "black +canvas" that tiles may be composed on. Fixes oss-fuzz 7574 +"graphicsmagick/enhance_fuzzer: Use-of-uninitialized-value in +EnhanceImage". (Credit to OSS-Fuzz).
  • +
  • coders/rle.c (ReadRLEImage): Check for EOF when reading comment. +Fixes oss-fuzz 7667 "graphicsmagick/coder_RLE_fuzzer: +Use-of-uninitialized-value in ReadRLEImage". (Credit to OSS-Fuzz).
  • +
  • coders/pdb.c (WritePDBImage): Avoid use of uninitialized +bytes. Fixes oss-fuzz 7638 "graphicsmagick/coder_PDB_fuzzer: +Use-of-uninitialized-value in WritePDBImage". (Credit to +OSS-Fuzz).
  • +
  • coders/rla.c (ReadRLAImage): Add many more validations, +including scanline offsets and number of channels. Fixes oss-fuzz +7653 "graphicsmagick/coder_RLA_fuzzer: Timeout in +graphicsmagick_coder_RLA_fuzzer". (Credit to OSS-Fuzz).
  • +
  • coders/txt.c (ReadTXTImage): Implement missing subrange logic to +read only the specified range of frames. Limits frames read from +oss-fuzz test case +clusterfuzz-testcase-minimized-coder_TEXT_fuzzer-6061076048248832 +"graphicsmagick/coder_TEXT_fuzzer: Timeout in +graphicsmagick_coder_TEXT_fuzzer". (Credit to OSS-Fuzz).
  • +
  • Magick++/lib/Image.cpp (read): Set subrange = 1 since this +interface is intended to read just one frame from the input file. +Use the STL-based interfaces to read multiple frames.
  • +
  • coders/fits.c (ReadFITSImage): Verify FITS header before reading +further. Rejects file from oss-fuzz 7650 +"graphicsmagick/coder_FITS_fuzzer: Out-of-memory in +graphicsmagick_coder_FITS_fuzzer". (Credit to OSS-Fuzz).
  • +
  • PerlMagick/Magick.xs (Get): Fix PerlMagick compilation problem +due to rename/repurposing of image->clip_mask.
  • +
+
+

2018-04-13 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/image.c, magick/image.h: In order to be able to +support SVG masks, and to be able to further extend the +Image data structure without changing its size, new data +structure ImageExtra (struct _ImageExtra) has been added. +Header file image.h contains only a forward declaration; +the members of ImageExtra are defined in file image.c. +Image member variable Image * clip_mask has been replaced +by ImageExtra * extra, and function prototypes that enable +access to ImageExtra have been added to image.h. The +clip_mask member variable now resides in ImageExtra. All +references to Image::clip_mask in the GraphicsMagick +source code have either been replaced with direct references +to ImageExtra::clip_mask (image.c), or have been replaced +with calls to access function ImageGetClipMask().
  • +
  • magick/render.c, magick/render.h: In order to be able to +support SVG masks, and to be able to further extend the +DrawInfo data structure without changing its size, new data +structure DrawInfoExtra (struct _DrawInfoExtra) has been added. +Header file render.h contains only a forward declaration; +the members of DrawInfoExtra are defined in file render.c. +DrawInfo member variable char * clip_path has been replaced by +DrawInfoExtra * extra, and function prototypes that enable +access to DrawInfoExtra have been added to render.h. The +clip_path member variable now resides in ImageExtra. All +references to DrawInfo::clip_path in the GraphicsMagick +source code have either been replaced with direct references +to DrawInfoExtra::clip_path (render.c), or have been +replaced with calls to access function DrawInfoGetClipPath().
  • +
  • magick/image.c (new functions CompositePathImage, +CompositeMaskImage, GetImageCompositeMask, +SetImageCompositeMask): Defined new data structure ImageExtra, +added create/destroy logic, and implemented associated access +functions. Implemented SVG masks.
  • +
  • magick/render.c (DrawImage, new function DrawCompositeMask): +Defined new data structure DrawInfoExtra, added create/destroy +logic, and implemented associated access functions. Impemented +SVG masks.
  • +
  • magick/pixel_cache.c (SyncCacheNexus, new function +CompositeCacheNexus): Fixed references to Image::clip_mask. +Implemented SVG masks.
  • +
  • coders/svg.c (SVGStartElement, SVGEndElement): Implemented +SVG masks.
  • +
  • locale/c.mgk, magick/gm_messages.mc, magick/local_c.h: +Added new error codes to support SVG masks.
  • +
  • coders/ps3.c, magick/enhance.c: Fixed references to +Image::clip_mask.
  • +
  • magick/draw.c, wand/drawing_wand.c: Fixed references to +DrawInfo::clip_path.
  • +
+
+

2018-04-13 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/wpg.c Crash on row overflow fixed oss-fuzz 7639 thanks to oss-fuzz.
  • +
+
+

2018-04-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dpx.c (ReadDPXImage): Add more header validations. +Always assure that scanline is initialized for Luma channel. Fixes +oss-fuzz 7544 "graphicsmagick/coder_DPX_fuzzer: +Use-of-uninitialized-value in WriteDPXImage". (Credit to OSS-Fuzz)
  • +
  • coders/pdb.c (ReadPDBImage): Add more EOF checks to avoid benign +use of uninitialized data. Fixes oss-fuzz 7545 +"graphicsmagick/coder_PDB_fuzzer: Use-of-uninitialized-value in +ReadPDBImage".
  • +
  • coders/wpg.c (InsertRow, UnpackWPGRaster): x & y should be +'unsigned long' to match type used by pixel cache APIs and image +rows/columns.
  • +
+
+

2018-04-08 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/wpg.c Stop reading when last row is reached. +This should stop oss-fuzz 7528 thanks to oss-fuzz.
  • +
+
+

2018-04-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/xcf.c (ReadXCFImage): Fix use of uninitialized data in +magick header string for runt file. Fixes oss-fuzz 7521 +"graphicsmagick/coder_XCF_fuzzer: Use-of-uninitialized-value in +LocaleNCompare". (Credit to OSS-Fuzz).
  • +
+
+

2018-04-09 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • OVERVIEW: Change set 9aaeeca0224c modified the drawing +of clipping paths to conform to the SVG spec. This change +set restores the previous behavior for non-SVG clients of +render.c, while still satisfying the SVG spec for SVG clients.
  • +
  • magick/render.h (DrawInfo): Added a bit field in member +"flags" to indicate that drawing should be SVG compliant.
  • +
  • magick/render.c (DrawImage): Now recognizes keyword +"svg-compliant", and tags DrawInfo accordingly. This +allows for existing features in render.c to be changed +to comply with the SVG spec without impacting the previous +behavior expected by non-SVG clients.
  • +
  • magick/render.c (DrawImage): Now uses DrawInfo "flags" +bit for SVG compliance in conjunction with "flags" bit +for "clipping path" to determine when to ignore changes +to fill color, stroke color, etc. This restores the +previous behavior for clipping paths for non-SVG clients.
  • +
  • coders/svg.c (SVGStartElement): The initial set of +MVG commands for rendering an SVG file now includes +new keyword "svg-compliant" (to indicate that certain +graphical elements should be drawn according to the +SVG spec), and includes an intialization of the SVG +"fill-rule" to "nonzero" (the SVG default) instead of +the internally initialized value of "evenodd".
  • +
  • coders/wpg.c: Fixed C99 "//" comments.
  • +
+
+

2018-04-08 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pict.c (ReadPICTImage): Copy tile exception info to main +image and don't composite tile if it has a problem. Fixes +oss-fuzz 7169 "graphicsmagick/enhance_fuzzer: +Use-of-uninitialized-value in EnhanceImage". (Credit to OSS-Fuzz)
  • +
  • coders/dib.c (ReadDIBImage): Do not increase decode bits/pixel +if compression=2, but use it to increase pixel packet size when +estimating bytes per line for decode buffer. Fixes oss-fuzz issue +7324 "graphicsmagick/coder_WPG_fuzzer: Use-of-uninitialized-value +in ReadDIBImage". (Credit to OSS-Fuzz)
  • +
  • coders/dpx.c (ReadDPXImage): When handling the first element of +a planar DPX, assure that the other channels are +initialized. Fixes oss-fuzz 7841 "graphicsmagick/coder_DPX_fuzzer: +Use-of-uninitialized-value in WriteDPXImage". (Credit to OSS-Fuzz)
  • +
  • coders/tim.c (ReadTIMImage): Only 4 and 8 bit TIM requires a +colormap. For other depths, force reading as DirectClass even if +the TIM file provides a colormap. Fixes oss-fuzz 7407 +"graphicsmagick/coder_TIM_fuzzer: Use-of-uninitialized-value in +SyncImageCallBack". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-08 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c The unread data contains crap in memory, +erase current image data. This should mute oss-fuzz 6604.
  • +
  • coders/wpg.c - condition "if(y<1) continue;" is redundant +and could be removed completely. +Allow logging in MatlabV4 module.
  • +
  • coders/svg.c - Do not use C++ syntax in C code - removed.
  • +
+
+

2018-04-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/wpg.c (UnpackWPGRaster): Fix uninitialized row 0 when +row-based RLE is used. Fixes oss-fuzz 6603 +"graphicsmagick/enhance_fuzzer: Use-of-uninitialized-value in +BlendCompositePixel". (Credit to OSS-Fuzz)
  • +
  • coders/pcd.c: Fix many issues, including oss-fuzz 6016 +"graphicsmagick/coder_PCD_fuzzer: Heap-double-free in +MagickRealloc" and oss-fuzz 6108 "graphicsmagick/coder_PCD_fuzzer: +Unknown signal in AllocateThreadViewDataSet". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dcm.c (funcDCM_BitsStored): Limit DICOM significant bits +to 16. Otherwise rescale map code blows up. Fixes oss-fuzz 7435 +"graphicsmagick/coder_DCM_fuzzer: Out-of-memory in +graphicsmagick_coder_DCM_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/pix.c (ReadPIXImage): Detect EOF. Reject RLE lenth of +zero. Fixes oss-fuzz 7440 "graphicsmagick/coder_PIX_fuzzer: +Out-of-memory in graphicsmagick_coder_PIX_fuzzer". (Credit to +OSS-Fuzz)
  • +
+
+

2018-04-05 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dpx.c (ReadDPXImage): Insist on having an element +descriptor we understand since otherwise we can not decode the +image. Fixes oss-fuzz 7410 "graphicsmagick/coder_DPX_fuzzer: +Use-of-uninitialized-value in WriteDPXImage". (Credit to OSS-Fuzz)
  • +
  • coders/avs.c, etc... (WriteAVSImage): Cache image list length +before writing image sequence so that progress monitor is +scalable. Helps with oss-fuzz 7404 +"graphicsmagick/coder_AVS_fuzzer: Timeout in +graphicsmagick_coder_AVS_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-05 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement, SVGEndElement), +magick/render.c (DrawImage): The current text position +is now maintained by DrawImage() instead of by +SVGStartElement() and SVGEndElement(). This change was +made to support the recently implmemented "use" and +"class" elements, which may make changes to the font +size that are not visible to the code in svg.c.
  • +
  • coders/svg.c (GetStyleTokens, SVGStartElement): The +list of SVG attributes is now reordered so that +"font-size", "class", and "style" are processed first. +This ensures that a change to the font size will be +processed before any dimensional attribute whose value +may depend on the font size (e.g., a width value +specified in "em" units).
  • +
  • coders/svg.c (ProcessStyleClassDefs): Fixed two memory +leaks associated with making an early return when +malformed input is detected.
  • +
  • magick/render.c (ExtractTokensBetweenPushPop): Fixed +an uninitialized variable condition which can occur when +malformed input is detected.
  • +
  • magick/render.h (DrawInfo), magick/render.c: DrawInfo +member "unused1" has been renamed "flags". It is now +used to tag a DrawInfo as being a clipping path or a +compositing mask.
  • +
+
+

2018-04-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pdb.c (ReadPDBImage): Update DirectClass pixels to avoid +use of uninitialized memory for 2 bits/pixel. Fixes oss-fuzz 7350 +"graphicsmagick/coder_PDB_fuzzer: Use-of-uninitialized-value in +WritePDBImage". (Credit to OSS-Fuzz)
  • +
  • coders/palm.c (ReadPALMImage): Fix use of uninitialized memory. +Fixes oss-fuzz 7325 "graphicsmagick/coder_PALM_fuzzer: +Use-of-uninitialized-value in TransparentImageCallBack". (Credit +to OSS-Fuzz)
  • +
  • coders/dcm.c (DCM_ReadNonNativeImages): Break out of reading +loop on EOF and properly report exception. Fixes oss-fuzz 7349 +"graphicsmagick/coder_DCM_fuzzer: Timeout in +graphicsmagick_coder_DCM_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/xcf.c (ReadXCFImage): Require that XCF file offsets be in +ascending order to avoid DOS. Fixes oss-fuzz 7333 +"graphicsmagick/coder_XCF_fuzzer: Out-of-memory in +graphicsmagick_coder_XCF_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/wpg.c (UnpackWPGRaster): Fix memory leak in error return +path. Fixes oss-fuzz 7338 "graphicsmagick/enhance_fuzzer: +Direct-leak in UnpackWPGRaster". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-03 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement): This changeset adds +support for SVG geometric transforms specified using the +style="transform: ..." syntax. This syntax is sometimes +used when exporting SVG files from Adobe Illustrator.
  • +
+
+

2018-04-02 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dpx.c (ReadDPXImage): Validate DPX packing method. Fixes +oss-fuzz 7296 "graphicsmagick/coder_DPX_fuzzer: +Use-of-uninitialized-value in WriteDPXImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-04-02 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement, SVGEndElement), +magick/render.c (DrawImage): This changeset adds support for +"class" styling attributes within a <style> section within +the <defs> section, and the ability to reference them from +other SVG elements by class="classname". SVG files exported +from Adobe Illustrator make extensive use of "class" definitions.
  • +
+
+

2018-04-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pict.c (ReadPICTImage): Fix leak of tile image on EOF. +This is a recent regression. Fixes oss-fuzz 7287 +"graphicsmagick/coder_PCT_fuzzer: Indirect-leak in +CloneImage". (Credit to OSS-Fuzz)
  • +
  • magick/pixel_cache.c (OpenCache): Use image->scene rather than +GetImageIndexInList(image) for scene-id part of cache info file +name.
  • +
  • coders/txt.c (WriteTXTImage): Optimize the progress indicator +since it is very inefficient with a large number of scenes and +oss-fuzz 7090 "graphicsmagick/coder_TEXT_fuzzer: Timeout in +graphicsmagick_coder_TEXT_fuzzer" consistently shows +GetImageListLength() in its stack traces.
  • +
  • coders/dcm.c (ReadDCMImage): DICOM reader was no longer +immediately quitting with excessive samples per pixel. This +caused spinning for a very long time when reading planar images +with large samples per pixel. This is a regression due to recent +changes. Fixes oss-fuzz 7269 "graphicsmagick/coder_DCM_fuzzer: +Timeout in graphicsmagick_coder_DCM_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/xcf.c (ReadXCFImage): Destroy layer info before returning +due to exception. This is a new regression due to adding more +checks. Fixes oss-fuzz 7277 "graphicsmagick/coder_XCF_fuzzer: +Direct-leak in ReadXCFImage". (Credit to OSS-Fuzz)
  • +
  • coders/pdb.c (ReadPDBImage): Assure that all bytes of scanline +are initialized while decoding. Fixes oss-fuzz 7051 +"graphicsmagick/coder_PDB_fuzzer: Use-of-uninitialized-value in +WritePDBImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-03-31 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pcx.c (ReadPCXImage): Assure that scanline is +initialized. Fixes oss-fuzz 6612 +"graphicsmagick/coder_PCX_fuzzer: Use-of-uninitialized-value in +WriteRLEPixels". (Credit to OSS-Fuzz)
  • +
  • coders/wpg.c (ReadWPGImage): Detect unexpected EOF and avoid use +of uninitialized data. Fixes oss-fuzz 6601 +"graphicsmagick/enhance_fuzzer: Use-of-uninitialized-value in +ImportIndexQuantumType". (Credit to OSS-Fuzz)
  • +
  • coders/sgi.c (ReadSGIImage): Assure that RLE decode buffer is +initialized. Fixes oss-fuzz 6599 +"graphicsmagick/coder_SGI_fuzzer: Use-of-uninitialized-value in +SyncImageCallBack" and oss-fuzz 6600 +"graphicsmagick/coder_SGI_fuzzer: Use-of-uninitialized-value in +SGIEncode". (Credit to OSS-Fuzz)
  • +
  • coders/viff.c (ReadVIFFImage): Fix blob I/O size validation to +avoid use of uninitialized data. Fixes oss-fuzz 6597 +"graphicsmagick/coder_VIFF_fuzzer: Use-of-uninitialized-value in +ThresholdImage". (Credit to OSS-Fuzz) +(ReadVIFFImage): Don't execute SetImageType(image,BilevelType) on +an image which has no pixels yet in order to avoid use of +uninitialized data. Fixes oss-fuzz 6597. (Credit to OSS-Fuzz)
  • +
  • coders/wbmp.c (ReadWBMPImage): Fix blob I/O size validation to +avoid use of uninitialized data. Fixes oss-fuzz 7047 +"graphicsmagick/coder_WBMP_fuzzer: Use-of-uninitialized-value in +ReadWBMPImage". (Credit to OSS-Fuzz)
  • +
  • coders/wpg.c (ExtractPostscript): Allow non-Postscript content +but force reading using the magick we already detected. Also log +the format that we detected.
  • +
  • coders/xcf.c (ReadOneLayer): Reject layer size of 0x0. Fixes +oss-fuzz 6636 "graphicsmagick/coder_XCF_fuzzer: Direct-leak in +MagickMallocAligned". (Credit to OSS-Fuzz) +(ReadXCFImage): Verify that seek offsets are within the bounds of +the file data. Fixes oss-fuzz 6682 +"graphicsmagick/coder_XCF_fuzzer: Out-of-memory in +graphicsmagick_coder_XCF_fuzzer". (Credit to OSS-Fuzz)
  • +
  • magick/pixel_cache.c (ModifyCache): Destroy CacheInfo if +OpenCache() fails so it is not leaked.
  • +
  • coders/wpg.c (ExtractPostscript): Enforce that embedded file is +a Postscript file. Fixes oss-fuzz 7235 +"graphicsmagick/coder_WPG_fuzzer: Indirect-leak in MagickRealloc". +This is indicated to be a regression. (Credit to OSS-Fuzz)
  • +
+
+

2018-03-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pict.c (ReadPICTImage): Check image pixel limits before +allocating memory for tile. Fixes oss-fuzz 7217 +"graphicsmagick/coder_PICT_fuzzer: Out-of-memory in +graphicsmagick_coder_PICT_fuzzer".
  • +
+
+

2018-03-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pcd.c (ReadPCDImage): Add checks for EOF. Fixes oss-fuzz +issue 7180 "graphicsmagick/coder_PCDS_fuzzer: Timeout in +graphicsmagick_coder_PCDS_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-03-29 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement, SVGEndElement), +magick/render.c (DrawImage): This changeset implements the SVG +"use" element. Graphical elements (e.g., "rect", "text", etc.) +can be tagged with an identifier using 'id="identifier"' when +defined within the "defs" section. They can then be referenced +elsewhere in the SVG file using:

    +

    <use xlink:href="#identifier" ... />

    +

    When referencing a graphical element by its identifier, the +following syntaxes are now treated as being the same:

    +

    href="#identifier" +href="url(#identifier)" +xlink:href="#identifier" +xlink:href="url(#identifier)"

    +
  • +
+
+

2018-03-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/tim.c (ReadTIMImage): Reader was not observing subimage +and subrange to quit after the specified frame range. Inspired by +oss-fuzz 7132 "graphicsmagick/coder_TIM_fuzzer: Timeout in +graphicsmagick_coder_TIM_fuzzer" (Credit to OSS-Fuzz)
  • +
+
+

2018-03-27 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement): Enable setting the +background color from the SVG file when the client +specifies style="background:color" inside the <svg> +... </svg> element.
  • +
+
+

2018-03-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/mtv.c (ReadMTVImage): Add some elementary tracing to MTV +reader.
  • +
  • coders/png.c (ReadMNGImage): Fix SourceForge issue 554 +"Divide-by-zero in ReadMNGImage (coders/png.c)". (Credit to Trace +Probe)
  • +
  • coders/bmp.c (ReadBMPImage): Assure that start position always +advances to avoid looping BMPs. Fixes oss-fuzz 7045 +"graphicsmagick/coder_BMP_fuzzer: Timeout in +graphicsmagick_coder_BMP_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/pict.c (DecodeImage): Verify that sufficient backing data +exists before allocating memory to read it. Fixes oss-fuzz 6629 +"graphicsmagick/coder_PCT_fuzzer: Out-of-memory in +graphicsmagick_coder_PCT_fuzzer". +(ReadPICTImage): Destroy tile_image in ThrowPICTReaderException() +macro to simplify logic.
  • +
+
+

2018-03-25 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Check whether datablock is really read. +Fixes oss-fuzz 7056 (Credit to OSS-Fuzz)
  • +
  • coders/txt.c Duplicate image check for data with fixed geometry +previous check is skipped. Fixes oss-fuzz 7090.
  • +
+
+

2018-03-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dcm.c (ReadDCMImage): Validate that samples per pixel is +in valid range. Fixes oss-fuzz 6260 +"graphicsmagick/coder_DCM_fuzzer: Out-of-memory in +graphicsmagick_coder_DCM_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/meta.c (format8BIM): Allocate space for null termination +and null terminate string. Fixes oss-fuzz 5985 +"graphicsmagick/coder_8BIMTEXT_fuzzer: Heap-buffer-overflow in +formatIPTCfromBuffer". (Credit to OSS-Fuzz)
  • +
  • coders/fits.c (ReadFITSImage): Include number of FITS scenes in +file size validations. Fixes oss-fuzz 6781 +"graphicsmagick/coder_FITS_fuzzer: Timeout in +graphicsmagick_coder_FITS_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-03-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/meta.c (format8BIM): Validate size request prior to +allocation. Fixes oss-fuzz issue 5974 +"graphicsmagick/coder_8BIMTEXT_fuzzer: Out-of-memory in +graphicsmagick_coder_8BIMTEXT_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-03-23 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Fix forged amount of frames 7076. (Credit to OSS-Fuzz)

    +
    +

    * coders/topol.c Check for forged image that overflows file size +(fuzz 6836).

    +
    +
  • +
+
+

2018-03-23 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c, render.h (DrawInfo, CloneDrawInfo, +DrawClipPath, DrawImage, GetDrawInfo): According to the SVG +spec, a clipping path is defined only by the geometry of its +constituent elements, and is not dependent on fill color/opacity, +stroke color/opacity, or stroke width. To ensure conformity +with the spec, when a clipping path is created, these SVG +elements are set to appropriate values, and any attempt to +modify them is ignored.

    +

    Also, whenever a clipping path is drawn, the associated image +attributes are now updated from the parent image structure. +This ensures that any added or modified attributes are up to +date.

    +
  • +
+
+

2018-03-22 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • +
    coders/topol.c Use rather MagickSwabArrayOfUInt32() to
    +

    flip all array elements at once.

    +

    * magick/annotate.c Compilation issue - using C++ syntax in C code.

    +
    +
    +
  • +
+
+

2018-03-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dpx.c (ReadDPXImage): Validate header length and offset +properties. Fixes oss-fuzz "graphicsmagick/coder_DPX_fuzzer: +Use-of-uninitialized-value in WriteDPXImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-03-20 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/annotate.c (RenderType): According to the SVG +spec, the 'font-family' element can be a comma-separated +list of one or more font family names. Function RenderType +in file annotate.c has been modified to support multiple +font family names as follows. The comma-separated list is +processed until the first available font family is found. +If no font family is found, or if font substitution occurred, +then the entire font family string is tested to see if it +exactly matches a font name, or if the font family string +with blanks changed to hypens exactly matches a font name. +If a font name match is found, the matched font overrides +the font substution. The font name matching functionality +is beyond what's in the SVG spec and is provided as a +convenience to the user.
  • +
+
+

2018-03-20 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Fix forged amount of frames 6755. (Credit to OSS-Fuzz)
  • +
+
+

2018-03-20 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/topol.c Redesign ReadBlobDwordLSB() to be more effective.
  • +
+
+

2018-03-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/xpm.c (ReadXPMImage): Reject XPM if its condensed version +contains non-whitespace control characters. Fixes oss-fuzz 7027 +"graphicsmagick/coder_XPM_fuzzer: Timeout in +graphicsmagick_coder_XPM_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-03-19 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/topol.c Fix tile index overflow fuzz 6634. (Credit to OSS-Fuzz)
  • +
+
+

2018-03-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dcm.c (DCM_ReadGrayscaleImage): Don't use rescale map if +it was not allocated. This issue was induced in this development +cycle due to disabling generating the rescale map. Fixes oss-fuzz +7021 "graphicsmagick/coder_DCM_fuzzer: Null-dereference READ in +DCM_ReadGrayscaleImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-03-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/color_lookup.c (QueryColorDatabase): Defend against +partial scanf() expression matching, resulting in use of +uninitialized data. Likely fixes oss-fuzz 6596 +"graphicsmagick/coder_XPM_fuzzer: Use-of-uninitialized-value in +IsMonochromeImage". (Credit to OSS-Fuzz)
  • +
  • coders/rle.c (ReadRLEImage): Validate number of colormap bits to +avoid undefined shift behavior. Fixes oss-fuzz 6630 +"graphicsmagick/enhance_fuzzer: Undefined-shift in +ReadRLEImage". (Credit to OSS-Fuzz)
  • +
  • coders/dcm.c (DCM_ReadRGBImage): Don't use rescale map if it was +not allocated. This issue was induced in this development cycle +due to disabling generating the rescale map. Fixes oss-fuzz 6995 +"graphicsmagick/coder_DCM_fuzzer: Null-dereference READ in +DCM_ReadRGBImage". (Credit to OSS-Fuzz)
  • +
  • coders/dib.c (DecodeImage): Report failure to decode to expected +amount of pixel data as an error. Fixes oss-fuzz 7007 +"graphicsmagick/enhance_fuzzer: Use-of-uninitialized-value in +EnhanceImage". (Credit to OSS-Fuzz)
  • +
  • coders/bmp.c (ReadBMPImage): Add file size and offset/seek +validations. Fixes oss-fuzz 6623 +"graphicsmagick/coder_BMP_fuzzer: Timeout in +graphicsmagick_coder_BMP_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-03-17 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • dcraw/dcraw.c Updated to version 9.27
  • +
+
+

2018-03-15 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/gif.c (ReadGIFImage): Fix botched fixes for use of +uninitialized data when reading GIF extension blocks. Hopefully +ok now.
  • +
+
+

2018-03-13 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/gif.c (ReadGIFImage): Fix use of uninitialized data when +reading GIF extension blocks. Fixes oss-fuzz 6609 +"graphicsmagick/coder_GIF_fuzzer: Use-of-uninitialized-value in +MagickArraySize". This seems to be a totally benign issue. (Credit +to OSS-Fuzz)
  • +
  • magick/magick.c (MagickSignal): Use an alternate signal stack, +if available. This is required for Go lang C language extensions +since Go lang requests an alternate signal sack, and uses small +stacks for its threads. If the library user has not allocated an +alternate signal stack, then behavior should be just as before. +Issue was originally reported by yzh杨振宏 on March 1, 2018 via +the graphicsmagick-help SourceForge mailing list.
  • +
+
+

2018-02-28 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/pixel_cache.c (AcquireCacheNexus): Add a check that the +pixel cache is compatible with the image dimensions. Fixes +oss-fuzz issues 5978 5988 5989 5990 5993 6016, and 6056, which are +all related to the PICT writer. (Credit to OSS-Fuzz)
  • +
  • magick/draw.c (DrawGetStrokeDashArray): Check for failure to +allocate memory. Patch submited by Petr Gajdos via email on +February 28, 2018.
  • +
+
+

2018-02-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/fits.c (ReadFITSImage): Fix signed integer overflow when +computing pixels size. Fixes oss-fuzz 6586 +"graphicsmagick/coder_FITS_fuzzer: Integer-overflow in +ReadFITSImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-02-27 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement, SVGEndElement): From the +SVG spec: "The 'foreignObject' element allows for inclusion +of a foreign namespace which has its graphical content drawn +by a different user agent." Code has been added to consume +and discard the 'foreignObject' element and any settings (e.g., +fill color) internal to it. Previously, settings internal +to the 'foreignObject' element would persist and "leak" into +the graphic elements that followed it, resulting in undesired +side effects (e.g., fill color other than the expected default).
  • +
+
+

2018-02-27 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (DrawPolygonPrimitive): Fixed a bug +introduced by changeset 39102dd1d456. For SVG, this +changeset applied both the group AND the fill opacity +values to fill patterns (similarly for stroke). For WMF, +however, this caused the fill pattern to be rendered as +100% transparent. A closer reading of the SVG spec does +NOT show that the fill opacity should be applied to the +fill pattern, so as of this latest changeset only the group +opacity value is applied to fill and stroke patterns.
  • +
+
+

2018-02-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/bmp.c (ReadBMPImage): Fix divide by zero regression added +by latest fixes. Fixes oss-fuzz 6583 +"graphicsmagick/coder_BMP_fuzzer: Divide-by-zero in ReadBMPImage". +(Credit to OSS-Fuzz)
  • +
+
+

2018-02-26 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pict.c (ReadPICTImage): Validate that PICT rectangles do +not have zero dimensions. Specify expected file type when reading +from a temporary file. Trace PICT rectangle dimensions. More +detection of blob EOF and more error handling. Fixes oss-fuzz +issue 6193 "graphicsmagick/coder_PCT_fuzzer: Unknown signal in +AllocateImageColormap" and likely many oss-fuzz ASAN/UBSAN issues +reported against "PCT" and "PICT" since this one problem appears +to be causing a spew of reports.
  • +
  • coders/png.c (ReadMNGImage): Detect and handle failure to +allocate global PLTE. Problem was reported via email from Petr +Gajdos on February 26, 2018.
  • +
+
+

2018-02-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/blob.c (ReadBlobLSBDouble): Make sure imported double is +a normal value. +(ReadBlobLSBDoubles): Make sure imported doubles are normal +values. +(ReadBlobLSBFloat): Make sure imported float is a normal value. +(ReadBlobLSBFloats): Make sure imported floats are normal values. +(ReadBlobMSBFloat): Make sure imported float is a normal value. +(ReadBlobMSBFloats): Make sure imported floats are normal values. +(ReadBlobMSBDouble): Make sure imported double is a normal value. +(ReadBlobMSBDoubles): Make sure imported doubles are normal +values.
  • +
  • magick/import.c (ImportFloat32Quantum): Make sure imported float +is a normal value. +(ImportFloat64Quantum): Make sure imported double is a normal +value.
  • +
  • magick/image.h (RoundDoubleToQuantum): Restore previous behavior +(from earlier today). +(RoundFloatToQuantum): Restore previous behavior (from earlier +today).
  • +
  • coders/bmp.c (ReadBMPImage): Fix UBSAN runtime error: left shift +of 205 by 24 places cannot be represented in type 'int'.
  • +
  • coders/ept.c (ReadEPTImage): Fix dereference of NULL pointer +which was detected by UBSAN in the test suite.
  • +
  • magick/image.h (RoundDoubleToQuantum): Check double value for +NaN and infinity in order to avoid undefined behavior. +(RoundFloatToQuantum): Check float value for NaN and infinity in +order to avoid undefined behavior.
  • +
  • magick/common.h (MAGICK_ISNAN): Add a isnan() wrapper macro. +(MAGICK_ISINF): Add a isinf() wrapper macro.
  • +
+
+

2018-02-25 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Fix oss-fuzz issue 6273 - Heap-use-after-free in +GetLocaleExceptionMessage. (Credit to OSS-Fuzz)
  • +
+
+

2018-02-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dcm.c (DCM_PostRescaleImage): Remove use of +DCM_PostRescaleImage() since its implementation is wrong and +accesses non-allocated heap memory. Problem was reported by Petr +Gajdos via email on February 8, 2018.
  • +
  • coders/jp2.c (ReadJP2Image): Use a ThrowJP2ReaderException macro +to automatically clean up when throwing an exception.
  • +
  • coders/bmp.c (ReadBMPImage): Report an error if RLE decode does +not produce the expected number of bytes. Fixes oss-fuzz issue +6015 "graphicsmagick/coder_BMP_fuzzer: Out-of-memory in +graphicsmagick_coder_BMP_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-02-23 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (DrawImage): Fixed a bug in which graphical +elements defined within <defs> ... </defs> were being rendered, +contrary to the SVG spec.
  • +
+
+

2018-02-23 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (DrawPolygonPrimitive): When filling or +stroking a polygon using a pattern, the fill (or stroke) +and group/object opacity values were not being applied to +the pattern (fixed).
  • +
+
+

2018-02-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/bmp.c (ReadBMPImage): Fix SeekBlob() return value checks. +Add more EOF checks. Require that a provided ba_offset be a +forward seek in order to avoid the possibility of endless looping.
  • +
+
+

2018-02-23 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Fix oss-fuzz issue 6301. (Credit to OSS-Fuzz)
  • +
+
+

2018-02-22 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/alpha_composite.c (BlendQuantumOpacity): The +pixel compositing equation used when compositing an +image into the output was incorrect and has been fixed.
  • +
  • magick/render.c (DrawPolygonPrimitive): When +compositing polygon edge pixels over a transparent +black background, the code would composite as if the +background were opaque black, resulting in the edge +pixels being too dark (fixed).
  • +
+
+

2018-02-21 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (DrawImage): Per the SVG spec, opacity, +fill-opacity, and stroke-opacity values are now clamped +to [0,1].

    +

    Also fixed two bugs introduced by changeset 91de8039f27d +(dated 2018-02-12): (1) a group/object opacity value +specified using a percentage was not being converted to a +value in [0,1]; (2) if fill-opacity or stroke-opacity was +1, and the group/object opacity value was set to 1, the +resulting fill-opacity or stroke-opacity value would be +set to 0 instead of 1.

    +
  • +
+
+

2018-02-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/viff.c (ReadVIFFImage): Fix excessive memory usage. +Fixes oss-fuzz 6006 "graphicsmagick/coder_XV_fuzzer: Out-of-memory +in graphicsmagick_coder_XV_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/txt.c (ReadInt): Avoid benign signed integer overflow due +to accepting an arbitrary number of digits. Fixes oss-fuzz 6002 +"graphicsmagick/coder_TEXT_fuzzer: Integer-overflow in +ReadInt". (Credit to OSS-Fuzz)
  • +
  • coders/viff.c (ReadVIFFImage): Verify that there is sufficient +data to back up colormap allocation request. Fixes oss-fuzz 5986 +"graphicsmagick/coder_VIFF_fuzzer: Out-of-memory in +graphicsmagick_coder_VIFF_fuzzer". (Credit to OSS-Fuzz)
  • +
  • magick/memory.c: Define MAGICK_MEMORY_HARD_LIMIT=value to abort +when memory request exceeds value. Useful to find location of +excessive memory requests.
  • +
+
+

2018-02-19 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement): Per the SVG spec, the +SVG coder now initializes the MVG coder (which renders +SVG graphical elements) with the the SVG defaults for +fill color, fill-opacity, stroke color, stroke-opacity, +and stroke-width. This makes the SVG coder independent +of the MVG coder intial state.
  • +
+
+

2018-02-19 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement): Fixed initialization of +x and y attributes per the SVG spec: for graphical elements +"image", "pattern", "text", "rect", and "use", if the x or y +attribute is not specified, the effect is as if a value of +"0" were specified.
  • +
+
+

2018-02-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/sun.c (ReadSUNImage): Fix edge case which broke file-size +validation logic. Fixes oss-fuzz issue 5981 +"graphicsmagick/coder_SUN_fuzzer: Out-of-memory in +graphicsmagick_coder_SUN_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/txt.c (ReadTXTImage): Validate that file size is +sufficient for claimed image properties. Fixes oss-fuzz issue +5960 "graphicsmagick/coder_TXT_fuzzer: Out-of-memory in +graphicsmagick_coder_TXT_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/tga.c (ReadTGAImage): Only allow 1 and 8 bit +colormapped/grey images. Fixes oss-fuzz issue 6314 +"graphicsmagick/coder_ICB_fuzzer: Undefined-shift in +ReadTGAImage". (Credit to OSS-Fuzz)
  • +
  • coders/bmp.c (ReadBMPImage): Detect and report when BMP height +value is out of range (too negative). Fixes oss-fuzz issue 6394 +"graphicsmagick/coder_BMP_fuzzer: Integer-overflow in +ReadBMPImage". (Credit to OSS-Fuzz)
  • +
  • coders/rla.c (ReadRLAImage): Detect when RLE decoding is +producing too many samples and report as an error. Fixes oss-fuzz +issue 6312 "graphicsmagick/coder_RLA_fuzzer: Timeout in +graphicsmagick_coder_RLA_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/fits.c (ReadFITSImage): Validate that file size is +sufficient for claimed image properties. Fixes oss-fuzz issue +6429 "graphicsmagick/coder_FITS_fuzzer: Timeout in +graphicsmagick_coder_FITS_fuzzer". (Credit to OSS-Fuzz)
  • +
  • magick/image.c (CloneImage): Check image pixel limits in +CloneImage() when it is used to change the image dimensions. This +avoids depending on the using code to detect and report such +issues.
  • +
  • coders/xcf.c (ReadXCFImage): Check image pixel limits after each +CloneImage() to assure that image is within specified resource +limits. Fixes oss-fuzz issue 6399 "graphicsmagick/enhance_fuzzer: +Timeout in graphicsmagick_enhance_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-02-16 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (TracePath): TracePath() was not +correctly processing multiple sets of cubic or quadratic +Bezier coordinates when the previous path data command was +not a cubic or quadratic Bezier command. This would result +in the first control point being equal to the current path +point instead of being computed using the current path +point and the second control point of the previous Bezier +command.
  • +
+
+

2018-02-15 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (TracePath): TracePath() was not +consuming commas (if present) at the end of a set of +points when multiple sets of points were specified for +various path commands (e.g., line, Bezier). This +resulted in the remaining sets of points being ignored +(fixed).
  • +
+
+

2018-02-15 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (TraceArcPath): No points are generated +by TraceArcPath() if the starting and ending arc points +are the same. For this case, the coordinate count was not +being set to zero before returning (fixed).
  • +
+
+

2018-02-15 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (DrawImage): Clipping of polygons in +DrawImage() would sometime result in a starting pixel +location that was greater than the ending pixel location, +causing a subsequent call to GetImagePixelsEx() to fail +due a column count <= 0. Modified the clipping code to +eliminate this condition, and also to return early if +the polygon lies completely outside the image boundaries. +Also fixed variable declarations from a previous commit +that were causing problems for the C89 compiler.
  • +
+
+

2018-02-13 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/topol.c (ReadTOPOLImage): Detect EOF immediately rather +than spinning. Fixes oss-fuzz issue 6303 +"graphicsmagick/coder_TOPOL_fuzzer: Timeout in +graphicsmagick_coder_TOPOL_fuzzer". (Credit to OSS-Fuzz)
  • +
  • coders/dcm.c (DCM_SetupRescaleMap): Avoid excessive left shift. +Fixes oss-fuzz issue 6256 "graphicsmagick/coder_DCM_fuzzer: +Undefined-shift in DCM_SetupRescaleMap". (Credit to OSS-Fuzz)
  • +
+
+

2018-02-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/wpg.c (ExtractPostscript): Detect EOF on input while +transferring bytes to Postscript file. Fixes oss-fuzz issue 6087 +"graphicsmagick/coder_WPG_fuzzer: NULL". Later identified to be +CVE-2017-17682 as previously discovered in ImageMagick. (Credit to +OSS-Fuzz)
  • +
  • coders/pdb.c (ReadPDBImage): Quit attempting to read image data +immediately at EOF. Fixes oss-fuzz issue 6252 +"graphicsmagick/coder_PDB_fuzzer: Timeout in +graphicsmagick_coder_PDB_fuzzer". (Credit to OSS-Fuzz)
  • +
+
+

2018-02-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/topol.c (ReadTOPOLImage): Avoid index out of bounds when +input filename does not use a file extension. Fixes oss-fuzz issue +6237 "graphicsmagick/coder_TOPOL_fuzzer: Index-out-of-bounds in +ReadTOPOLImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-02-12 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (DrawImage): Object/group opacity, +when set in DrawImage(), would overwrite the fill +and stroke opacities. This has been fixed so that +the object opacity is now combined with the fill +and stroke opacities per the SVG spec.
  • +
+
+

2018-02-12 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/mat.c Fix oss-fuzz issue 6021. (Credit to OSS-Fuzz)
  • +
+
+

2018-02-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dcm.c (ReadDCMImage): Avoid undefined left shift of +short. Fix memory leaks in error reporting paths. Fixes oss-fuzz +issue 6217 "graphicsmagick/coder_DCM_fuzzer: Undefined-shift in +ReadDCMImage". (Credit to OSS-Fuzz)
  • +
  • coders/dpx.c (ReadDPXImage): Avoid divide by zero exception in +the case where reference high equals reference low. Fixes oss-fuzz +issue 6215 "graphicsmagick/coder_DPX_fuzzer: Divide-by-zero in +ReadDPXImage". (Credit to OSS-Fuzz)
  • +
  • coders/topol.c (ReadTOPOLImage): Avoid index out of bounds when +input filename does not use a file extension.
  • +
  • coders/cut.c (ReadCUTImage): Avoid index out of bounds when +input filename does not use a file extension. Fixes oss-fuzz issue +6218 "graphicsmagick/coder_CUT_fuzzer: Index-out-of-bounds in +ReadCUTImage". (Credit to OSS-Fuzz)
  • +
  • coders/pwp.c (ReadPWPImage): Force temporary file to be read as +a SFW file rather than autodetecting the format. Fixes oss-fuzz +issue 6220 "graphicsmagick/coder_PWP_fuzzer: Indirect-leak in +AllocateImage". (Credit to OSS-Fuzz)
  • +
+
+

2018-02-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pdf.c (WritePDFImage): Assure that xref memory is not +leaked if an exception is thrown. Fixes oss-fuzz issue 5968 +"graphicsmagick/coder_EPDF_fuzzer: Direct-leak in MagickRealloc". +(Credit to OSS-Fuzz)
  • +
  • coders/tim.c (ReadTIMImage): Verify that 4/8 bit PSX TIM +provides a CLUT and verify indexes. Fixes oss-fuzz issue 5972 +"graphicsmagick/coder_TIM_fuzzer: Null-dereference WRITE in +ReadTIMImage". (Credit to OSS-Fuzz)
  • +
  • coders/topol.c (ReadTOPOLImage): Add additional header +validations. Fixes oss-fuzz issue 5975 +"graphicsmagick/coder_TOPOL_fuzzer: Floating-point-exception in +ReadTOPOLImage". (Credit to OSS-Fuzz)
  • +
  • coders/bmp.c (ReadBMPImage): Avoid possible division by zero +when decoding CIE primary values. (Credit to OSS-Fuzz)
  • +
  • magick/export.c (ExportViewPixelArea): Only compute +unsigned_maxvalue if sample_bits <= 32.
  • +
  • magick/import.c (ImportViewPixelArea): Assure that +double_maxvalue minus double_minvalue is not zero, or excessively +close to zero to avoid divide by zero exception or impossible +scaling factor. (Credit to OSS-Fuzz) +(ImportViewPixelArea): Only compute unsigned_maxvalue if +sample_bits <= 32.
  • +
+
+

2018-02-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dib.c (ReadDIBImage): Validate that image width is not +too negative such that it's absolute value can not fit in 32-bit +unsigned width. Resolves oss-fuzz issue 6179 +"graphicsmagick/coder_ICO_fuzzer: Integer-overflow in +ReadDIBImage". (Credit to OSS-Fuzz)
  • +
  • coders/dcm.c (funcDCM_BitsStored): Validate DICOM datum size. +Use a different means to determine the maximum value which does +not use excessive shifting. Resolves oss-fuzz issue 6165 +"graphicsmagick/coder_DCM_fuzzer: Undefined-shift in +funcDCM_BitsStored". (Credit to OSS-Fuzz)
  • +
+
+

2018-02-08 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/dpx.c (ReadWordU32BE): Add casts to avoid default type +promotion from unsigned char to 'int' leading to undefined +behavior for 24 bit shift. Fixes oss-fuzz issue 6058 +"graphicsmagick/coder_DPX_fuzzer: Undefined-shift in +ReadWordU32BE". (Credit to OSS-Fuzz) +(ReadDPXImage): Require that the file has at least one element. +Add bountiful casts for values which are left-shifted. Fixes +oss-fuzz issue 5962 "graphicsmagick/coder_DPX_fuzzer: +Undefined-shift in ReadDPXImage". (Credit to OSS-Fuzz)
  • +
  • coders/dcm.c (DCM_ReadOffsetTable): Add casts Add casts to avoid +default type promotion from unsigned char to 'int' leading to +undefined behavior for 16 bit shift. Fixes oss-fuzz issue 5980 +"graphicsmagick/coder_DCM_fuzzer: Undefined-shift in +DCM_ReadOffsetTable". (Credit to OSS-Fuzz)
  • +
  • magick/module_aliases.h (ModuleAliases): Add missing mapping +from "ICODIB" format to "DIB" module.
  • +
  • magick/import.c (ImportUInt32Quantum): Add casts to avoid +default type promotion from unsigned char to 'int' leading to +undefined behavior for 24 bit shift. Fixes oss-fuzz +"graphicsmagick/coder_P7_fuzzer: Undefined-shift in +ImportRGBQuantumType". (Credit to OSS-Fuzz)
  • +
+
+

2018-02-07 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • coders/wpg.c Fix oss-fuzz issue 5964 +"graphicsmagick/coder_MAT_fuzzer: Heap-use-after-free in +GetLocaleExceptionMessage". (Credit to OSS-Fuzz)
  • +
+
+

2018-02-07 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/render.c (IsPoint): Fixed a bug in which +IsPoint() would reject as a valid coordinate value +strings that did not begin with an integer: e.g., +"0.25" would be accepted, but ".25" would not.
  • +
+
+

2018-02-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/cut.c (ReadCUTImage): Fix DestroyImageInfo() of NULL +pointer leading to assertion. Fixes oss-fuzz issue 6067 +"graphicsmagick/coder_CUT_fuzzer: Unknown signal in +DestroyImageInfo".
  • +
  • coders/tga.c (ReadTGAImage): Throw exception rather than +assertion for unexpected comment size. Fixes oss-fuzz issue 5961 +"graphicsmagick/coder_ICB_fuzzer: ASSERT: (size_t) +(tga_info.id_length+1) == commentsize".
  • +
+
+

2018-02-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pdf.c (WritePDFImage): Free 'xref' allocation before +error return. Fixes oss-fuzz issue 5968 +"graphicsmagick/coder_EPDF_fuzzer: Direct-leak in MagickRealloc".
  • +
+
+

2018-02-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/pdb.c (ReadPDBImage): Fix heap buffer overflow if blob is +already at EOF when comment is read. Fixes oss-fuzz issue 5997 +"graphicsmagick/coder_PDB_fuzzer: Heap-buffer-overflow in +SetImageAttribute".
  • +
  • coders/dpx.c (ReadDPXImage): Fix memory leak of user data if +user data is truncated. Fix consumption of one uninitialized +stack bytes. Fixes oss-fuzz issue 5973: +graphicsmagick/enhance_fuzzer: Direct-leak in ReadDPXImage.
  • +
  • coders/pnm.c (ReadPNMImage): Detect and avoid division by zero. +Fixes Issue 5959 in oss-fuzz: graphicsmagick/coder_P7_fuzzer: +Divide-by-zero in ReadPNMImage
  • +
  • magick/xwindow.c (MagickXClientMessage): Eliminate valgrind +gripe about use of uninitialized stack data by clearing allocation +to zero. +(MagickXMakeImage): Eliminate valgrind gripe about use of +uninitialized heap data by clearing allocation to zero.
  • +
  • coders/pwp.c (ReadPWPImage): Remove bogus EOF test on an image +with a closed blob. Fixes Issue 5957 in oss-fuzz: +graphicsmagick/coder_PWP_fuzzer: ASSERT: image->blob->type != +UndefinedStream.
  • +
  • www/Changes.rst: Fix typo with spelling "ChangeLog-2017.html". +Resolves SourceForge issue #544 "dead link 2017 changelog page on +GraphicsMagick web site".
  • +
+
+

2018-02-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/static.c (OpenModule): Assure that status is initialized. +Resolves Coverity 261207 "Uninitialized scalar variable".
  • +
  • wand/magick_wand.c (MagickHasColormap): New function to test if +the image has a colormap. +(MagickIsGrayImage): New function to test if the image uses only +gray pixels. +(MagickIsMonochromeImage): New function to test if the image uses +only monochrome pixels. +(MagickIsOpaqueImage): New function to test if the image uses only +opaque pixels. +(MagickIsPaletteImage): New function to test if the image is based +on a color palette. Above functions are written by Troy Patteson +and submitted via SourceForge patch #54 "Wand API patches: has +colormap, is gray image, is monochrome image, is opaque image, is +palette image".
  • +
  • fuzzing: Added initial OSS-Fuzz integration by Alex Gaynor. +From SourceForge patch #55 "OSS-Fuzz integration"
  • +
  • coders/png.c (ReadMNGImage): Fix free using possibly unallocated +pointer value.
  • +
  • magick/blob.c (SeekBlob): Remove implicit extension of blob +allocation size based on seek offset. Besides making an +assumption about how the blob memory was allocated, this +reallocation feature provides a memory DOS opportunity. Resolves +issue reported by Alex Gaynor via email entitled "Security issue +with memory management in Magick++" to the graphicsmagick-security +list on 31 Jan 2018. +(SeekBlob):
  • +
  • coders/jpeg.c (ReadIPTCProfile): Revert inadvertent wrong return +codes added by change on December 9, 2017. Fixes SourceForge bug +542 "Improper call to JPEG library in state 201" since 1.3.28.
  • +
+
+

2018-02-01 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/annotate.c (RenderFreetype): Fixed the text +opacity computation in RenderFreeType(). This bug caused +the text fill color to bleed into the character cell when +the SVG "fill-opacity" is less than 1.0.
  • +
+
+

2018-02-01 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • magick/attribute.c (CloneImageAttributes): Fixed a bug +in which the source image attributes would always replace +the destination image attributes instead of being appended +to them, and the destination image attributes would become +a memory leak.
  • +
+
+

2018-01-31 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement): Fixed a bug in which the +x,y location values for a <text> or <tspan> were overwritten +by the x,y values for the next <tspan> before the previous +values were used. This caused the text associated with the +previous <text> or <tspan> to appear at the location +specified for the next <tspan>.
  • +
+
+

2018-01-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/static.c: Use !defined(SupportMagickModules) to enable +static module loader. Fixes SourceForge bug #543 "Multiple +definition of "OpenModule" (etc) when cross-compiling shared".
  • +
+
+

2018-01-29 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement): A terminating '>' in +a geometry string is interpreted to mean that the dimensions +of an image should only be changed if its width or height +exceeds the geometry specification. For an unapparent and +undocumented reason, a terminating '>', if present, was +being nulled out, making this feature unusable for SVG files +(now fixed).
  • +
+
+

2018-01-29 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (ReadSVGImage): If there is a geometry string +in image_info->size (e.g., gm convert -size "50x50%" in.svg +out.png), AllocateImage() sets image->columns and image->rows +to the width and height values from the size string. However, +this makes no sense if the size string was something like +"50x50%" (we'll get columns = rows = 50). So we set columns +and rows to 0 after AllocateImage(), which is the same as if +no size string was supplied by the client. This also results +in svg_info.bounds to be set to 0,0 (i.e., unknown), so that +svg_info.bounds will later be set using the image size +information from either the svg "canvas" width/height or from +the viewbox. Later, variable "page" is set from +svg_info->bounds. Then the geometry string in image_info->size +gets applied to the (now known) "page" width and height when +SvgStartElement() calls GetMagickGeometry(), and the intended +result is obtained.
  • +
+
+

2018-01-24 Greg Wolfe <gregory.wolfe@kodakalaris.com>

+
+
    +
  • coders/svg.c (SVGStartElement): When the density (DPI) +is specified using the ImageInfo::density member, the derived +scale factor is incorrectly applied a second time to the +width and height members of variable RectangleInfo page. +Fixes SourceForge ticket #451.
  • +
+
+

2018-01-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/static.c: Use a lazy-loader for static modules with the +same external interface as the lazy-loader for dynamic modules.
  • +
+
+

2018-01-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • NEWS.txt: Prepare for 1.3.28 release.
  • +
+
+

2018-01-17 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • NEWS.txt: Update with changes since previous release.
  • +
+
+

2018-01-14 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • PerlMagick/Magick.xs: Compiler warnings reduction.
  • +
  • magick/pixel_cache.h: Mark GetPixels(), GetIndexes(), and +GetOnePixel() as deprecated. Compilers may produce a warning if +these functions are used.
  • +
  • magick/pixel_cache.c (InterpolateColor): Return black pixel if +InterpolateViewColor() reports failure.
  • +
  • coders/png.c (ReadMNGImage): Fix memory leak of chunk and +mng_info in error path.
  • +
  • coders/gif.c (ReadGIFImage): Fix memory leak of global colormap.
  • +
+
+

2018-01-13 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/symbols.h: Fix SourceForge issue #538 "13 symbols in +common with ImageMagick despite --enable-symbol-prefix".
  • +
  • coders/bmp.c (ReadBMPImage): Fix non-terminal loop due to +unexpected bit-field mask value. Fixes SourceForge issue #541 +"Infinite Loop in ReadBMPImage (coders/bmp.c)".
  • +
  • coders/jpeg.c (JPEGMessageHandler): Revert code added on +2017-07-08 to promote certain warnings from libjpeg to errors. +Add code to rationalize claimed image dimensions based on file +size. Resolves SourceForge issue #539 "Images with libjpeg +warnings result in error".
  • +
+
+

2018-01-11 Fojtik Jaroslav <JaFojtik@seznam.cz>

+
+
    +
  • +
    coders/wpg.c Recursive ReadImage could return multiple scenes
    +
    fixed.
    +
    +
  • +
+
+

2018-01-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • coders/png.c (ReadOnePNGImage): Quit 'passes' loop if we +encountered an error
  • +
  • magick/pixel_cache.c (SetNexus): Fix heap overwrite in +AcquireCacheNexus() due to SetNexus() not using an allocated +staging area for the pixels like it should. This problem impacts +all 1.3.X releases. Resolves SourceForge issues 532 +"heap-buffer-overflow bug in ReadWPGImage" and #531 +"heap-buffer-overflow in AcquireCacheNexus".
  • +
  • magick/pixel_cache.c (InterpolateViewColor): Now returns +MagickPassFail rather than void. Code using this function is +updated to check the return status.
  • +
+
+

2018-01-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/describe.c (DescribeImage): Discriminate between +AcquireImagePixels() returning NULL or finding a transparent +pixel. This avoids use of a null pointer in the case where +AcquireImagePixels() returns NULL.
  • +
+
+

2017-12-31 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

+
+
    +
  • magick/static.c: Change static module initialization to be based +on an initialized list rather than a squence of function calls in +order to simplify maintenance and possibly address future +requirements.
  • +
+
+

2017-12-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>

  • Copyright.txt: Bump copyright years and rotate ChangeLog.
  • diff --git a/www/Changelog.rst b/www/Changelog.rst index 50e2029..6eb13e0 100644 --- a/www/Changelog.rst +++ b/www/Changelog.rst @@ -1,252 +1,2612 @@ -2017-07-04 Bob Friesenhahn +2018-11-17 Bob Friesenhahn - - NEWS.txt: Make sure is up to date. + - www/index.rst: Update in preparation for 1.3.31 release. - - www/index.rst: Update for 1.3.26 release. + - version.sh: Update library versioning in preparation for + 1.3.31 release. - - version.sh: Update library versioning for 1.3.26 release. + - NEWS.txt: Update news in preparation for 1.3.31 release. - - magick/command.c (BatchCommand): Add ferror() checks around - batch input loop. +2018-11-15 Bob Friesenhahn -2017-07-03 Glenn Randers-Pehrson + - magick/command.c (BenchmarkUsage): Document the benchmark + command better. - - coders/png.c: Reject a PNG file if the file size is too small - (less than 61 bytes). Reject a JNG file if it is too small (less - than 147 bytes). - - coders/jpeg.c: Reject a JPEG file if the file size is too small - (less than 107 bytes). +2018-11-14 Bob Friesenhahn -2017-07-02 Bob Friesenhahn + - magick/resize.c (HorizontalFilter, VerticalFilter): quantum is a + pointer so it's value can not be usefully flushed. Use a local + variable and then update quantum pointer when done. - - coders/dpx.c (ReadDPXImage): Compute required file size and - verify that sufficient data exists in file before allocating - memory to decode the image data. Resolves problem with DPX file - with valid header (but a huge claimed image width) provided - provided via email on Thu, 29 Jun 2017 by LCatro. This issue has - been assigned CVE-2017-10799. +2018-11-11 Bob Friesenhahn -2016-07-02 Fojtik Jaroslav + - magick/\*: Changed row\_count tallying to use 'omp atomic' and + status update to use 'omp flush' for progress and error + indication. This replaces most use of 'omp critical' for this + purpose. Changed some lumpy algorithms which were using 'static' + scheduling to 'guided' scheduling due to observing better results. + Also added prolific 'restrict' annotations where they were + missing. - - coders/mat.c Check whether reported object size overflows file size. + - www/security.rst: Documented a PGP private key for file signing + or private correspondence. -2016-07-01 Fojtik Jaroslav +2018-11-10 Bob Friesenhahn - - coders/mat.c Safety check for forged and or corrupted data. - This issue has been assigned CVE-2017-10800. + - www/authors.rst: Moved "Glenn Randers-Pehrson" and "Gregory J + Wolfe" to the "Former Contributor" category. -2017-07-01 Bob Friesenhahn +2018-11-09 Bob Friesenhahn - - coders/tiff.c ("QuantumTransferMode"): Use a generalized method - to enforce that buffer overflow can not happen while importing - pixels. Resolves problem with RGB TIFF claiming only one sample - per pixel provided via email on Thu, 29 Jun 2017 by LCatro. This - issue has been assigned CVE-2017-10794. + - Added many GCC function annotations in the libraries and coders. -2017-06-29 Bob Friesenhahn +2018-11-07 Bob Friesenhahn - - magick/command.c: Convert bare 'unsigned int' to MagickPassFail - where suitable to make intentions clear. Convert True/False to - MagickTrue/MagickFalse or MagickPass/MagickFail according to - purpose. This is a continuation of a gradual migration and does - not represent an API change. + - configure.ac: Use printf rather than echo to portably expand tab + requests in configuration summary. -2017-06-25 Glenn Randers-Pehrson +2018-11-01 Bob Friesenhahn - - coders/png.c: Avoid NULL dereference when MAGN chunk processing - fails (https://sourceforge.net/p/graphicsmagick/bugs/426/). Expand - TABs. + - configure.ac: Use pkg-config data as the initial choice when + configuring for FreeType 2.0 and libxml-2.0. Only fall back to + invoking an external script (and then traditional methods) if + pkg-config fails. -2017-06-25 Bob Friesenhahn + - coders/msl.c (ProcessMSLScript): Release msl\_image if OpenBlob + fails. Similar to ImageMagick CVE-2018-18544. Problem was + reported to us via email from Petr Gajdos on Thu, 1 Nov 2018. - - NEWS.txt: Update NEWS with changes since the previous release. +2018-10-27 Bob Friesenhahn - - www/programming.rst: Switch the Lua link to - https://github.com/arcapos/luagraphicsmagick, which is a more - complete and direct interface from Lua to GraphicsMagick's Wand - API. + - coders/miff.c (WriteMIFFImage): Only run + strlen(attribute->value) once per attribute since the length won't + change. May address oss-fuzz 11158 + "graphicsmagick/coder\_MIFF\_fuzzer: Timeout in + graphicsmagick\_coder\_MIFF\_fuzzer". (Credit to OSS-Fuzz) -2017-06-24 Bob Friesenhahn + - Fix compilation warnings observed with GCC 8.2.0. - - VisualMagick/installer/gm-foo-dll.iss: Remove PerlMagick from - the slim Inno Setup installer builder and remove mention of - PerlMagick from the installer documentation. +2018-10-26 Bob Friesenhahn - - TclMagick/generic/TclMagick.c (magickCmd): Resolve SourceForge - patch #51 "TclMagick: memory access error; possible segfault". - (newMagickObj): Fix formatting of pointer value so it is 64-bit - safe. Resolves SourceForge patch #50 "TclMagick: 64-bit - portability issue". + - magick/pixel\_iterator.c (PixelIterateMonoModifyImplementation): + Use atomic and flush rather than critical construct for a small + speedup. - - coders/pict.c (ReadPICTImage): Avoid possible use of negative - value when indexing array, which would cause buffer overflow. - Resolves SourceForge issue #427 "One possible buffer overflow - vulnerability in - GraphicsMagick-1.3.25/coders/pict.c:ReadPICTImage()". + - magick/monitor.c (MagickMonitorFormatted): Serialize calls to + the progress monitor so that the caller does not need to perform + this serialization. + (MagickMonitor): Serialize calls to the progress monitor so that + the caller does not need to perform this serialization. This + function is now marked as deprecated. + (InitializeMagickMonitor): New private function to initialize + monitor functionality. + (DestroyMagickMonitor): New private function to destroy monitor + functionality. -2017-06-22 Glenn Randers-Pehrson +2018-10-23 Bob Friesenhahn - - coders/png.c: Stop memory leak when reading invalid JNG image. - Fixes CVE-2017-8350. + - coders/gif.c (ReadGIFImage): Improve the efficiency of storing a + GIF comment in order to avoid a DOS opportunity. Fixes oss-fuzz + 11096 "graphicsmagick/coder\_GIF\_fuzzer: Timeout in + graphicsmagick\_coder\_GIF\_fuzzer". (Credit to OSS-Fuzz) -2017-06-18 Bob Friesenhahn +2018-10-21 Bob Friesenhahn - - coders/png.c: Fix lcms2.h inclusion logic. + - PerlMagick/Makefile.PL.in: Use MAGICK\_API\_LIBS to obtain the + list of libraries to use when linking. - - wand/magick\_wand.c (MagickSetImageOrientation): Eliminate use of - snprintf, which is not supported by older Visual Studio. + - configure.ac: OpenMP library is normally supplied due to a + CFLAGS option so only supply it in cases where the CFLAGS option + may be lost or it might not be used. Otherwise the compiler may + apply the library twice when linking. -2017-06-09 Glenn Randers-Pehrson +2018-10-20 Bob Friesenhahn - - coders/png.c: Accept exIf chunks whose data segment - erroneously begins with "Exif\0\0". + - configure.ac: Remove Ghostscript library support (--with-gslib) + from configure script. The 'HasGS' pre-processor defines which + were enabled by this remain in the source code so it is still + possible to use this library if absolutely necessary + (e.g. CPPFLAGS=-DHasGS LIBS=-lgs). -2017-06-01 Glenn Randers-Pehrson + - tests/rwfile.tap: Test TIFF format with all supported + compression options. - - coders/png.c: Removed experimental zxIF chunk support. That - proposal is dead. + - tests/{rwblob.c, rwfile.c} (main): Use StringToCompressionType() + to parse compression option. Also consider requested compression + algorithm when deciding if format is lossy. -2017-05-27 Bob Friesenhahn + - coders/tiff.c (WriteTIFFImage): WebP compression needs + PHOTOMETRIC\_RGB. Fix wrong rows-per-strip calculation when using + LZMA compression. - - config/log.mgk: Added documentation suggested by SourceForge - issue #419 "Consider a small patch to log.mgk". + - tests/rwblob.tap: Added a rwblob test to verify that lower-case + magick works. - - www/Changes.rst: Add missing link to most recent changes. + - magick/static.c (OpenModule): Upper case magick string before + searching static modules list. Fixes Debian bug 911386 + "libgraphicsmagick-q16-3: graphicsmagick 1.3.30 has made formats + case-sensitive at the API level". -2017-05-24 Bob Friesenhahn + - filters/analyze.c (AnalyzeImage): X and y should be unsigned + long to match image rows/columns type. Calculate total pixels by + simple multiplication rather than counting. - - www/Magick++/Image.rst: Improve documentation for Magick++ - Image::iccColorProfile() and Image::renderingIntent(). +2018-10-14 Bob Friesenhahn -2017-05-21 Bob Friesenhahn + - coders/tiff.c (WriteTIFFImage): Support WebP compression in + TIFF. This requires a libtiff release after 4.0.9. - - tiff: Update to libtiff 4.0.8. + - magick/image.h ("C"): WebPCompression added to CompressionType + enumeration. -2017-03-19 Glenn Randers-Pehrson +2018-10-13 Bob Friesenhahn - - coders/png.c: Quieted a new Coverity complaint about a potential - text buffer overrun. + - configure.ac: Configure for the Zstd library. Use + --without-zstd to disable searching for this library. Libtiff may + require this library to successfully link so static linkage could + fail if searching for libzstd is disabled. -2017-03-19 Bob Friesenhahn + - magick/image.h ("C"): ZSTDCompression added to CompressionType + enumeration. - - magick/image.c (SetImageInfo): Ignore empty magic prefix - specification and do not remove colon character from start of - filename. Resolves SourceForge bug #415 "Inconsistent Behavior w/ - input\_file Parameter". + - coders/tiff.c (WriteTIFFImage): Support Zstd compression in + TIFF. This requires a libtiff release after 4.0.9. -2017-03-18 Glenn Randers-Pehrson +2018-10-10 Bob Friesenhahn - - coders/png.c: Added new private orNT PNG chunk, to - preserve image->orientation when it is defined and not - the default TopLeft. - - coders/jpeg.c: Mention image->orientation in the log when - writing a JPEG. + - magick/command.c (GMCommandSingle): Add 'compare' to the list of + command names that gm will support as a command if copied to or + linked from that name. There was already a 'compare' link + installed when the '--enable-magick-compat' configure option is + used, but it could not possibly function without being blessed by + this list. Related to Debian bug #910652 + "graphicsmagick-imagemagick-compat: Doesn't ship a compare tool". -2017-03-15 Glenn Randers-Pehrson +2018-09-30 Bob Friesenhahn - - coders/png.c (WriteOnePNGImage): Add version info about - gm, libpng, zlib, and lcms to the PNG debug log. + - Magick++/lib/Magick++/Drawable.h: Block unused-private-field + warnings from Clang due to \_dummy members which were intentionally + included in some parent class definitions. -2017-03-04 Bob Friesenhahn + - magick/widget.c (XEditText): Fix compilation warnings about + cases which fall-through. - - magick/command.c (ImportImageCommand): Fix handling of -frame - options. Option handling was incorrect due to option checking the - frame option after it had been freed. Checking the frame dash - option before freeing the argument solves the problem. From patch - provided by Victor Ananjevsky as SourceForge patch #49 "-frame - doesn't work in gm import". + - magick/display.c (MagickXAnnotateEditImage): Fix compilation + warnings about cases which fall-through. - - Magick++/lib/Image.cpp (attribute): Added Image attribute method - which accepts a 'char \*' argument, and will remove the attribute - if the value argument is NULL. From patch provided by "Gints" as - SourceForge patch #46 "C++ api - method to clear/remove - attribute". + - coders/pict.c (WritePICTImage): Add more checks to memory + allocation calculations. - - VisualMagick/configure/configure.cpp (InitInstance): Applied - patch by Paul McConkey to allow the quantum command line argument - to set the default value in the wizard drop list. This allows - setting the quantum depth when the /nowizard argument was - supplied. Resolves SourceForge patch #48 "When running from the - command line configure.exe does not use the quantum argument". - The provided configure.exe still needs to be rebuilt to - incorporate this change. + - magick/pixel\_cache.c (DestroyCacheInfo): Eliminate intentional + fall-through logic in switch statement which results in compiler + warnings. Eliminate switch statements entirely and split + unrelated logic. - - magick/command.c (MogrifyImage): The -orient command now also - updates the orientation in the EXIF profile, if it exists. + - coders/txt.c (ReadTXTImage): Fix comparison between pointer and + '\0' rather than NULL as was obviously intended. - - Magick++/lib/Image.cpp (orientation): Update orientation in EXIF - profile, if it exists. + - coders/msl.c (MSLStartElement): Add missing 'break' statements + after ThrowException() calls. Otherwise execution falls through + into unrelated switch cases and throws a redundant exception. -2017-03-03 Bob Friesenhahn +2018-09-29 Bob Friesenhahn - - coders/jp2.c: Support PGX JPEG 2000 format for reading and - writing (within the bounds of what JasPer supports). + - coders/meta.c (parse8BIM): Eliminate repeated use of strlen() + which scans the entire remaining string on each cycle. Fixes + oss-fuzz 10667 "graphicsmagick/coder\_IPTCTEXT\_fuzzer: Timeout in + graphicsmagick\_coder\_IPTCTEXT\_fuzzer". (Credit to OSS-Fuzz) -2017-02-23 Bob Friesenhahn +2018-09-26 Bob Friesenhahn - - coders/tiff.c (QuantumTransferMode): Fix out of bounds read when - reading CMYKA TIFF which claims to have only 2 samples per pixel. - Problem was reported via email on February 15, 2017 by Valon - Chu. This issue was assigned CVE-2017-6335. + - magick/utility.c (MagickGetToken): Fix possible read up to four + bytes beyond end of stack allocated token buffer. Fixes oss-fuzz + 10653 "graphicsmagick/coder\_MVG\_fuzzer: Stack-buffer-overflow in + MagickGetToken". (Credit to OSS-Fuzz) -2017-01-29 Bob Friesenhahn +2018-09-22 Bob Friesenhahn - - doc/options.imdoc (-geometry): Geometry documentation changes - suggested by Jon Wong. + - fuzzing/coder\_fuzzer.cc (LLVMFuzzerTestOneInput): Limit the + maximum number of JPEG progressive scans to 50. -2017-01-26 Glenn Randers-Pehrson + - coders/jpeg.c (ReadJPEGImage): Apply a default limit of 100 + progressive scans before the reader quits with an error. This + limit may be adjusted using the -define mechanism like -define + JPEG:max-scan-number=500. Also respond more quickly to files + which exceed the maximum image dimensions. Fixes oss-fuzz 10258 + "graphicsmagick/coder\_JPEG\_fuzzer: Timeout in + graphicsmagick\_coder\_JPEG\_fuzzer". (Credit to OSS-Fuzz) - - coders/png.c: Added support for a proposed new PNG chunk - (zxIf, read-only) that is currently being discussed on the - png-mng-misc at lists.sourceforge.net mailing list. Enable - exIf and zxIf with CPPFLAGS="-DexIf\_SUPPORTED -DxzIf\_SUPPORTED". - If exIf is enabled, only the uncompressed exIF chunk will be - written and the hex-encoded zTXt chunk containing the raw Exif - profile won't be written. +2018-09-20 Bob Friesenhahn -2017-01-25 Bob Friesenhahn + - coders/png.c (ReadMNGImage): mng\_LOOP chunk must be at least 5 + bytes long. Fixes oss-fuzz 10455 + "graphicsmagick/coder\_MNG\_fuzzer: Use-of-uninitialized-value in + ReadMNGImage". (Credit to OSS-Fuzz) - - coders/msl.c (MSLStartElement): Change test for NULL image - pointer to before it is used rather than after it is used. - Problem reported by Petr Gajdos on 2017-01-25. +2018-09-15 Bob Friesenhahn -2017-01-22 Bob Friesenhahn + - magick/render.c (TraceEllipse): Detect arithmetic overflow when + computing the number of points to allocate for an ellipse. Fixes + oss-fuzz 10306 "graphicsmagick/coder\_MVG\_fuzzer: + Heap-buffer-overflow in TracePoint". (Credit to OSS-Fuzz) - - TclMagick/unix/m4/tcl.m4: Update tcl.m4 to TEA 3.10. File - supplied by Massimo Manghi. +2018-09-12 Bob Friesenhahn -2017-01-21 Glenn Randers-Pehrson + - magick/attribute.c (GenerateEXIFAttribute): Eliminate undefined + shift. Also right-sized involved data types. Fixes oss-fuzz + 10309 "graphicsmagick/coder\_JPG\_fuzzer: Undefined-shift in + Read32s". (Credit to OSS-Fuzz) - - coders/png.c: Added support for a proposed new PNG - chunk (exIf read-write, eXIf read-only) that is currently - being discussed on the png-mng-misc at lists.sourceforge.net - mailing list. +2018-09-09 Bob Friesenhahn -2017-01-21 Glenn Randers-Pehrson + - magick/render.c (DrawClipPath): Fix Coverity 319663 "Null + pointer dereferences". Totally insignificant. - - coders/png.c: Added read\_user\_chunk\_callback() function - and used it to implement a private PNG caNv (canvas) chunk - for remembering the original dimensions and offsets when an - image is cropped. Previously we used the oFFs chunk for this - purpose, but this had potential conflicts with other applications - that also use the oFFs chunk. + - coders/wpg.c (ReadWPGImage): Mask/fix Coverity 319664 "Error + handling issues". -2017-01-07 Bob Friesenhahn + - magick/attribute.c (FindEXIFAttribute): Change size types from + signed to unsigned and check for unsigned overflow. + (GenerateEXIFAttribute): Change size types from signed to unsigned + and check for unsigned overflow. Fixes oss-fuzz 10283 + "graphicsmagick/coder\_JPG\_fuzzer: Integer-overflow in + GenerateEXIFAttribute". (Credit to OSS-Fuzz) - - TclMagick/Makefile.am (AM\_DISTCHECK\_CONFIGURE\_FLAGS): Applied - patch by Massimo Manghi to set AM\_DISTCHECK\_CONFIGURE\_FLAGS so - that 'make distcheck' remembers configuration options, and also to - uninstall pkgIndex.tcl. + - coders/sfw.c (ReadSFWImage): Enforce that file is read using the + JPEG reader. (Credit to OSS-Fuzz) - - magick/image.c (SetImageEx): Use PixelIterateMonoSet() for - possibly improved efficiency. + - coders/miff.c (ReadMIFFImage): Fix leak of 'values' buffer due + to change made yesterday. - - magick/pixel\_iterator.c (PixelIterateMonoSet): New pixel - iterator intended for use when initializing image pixels, without - regard to existing values. + - coders/mpc.c (ReadMPCImage): Fix leak of 'values' buffer due to + change made yesterday. Fixes oss-fuzz 10277 + "graphicsmagick/coder\_MPC\_fuzzer: Direct-leak in + ReadMPCImage". (Credit to OSS-Fuzz) -2017-01-01 Bob Friesenhahn +2018-09-08 Bob Friesenhahn - - Copyright.txt: Bump copyright years and rotate ChangeLog. + - coders/miff.c (ReadMIFFImage): Support legacy keyword + 'color-profile' for ICC color profile as was used by ImageMagick + 4.2.9. + + - coders/mpc.c (ReadMPCImage): Require that first keyword/value be + id=MagickCache + + - coders/miff.c (ReadMIFFImage): Require that first keyword/value + be id=ImageMagick. + +2018-09-06 Bob Friesenhahn + + - coders/dcm.c (DCM\_ReadElement): Add more size checks. + + - coders/jnx.c (ExtractTileJPG): Enforce that JPEG tiles are read + by the JPEG coder. Fixes oss-fuzz 10147 + "graphicsmagick/coder\_JNX\_fuzzer: Use-of-uninitialized-value in + funcDCM\_PhotometricInterpretation". (Credit to OSS-Fuzz) + +2018-09-10 Fojtik Jaroslav + + - coders/wpg.c Zero fill raster error recovery. + +2018-08-29 Bob Friesenhahn + + - magick/render.c (ConvertPrimitiveToPath): Second attempt to + prevent heap write overflow of PathInfo array. Fixes oss-fuzz + 10096 "Heap-buffer-overflow in ConvertPrimitiveToPath". (Credit to + OSS-Fuzz) + +2018-08-25 Bob Friesenhahn + + - coders/tiff.c ("QuantumTransferMode"): CIE Log images with an + alpha channel are not supported. Fixes oss-fuzz 10013 + "graphicsmagick/coder\_TIFF\_fuzzer: Use-of-uninitialized-value in + DisassociateAlphaRegion". (Credit to OSS-Fuzz) + + - magick/render.c (DrawImage): SetImageAttribute() appends new + text to any existing value, leading to every increasing memory + consumption if the existing value is not deleted first by the + unwary. Fixes oss-fuzz 9983 "graphicsmagick/coder\_MVG\_fuzzer: + Timeout in graphicsmagick\_coder\_MVG\_fuzzer" and oss-fuzz 10016 + "graphicsmagick/coder\_MVG\_fuzzer: Out-of-memory in + graphicsmagick\_coder\_MVG\_fuzzer". (Credit to OSS-Fuzz) + + - magick/utility.c (TranslateTextEx): Fix off-by-one in loop + bounds check which allowed a one-byte stack write overflow. Fixes + oss-fuzz 10055 "graphicsmagick/coder\_MVG\_fuzzer: + Stack-buffer-overflow in TranslateTextEx". (Credit to OSS-Fuzz) + + - magick/render.c (DrawImage): Be more precise about error + detection and reporting, and return from an error more quickly. + Also added MAX\_DRAWIMAGE\_RECURSION pre-processor definition to + allow adjusting the drawing recursion limit. The drawing + recursion limit is still 100, which seems exceptionally generous. + + - magick/constitute.c (WriteImage): Produce a more useful error + message if an encoding delegate is not available. + + - magick/nt\_base.h (isnan): Try adding a MSVC replacement for + missing isnan() function. Not yet tested. + +2018-08-25 Fojtik Jaroslav + + - coders/wpg.c This should fix intentional 64 bit file offset + overflow as depictedin OSS-fuzz-9936. Thanks to OSS-Fuzz. + +2018-08-22 Bob Friesenhahn + + - magick/render.c (ConvertPrimitiveToPath): Need to enlarge + PathInfo array allocation to avoid possible heap write overflow. + Fixes oss-fuzz 9651 "graphicsmagick/coder\_MVG\_fuzzer: + Heap-buffer-overflow in ConvertPrimitiveToPath". (Credit to + OSS-Fuzz) + +2018-08-20 Bob Friesenhahn + + - coders/mpc.c (ReadMPCImage): Insist that the format be + identified prior to any comment, and that there is only one + comment. + + - coders/miff.c (ReadMIFFImage): Insist that the format be + identified prior to any comment, and that there is only one + comment. Fixes oss-fuzz 9979 "graphicsmagick/coder\_MIFF\_fuzzer: + Timeout in graphicsmagick\_coder\_MIFF\_fuzzer". This is not a + serious issue, but the code runs slowly under UBSAN. (Credit to + OSS-Fuzz) + +2018-08-19 Bob Friesenhahn + + - magick/utility.c (MagickAtoFChk): Add additional validation + checks for floating point values. NAN and +/- INFINITY values + also map to 0.0. Fixes oss-fuzz 9630 + "graphicsmagick/coder\_MVG\_fuzzer: Integer-overflow in + IsNexusInCore" and oss-fuzz 9612 "graphicsmagick/coder\_MVG\_fuzzer: + Integer-overflow in SetCacheNexus". (Credit to OSS-Fuzz) + + - magick/render.c (DrawImage): Add missing error-reporting logic + to return immediately upon memory reallocation failure. Apply + memory resource limits to PrimitiveInfo array allocation. Fixes + oss-fuzz 9576 "graphicsmagick/coder\_MVG\_fuzzer: Null-dereference + READ in DrawImage", oss-fuzz 9593 + "graphicsmagick/coder\_MVG\_fuzzer: Out-of-memory in + graphicsmagick\_coder\_MVG\_fuzzer", oss-fuzz 9648 + "graphicsmagick/coder\_MVG\_fuzzer: Unknown signal in + DrawImage". (Credit to OSS-Fuzz) + +2018-08-16 Fojtik Jaroslav + + - coder/mat.c Explicitly reject non-seekable streams. + +2018-08-15 Fojtik Jaroslav + + - coder/mat.c Correctly check GetBlobSize(image) even for zipstreams. + +2018-08-14 Fojtik Jaroslav + + - coders/mat.c More aggresive data corruption checking. + +2018-08-09 Bob Friesenhahn + + - coders/xbm.c (XBMInteger): Limit the number of hex digits parsed + to avoid signed integer overflow. Fixes oss-fuzz 9746 + "graphicsmagick/coder\_XBM\_fuzzer: Undefined-shift in + XBMInteger". (Credit to OSS-Fuzz) + +2018-08-07 Fojtik Jaroslav + + - coders/mat.c Typecast difference to quantum. + +2018-08-05 Bob Friesenhahn + + - coders/mat.c (InsertComplexFloatRow): Avoid signed + overflow. Fixes oss-fuzz 9667 "graphicsmagick/coder\_MAT\_fuzzer: + Integer-overflow in InsertComplexFloatRow". (Credit to OSS-Fuzz) + + - coders/xbm.c (ReadXBMImage): Add validations for row and column + dimensions. Fixes oss-fuzz 9736 "graphicsmagick/coder\_XBM\_fuzzer: + Out-of-memory in graphicsmagick\_coder\_XBM\_fuzzer". (Credit to + OSS-Fuzz) + +2018-08-04 Fojtik Jaroslav + + - coders/wpg.c Add mechanism to approve embedded subformats in + WPG. This should mute oss-fuzz 9559. (Credit to OSS-Fuzz) + +2018-07-24 Bob Friesenhahn + + - coders/mvg.c (ReadMVGImage): Fix memory leak added on + 2018-07-21. Fixes oss-fuzz 9548 "graphicsmagick/coder\_MVG\_fuzzer: + Direct-leak in CloneDrawInfo". (Credit to OSS-Fuzz) + +2018-07-23 Bob Friesenhahn + + - coders/cineon.c (ReadCINEONImage): Fix SourceForge issue 571 + "Unexpected hang on a crafted Cineon image" by detecting and + quitting on EOF appropriately, and verifying that file size is + sufficient for claimed pixel dimensions when possible. + + - fuzzing/oss-fuzz-build.sh, fuzzing/dictionaries/MVG.dict: Added + MVG fuzzing dictionary by Alex Gaynor. + +2018-07-22 Bob Friesenhahn + + - magick/pixel\_cache.c (SetNexus): For requests one pixel tall, + SetNexus() was wrongly using pixels in-core rather than using a + staging area for the case where the nexus rows extend beyond the + image raster boundary, leading to heap overflow. This can happen + when virtual pixels outside the image bounds are accessed. Fixes + oss-fuzz 9512 "graphicsmagick/graphicsmagick\_coder\_MVG\_fuzzer: + Heap-buffer-overflow in AcquireCacheNexus". (Credit to OSS-Fuzz) + + - magick/render.c (ExtractTokensBetweenPushPop): + ExtractTokensBetweenPushPop() needs to always return a valid + pointer into the primitive string. Fixes oss-fuzz 9511 + "graphicsmagick/graphicsmagick\_coder\_MVG\_fuzzer: Null-dereference + READ in DrawImage". (Credit to OSS-Fuzz) + (DrawPolygonPrimitive): Fix leak of polygon set when object is + completely outside image. Fixes oss-fuzz 9513 + "graphicsmagick/graphicsmagick\_coder\_MVG\_fuzzer: Direct-leak in + AllocateThreadViewDataSet". (Credit to OSS-Fuzz) + +2018-07-21 Bob Friesenhahn + + - magick/blob.c (FileToBlob): Use confirm access APIs to verify + that read access to this path is allowed by policy. Check that + file is a regular file before proceeding to open and read from it. + + - coders/mvg.c (ReadMVGImage): Don't allow MVG files to side-load + a file as the drawing primitive using '@' syntax. Fixes oss-fuzz + 9494 "graphicsmagick/coder\_MVG\_fuzzer: Sanitizer CHECK failure in + "((0)) != (0)" (0x0, 0x0)". (Credit to OSS-Fuzz) + +2018-07-19 Bob Friesenhahn + + - coders/mvg.c (ReadMVGImage): Don't assume that in-memory MVG + blob is a null-terminated C string. Fixes oss-fuzz 9469 + "graphicsmagick/coder\_MVG\_fuzzer: Heap-buffer-overflow in + AllocateString". (Credit to OSS-Fuzz) + +2018-07-12 Bob Friesenhahn + + - coders/miff.c (ReadMIFFImage): Detect EOF when reading using + ReadBlobZC() and avoid subsequent heap read overflow. Fixes + oss-fuzz 9357 "graphicsmagick/coder\_MIFF\_fuzzer: + Heap-buffer-overflow in ImportRGBQuantumType". (Credit to + OSS-Fuzz) + +2018-07-11 Bob Friesenhahn + + - fuzzing/oss-fuzz-build.sh (CFLAGS): Try disabling SIMD + instructions in libjpeg-turbo build. + +2018-07-10 Bob Friesenhahn + + - coders/png.c (WriteOnePNGImage): Free png\_pixels as soon as + possible. This might help with oss-fuzz 9334 + "graphicsmagick/coder\_PNG8\_fuzzer: Direct-leak in + WriteOnePNGImage", which we have yet to reproduce. It is not + clear if png\_pixels is being clobbered by longjmp or if something + else is going on. + +2018-06-26 Bob Friesenhahn + + - coders/jpeg.c (ReadJPEGImage): Provide a memory resource limit + (of 1/5th the memory resource limit for Graphicsmagick) to libjpeg + to limit how much memory it might consume for itself while reading + a file. Fixes oss-fuzz 9096 "graphicsmagick/coder\_JPEG\_fuzzer: + Timeout in graphicsmagick\_coder\_JPEG\_fuzzer". (Credit to + OSS-Fuzz) + (ReadJPEGImage): Make sure that JPEG pixels array is initialized + in case libjpeg fails to completely initialize it. May fix + oss-fuzz 9115 "graphicsmagick/coder\_JPEG\_fuzzer: + Use-of-uninitialized-value in ReadJPEGImage". We are not sure + since the problem was not reproduced. (Credit to OSS-Fuzz) + +2018-06-23 Bob Friesenhahn + + - version.sh: Update library versioning for 1.3.30 release. + + - NEWS.txt: Update news for 1.3.30 release. + +2018-06-22 Bob Friesenhahn + + - coders/dpx.c (ReadDPXImage): Report exception on EOF file + reading DPX pixel data. Fixes oss-fuzz 8104 + "graphicsmagick/coder\_DPX\_fuzzer: Use-of-uninitialized-value in + WriteDPXImage", oss-fuzz 8297 "graphicsmagick/enhance\_fuzzer: + Use-of-uninitialized-value in EnhanceImage", and oss-fuzz 8133 + "graphicsmagick/coder\_DPX\_fuzzer: Use-of-uninitialized-value in + RGBTransformPackets". (Credit to OSS-Fuzz) + +2018-06-20 Bob Friesenhahn + + - coders/cmyk.c (ReadCMYKImage): Free scanline buffer in error + path. Fixes SourceForge issue #567 "small memory leak in rgb.c, + gray.c and cmyk.c" reported by Petr Gajdos. + + - coders/gray.c (ReadGRAYImage): Free scanline buffer in error + path. Fixes SourceForge issue #567 "small memory leak in rgb.c, + gray.c and cmyk.c" reported by Petr Gajdos. + + - coders/rgb.c (ReadRGBImage): Free scanline buffer in error + path. Fixes SourceForge issue #567 "small memory leak in rgb.c, + gray.c and cmyk.c" reported by Petr Gajdos. + + - coders/jpeg.c (ReadJPEGImage): Avoid memory leak of profile + buffer when longjmp-based exception is thrown while reading a + profile. Fixes oss-fuzz 8957 "graphicsmagick/enhance\_fuzzer: + Direct-leak in ReadGenericProfile". (Credit to OSS-Fuzz) + +2018-06-17 Bob Friesenhahn + + - coders/xcf.c (load\_level): Make sure to free 'tile\_image' before + returning exception. Fixes oss-fuzz 8935 + "graphicsmagick/coder\_XCF\_fuzzer: Indirect-leak in + CloneImage". (Credit to OSS-Fuzz) + + - coders/jpeg.c (ReadJPEGImage): Allow three warnings of any given + type before promoting the next warning of the same type to a hard + error. The warning limit may be adjusted by the user using + -define jpeg:max-warnings=. Fixes oss-fuzz 8704 + "graphicsmagick/coder\_JPG\_fuzzer: Out-of-memory in + graphicsmagick\_coder\_JPG\_fuzzer". (Credit to OSS-Fuzz) + + - coders/png.c (ReadPNGImage): Detect EOF when reading + magic\_number. Fixes oss-fuzz 8944 + "graphicsmagick/coder\_PNG\_fuzzer: Use-of-uninitialized-value in + ReadPNGImage". (Credit to OSS-Fuzz) + (ReadPNGImage, ReadJNGImage): Makes sure that return value of + ReadBlob() is always checked to detect EOF. + +2018-06-16 Bob Friesenhahn + + - coders/tiff.c (ReadTIFFImage): Re-structure exception reporting + so that QuantumTransferMode() exceptions thrown for + PLANARCONFIG\_SEPARATE images are handled immediately. Fixes + oss-fuzz 8896 "graphicsmagick/coder\_BIGTIFF\_fuzzer: + Use-of-uninitialized-value in DisassociateAlphaRegion". (Credit to + OSS-Fuzz) + (ReadTIFFImage): tsize\_t is a signed type so be prepared for + unexpected negative values produced by libtiff size functions. + Fixes oss-fuzz 8934 "graphicsmagick/coder\_TIFF\_fuzzer: Sanitizer + CHECK failure in "((0)) != (0)" (0x0, 0x0)". (Credit to OSS-Fuzz) + +2018-06-16 Fojtik Jaroslav + + - coders/wpg.c Fix oss-fuzz 7735 "graphicsmagick/coder\_WPG\_fuzzer: + Use-of-uninitialized-value in ReadWPGImage". (Credit to OSS-Fuzz) + +2018-06-11 Bob Friesenhahn + + - coders/png.c (ReadMNGImage): ENDL chunk must be at least one + byte in size. Fixes oss-fuzz 8832 + "graphicsmagick/coder\_MNG\_fuzzer: Null-dereference READ in + ReadMNGImage". (Credit to OSS-Fuzz) + (ReadMNGImage): Length of DISC chunk must be evenly divisible by + 2. Fixes oss-fuzz 8834 "graphicsmagick/coder\_MNG\_fuzzer: + Heap-buffer-overflow in ReadMNGImage". (Credit to OSS-Fuzz) + +2018-06-10 Bob Friesenhahn + + - coders/mpc.c (ReadMPCImage): Detect end of file while reading + image directory. Similar to MIFF fixes for ImageMagick + CVE-2017-18272. + (RegisterMPCImage): Require seekable stream since MPC is strictly + a file-based format and so GetBlobSize() is assured to work. + Similar to MIFF behavior. Claimed to be part of the resolution + for ImageMagick CVE CVE-2017-11449. Suggested by Petr Gajdos via + email on January 3, 2018. + +2018-06-09 Bob Friesenhahn + + - coders/miff.c (ReadMIFFImage): Detect end of file while reading + image directory. Fixes SourceForge issue 565 "ImageMagick + CVE-2017-18272 applies to GraphicsMagick". Thanks to Petr Gajdos + for reporting this issue to us. + + - magick/import.c (ImportViewPixelArea): Use appropriate + bits\_per\_sample validations for FloatQuantumSampleType. Fixes + oss-fuzz 8780 "graphicsmagick/coder\_PTIF\_fuzzer: + Use-of-uninitialized-value in HorizontalFilter". (Credit to + OSS-Fuzz) + +2018-06-09 Fojtik Jaroslav + + - coders/mat.c More than 4GiB are not supported in MAT! + +2018-06-09 Bob Friesenhahn + + - coders/mat.c (ReadMATImage): Add casts to avoid arithmetic + overflow when computing size and offsets. Fixes oss-fuzz 8801 + "graphicsmagick/coder\_MAT\_fuzzer: Timeout in + graphicsmagick\_coder\_MAT\_fuzzer". (Credit to OSS-Fuzz) + + - magick/blob.c (ReadBlobLSBDoubles, ReadBlobMSBDoubles): Only + byte-swap doubles or test doubles for NAN if we have read enough + bytes for at least one double value. + (ReadBlob): Add an assertion to enforce that ReadBlob() will never + report reading more bytes than requested due to some + implementation issue. + +2018-06-08 Bob Friesenhahn + + - magick/blob.c (ReadBlob, WriteBlob): gzread(), BZ2\_bzread(), + gzwrite(), BZ2\_bzwrite() return type 'int' rather than 'size\_t' + like their stdio equivalents. Use correct signed type to avoid + returning a negative value into an unsigned type, forming a huge + positive value. Fixes oss-fuzz 8600 + "graphicsmagick/coder\_MAT\_fuzzer: Heap-buffer-overflow in + ReadBlobLSBDoubles". (Credit to OSS-Fuzz) + +2018-06-07 Bob Friesenhahn + + - coders/png.c (png\_read\_raw\_profile): Try to shore up parsing of + raw profile reading to avoid heap read overruns. Fixes oss-fuzz + 8763 "graphicsmagick/coder\_PNG32\_fuzzer: Heap-buffer-overflow in + png\_read\_raw\_profile". (Credit to OSS-Fuzz) + +2018-06-07 Fojtik Jaroslav + + - coders/mat.c Reduce stack usage for 64 bit architecture. + +2018-06-06 Fojtik Jaroslav + + - coders/wpg.c Check return values of SeekBlob for more safety. + +2018-06-06 Bob Friesenhahn + + - coders/png.c (ReadOneJNGImage): Use DestroyImageList() rather + than DestroyImage() on returned Image from supposed read of JPEG + data, in case multiple frames were unexpectedly returned. Also + add "JPEG:" prefix to filename when reading from temporary file to + force that it can only be read as a JPEG file, disabling format + auto-detection based on file header. Fixes oss-fuzz 8755 + "graphicsmagick/coder\_JNG\_fuzzer: Indirect-leak in + AllocateImage". (Credit to OSS-Fuzz) + +2018-06-05 Bob Friesenhahn + + - magick/blob.c (EOFBlob): Implement EOF detection for ZipStream. + Does some archaic zlib not provide gzeof()? Fixes oss-fuzz 8550 + "graphicsmagick/coder\_MAT\_fuzzer: Timeout in + graphicsmagick\_coder\_MAT\_fuzzer". (Credit to OSS-Fuzz) + +2018-06-04 Bob Friesenhahn + + - coders/png.c (ReadOnePNGImage): Skip adding empty raw profile. + Fixes oss-fuzz "graphicsmagick/coder\_PNG\_fuzzer: + Heap-buffer-overflow in png\_read\_raw\_profile". (Credit to + OSS-Fuzz) + +2018-06-03 Bob Friesenhahn + + - NEWS.txt: Update NEWS with latest changes. + + - coders/dcm.c (DCM\_ReadRGBImage): Force the image to DirectClass + to avoid later use of uninitialized indexes. Fixes oss-fuzz 8602 + "graphicsmagick/coder\_DCM\_fuzzer: Use-of-uninitialized-value in + DCM\_PostRescaleImage". (Credit to OSS-Fuzz) + (DCM\_ReadPlanarRGBImage): Force the image to DirectClass to avoid + later use of uninitialized indexes. + + - coders/png.c (ReadMNGImage): Free chunk memory in error + reporting path to avoid leak. Fixes oss-fuzz 8721 + "graphicsmagick/coder\_MNG\_fuzzer: Direct-leak in + ReadMNGImage". (Credit to OSS-Fuzz) + +2018-06-02 Bob Friesenhahn + + - magick/constitute.c (ReadImage): Assure that an error exception + is thrown if coder returns null without properly reporting an + exception. + + - magick/blob.c (BlobToImage): Assure that an error exception is + thrown if coder returns null without properly reporting an + exception. + + - coders/png.c (ReadMNGImage): Disable mystery "linked list is + corrupted" code. Assure that exceptions are reported to the + correct place so they are not lost. Fixes oss-fuzz 8710 + "graphicsmagick/coder\_MNG\_fuzzer: Indirect-leak in + AllocateImage". (Credit to OSS-Fuzz) + + - coders/tiff.c (ReadTIFFImage): Initialize allocated scanline, + strip, or tile to zero in order to avoid complaint about use of + uninitialized data if libtiff fails to write all the bytes. Fixes + oss-fuzz 8551 "graphicsmagick/coder\_TIFF\_fuzzer: + Use-of-uninitialized-value in ImportGrayQuantumType". (Credit to + OSS-Fuzz) + + - magick/annotate.c (RenderFreetype): Throw an exception if + DrawInfo font is null. Should fix oss-fuzz 8557 + "graphicsmagick/coder\_PCD\_fuzzer: Unknown signal in + RenderFreetype" and may fix oss-fuzz 8544 + "graphicsmagick/coder\_PCD\_fuzzer: Null-dereference READ in + RenderFreetype". (Credit to OSS-Fuzz) + + - coders/jpeg.c (ReadGenericProfile): Add/improve tracing for + profile size and when JPEG header is being read. + +2018-06-01 Bob Friesenhahn + + - coders/png.c (ReadOneJNGImage): Report a useful exception for + the case when the JNG file fails to provide the necessary image + chunks to allocate the color image. Inspired by oss-fuzz 8666 + "graphicsmagick/coder\_JNG\_fuzzer: ASSERT: data != (const char \*) + NULL" although the reported issue was not reproduced. + +2018-05-31 Bob Friesenhahn + + - coders/png.c (ReadMNGImage): Fix off-by-one in length validation + for TERM chunk which allowed one byte heap read overflow. Fixes + oss-fuzz 8615 "graphicsmagick/coder\_MNG\_fuzzer: + Heap-buffer-overflow in mng\_get\_long". (Credit to OSS-Fuzz) + (ReadMNGImage): Fix leak of MngInfo in error reporting path. + Fixes oss-fuzz 8604 "graphicsmagick/coder\_MNG\_fuzzer: Direct-leak + in ReadMNGImage". (Credit to OSS-Fuzz) + (ReadMNGImage): Verify that claimed chunk size does not exceed + input size. Fixes oss-fuzz 8564 "graphicsmagick/coder\_MNG\_fuzzer: + Out-of-memory in graphicsmagick\_coder\_MNG\_fuzzer". (Credit to + OSS-Fuzz) + + - coders/tiff.c (ReadTIFFImage): Reject files with excessive + samples-per-pixel or extra-samples. Avoids potential issues + observed in oss-fuzz 8634 "graphicsmagick/coder\_BIGTIFF\_fuzzer: + Undefined-shift in ImportAlphaQuantumType". (Credit to OSS-Fuzz) + +2018-05-30 Bob Friesenhahn + + - coders/png.c (ReadMNGImage): Assure that object id index is + always less than MNG\_MAX\_OBJECTS to avoid overflow. Fixes + oss-fuzz 8596 "graphicsmagick/coder\_MNG\_fuzzer: + Index-out-of-bounds in ReadMNGImage" and likely other issues yet + to be reported. (Credit to OSS-Fuzz) + +2018-05-30 Greg Wolfe + + - magick/render.c (CompareEdges): Per ticket #562, + function CompareEdges() did not conform to the qsort() + requirement that if CompareEdges(edge0,edge1) returns + -1 (i.e., edge0 "less than" edge1), then + CompareEdges(edge1,edge0) should return 1 (edge1 + "greater than" edge0). This has been fixed. + +2018-05-30 Bob Friesenhahn + + - coders/png.c (ReadOneJNGImage): Deal with JDAA JNG chunk with + length zero. Fixes oss-fuzz 8562 + "graphicsmagick/coder\_JNG\_fuzzer: ASSERT: data != (const char \*) + NULL". (Credit to OSS-Fuzz) + + - coders/tiff.c (ReadTIFFImage): Check that the bits-per-sample is + supported by the implementation before attempting to decode the + image. Fixes oss-fuzz 8554 "graphicsmagick/coder\_BIGTIFF\_fuzzer: + Undefined-shift in MagickBitStreamMSBWrite". (Credit to OSS-Fuzz) + + - coders/png.c (ReadMNGImage): Eliminate use of uninitialized + header magic data by checking for EOF first. Fixes oss-fuzz 8597 + "graphicsmagick/coder\_MNG\_fuzzer: Use-of-uninitialized-value in + ReadMNGImage". (Credit to OSS-Fuzz) + +2018-05-25 Bob Friesenhahn + + - fuzzing/oss-fuzz-build.sh: More fixes based on what is observed + in oss-fuzz build log. + +2018-05-24 Fojtik Jaroslav + + - coders/jnx.c The attribute should belong to only one scene and + not to whole image list. + +2018-05-24 Bob Friesenhahn + + - fuzzing/oss-fuzz-build.sh: Changes to add CPPFLAGS to configure + executions to hopefully get oss-fuzz build closer to success. + +2018-05-23 Bob Friesenhahn + + - PerlMagick/t/jpeg/read.t: Add a JNX reader test case. + + - coders/jnx.c (ReadJNXImage): JNX image depth should be 8. + + - fuzzing/oss-fuzz-build.sh: Apply patch from Alex Gaynor to + switch libpng to autotools build system, as well as configure + GraphicsMagick with '--with-quantum-depth=16'. + +2018-05-22 Bob Friesenhahn + + - coders/tiff.c (ReadTIFFImage): Validate tile memory requests for + the TIFFReadRGBATile() case in the same way as the TIFFReadTile() + case. Fixes oss-fuzz 8434 "graphicsmagick/coder\_BIGTIFF\_fuzzer: + Out-of-memory in graphicsmagick\_coder\_BIGTIFF\_fuzzer". (Credit to + OSS-Fuzz) + +2018-05-21 Bob Friesenhahn + + - coders/tile.c (ReadTILEImage): Remove any existing size request + when while image to tile. This avoids size being used for both + the input image size and the tile image size. Fixes SourceForge + issue #563 "tile: appears to blow image up by 100% before + applying tiling". + +2018-05-20 Bob Friesenhahn + + - fuzzing/oss-fuzz-build.sh: Patch from Paul Kehrer to disable + libpng test programs and binaries while building libpng in support + of oss-fuzz testing. + + - coders/dcm.c (DCM\_ReadGrayscaleImage): If a palette was + provided, the image may be in PseudoClass but we need DirectClass + for gray image when GRAYSCALE\_USES\_PALETTE is not defined. Fixes + oss-fuzz 7550 "graphicsmagick/coder\_DCM\_fuzzer: + Use-of-uninitialized-value in SyncImageCallBack". (Credit to + OSS-Fuzz) + (ReadDCMImage): Restore use of DCM\_PostRescaleImage() in order to + obtain suitably scaled DICOM again. Hopefully it is more robust + now. + (DCM\_ReadPaletteImage): Assure that DirectClass pixels are + initialized. + +2018-05-19 Bob Friesenhahn + + - coders/tiff.c (ReadTIFFImage): Remove strange addition of + image->columns to pixel buffer offsets which now causes a heap + overflow since the buffer has been right-sized. Perhaps the extra + offset plus the over-sized allocation was some attempt to avoid + buffer over/underflows due to bugs in libtiff. Fixes oss-fuzz 8384 + "graphicsmagick/coder\_BIGTIFF\_fuzzer: Heap-buffer-overflow in + put1bitbwtile" which is described to be a regression. (Credit to + OSS-Fuzz) + + - magick/render.c (DrawImage): Fix wrong range checks which caused + spurious "Parsing of SVG images fail with "Non-conforming drawing + primitive definition (push)" failure. Fixes SourceForge issue 561 + "Parsing of SVG images fail with "Non-conforming drawing primitive + definition (push)"" which is due to problems caused by the fix for + SourceForge issue 517. + + - coders/tiff.c (WritePTIFImage): Use '-define + ptif:minimum-geometry=' to specify the smallest + subresolution frame which is produced by the PTIF (Pyramid TIFF) + writer. + +2018-05-18 Bob Friesenhahn + + - coders/tiff.c (WritePTIFImage): Allow 1x1 input image to be + supported. + + - coders/png.c (ReadOneJNGImage): Unconditionally free JDAT chunk + memory. Fixes oss-fuzz 8366 "graphicsmagick/coder\_JNG\_fuzzer: + Direct-leak in ReadOneJNGImage". (Credit to OSS-Fuzz) + + - coders/tiff.c (WritePTIFImage): Fix leak of pyramid Image list + if ResizeImage() fails. Fixes oss-fuzz 8364 + "graphicsmagick/coder\_PTIF\_fuzzer: Indirect-leak in + CloneImage". (Credit to OSS-Fuzz) + +2018-05-17 Bob Friesenhahn + + - coders/tiff.c (WriteTIFFImage): Add and use + ThrowTIFFWriterException() macro to consistently clean-up when + throwing writer exception. May fix oss-fuzz 8321 + "graphicsmagick/coder\_EPT\_fuzzer: Direct-leak in + TIFFClientOpen". (Credit to OSS-Fuzz) + (ReadTIFFImage): Add and use ThrowTIFFReaderException() macro to + consistently clean-up when throwing reader exception. + +2018-05-16 Greg Wolfe + + - magick/alpha\_composite.h (AlphaCompositePixel): The + macro definition for MagickAlphaCompositeQuantum in + alpha\_composite.h computes an expression of the form: + + a \* b + c \* d \* e + + Code in function AlphaCompositePixel() (also in + alpha\_composite.h) multiplies the result of this macro + by variable "delta" as follows: + + delta \* a \* b + c \* d \* e + + However, the intended result is actually: + + delta \* ( a \* b + c \* d \* e ) + + The macro definition has been modified to enclose the + entire expression in parentheses. + + The effects of this bug were particularly evident at the + boundary between a stroked polygon and a transparent + black region. More generally, an incorrect composited + pixel value was being computed by AlphaCompositePixel() + whenever the output alpha value was not 100% opaque. + +2018-05-16 Bob Friesenhahn + + - tests/rwblob.tap: Add a test for PTIF format. + + - coders/tiff.c (WritePTIFImage): Fix Image blob referencing in + order to avoid double-free when writing PTIF to memory BLOB. Fixes + oss-fuzz 8280 "graphicsmagick/coder\_PTIF\_fuzzer: Heap-double-free + in Magick::BlobRef::~BlobRef". (Credit to OSS-Fuzz) + +2018-05-14 Bob Friesenhahn + + - coders/tiff.c (WriteTIFFImage): Use libtiff's + TIFFDefaultStripSize() function rather than an old porting macro + required by some defunct libtiff version. Expected to fix + oss-fuzz 8248 "graphicsmagick/coder\_EPT\_fuzzer: + Floating-point-exception in WriteTIFFImage". (Credit to OSS-Fuzz) + +2018-05-13 Fojtik Jaroslav + + - coders/mat.c Fix potentional leak when compressed object is + corrupted. Fixes oss-fuzz 8251 (Credit to OSS-Fuzz) + +2018-05-13 Bob Friesenhahn + + - coders/tiff.c (ReadTIFFImage): Fix leak of Image when + TIFFReadRGBAImage() reports failure. Also harden buffer + allocation calculation. Fixes oss-fuzz 8275 + "graphicsmagick/coder\_BIGTIFF\_fuzzer: Indirect-leak in + AllocateImage". (Credit to OSS-Fuzz) + + - coders/ept.c (ReadEPTImage): Add validations of 'count' and + 'filesize' read from EPT file. In response to oss-fuzz 8248 + "graphicsmagick/coder\_EPT\_fuzzer: Floating-point-exception in + WriteTIFFImage" but we are unable to recreate the oss-fuzz issue + since the EPT reader already immediately reports an EOF exception. + +2018-05-12 Bob Friesenhahn + + - fuzzing/oss-fuzz-build.sh: Apply SourceForge patch #57 "Add + fuzzing support for jpeg + freetype delegates" by Alex Gaynor. + + - coders/png.c (read\_user\_chunk\_callback): Fix memory leak and use + of uninitialized memory when handling eXIf chunk. Fixes oss-fuzz + 8247 "graphicsmagick/coder\_PNG24\_fuzzer: Direct-leak in + png\_malloc". (Credit to OSS-Fuzz) + +2018-05-11 Bob Friesenhahn + + - fuzzing/oss-fuzz-build.sh: Apply SourceForge patch #56 "Use a + few delegate libraries in fuzzing" by Alex Gaynor. + +2018-05-10 Bob Friesenhahn + + - tests/rwfile.tap: MIFF zip and bzip compression tests do not + fail if zlib and bzlib are not available because the compression + request is silently changed to no compression. +2018-05-07 Greg Wolfe + - magick/render.c (DrawImage, InsertAttributeIntoInputStream): + For a reference such as 'class="classname"', the "classname" + is now allowed to be undefined. + + - coders.svg.c (ProcessStyleClassDefs): Class definitions + defined within a