Commit 5311b7a80 for imagemagick.org
commit 5311b7a803586214ad18c84f949471cad8d7e1fd
Author: Gareth Davidson <gaz@bitplane.net>
Date: Sun Aug 23 08:34:54 2026 +0100
Amiga Workbench .info coder (image/x-amiga-icon) (#8606)
diff --git a/MagickCore/methods.h b/MagickCore/methods.h
index 2b65e683e..df55ba58e 100644
--- a/MagickCore/methods.h
+++ b/MagickCore/methods.h
@@ -997,6 +997,7 @@ extern "C" {
#define RegisterVIDImage PrependMagickMethod(RegisterVIDImage)
#define RegisterVIFFImage PrependMagickMethod(RegisterVIFFImage)
#define RegisterVIPSImage PrependMagickMethod(RegisterVIPSImage)
+#define RegisterWBINFOImage PrependMagickMethod(RegisterWBINFOImage)
#define RegisterWBMPImage PrependMagickMethod(RegisterWBMPImage)
#define RegisterWEBPImage PrependMagickMethod(RegisterWEBPImage)
#define RegisterWPGImage PrependMagickMethod(RegisterWPGImage)
@@ -1382,6 +1383,7 @@ extern "C" {
#define UnregisterVIDImage PrependMagickMethod(UnregisterVIDImage)
#define UnregisterVIFFImage PrependMagickMethod(UnregisterVIFFImage)
#define UnregisterVIPSImage PrependMagickMethod(UnregisterVIPSImage)
+#define UnregisterWBINFOImage PrependMagickMethod(UnregisterWBINFOImage)
#define UnregisterWBMPImage PrependMagickMethod(UnregisterWBMPImage)
#define UnregisterWEBPImage PrependMagickMethod(UnregisterWEBPImage)
#define UnregisterWPGImage PrependMagickMethod(UnregisterWPGImage)
diff --git a/MagickCore/static.h b/MagickCore/static.h
index cf94243e8..ef9c4c186 100644
--- a/MagickCore/static.h
+++ b/MagickCore/static.h
@@ -160,6 +160,7 @@ extern ModuleExport size_t
RegisterVIDEOImage(void),
RegisterVIFFImage(void),
RegisterVIPSImage(void),
+ RegisterWBINFOImage(void),
RegisterWBMPImage(void),
RegisterWEBPImage(void),
RegisterWMFImage(void),
@@ -303,6 +304,7 @@ extern ModuleExport void
UnregisterVIDEOImage(void),
UnregisterVIFFImage(void),
UnregisterVIPSImage(void),
+ UnregisterWBINFOImage(void),
UnregisterWBMPImage(void),
UnregisterWEBPImage(void),
UnregisterWMFImage(void),
diff --git a/Makefile.in b/Makefile.in
index 1f234693f..45e6ef468 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -593,18 +593,18 @@ am__MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la_SOURC
coders/uyvy.c coders/uyvy.h coders/vicar.c coders/vicar.h \
coders/vid.c coders/vid.h coders/video.c coders/video.h \
coders/viff.c coders/viff.h coders/vips.c coders/vips.h \
- coders/wbmp.c coders/wbmp.h coders/webp.h coders/wmf.h \
- coders/wpg.c coders/wpg.h coders/xbm.c coders/xbm.h \
- coders/xc.c coders/xcf.c coders/xcf.h coders/xc.h coders/x.h \
- coders/xpm.c coders/xpm.h coders/xps.c coders/xps.h \
- coders/xwd.h coders/yaml.c coders/yaml.h coders/ycbcr.c \
- coders/ycbcr.h coders/yuv.c coders/yuv.h coders/dps.c \
- coders/djvu.c coders/dmr.c coders/exr.c coders/flif.c \
- coders/fpx.c coders/clipboard.c coders/emf.c coders/heic.c \
- coders/jbig.c coders/jpeg.c coders/jp2.c coders/jxl.c \
- coders/png.c coders/ept.c coders/tiff.c coders/uhdr.c \
- coders/webp.c coders/wmf.c coders/x.c coders/xwd.c \
- filters/analyze.c
+ coders/wbinfo.c coders/wbinfo.h coders/wbmp.c coders/wbmp.h \
+ coders/webp.h coders/wmf.h coders/wpg.c coders/wpg.h \
+ coders/xbm.c coders/xbm.h coders/xc.c coders/xcf.c \
+ coders/xcf.h coders/xc.h coders/x.h coders/xpm.c coders/xpm.h \
+ coders/xps.c coders/xps.h coders/xwd.h coders/yaml.c \
+ coders/yaml.h coders/ycbcr.c coders/ycbcr.h coders/yuv.c \
+ coders/yuv.h coders/dps.c coders/djvu.c coders/dmr.c \
+ coders/exr.c coders/flif.c coders/fpx.c coders/clipboard.c \
+ coders/emf.c coders/heic.c coders/jbig.c coders/jpeg.c \
+ coders/jp2.c coders/jxl.c coders/png.c coders/ept.c \
+ coders/tiff.c coders/uhdr.c coders/webp.c coders/wmf.c \
+ coders/x.c coders/xwd.c filters/analyze.c
am__objects_1 = MagickCore/libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-accelerate.lo \
MagickCore/libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-animate.lo \
MagickCore/libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-annotate.lo \
@@ -834,6 +834,7 @@ am__objects_21 = coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_
coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-video.lo \
coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-viff.lo \
coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-vips.lo \
+ coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.lo \
coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.lo \
coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wpg.lo \
coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-xbm.lo \
@@ -1922,6 +1923,15 @@ coders_vips_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_CFLAGS) $(CFLAGS) $(coders_vips_la_LDFLAGS) $(LDFLAGS) -o \
$@
@WITH_MODULES_TRUE@am_coders_vips_la_rpath = -rpath $(codersdir)
+coders_wbinfo_la_DEPENDENCIES = $(MAGICKCORE_LIBS) \
+ $(am__DEPENDENCIES_1)
+am_coders_wbinfo_la_OBJECTS = coders/wbinfo_la-wbinfo.lo
+coders_wbinfo_la_OBJECTS = $(am_coders_wbinfo_la_OBJECTS)
+coders_wbinfo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(coders_wbinfo_la_LDFLAGS) $(LDFLAGS) \
+ -o $@
+@WITH_MODULES_TRUE@am_coders_wbinfo_la_rpath = -rpath $(codersdir)
coders_wbmp_la_DEPENDENCIES = $(MAGICKCORE_LIBS)
am_coders_wbmp_la_OBJECTS = coders/wbmp_la-wbmp.lo
coders_wbmp_la_OBJECTS = $(am_coders_wbmp_la_OBJECTS)
@@ -2479,6 +2489,7 @@ am__depfiles_remade = ./$(DEPDIR)/dummy.Po \
coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-video.Plo \
coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-viff.Plo \
coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-vips.Plo \
+ coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.Plo \
coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.Plo \
coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-webp.Plo \
coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wmf.Plo \
@@ -2622,6 +2633,7 @@ am__depfiles_remade = ./$(DEPDIR)/dummy.Po \
coders/$(DEPDIR)/video_la-video.Plo \
coders/$(DEPDIR)/viff_la-viff.Plo \
coders/$(DEPDIR)/vips_la-vips.Plo \
+ coders/$(DEPDIR)/wbinfo_la-wbinfo.Plo \
coders/$(DEPDIR)/wbmp_la-wbmp.Plo \
coders/$(DEPDIR)/webp_la-webp.Plo \
coders/$(DEPDIR)/wmf_la-wmf.Plo \
@@ -2745,15 +2757,15 @@ SOURCES = $(Magick___lib_libMagick___@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_
$(coders_url_la_SOURCES) $(coders_uyvy_la_SOURCES) \
$(coders_vicar_la_SOURCES) $(coders_vid_la_SOURCES) \
$(coders_video_la_SOURCES) $(coders_viff_la_SOURCES) \
- $(coders_vips_la_SOURCES) $(coders_wbmp_la_SOURCES) \
- $(coders_webp_la_SOURCES) $(coders_wmf_la_SOURCES) \
- $(coders_wpg_la_SOURCES) $(coders_x_la_SOURCES) \
- $(coders_xbm_la_SOURCES) $(coders_xc_la_SOURCES) \
- $(coders_xcf_la_SOURCES) $(coders_xpm_la_SOURCES) \
- $(coders_xps_la_SOURCES) $(coders_xwd_la_SOURCES) \
- $(coders_yaml_la_SOURCES) $(coders_ycbcr_la_SOURCES) \
- $(coders_yuv_la_SOURCES) $(filters_analyze_la_SOURCES) \
- $(Magick___demo_analyze_SOURCES) \
+ $(coders_vips_la_SOURCES) $(coders_wbinfo_la_SOURCES) \
+ $(coders_wbmp_la_SOURCES) $(coders_webp_la_SOURCES) \
+ $(coders_wmf_la_SOURCES) $(coders_wpg_la_SOURCES) \
+ $(coders_x_la_SOURCES) $(coders_xbm_la_SOURCES) \
+ $(coders_xc_la_SOURCES) $(coders_xcf_la_SOURCES) \
+ $(coders_xpm_la_SOURCES) $(coders_xps_la_SOURCES) \
+ $(coders_xwd_la_SOURCES) $(coders_yaml_la_SOURCES) \
+ $(coders_ycbcr_la_SOURCES) $(coders_yuv_la_SOURCES) \
+ $(filters_analyze_la_SOURCES) $(Magick___demo_analyze_SOURCES) \
$(Magick___demo_button_SOURCES) $(Magick___demo_demo_SOURCES) \
$(Magick___demo_detrans_SOURCES) $(Magick___demo_flip_SOURCES) \
$(Magick___demo_gravity_SOURCES) \
@@ -2842,15 +2854,15 @@ DIST_SOURCES = $(Magick___lib_libMagick___@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUF
$(coders_url_la_SOURCES) $(coders_uyvy_la_SOURCES) \
$(coders_vicar_la_SOURCES) $(coders_vid_la_SOURCES) \
$(coders_video_la_SOURCES) $(coders_viff_la_SOURCES) \
- $(coders_vips_la_SOURCES) $(coders_wbmp_la_SOURCES) \
- $(coders_webp_la_SOURCES) $(coders_wmf_la_SOURCES) \
- $(coders_wpg_la_SOURCES) $(coders_x_la_SOURCES) \
- $(coders_xbm_la_SOURCES) $(coders_xc_la_SOURCES) \
- $(coders_xcf_la_SOURCES) $(coders_xpm_la_SOURCES) \
- $(coders_xps_la_SOURCES) $(coders_xwd_la_SOURCES) \
- $(coders_yaml_la_SOURCES) $(coders_ycbcr_la_SOURCES) \
- $(coders_yuv_la_SOURCES) $(filters_analyze_la_SOURCES) \
- $(Magick___demo_analyze_SOURCES) \
+ $(coders_vips_la_SOURCES) $(coders_wbinfo_la_SOURCES) \
+ $(coders_wbmp_la_SOURCES) $(coders_webp_la_SOURCES) \
+ $(coders_wmf_la_SOURCES) $(coders_wpg_la_SOURCES) \
+ $(coders_x_la_SOURCES) $(coders_xbm_la_SOURCES) \
+ $(coders_xc_la_SOURCES) $(coders_xcf_la_SOURCES) \
+ $(coders_xpm_la_SOURCES) $(coders_xps_la_SOURCES) \
+ $(coders_xwd_la_SOURCES) $(coders_yaml_la_SOURCES) \
+ $(coders_ycbcr_la_SOURCES) $(coders_yuv_la_SOURCES) \
+ $(filters_analyze_la_SOURCES) $(Magick___demo_analyze_SOURCES) \
$(Magick___demo_button_SOURCES) $(Magick___demo_demo_SOURCES) \
$(Magick___demo_detrans_SOURCES) $(Magick___demo_flip_SOURCES) \
$(Magick___demo_gravity_SOURCES) \
@@ -4077,6 +4089,8 @@ MAGICKCORE_CODER_SRCS = \
coders/viff.h \
coders/vips.c \
coders/vips.h \
+ coders/wbinfo.c \
+ coders/wbinfo.h \
coders/wbmp.c \
coders/wbmp.h \
coders/webp.h \
@@ -4256,6 +4270,7 @@ CODERS_NOINST_HDRS = \
coders/video.h \
coders/viff.h \
coders/vips.h \
+ coders/wbinfo.h \
coders/wbmp.h \
coders/webp.h \
coders/wmf.h \
@@ -4385,6 +4400,7 @@ CODERS_NOINST_HDRS = \
@WITH_MODULES_TRUE@ coders/video.la \
@WITH_MODULES_TRUE@ coders/viff.la \
@WITH_MODULES_TRUE@ coders/vips.la \
+@WITH_MODULES_TRUE@ coders/wbinfo.la \
@WITH_MODULES_TRUE@ coders/wbmp.la \
@WITH_MODULES_TRUE@ coders/wpg.la \
@WITH_MODULES_TRUE@ coders/xbm.la \
@@ -5190,6 +5206,12 @@ coders_vips_la_CPPFLAGS = $(MAGICK_CODER_CPPFLAGS)
coders_vips_la_LDFLAGS = $(MODULECOMMONFLAGS)
coders_vips_la_LIBADD = $(MAGICKCORE_LIBS) $(MATH_LIBS)
+# WBINFO coder module
+coders_wbinfo_la_SOURCES = coders/wbinfo.c
+coders_wbinfo_la_CPPFLAGS = $(MAGICK_CODER_CPPFLAGS)
+coders_wbinfo_la_LDFLAGS = $(MODULECOMMONFLAGS)
+coders_wbinfo_la_LIBADD = $(MAGICKCORE_LIBS) $(ZLIB_LIBS)
+
# WBMP coder module
coders_wbmp_la_SOURCES = coders/wbmp.c
coders_wbmp_la_CPPFLAGS = $(MAGICK_CODER_CPPFLAGS)
@@ -7216,6 +7238,8 @@ coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-vi
coders/$(am__dirstamp) coders/$(DEPDIR)/$(am__dirstamp)
coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-vips.lo: \
coders/$(am__dirstamp) coders/$(DEPDIR)/$(am__dirstamp)
+coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.lo: \
+ coders/$(am__dirstamp) coders/$(DEPDIR)/$(am__dirstamp)
coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.lo: \
coders/$(am__dirstamp) coders/$(DEPDIR)/$(am__dirstamp)
coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wpg.lo: \
@@ -8014,6 +8038,11 @@ coders/vips_la-vips.lo: coders/$(am__dirstamp) \
coders/vips.la: $(coders_vips_la_OBJECTS) $(coders_vips_la_DEPENDENCIES) $(EXTRA_coders_vips_la_DEPENDENCIES) coders/$(am__dirstamp)
$(AM_V_CCLD)$(coders_vips_la_LINK) $(am_coders_vips_la_rpath) $(coders_vips_la_OBJECTS) $(coders_vips_la_LIBADD) $(LIBS)
+coders/wbinfo_la-wbinfo.lo: coders/$(am__dirstamp) \
+ coders/$(DEPDIR)/$(am__dirstamp)
+
+coders/wbinfo.la: $(coders_wbinfo_la_OBJECTS) $(coders_wbinfo_la_DEPENDENCIES) $(EXTRA_coders_wbinfo_la_DEPENDENCIES) coders/$(am__dirstamp)
+ $(AM_V_CCLD)$(coders_wbinfo_la_LINK) $(am_coders_wbinfo_la_rpath) $(coders_wbinfo_la_OBJECTS) $(coders_wbinfo_la_LIBADD) $(LIBS)
coders/wbmp_la-wbmp.lo: coders/$(am__dirstamp) \
coders/$(DEPDIR)/$(am__dirstamp)
@@ -8629,6 +8658,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-video.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-viff.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-vips.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-webp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wmf.Plo@am__quote@ # am--include-marker
@@ -8773,6 +8803,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/video_la-video.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/viff_la-viff.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/vips_la-vips.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/wbinfo_la-wbinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/wbmp_la-wbmp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/webp_la-webp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@coders/$(DEPDIR)/wmf_la-wmf.Plo@am__quote@ # am--include-marker
@@ -10273,6 +10304,13 @@ coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-vi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-vips.lo `test -f 'coders/vips.c' || echo '$(srcdir)/'`coders/vips.c
+coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.lo: coders/wbinfo.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.lo -MD -MP -MF coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.Tpo -c -o coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.lo `test -f 'coders/wbinfo.c' || echo '$(srcdir)/'`coders/wbinfo.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.Tpo coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='coders/wbinfo.c' object='coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.lo `test -f 'coders/wbinfo.c' || echo '$(srcdir)/'`coders/wbinfo.c
+
coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.lo: coders/wbmp.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.lo -MD -MP -MF coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.Tpo -c -o coders/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.lo `test -f 'coders/wbmp.c' || echo '$(srcdir)/'`coders/wbmp.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.Tpo coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.Plo
@@ -11568,6 +11606,13 @@ coders/vips_la-vips.lo: coders/vips.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(coders_vips_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o coders/vips_la-vips.lo `test -f 'coders/vips.c' || echo '$(srcdir)/'`coders/vips.c
+coders/wbinfo_la-wbinfo.lo: coders/wbinfo.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(coders_wbinfo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT coders/wbinfo_la-wbinfo.lo -MD -MP -MF coders/$(DEPDIR)/wbinfo_la-wbinfo.Tpo -c -o coders/wbinfo_la-wbinfo.lo `test -f 'coders/wbinfo.c' || echo '$(srcdir)/'`coders/wbinfo.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) coders/$(DEPDIR)/wbinfo_la-wbinfo.Tpo coders/$(DEPDIR)/wbinfo_la-wbinfo.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='coders/wbinfo.c' object='coders/wbinfo_la-wbinfo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(coders_wbinfo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o coders/wbinfo_la-wbinfo.lo `test -f 'coders/wbinfo.c' || echo '$(srcdir)/'`coders/wbinfo.c
+
coders/wbmp_la-wbmp.lo: coders/wbmp.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(coders_wbmp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT coders/wbmp_la-wbmp.lo -MD -MP -MF coders/$(DEPDIR)/wbmp_la-wbmp.Tpo -c -o coders/wbmp_la-wbmp.lo `test -f 'coders/wbmp.c' || echo '$(srcdir)/'`coders/wbmp.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) coders/$(DEPDIR)/wbmp_la-wbmp.Tpo coders/$(DEPDIR)/wbmp_la-wbmp.Plo
@@ -13303,6 +13348,7 @@ distclean: distclean-am
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-video.Plo
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-viff.Plo
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-vips.Plo
+ -rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.Plo
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.Plo
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-webp.Plo
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wmf.Plo
@@ -13447,6 +13493,7 @@ distclean: distclean-am
-rm -f coders/$(DEPDIR)/video_la-video.Plo
-rm -f coders/$(DEPDIR)/viff_la-viff.Plo
-rm -f coders/$(DEPDIR)/vips_la-vips.Plo
+ -rm -f coders/$(DEPDIR)/wbinfo_la-wbinfo.Plo
-rm -f coders/$(DEPDIR)/wbmp_la-wbmp.Plo
-rm -f coders/$(DEPDIR)/webp_la-webp.Plo
-rm -f coders/$(DEPDIR)/wmf_la-wmf.Plo
@@ -13811,6 +13858,7 @@ maintainer-clean: maintainer-clean-am
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-video.Plo
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-viff.Plo
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-vips.Plo
+ -rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbinfo.Plo
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wbmp.Plo
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-webp.Plo
-rm -f coders/$(DEPDIR)/MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la-wmf.Plo
@@ -13955,6 +14003,7 @@ maintainer-clean: maintainer-clean-am
-rm -f coders/$(DEPDIR)/video_la-video.Plo
-rm -f coders/$(DEPDIR)/viff_la-viff.Plo
-rm -f coders/$(DEPDIR)/vips_la-vips.Plo
+ -rm -f coders/$(DEPDIR)/wbinfo_la-wbinfo.Plo
-rm -f coders/$(DEPDIR)/wbmp_la-wbmp.Plo
-rm -f coders/$(DEPDIR)/webp_la-webp.Plo
-rm -f coders/$(DEPDIR)/wmf_la-wmf.Plo
diff --git a/coders/Makefile.am b/coders/Makefile.am
index 0a994c2d9..2bee11ad6 100644
--- a/coders/Makefile.am
+++ b/coders/Makefile.am
@@ -361,6 +361,8 @@ MAGICKCORE_CODER_SRCS = \
coders/viff.h \
coders/vips.c \
coders/vips.h \
+ coders/wbinfo.c \
+ coders/wbinfo.h \
coders/wbmp.c \
coders/wbmp.h \
coders/webp.h \
@@ -540,6 +542,7 @@ CODERS_NOINST_HDRS = \
coders/video.h \
coders/viff.h \
coders/vips.h \
+ coders/wbinfo.h \
coders/wbmp.h \
coders/webp.h \
coders/wmf.h \
@@ -669,6 +672,7 @@ coders_LTLIBRARIES = \
coders/video.la \
coders/viff.la \
coders/vips.la \
+ coders/wbinfo.la \
coders/wbmp.la \
coders/wpg.la \
coders/xbm.la \
@@ -1478,6 +1482,12 @@ coders_vips_la_CPPFLAGS = $(MAGICK_CODER_CPPFLAGS)
coders_vips_la_LDFLAGS = $(MODULECOMMONFLAGS)
coders_vips_la_LIBADD = $(MAGICKCORE_LIBS) $(MATH_LIBS)
+# WBINFO coder module
+coders_wbinfo_la_SOURCES = coders/wbinfo.c
+coders_wbinfo_la_CPPFLAGS = $(MAGICK_CODER_CPPFLAGS)
+coders_wbinfo_la_LDFLAGS = $(MODULECOMMONFLAGS)
+coders_wbinfo_la_LIBADD = $(MAGICKCORE_LIBS) $(ZLIB_LIBS)
+
# WBMP coder module
coders_wbmp_la_SOURCES = coders/wbmp.c
coders_wbmp_la_CPPFLAGS = $(MAGICK_CODER_CPPFLAGS)
diff --git a/coders/coders-list.h b/coders/coders-list.h
index 2691d78bd..336069d9c 100644
--- a/coders/coders-list.h
+++ b/coders/coders-list.h
@@ -180,6 +180,7 @@ AddMagickCoder(VID)
AddMagickCoder(VIDEO)
AddMagickCoder(VIFF)
AddMagickCoder(VIPS)
+AddMagickCoder(WBINFO)
AddMagickCoder(WBMP)
#if defined(MAGICKCORE_WEBP_DELEGATE)
AddMagickCoder(WEBP)
diff --git a/coders/coders.h b/coders/coders.h
index 1bf290ecf..251389a9c 100644
--- a/coders/coders.h
+++ b/coders/coders.h
@@ -182,6 +182,7 @@
#include "coders/video.h"
#include "coders/viff.h"
#include "coders/vips.h"
+#include "coders/wbinfo.h"
#include "coders/wbmp.h"
#if defined(MAGICKCORE_WEBP_DELEGATE)
#include "coders/webp.h"
diff --git a/coders/wbinfo.c b/coders/wbinfo.c
new file mode 100644
index 000000000..812953a53
--- /dev/null
+++ b/coders/wbinfo.c
@@ -0,0 +1,1629 @@
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% W W BBBB IIIII N N FFFFF OOO %
+% W W B B I NN N F O O %
+% W W W BBBB I N N N FFF O O %
+% WW WW B B I N NN F O O %
+% W W BBBB IIIII N N F OOO %
+% %
+% %
+% Read Amiga Workbench Icon Image Format %
+% %
+% Software Design %
+% Gareth Davidson %
+% March 2026 %
+% %
+% %
+% Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
+% dedicated to making software imaging solutions freely available. %
+% %
+% You may not use this file except in compliance with the License. You may %
+% obtain a copy of the License at %
+% %
+% https://imagemagick.org/license/ %
+% %
+% Unless required by applicable law or agreed to in writing, software %
+% distributed under the License is distributed on an "AS IS" BASIS, %
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
+% See the License for the specific language governing permissions and %
+% limitations under the License. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%
+*/
+
+/*
+ Include declarations.
+*/
+#include "MagickCore/studio.h"
+#include "MagickCore/blob.h"
+#include "MagickCore/blob-private.h"
+#include "MagickCore/cache.h"
+#include "MagickCore/exception.h"
+#include "MagickCore/exception-private.h"
+#include "MagickCore/image.h"
+#include "MagickCore/image-private.h"
+#include "MagickCore/list.h"
+#include "MagickCore/log.h"
+#include "MagickCore/magick.h"
+#include "MagickCore/memory_.h"
+#include "MagickCore/monitor.h"
+#include "MagickCore/monitor-private.h"
+#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/quantum-private.h"
+#include "MagickCore/static.h"
+#include "MagickCore/string_.h"
+#include "MagickCore/module.h"
+#if defined(MAGICKCORE_ZLIB_DELEGATE)
+#include <zlib.h>
+#endif
+
+/*
+ Define declarations.
+*/
+#define AmigaIconMagic 0xE310
+#define MaxAmigaIconDimension 1024
+#define MaxAmigaIconFormScanSize (64UL*1024UL*1024UL)
+#define MaxAmigaIconImageChunks 8
+#define MaxAmigaIconScenes 8
+#define MaxAmigaIconToolTypes 4096
+#define MaxNewIconBitCount \
+ ((size_t) MaxAmigaIconDimension*MaxAmigaIconDimension*16)
+
+/*
+ Typedef declarations.
+*/
+typedef enum
+{
+ AmigaIconChunkContinue, /* keep walking the chunk list */
+ AmigaIconChunkStop, /* malformed chunk: stop, keep images so far */
+ AmigaIconChunkFatal /* abort the read */
+} AmigaIconChunkStatus;
+
+static MagickBooleanType GetRemainingBlobSize(Image *image,size_t *remaining)
+{
+ MagickOffsetType
+ offset;
+
+ MagickSizeType
+ blob_size;
+
+ offset=TellBlob(image);
+ blob_size=GetBlobSize(image);
+ if ((offset < 0) || ((MagickSizeType) offset > blob_size) ||
+ (blob_size-(MagickSizeType) offset > (MagickSizeType) MAGICK_SIZE_MAX))
+ {
+ *remaining=0;
+ return(MagickFalse);
+ }
+ *remaining=(size_t) (blob_size-(MagickSizeType) offset);
+ return(MagickTrue);
+}
+
+/*
+ Amiga Workbench system palettes.
+*/
+static const unsigned char AmigaWB1x[4][3] =
+{
+ {85,170,255},{255,255,255},{0,0,0},{255,136,0}
+};
+
+static const unsigned char AmigaWB2x[8][3] =
+{
+ {149,149,149},{0,0,0},{255,255,255},{59,103,162},
+ {123,123,123},{175,175,175},{170,144,124},{255,169,151}
+};
+
+static unsigned int BitsToUInt(const unsigned char *data,size_t total_bits,
+ size_t *bit_pos,size_t count)
+{
+ size_t
+ i;
+
+ unsigned int
+ val;
+
+ val=0;
+ for (i=0; i < count; i++)
+ {
+ val<<=1;
+ if (*bit_pos < total_bits)
+ {
+ size_t
+ bit_idx,
+ byte_idx;
+
+ byte_idx=(*bit_pos) >> 3;
+ bit_idx=7-((*bit_pos) & 7);
+ val|=(unsigned int) ((data[byte_idx] >> bit_idx) & 1);
+ }
+ (*bit_pos)++;
+ }
+ return(val);
+}
+
+/*
+ Count expanded bits from a NewIcon encoded line (for buffer sizing).
+*/
+static size_t NewIconLineBitCount(const char *src,size_t src_len)
+{
+ size_t
+ bit_count,
+ ch_idx;
+
+ bit_count=0;
+ for (ch_idx=0; ch_idx < src_len; ch_idx++)
+ {
+ unsigned int
+ byte;
+
+ byte=(unsigned int) (unsigned char) src[ch_idx];
+ if (byte < 32)
+ continue;
+ if (byte <= 208)
+ bit_count+=7;
+ else
+ bit_count+=(size_t) (byte-208)*7;
+ if (bit_count > MaxNewIconBitCount)
+ return(bit_count);
+ }
+ return(bit_count);
+}
+
+/*
+ Decode one NewIcon 7-bit encoded line into a bit buffer.
+
+ Each character maps to 7 bits; characters above 208 are RLE zero runs.
+ Returns the number of bits written.
+*/
+static size_t DecodeNewIconLine(const char *src,size_t src_len,
+ unsigned char *bits,size_t bits_alloc,size_t bit_offset)
+{
+ size_t
+ bit_count,
+ ch_idx;
+
+ bit_count=bit_offset;
+ for (ch_idx=0; ch_idx < src_len; ch_idx++)
+ {
+ int
+ bit_i;
+
+ unsigned int
+ byte,
+ val;
+
+ byte=(unsigned int) (unsigned char) src[ch_idx];
+ if (byte < 32)
+ continue;
+ if (byte <= 159)
+ val=byte-32;
+ else if (byte <= 208)
+ val=byte-81;
+ else
+ {
+ bit_count+=(size_t) (byte-208)*7;
+ continue;
+ }
+ for (bit_i=6; bit_i >= 0; bit_i--)
+ {
+ if (bit_count < bits_alloc*8)
+ {
+ if ((val >> bit_i) & 1)
+ bits[bit_count >> 3]|=(unsigned char) (1 << (7-(bit_count & 7)));
+ }
+ bit_count++;
+ }
+ }
+ return(bit_count);
+}
+
+/*
+ Decode GlowIcon/ColorIcon RLE data.
+
+ The RLE operates on a bit stream where entries are `depth` bits wide,
+ but control bytes are always 8 bits.
+
+ Returns allocated buffer with decoded bytes (one byte per entry).
+ Caller must free with RelinquishMagickMemory().
+*/
+static unsigned char *DecodeAmigaRLE(const unsigned char *data,
+ size_t data_size,size_t depth,size_t expected_count,size_t *decoded_count,
+ MagickBooleanType *complete)
+{
+ size_t
+ bit_pos,
+ count,
+ i,
+ n,
+ total_bits;
+
+ unsigned char
+ *result;
+
+ unsigned int
+ control,
+ val;
+
+ result=(unsigned char *) AcquireQuantumMemory(expected_count,
+ sizeof(*result));
+ if (result == (unsigned char *) NULL)
+ return((unsigned char *) NULL);
+ *complete=MagickFalse;
+ total_bits=data_size*8;
+ bit_pos=0;
+ count=0;
+ while ((bit_pos+8 <= total_bits) && (count < expected_count))
+ {
+ control=BitsToUInt(data,total_bits,&bit_pos,8);
+ if (control == 128)
+ continue;
+ if (control <= 127)
+ {
+ n=(size_t) control+1;
+ for (i=0; i < n; i++)
+ {
+ if (count >= expected_count)
+ break;
+ if (bit_pos+depth > total_bits)
+ {
+ *decoded_count=count;
+ return(result);
+ }
+ result[count++]=(unsigned char) BitsToUInt(data,total_bits,&bit_pos,
+ depth);
+ }
+ }
+ else
+ {
+ if (bit_pos+depth > total_bits)
+ {
+ *decoded_count=count;
+ return(result);
+ }
+ val=BitsToUInt(data,total_bits,&bit_pos,depth);
+ n=257-(size_t) control;
+ for (i=0; i < n; i++)
+ {
+ if (count >= expected_count)
+ break;
+ result[count++]=(unsigned char) val;
+ }
+ }
+ }
+ *decoded_count=count;
+ *complete=count == expected_count ? MagickTrue : MagickFalse;
+ return(result);
+}
+
+static inline void SetAmigaPixelRGBA(const Image *image,Quantum *q,
+ unsigned char r,unsigned char g,unsigned char b,unsigned char a)
+{
+ SetPixelRed(image,ScaleCharToQuantum(r),q);
+ SetPixelGreen(image,ScaleCharToQuantum(g),q);
+ SetPixelBlue(image,ScaleCharToQuantum(b),q);
+ SetPixelAlpha(image,ScaleCharToQuantum(a),q);
+}
+
+static MagickBooleanType AppendAmigaImage(Image **image,size_t width,
+ size_t height,size_t scene,const ImageInfo *image_info,
+ ExceptionInfo *exception)
+{
+ if (scene > 0)
+ {
+ AcquireNextImage(image_info,*image,exception);
+ if (GetNextImageInList(*image) == (Image *) NULL)
+ return(MagickFalse);
+ *image=SyncNextImageInList(*image);
+ if (*image == (Image *) NULL)
+ return(MagickFalse);
+ }
+ if (SetImageExtent(*image,width,height,exception) == MagickFalse)
+ {
+ if (scene > 0)
+ DeleteImageFromList(image);
+ return(MagickFalse);
+ }
+ (*image)->depth=8;
+ (*image)->alpha_trait=BlendPixelTrait;
+ (*image)->scene=scene;
+ return(MagickTrue);
+}
+
+/*
+ Render a paletted image (NewIcon or GlowIcon) to DirectClass RGBA.
+*/
+static MagickBooleanType RenderPalettedAmigaImage(Image *image,size_t width,
+ size_t height,const unsigned char *pixels,size_t pixel_count,
+ const unsigned char *palette,size_t pal_entries,
+ MagickBooleanType has_transparent,unsigned char transparent_idx,
+ ExceptionInfo *exception)
+{
+ ssize_t
+ y;
+
+ for (y=0; y < (ssize_t) height; y++)
+ {
+ Quantum
+ *q;
+
+ ssize_t
+ x;
+
+ q=QueueAuthenticPixels(image,0,y,width,1,exception);
+ if (q == (Quantum *) NULL)
+ return(MagickFalse);
+ for (x=0; x < (ssize_t) width; x++)
+ {
+ size_t
+ pi;
+
+ unsigned char
+ idx;
+
+ pi=(size_t) y*width+(size_t) x;
+ idx=pi < pixel_count ? pixels[pi] : 0;
+ if ((palette != (const unsigned char *) NULL) &&
+ ((size_t) idx < pal_entries))
+ {
+ SetPixelRed(image,ScaleCharToQuantum(palette[idx*3]),q);
+ SetPixelGreen(image,ScaleCharToQuantum(palette[idx*3+1]),q);
+ SetPixelBlue(image,ScaleCharToQuantum(palette[idx*3+2]),q);
+ }
+ else
+ {
+ SetPixelRed(image,0,q);
+ SetPixelGreen(image,0,q);
+ SetPixelBlue(image,0,q);
+ }
+ if (has_transparent && (idx == transparent_idx))
+ SetPixelAlpha(image,TransparentAlpha,q);
+ else
+ SetPixelAlpha(image,OpaqueAlpha,q);
+ q+=(ptrdiff_t) GetPixelChannels(image);
+ }
+ if (SyncAuthenticPixels(image,exception) == MagickFalse)
+ return(MagickFalse);
+ }
+ return(MagickTrue);
+}
+
+/*
+ Free a bitplane array; NULL entries are ignored.
+*/
+static unsigned char **RelinquishPlanes(unsigned char **planes,size_t count)
+{
+ size_t
+ i;
+
+ for (i=0; i < count; i++)
+ planes[i]=(unsigned char *) RelinquishMagickMemory(planes[i]);
+ return((unsigned char **) RelinquishMagickMemory(planes));
+}
+
+/*
+ Read and render a classic planar Amiga icon image from the blob.
+
+ Reads the 20-byte Image header, bitplane data, selects the system palette,
+ renders to a new scene, and increments *scene. Returns MagickTrue on
+ success. On failure the blob position is indeterminate.
+*/
+static MagickBooleanType ReadAndRenderClassicImage(Image **image,
+ size_t *scene,unsigned int user_data,const ImageInfo *image_info,
+ ExceptionInfo *exception)
+{
+ const unsigned char
+ (*palette)[3];
+
+ MagickBooleanType
+ render_status;
+
+ size_t
+ bytes_per_row,
+ num_colors,
+ p_idx,
+ plane_size,
+ remaining,
+ words_per_row;
+
+ ssize_t
+ y;
+
+ unsigned char
+ plane_pick,
+ plane_on_off,
+ **planes;
+
+ unsigned short
+ depth,
+ height,
+ width;
+
+ /*
+ checked ~300k icons and only 64 set left_edge or top_edge, and every one
+ was corruption that pushed the image out of bounds. So we'll skip those.
+ */
+ (void) ReadBlobMSBShort(*image); /* left_edge */
+ (void) ReadBlobMSBShort(*image); /* top_edge */
+ width=ReadBlobMSBShort(*image);
+ height=ReadBlobMSBShort(*image);
+ depth=ReadBlobMSBShort(*image);
+ (void) ReadBlobMSBLong(*image); /* image_data ptr */
+ plane_pick=(unsigned char) ReadBlobByte(*image);
+ plane_on_off=(unsigned char) ReadBlobByte(*image);
+ (void) ReadBlobMSBLong(*image); /* next ptr */
+ if (EOFBlob(*image) != MagickFalse)
+ return(MagickFalse);
+ if ((width == 0) || (height == 0) || (depth == 0) ||
+ (width > MaxAmigaIconDimension) ||
+ (height > MaxAmigaIconDimension) || (depth > 8))
+ return(MagickFalse);
+ words_per_row=((size_t) width+15)/16;
+ bytes_per_row=words_per_row*2;
+ if (HeapOverflowSanityCheckGetSize(bytes_per_row,(size_t) height,
+ &plane_size) != MagickFalse)
+ return(MagickFalse);
+ if ((GetRemainingBlobSize(*image,&remaining) == MagickFalse) ||
+ (HeapOverflowSanityCheck(plane_size,(size_t) depth) != MagickFalse) ||
+ (plane_size*(size_t) depth > remaining))
+ return(MagickFalse);
+ planes=(unsigned char **) AcquireQuantumMemory((size_t) depth,
+ sizeof(*planes));
+ if (planes == (unsigned char **) NULL)
+ return(MagickFalse);
+ (void) memset(planes,0,(size_t) depth*sizeof(*planes));
+ for (p_idx=0; p_idx < (size_t) depth; p_idx++)
+ {
+ planes[p_idx]=(unsigned char *) AcquireQuantumMemory(plane_size,
+ sizeof(*planes[p_idx]));
+ if ((planes[p_idx] == (unsigned char *) NULL) ||
+ (ReadBlob(*image,plane_size,planes[p_idx]) != (ssize_t) plane_size))
+ {
+ planes=RelinquishPlanes(planes,(size_t) depth);
+ return(MagickFalse);
+ }
+ }
+ if (user_data & 255)
+ {
+ palette=AmigaWB2x;
+ num_colors=8;
+ }
+ else
+ {
+ palette=AmigaWB1x;
+ num_colors=4;
+ }
+ if (AppendAmigaImage(image,(size_t) width,(size_t) height,
+ *scene,image_info,exception) == MagickFalse)
+ {
+ planes=RelinquishPlanes(planes,(size_t) depth);
+ return(MagickFalse);
+ }
+ render_status=MagickTrue;
+ for (y=0; y < (ssize_t) height; y++)
+ {
+ Quantum
+ *q;
+
+ ssize_t
+ x;
+
+ q=QueueAuthenticPixels(*image,0,y,(size_t) width,1,exception);
+ if (q == (Quantum *) NULL)
+ {
+ render_status=MagickFalse;
+ break;
+ }
+ for (x=0; x < (ssize_t) width; x++)
+ {
+ size_t
+ bit_idx,
+ byte_idx,
+ data_plane,
+ plane_num;
+
+ unsigned int
+ color_index;
+
+ byte_idx=(size_t) y*bytes_per_row+((size_t) x >> 3);
+ bit_idx=7-((size_t) x & 7);
+ color_index=0;
+ data_plane=0;
+ for (plane_num=0; plane_num < (size_t) depth; plane_num++)
+ {
+ if (plane_pick & (1 << plane_num))
+ {
+ if (data_plane < (size_t) depth)
+ color_index|=(unsigned int)
+ (((planes[data_plane][byte_idx] >> bit_idx) & 1) << plane_num);
+ data_plane++;
+ }
+ else if (plane_on_off & (1 << plane_num))
+ color_index|=(1U << plane_num);
+ }
+ if (color_index < num_colors)
+ {
+ SetPixelRed(*image,ScaleCharToQuantum(palette[color_index][0]),q);
+ SetPixelGreen(*image,ScaleCharToQuantum(palette[color_index][1]),q);
+ SetPixelBlue(*image,ScaleCharToQuantum(palette[color_index][2]),q);
+ }
+ else
+ {
+ SetPixelRed(*image,0,q);
+ SetPixelGreen(*image,0,q);
+ SetPixelBlue(*image,0,q);
+ }
+ if (color_index == 0)
+ SetPixelAlpha(*image,TransparentAlpha,q);
+ else
+ SetPixelAlpha(*image,OpaqueAlpha,q);
+ q+=(ptrdiff_t) GetPixelChannels(*image);
+ }
+ if (SyncAuthenticPixels(*image,exception) == MagickFalse)
+ {
+ render_status=MagickFalse;
+ break;
+ }
+ }
+ planes=RelinquishPlanes(planes,(size_t) depth);
+ if (render_status == MagickFalse)
+ {
+ if (*scene > 0)
+ DeleteImageFromList(image);
+ return(MagickFalse);
+ }
+ (*scene)++;
+ return(MagickTrue);
+}
+
+/*
+ Decode and render a NewIcon image from collected IM1=/IM2= lines.
+
+ Returns MagickTrue if an image was successfully decoded and rendered.
+*/
+static MagickBooleanType DecodeAndRenderNewIcon(Image **image,size_t *scene,
+ char **im_lines,size_t im_count,const ImageInfo *image_info,
+ ExceptionInfo *exception)
+{
+ char
+ *first_line;
+
+ size_t
+ bit_count,
+ bit_pos,
+ line_bits_alloc,
+ line_bits_bytes,
+ line_idx,
+ ni_depth,
+ ni_height,
+ ni_num_colors,
+ ni_transparent,
+ ni_width,
+ pal_idx,
+ pix_count;
+
+ unsigned char
+ *line_bits,
+ *ni_palette,
+ *ni_pixels;
+
+ if ((im_count == 0) || (im_lines == (char **) NULL))
+ return(MagickFalse);
+ first_line=im_lines[0];
+ if (strlen(first_line) < 5)
+ return(MagickFalse);
+ ni_transparent=((unsigned char) first_line[0] == 66) ? 1 : 0;
+ if (((unsigned char) first_line[1] < 33) ||
+ ((unsigned char) first_line[2] < 33) ||
+ ((unsigned char) first_line[3] < 33) ||
+ ((unsigned char) first_line[4] < 33))
+ return(MagickFalse);
+ ni_width=(size_t) ((unsigned char) first_line[1]-33);
+ ni_height=(size_t) ((unsigned char) first_line[2]-33);
+ ni_num_colors=(size_t) (((unsigned char) first_line[3]-33) << 6)+
+ (size_t) ((unsigned char) first_line[4]-33);
+ if ((ni_width == 0) || (ni_height == 0) || (ni_num_colors == 0) ||
+ (ni_width > MaxAmigaIconDimension) ||
+ (ni_height > MaxAmigaIconDimension) ||
+ (ni_num_colors > 256))
+ return(MagickFalse);
+ ni_depth=1;
+ while (((size_t) 1 << ni_depth) < ni_num_colors)
+ ni_depth++;
+ /*
+ Find max expanded bit count to size the reusable decode buffer.
+ */
+ line_bits_alloc=NewIconLineBitCount(first_line+5,strlen(first_line+5));
+ for (line_idx=1; line_idx < im_count; line_idx++)
+ {
+ size_t
+ ll;
+
+ ll=NewIconLineBitCount(im_lines[line_idx],strlen(im_lines[line_idx]));
+ if (ll > line_bits_alloc)
+ line_bits_alloc=ll;
+ }
+ line_bits_alloc+=7;
+ if (line_bits_alloc > MaxNewIconBitCount)
+ return(MagickFalse);
+ line_bits_bytes=(line_bits_alloc+7)/8+1;
+ line_bits=(unsigned char *) AcquireQuantumMemory(line_bits_bytes,
+ sizeof(*line_bits));
+ if (line_bits == (unsigned char *) NULL)
+ return(MagickFalse);
+ /*
+ First line: extract palette only, discard remaining bits.
+ */
+ (void) memset(line_bits,0,line_bits_bytes*sizeof(*line_bits));
+ bit_count=DecodeNewIconLine(first_line+5,strlen(first_line+5),line_bits,
+ line_bits_bytes,0);
+ if (bit_count < ni_num_colors*24)
+ {
+ line_bits=(unsigned char *) RelinquishMagickMemory(line_bits);
+ return(MagickFalse);
+ }
+ ni_palette=(unsigned char *) AcquireQuantumMemory(ni_num_colors*3+3,
+ sizeof(*ni_palette));
+ if (ni_palette == (unsigned char *) NULL)
+ {
+ line_bits=(unsigned char *) RelinquishMagickMemory(line_bits);
+ return(MagickFalse);
+ }
+ (void) memset(ni_palette,0,(ni_num_colors*3+3)*sizeof(*ni_palette));
+ bit_pos=0;
+ for (pal_idx=0; pal_idx < ni_num_colors; pal_idx++)
+ {
+ ni_palette[pal_idx*3]=(unsigned char) BitsToUInt(line_bits,bit_count,
+ &bit_pos,8);
+ ni_palette[pal_idx*3+1]=(unsigned char) BitsToUInt(line_bits,bit_count,
+ &bit_pos,8);
+ ni_palette[pal_idx*3+2]=(unsigned char) BitsToUInt(line_bits,bit_count,
+ &bit_pos,8);
+ }
+ /*
+ Subsequent lines: extract pixels per-line, discard leftover bits.
+ */
+ ni_pixels=(unsigned char *) AcquireQuantumMemory(ni_width*ni_height+1,
+ sizeof(*ni_pixels));
+ if (ni_pixels == (unsigned char *) NULL)
+ {
+ ni_palette=(unsigned char *) RelinquishMagickMemory(ni_palette);
+ line_bits=(unsigned char *) RelinquishMagickMemory(line_bits);
+ return(MagickFalse);
+ }
+ (void) memset(ni_pixels,0,(ni_width*ni_height+1)*sizeof(*ni_pixels));
+ pix_count=0;
+ for (line_idx=1; line_idx < im_count &&
+ pix_count < ni_width*ni_height; line_idx++)
+ {
+ size_t
+ lbp;
+
+ (void) memset(line_bits,0,line_bits_bytes*sizeof(*line_bits));
+ bit_count=DecodeNewIconLine(im_lines[line_idx],strlen(im_lines[line_idx]),
+ line_bits,line_bits_bytes,0);
+ lbp=0;
+ while ((lbp+ni_depth <= bit_count) && (pix_count < ni_width*ni_height))
+ ni_pixels[pix_count++]=(unsigned char) BitsToUInt(line_bits,bit_count,
+ &lbp,ni_depth);
+ }
+ line_bits=(unsigned char *) RelinquishMagickMemory(line_bits);
+ if (pix_count < ni_width*ni_height)
+ {
+ ni_pixels=(unsigned char *) RelinquishMagickMemory(ni_pixels);
+ ni_palette=(unsigned char *) RelinquishMagickMemory(ni_palette);
+ return(MagickFalse);
+ }
+ /*
+ Render NewIcon to image.
+ */
+ if (AppendAmigaImage(image,ni_width,ni_height,*scene,image_info,
+ exception) == MagickFalse)
+ {
+ ni_pixels=(unsigned char *) RelinquishMagickMemory(ni_pixels);
+ ni_palette=(unsigned char *) RelinquishMagickMemory(ni_palette);
+ return(MagickFalse);
+ }
+ if (RenderPalettedAmigaImage(*image,ni_width,ni_height,ni_pixels,pix_count,
+ ni_palette,ni_num_colors,ni_transparent ? MagickTrue : MagickFalse,0,
+ exception) == MagickFalse)
+ {
+ ni_pixels=(unsigned char *) RelinquishMagickMemory(ni_pixels);
+ ni_palette=(unsigned char *) RelinquishMagickMemory(ni_palette);
+ if (*scene > 0)
+ DeleteImageFromList(image);
+ return(MagickFalse);
+ }
+ ni_pixels=(unsigned char *) RelinquishMagickMemory(ni_pixels);
+ ni_palette=(unsigned char *) RelinquishMagickMemory(ni_palette);
+ (*scene)++;
+ return(MagickTrue);
+}
+
+/*
+ Read the ToolTypes string table and decode NewIcon (IM1=/IM2=) images
+ found in it. Returns AmigaIconChunkContinue on success,
+ AmigaIconChunkStop when the table is truncated (keep the images decoded
+ so far) and AmigaIconChunkFatal on hard failures (exception is set).
+*/
+static AmigaIconChunkStatus ReadToolTypesNewIcons(Image **image,size_t *scene,
+ const ImageInfo *image_info,ExceptionInfo *exception)
+{
+ char
+ **im1_lines,
+ **im2_lines,
+ **tooltypes;
+
+ MagickBooleanType
+ newicon_failure,
+ tooltypes_corrupt,
+ tooltypes_resource_failure;
+
+ size_t
+ im1_alloc,
+ im1_count,
+ im2_alloc,
+ im2_count,
+ num_entries,
+ remaining,
+ tt_idx;
+
+ unsigned int
+ count_field;
+
+ if (EOFBlob(*image) != MagickFalse)
+ return(AmigaIconChunkStop);
+ count_field=ReadBlobMSBLong(*image);
+ if (GetRemainingBlobSize(*image,&remaining) == MagickFalse)
+ return(AmigaIconChunkStop);
+ if (count_field < 8)
+ num_entries=0;
+ else
+ num_entries=(size_t) (count_field/4-1);
+ if ((num_entries > remaining/4) || (num_entries > MaxAmigaIconToolTypes))
+ return(AmigaIconChunkStop);
+ tooltypes=(char **) NULL;
+ if (num_entries > 0)
+ {
+ tooltypes=(char **) AcquireQuantumMemory(num_entries,
+ sizeof(*tooltypes));
+ if (tooltypes == (char **) NULL)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ ResourceLimitError,"MemoryAllocationFailed","`%s'",
+ (*image)->filename);
+ return(AmigaIconChunkFatal);
+ }
+ (void) memset(tooltypes,0,num_entries*sizeof(*tooltypes));
+ }
+ /*
+ Read all tooltype strings, collect IM1=/IM2= lines.
+ */
+ newicon_failure=MagickFalse;
+ tooltypes_corrupt=MagickFalse;
+ tooltypes_resource_failure=MagickFalse;
+ im1_lines=(char **) NULL;
+ im2_lines=(char **) NULL;
+ im1_count=0;
+ im1_alloc=0;
+ im2_count=0;
+ im2_alloc=0;
+ for (tt_idx=0; tt_idx < num_entries; tt_idx++)
+ {
+ unsigned int
+ text_len;
+
+ if (EOFBlob(*image) != MagickFalse)
+ break;
+ text_len=ReadBlobMSBLong(*image);
+ if ((GetRemainingBlobSize(*image,&remaining) == MagickFalse) ||
+ (text_len == 0) || ((size_t) text_len > remaining) ||
+ (text_len == UINT_MAX))
+ {
+ tooltypes_corrupt=MagickTrue;
+ break;
+ }
+ tooltypes[tt_idx]=(char *) AcquireQuantumMemory((size_t) text_len+1,
+ sizeof(char));
+ if (tooltypes[tt_idx] == (char *) NULL)
+ {
+ tooltypes_resource_failure=MagickTrue;
+ break;
+ }
+ if (ReadBlob(*image,text_len,(unsigned char *) tooltypes[tt_idx]) !=
+ (ssize_t) text_len)
+ {
+ tooltypes[tt_idx]=(char *) RelinquishMagickMemory(tooltypes[tt_idx]);
+ tooltypes[tt_idx]=(char *) NULL;
+ tooltypes_corrupt=MagickTrue;
+ break;
+ }
+ tooltypes[tt_idx][text_len]='\0';
+ if (strncmp(tooltypes[tt_idx],"IM1=",4) == 0)
+ {
+ if (im1_count >= im1_alloc)
+ {
+ char
+ **new_lines;
+
+ im1_alloc=im1_alloc == 0 ? 16 : im1_alloc*2;
+ new_lines=(char **) ResizeQuantumMemory(im1_lines,im1_alloc,
+ sizeof(*im1_lines));
+ if (new_lines == (char **) NULL)
+ {
+ tooltypes_resource_failure=MagickTrue;
+ break;
+ }
+ im1_lines=new_lines;
+ }
+ im1_lines[im1_count++]=tooltypes[tt_idx]+4;
+ }
+ else if (strncmp(tooltypes[tt_idx],"IM2=",4) == 0)
+ {
+ if (im2_count >= im2_alloc)
+ {
+ char
+ **new_lines;
+
+ im2_alloc=im2_alloc == 0 ? 16 : im2_alloc*2;
+ new_lines=(char **) ResizeQuantumMemory(im2_lines,im2_alloc,
+ sizeof(*im2_lines));
+ if (new_lines == (char **) NULL)
+ {
+ tooltypes_resource_failure=MagickTrue;
+ break;
+ }
+ im2_lines=new_lines;
+ }
+ im2_lines[im2_count++]=tooltypes[tt_idx]+4;
+ }
+ }
+ /*
+ Decode NewIcon from IM1= and IM2= lines.
+ */
+ if ((tooltypes_corrupt == MagickFalse) &&
+ (tooltypes_resource_failure == MagickFalse))
+ {
+ if ((DecodeAndRenderNewIcon(image,scene,im1_lines,im1_count,
+ image_info,exception) == MagickFalse) &&
+ (exception->severity >= ErrorException))
+ newicon_failure=MagickTrue;
+ if ((newicon_failure == MagickFalse) &&
+ (DecodeAndRenderNewIcon(image,scene,im2_lines,im2_count,
+ image_info,exception) == MagickFalse) &&
+ (exception->severity >= ErrorException))
+ newicon_failure=MagickTrue;
+ }
+ if (im1_lines != (char **) NULL)
+ im1_lines=(char **) RelinquishMagickMemory(im1_lines);
+ if (im2_lines != (char **) NULL)
+ im2_lines=(char **) RelinquishMagickMemory(im2_lines);
+ if (tooltypes != (char **) NULL)
+ {
+ for (tt_idx=0; tt_idx < num_entries; tt_idx++)
+ if (tooltypes[tt_idx] != (char *) NULL)
+ tooltypes[tt_idx]=(char *)
+ RelinquishMagickMemory(tooltypes[tt_idx]);
+ tooltypes=(char **) RelinquishMagickMemory(tooltypes);
+ }
+ if (tooltypes_resource_failure != MagickFalse)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ ResourceLimitError,"MemoryAllocationFailed","`%s'",
+ (*image)->filename);
+ return(AmigaIconChunkFatal);
+ }
+ if (tooltypes_corrupt != MagickFalse)
+ return(AmigaIconChunkStop);
+ if (newicon_failure != MagickFalse)
+ return(AmigaIconChunkFatal);
+ return(AmigaIconChunkContinue);
+}
+
+/*
+ Decode and render one GlowIcon IMAG chunk. A palette-less IMAG reuses
+ the previous chunk's palette via last_pal_data and last_pal_count; a
+ rendered chunk's own palette replaces the saved one.
+*/
+static AmigaIconChunkStatus DecodeAndRenderGlowIcon(Image **image,
+ size_t *scene,const unsigned char *chunk,size_t chunk_size,
+ size_t icon_width,size_t icon_height,unsigned char **last_pal_data,
+ size_t *last_pal_count,const ImageInfo *image_info,
+ ExceptionInfo *exception)
+{
+ const unsigned char
+ *render_pal;
+
+ MagickBooleanType
+ rle_complete,
+ status;
+
+ size_t
+ image_size,
+ num_pal_colors,
+ pal_count,
+ palette_size,
+ pixel_count,
+ render_pal_entries;
+
+ unsigned char
+ has_palette,
+ has_transparent,
+ imag_depth,
+ imag_flags,
+ image_format,
+ num_colors_m1,
+ *pal_data,
+ palette_format,
+ *pixel_data,
+ transparent_color;
+
+ if ((chunk_size < 10) || (icon_width == 0) || (icon_height == 0) ||
+ (icon_width > MaxAmigaIconDimension) ||
+ (icon_height > MaxAmigaIconDimension))
+ return(AmigaIconChunkContinue);
+ transparent_color=chunk[0];
+ num_colors_m1=chunk[1];
+ imag_flags=chunk[2];
+ image_format=chunk[3];
+ palette_format=chunk[4];
+ imag_depth=chunk[5];
+ image_size=(((size_t) chunk[6] << 8) | (size_t) chunk[7])+1;
+ palette_size=(((size_t) chunk[8] << 8) | (size_t) chunk[9])+1;
+ has_transparent=(imag_flags & 1) ? 1 : 0;
+ has_palette=(imag_flags & 2) ? 1 : 0;
+ num_pal_colors=(size_t) num_colors_m1+1;
+ if ((imag_depth == 0) || (imag_depth > 8) || (image_size > chunk_size-10))
+ return(AmigaIconChunkStop);
+ /*
+ Decode image pixels.
+ */
+ if (image_format == 1)
+ {
+ rle_complete=MagickFalse;
+ pixel_data=DecodeAmigaRLE(chunk+10,image_size,(size_t) imag_depth,
+ icon_width*icon_height,&pixel_count,&rle_complete);
+ if ((pixel_data != (unsigned char *) NULL) &&
+ (rle_complete == MagickFalse))
+ {
+ pixel_data=(unsigned char *) RelinquishMagickMemory(pixel_data);
+ return(AmigaIconChunkStop);
+ }
+ }
+ else
+ {
+ pixel_count=image_size;
+ if (pixel_count > icon_width*icon_height)
+ pixel_count=icon_width*icon_height;
+ pixel_data=(unsigned char *) AcquireQuantumMemory(pixel_count+1,
+ sizeof(*pixel_data));
+ if (pixel_data != (unsigned char *) NULL)
+ (void) memcpy(pixel_data,chunk+10,pixel_count);
+ }
+ if (pixel_data == (unsigned char *) NULL)
+ return(AmigaIconChunkStop);
+ /*
+ Decode palette.
+ */
+ pal_data=(unsigned char *) NULL;
+ pal_count=0;
+ if (has_palette && (palette_size <= chunk_size-10-image_size))
+ {
+ if (palette_format == 1)
+ {
+ rle_complete=MagickFalse;
+ pal_data=DecodeAmigaRLE(chunk+10+image_size,palette_size,8,
+ num_pal_colors*3,&pal_count,&rle_complete);
+ if ((pal_data != (unsigned char *) NULL) &&
+ (rle_complete == MagickFalse))
+ {
+ pal_data=(unsigned char *) RelinquishMagickMemory(pal_data);
+ pixel_data=(unsigned char *)
+ RelinquishMagickMemory(pixel_data);
+ return(AmigaIconChunkStop);
+ }
+ }
+ else
+ {
+ pal_count=palette_size;
+ if (pal_count > num_pal_colors*3)
+ pal_count=num_pal_colors*3;
+ pal_data=(unsigned char *) AcquireQuantumMemory(pal_count+1,
+ sizeof(*pal_data));
+ if (pal_data != (unsigned char *) NULL)
+ (void) memcpy(pal_data,chunk+10+image_size,pal_count);
+ }
+ }
+ if (pal_data != (unsigned char *) NULL)
+ {
+ render_pal=pal_data;
+ render_pal_entries=pal_count/3;
+ }
+ else
+ {
+ render_pal=*last_pal_data;
+ render_pal_entries=*last_pal_count/3;
+ }
+ status=AppendAmigaImage(image,icon_width,icon_height,*scene,image_info,
+ exception);
+ if (status != MagickFalse)
+ status=RenderPalettedAmigaImage(*image,icon_width,icon_height,pixel_data,
+ pixel_count,render_pal,render_pal_entries,has_transparent ? MagickTrue :
+ MagickFalse,transparent_color,exception);
+ pixel_data=(unsigned char *) RelinquishMagickMemory(pixel_data);
+ if (status == MagickFalse)
+ {
+ if (pal_data != (unsigned char *) NULL)
+ pal_data=(unsigned char *) RelinquishMagickMemory(pal_data);
+ return(AmigaIconChunkFatal);
+ }
+ if (pal_data != (unsigned char *) NULL)
+ {
+ if (*last_pal_data != (unsigned char *) NULL)
+ *last_pal_data=(unsigned char *)
+ RelinquishMagickMemory(*last_pal_data);
+ *last_pal_data=pal_data;
+ *last_pal_count=pal_count;
+ }
+ (*scene)++;
+ return(AmigaIconChunkContinue);
+}
+
+#if defined(MAGICKCORE_ZLIB_DELEGATE)
+/*
+ Decode and render one zlib-compressed ARGB chunk (OS4-style icons).
+*/
+static AmigaIconChunkStatus DecodeAndRenderARGBIcon(Image **image,
+ size_t *scene,const unsigned char *chunk,size_t chunk_size,
+ size_t icon_width,size_t icon_height,const ImageInfo *image_info,
+ ExceptionInfo *exception)
+{
+ ssize_t
+ y;
+
+ uLongf
+ raw_size;
+
+ unsigned char
+ *argb_raw;
+
+ if ((chunk_size <= 10) || (icon_width == 0) || (icon_height == 0) ||
+ (icon_width > MaxAmigaIconDimension) ||
+ (icon_height > MaxAmigaIconDimension))
+ return(AmigaIconChunkContinue);
+ raw_size=(uLongf) (icon_width*icon_height*4);
+ argb_raw=(unsigned char *) AcquireQuantumMemory((size_t) raw_size+1,
+ sizeof(*argb_raw));
+ if (argb_raw == (unsigned char *) NULL)
+ return(AmigaIconChunkContinue);
+ if (uncompress(argb_raw,&raw_size,chunk+10,(uLong) (chunk_size-10)) != Z_OK)
+ {
+ argb_raw=(unsigned char *) RelinquishMagickMemory(argb_raw);
+ return(AmigaIconChunkContinue);
+ }
+ if (AppendAmigaImage(image,icon_width,icon_height,*scene,image_info,
+ exception) == MagickFalse)
+ {
+ argb_raw=(unsigned char *) RelinquishMagickMemory(argb_raw);
+ return(AmigaIconChunkFatal);
+ }
+ for (y=0; y < (ssize_t) icon_height; y++)
+ {
+ Quantum
+ *q;
+
+ ssize_t
+ x;
+
+ q=QueueAuthenticPixels(*image,0,y,icon_width,1,exception);
+ if (q == (Quantum *) NULL)
+ break;
+ for (x=0; x < (ssize_t) icon_width; x++)
+ {
+ size_t
+ pi;
+
+ pi=((size_t) y*icon_width+(size_t) x)*4;
+ if (pi+3 < (size_t) raw_size)
+ SetAmigaPixelRGBA(*image,q,argb_raw[pi+1],argb_raw[pi+2],
+ argb_raw[pi+3],argb_raw[pi]);
+ else
+ SetAmigaPixelRGBA(*image,q,0,0,0,0);
+ q+=(ptrdiff_t) GetPixelChannels(*image);
+ }
+ if (SyncAuthenticPixels(*image,exception) == MagickFalse)
+ break;
+ }
+ argb_raw=(unsigned char *) RelinquishMagickMemory(argb_raw);
+ if (y < (ssize_t) icon_height)
+ return(AmigaIconChunkFatal);
+ (*scene)++;
+ return(AmigaIconChunkContinue);
+}
+#endif
+
+/*
+ Walk the IFF chunks of a FORM ICON (FACE, IMAG, ARGB) and render each
+ image found. Returns MagickFalse only on a fatal error; a malformed
+ chunk stops the walk but keeps any images already decoded.
+*/
+static MagickBooleanType ParseFormIconChunks(Image **image,size_t *scene,
+ const unsigned char *chunks,size_t chunks_size,const ImageInfo *image_info,
+ ExceptionInfo *exception)
+{
+ AmigaIconChunkStatus
+ chunk_status;
+
+ size_t
+ chunk_pos,
+ image_chunks,
+ icon_height,
+ icon_width,
+ last_pal_count;
+
+ unsigned char
+ *last_pal_data;
+
+ chunk_pos=0;
+ image_chunks=0;
+ icon_width=0;
+ icon_height=0;
+ last_pal_data=(unsigned char *) NULL;
+ last_pal_count=0;
+ chunk_status=AmigaIconChunkContinue;
+ while (chunk_pos+8 <= chunks_size)
+ {
+ const unsigned char
+ *chunk_id;
+
+ size_t
+ chunk_data,
+ chunk_size;
+
+ chunk_id=chunks+chunk_pos;
+ chunk_size=((size_t) chunks[chunk_pos+4] << 24) |
+ ((size_t) chunks[chunk_pos+5] << 16) |
+ ((size_t) chunks[chunk_pos+6] << 8) |
+ (size_t) chunks[chunk_pos+7];
+ chunk_data=chunk_pos+8;
+ if ((chunk_size == 0) || (chunk_size > chunks_size-chunk_data))
+ break;
+ chunk_pos=chunk_data+chunk_size;
+ if (chunk_size & 1)
+ chunk_pos++; /* IFF padding */
+ if (memcmp(chunk_id,"FACE",4) == 0)
+ {
+ if (chunk_size >= 4)
+ {
+ icon_width=(size_t) chunks[chunk_data]+1;
+ icon_height=(size_t) chunks[chunk_data+1]+1;
+ }
+ }
+ else if (memcmp(chunk_id,"IMAG",4) == 0)
+ {
+ if ((*scene >= MaxAmigaIconScenes) ||
+ (image_chunks >= MaxAmigaIconImageChunks))
+ chunk_status=AmigaIconChunkStop;
+ else
+ {
+ image_chunks++;
+ chunk_status=DecodeAndRenderGlowIcon(image,scene,
+ chunks+chunk_data,chunk_size,icon_width,icon_height,
+ &last_pal_data,&last_pal_count,image_info,exception);
+ }
+ }
+#if defined(MAGICKCORE_ZLIB_DELEGATE)
+ else if (memcmp(chunk_id,"ARGB",4) == 0)
+ {
+ if ((*scene >= MaxAmigaIconScenes) ||
+ (image_chunks >= MaxAmigaIconImageChunks))
+ chunk_status=AmigaIconChunkStop;
+ else
+ {
+ image_chunks++;
+ chunk_status=DecodeAndRenderARGBIcon(image,scene,
+ chunks+chunk_data,chunk_size,icon_width,icon_height,image_info,
+ exception);
+ }
+ }
+#endif
+ if (chunk_status != AmigaIconChunkContinue)
+ break;
+ }
+ if (last_pal_data != (unsigned char *) NULL)
+ last_pal_data=(unsigned char *) RelinquishMagickMemory(last_pal_data);
+ return(chunk_status == AmigaIconChunkFatal ? MagickFalse : MagickTrue);
+}
+
+/*
+ Finish a read whose trailing sections (text fields, tooltypes or
+ DrawerData2) are truncated. Real-world icons are often cut short after
+ the image data, so keep the images already decoded and warn.
+*/
+static Image *FinishTruncatedWBINFO(Image *image,const ImageInfo *image_info,
+ ExceptionInfo *exception)
+{
+ (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageWarning,
+ "InsufficientImageDataInFile","`%s'",image_info->filename);
+ if (CloseBlob(image) == MagickFalse)
+ return(DestroyImageList(image));
+ return(GetFirstImageInList(image));
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% I s W B I N F O %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% IsWBINFO() returns MagickTrue if the image format type, identified by
+% the magick string, is an Amiga Workbench icon file.
+%
+% The format of the IsWBINFO method is:
+%
+% MagickBooleanType IsWBINFO(const unsigned char *magick,
+% const size_t length)
+%
+*/
+static MagickBooleanType IsWBINFO(const unsigned char *magick,
+ const size_t length)
+{
+ if (length < 2)
+ return(MagickFalse);
+ if ((magick[0] == 0xE3) && (magick[1] == 0x10))
+ return(MagickTrue);
+ return(MagickFalse);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% R e a d W B I N F O I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ReadWBINFOImage() reads an Amiga Workbench .info icon file and returns
+% it as one or more images. Each icon generation (Classic, NewIcon,
+% GlowIcon, ARGB) becomes a separate image in the returned list.
+%
+% The format of the ReadWBINFOImage method is:
+%
+% Image *ReadWBINFOImage(const ImageInfo *image_info,
+% ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image_info: the image info.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+static Image *ReadWBINFOImage(const ImageInfo *image_info,
+ ExceptionInfo *exception)
+{
+ Image
+ *image;
+
+ MagickBooleanType
+ status;
+
+ size_t
+ scene;
+
+ unsigned int
+ gadget_render,
+ has_default_tool,
+ has_drawer_data,
+ has_tool_window,
+ has_tooltypes,
+ select_render,
+ user_data;
+
+ unsigned short
+ magic;
+
+ /*
+ Open image file.
+ */
+ assert(image_info != (const ImageInfo *) NULL);
+ assert(image_info->signature == MagickCoreSignature);
+ assert(exception != (ExceptionInfo *) NULL);
+ assert(exception->signature == MagickCoreSignature);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s",
+ image_info->filename);
+ image=AcquireImage(image_info,exception);
+ status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
+ if (status == MagickFalse)
+ {
+ image=DestroyImageList(image);
+ return((Image *) NULL);
+ }
+ /*
+ Read 78-byte DiskObject header (big-endian).
+ */
+ magic=ReadBlobMSBShort(image);
+ if (magic != AmigaIconMagic)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ /*
+ Skip version(2) and the embedded Gadget up to gadget_render: next(4),
+ left_edge(2), top_edge(2), width(2), height(2), flags(2), activation(2),
+ gadget_type(2).
+ */
+ if (SeekBlob(image,20,SEEK_CUR) < 0)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ gadget_render=ReadBlobMSBLong(image);
+ select_render=ReadBlobMSBLong(image);
+ /* gadget_text(4), mutual_exclude(4), special_info(4), gadget_id(2) */
+ if (SeekBlob(image,14,SEEK_CUR) < 0)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ user_data=ReadBlobMSBLong(image);
+ /* End of embedded Gadget, now at offset 48: icon_type(1), padding(1) */
+ if (SeekBlob(image,2,SEEK_CUR) < 0)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ has_default_tool=ReadBlobMSBLong(image);
+ has_tooltypes=ReadBlobMSBLong(image);
+ /* current_x(4), current_y(4) */
+ if (SeekBlob(image,8,SEEK_CUR) < 0)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ has_drawer_data=ReadBlobMSBLong(image);
+ has_tool_window=ReadBlobMSBLong(image);
+ /* stack_size(4), now at offset 78 */
+ if (SeekBlob(image,4,SEEK_CUR) < 0)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ if (EOFBlob(image) != MagickFalse)
+ ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
+ scene=0;
+ /*
+ Skip DrawerData (56 bytes) if present.
+ */
+ if (has_drawer_data)
+ {
+ size_t
+ remaining;
+
+ if ((GetRemainingBlobSize(image,&remaining) == MagickFalse) ||
+ (remaining < 56))
+ ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
+ if (SeekBlob(image,56,SEEK_CUR) < 0)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ }
+ /*
+ Read classic planar image(s).
+ */
+ if (gadget_render)
+ {
+ if (ReadAndRenderClassicImage(&image,&scene,user_data,image_info,
+ exception) == MagickFalse)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ }
+ if (select_render)
+ {
+ if (ReadAndRenderClassicImage(&image,&scene,user_data,image_info,
+ exception) == MagickFalse)
+ {
+ if (scene == 0)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ return(FinishTruncatedWBINFO(image,image_info,exception));
+ }
+ }
+ /*
+ Skip DefaultTool if present.
+ */
+ if (has_default_tool)
+ {
+ size_t
+ remaining;
+
+ unsigned int
+ text_len;
+
+ text_len=ReadBlobMSBLong(image);
+ if ((GetRemainingBlobSize(image,&remaining) == MagickFalse) ||
+ ((size_t) text_len > remaining))
+ {
+ if (scene == 0)
+ ThrowReaderException(CorruptImageError,
+ "InsufficientImageDataInFile");
+ return(FinishTruncatedWBINFO(image,image_info,exception));
+ }
+ if (SeekBlob(image,(MagickOffsetType) text_len,SEEK_CUR) < 0)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ }
+ /*
+ Read ToolTypes and decode NewIcons if present.
+ */
+ if (has_tooltypes)
+ {
+ AmigaIconChunkStatus
+ tooltypes_status;
+
+ tooltypes_status=ReadToolTypesNewIcons(&image,&scene,image_info,
+ exception);
+ if (tooltypes_status == AmigaIconChunkFatal)
+ return(DestroyImageList(image));
+ if (tooltypes_status == AmigaIconChunkStop)
+ {
+ if (scene == 0)
+ ThrowReaderException(CorruptImageError,
+ "InsufficientImageDataInFile");
+ return(FinishTruncatedWBINFO(image,image_info,exception));
+ }
+ }
+ /*
+ Skip ToolWindow if present.
+ */
+ if (has_tool_window)
+ {
+ size_t
+ remaining;
+
+ unsigned int
+ text_len;
+
+ text_len=ReadBlobMSBLong(image);
+ if ((GetRemainingBlobSize(image,&remaining) == MagickFalse) ||
+ ((size_t) text_len > remaining))
+ {
+ if (scene == 0)
+ ThrowReaderException(CorruptImageError,
+ "InsufficientImageDataInFile");
+ return(FinishTruncatedWBINFO(image,image_info,exception));
+ }
+ if (SeekBlob(image,(MagickOffsetType) text_len,SEEK_CUR) < 0)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ }
+ /*
+ Skip DrawerData2 (6 bytes) if present.
+ */
+ if (has_drawer_data && (user_data & 255))
+ {
+ size_t
+ remaining;
+
+ if ((GetRemainingBlobSize(image,&remaining) == MagickFalse) ||
+ (remaining < 6))
+ {
+ if (scene == 0)
+ ThrowReaderException(CorruptImageError,
+ "InsufficientImageDataInFile");
+ return(FinishTruncatedWBINFO(image,image_info,exception));
+ }
+ if (SeekBlob(image,6,SEEK_CUR) < 0)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ }
+ /*
+ Scan for FORM ICON (GlowIcons and ARGB images).
+ Read a bounded tail buffer and search for "FORM" + "ICON".
+ */
+ {
+ size_t
+ remaining;
+
+ if ((GetRemainingBlobSize(image,&remaining) != MagickFalse) &&
+ (remaining > 16) && (remaining <= MaxAmigaIconFormScanSize))
+ {
+ unsigned char
+ *rest_data;
+
+ rest_data=(unsigned char *) AcquireQuantumMemory(remaining,
+ sizeof(*rest_data));
+ if (rest_data != (unsigned char *) NULL)
+ {
+ ssize_t
+ bytes_read;
+
+ bytes_read=ReadBlob(image,remaining,rest_data);
+ if (bytes_read > 12)
+ {
+ size_t
+ search_pos;
+
+ for (search_pos=0; search_pos+12 <= (size_t) bytes_read;
+ search_pos++)
+ {
+ size_t
+ form_size;
+
+ if ((memcmp(rest_data+search_pos,"FORM",4) != 0) ||
+ (memcmp(rest_data+search_pos+8,"ICON",4) != 0))
+ continue;
+ form_size=((size_t) rest_data[search_pos+4] << 24) |
+ ((size_t) rest_data[search_pos+5] << 16) |
+ ((size_t) rest_data[search_pos+6] << 8) |
+ (size_t) rest_data[search_pos+7];
+ if (form_size > (size_t) bytes_read-search_pos-8)
+ continue; /* truncated FORM, skip */
+ if ((form_size >= 4) &&
+ (ParseFormIconChunks(&image,&scene,
+ rest_data+search_pos+12,form_size-4,image_info,
+ exception) == MagickFalse))
+ {
+ rest_data=(unsigned char *)
+ RelinquishMagickMemory(rest_data);
+ return(DestroyImageList(image));
+ }
+ break; /* only process first FORM ICON */
+ }
+ }
+ rest_data=(unsigned char *) RelinquishMagickMemory(rest_data);
+ }
+ }
+ }
+
+ if (scene == 0)
+ ThrowReaderException(ImageError,"NoImagesWereFound");
+ if (CloseBlob(image) == MagickFalse)
+ return(DestroyImageList(image));
+ return(GetFirstImageInList(image));
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% R e g i s t e r W B I N F O I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% RegisterWBINFOImage() adds attributes for the Amiga Workbench Icon format to
+% the list of supported formats.
+%
+% The format of the RegisterWBINFOImage method is:
+%
+% size_t RegisterWBINFOImage(void)
+%
+*/
+ModuleExport size_t RegisterWBINFOImage(void)
+{
+ MagickInfo
+ *entry;
+
+ entry=AcquireMagickInfo("WBINFO","WBINFO","Amiga Workbench Icon");
+ entry->decoder=(DecodeImageHandler *) ReadWBINFOImage;
+ entry->magick=(IsImageFormatHandler *) IsWBINFO;
+ entry->flags^=CoderAdjoinFlag;
+ entry->flags|=CoderDecoderSeekableStreamFlag;
+ entry->mime_type=ConstantString("image/x-amiga-icon");
+ (void) RegisterMagickInfo(entry);
+ return(MagickImageCoderSignature);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% U n r e g i s t e r W B I N F O I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% UnregisterWBINFOImage() removes format registrations made by the
+% WBINFO module from the list of supported formats.
+%
+% The format of the UnregisterWBINFOImage method is:
+%
+% UnregisterWBINFOImage(void)
+%
+*/
+ModuleExport void UnregisterWBINFOImage(void)
+{
+ (void) UnregisterMagickInfo("WBINFO");
+}
diff --git a/coders/wbinfo.h b/coders/wbinfo.h
new file mode 100644
index 000000000..60d533135
--- /dev/null
+++ b/coders/wbinfo.h
@@ -0,0 +1,32 @@
+/*
+ Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization
+ dedicated to making software imaging solutions freely available.
+
+ You may not use this file except in compliance with the License. You may
+ obtain a copy of the License at
+
+ https://imagemagick.org/license/
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include "coders/coders-private.h"
+
+#define MagickWBINFOHeaders \
+ MagickCoderHeader("WBINFO", 0, "\xe3\x10")
+
+#define MagickWBINFOAliases
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+MagickCoderExports(WBINFO)
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif