xpm.c revision 4cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7
1afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/* 27c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell% % 47c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell% % 57c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell% % 67c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell% X X PPPP M M % 77c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell% X X P P MM MM % 87c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell% X PPPP M M M % 9afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner% X X P M M % 10efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner% X X P M M % 11efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner% % 12afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner% % 13afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner% Read/Write X Windows system Pixmap Format % 14afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner% % 15afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner% Software Design % 16e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman% John Cristy % 17afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner% July 1992 % 18afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner% % 19d1a85a744cc1001c2b7fc37cf37aca266964f519Brian Gaeke% % 20e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization % 21e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman% dedicated to making software imaging solutions freely available. % 22afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner% % 236520785dcd22012535934098942d57c07c7631c2Chris Lattner% You may not use this file except in compliance with the License. You may % 24afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner% obtain a copy of the License at % 255e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner% % 265da69c79f9c4490c6657c207430dfeb1060fc4ddChris Lattner% http://www.imagemagick.org/script/license.php % 27551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer% % 28551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer% Unless required by applicable law or agreed to in writing, software % 29551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer% distributed under the License is distributed on an "AS IS" BASIS, % 30fb4b96e77e2930bf3d0c148f1c3685b6a4434666Chris Lattner% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner% See the License for the specific language governing permissions and % 32d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke% limitations under the License. % 33d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke% % 34c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke% 36d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke% 376db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner*/ 386db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner 396db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner/* 406db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner Include declarations. 4147ae4a1cee5eec5767a11403c0fac7c91ec45461Chris Lattner*/ 4247ae4a1cee5eec5767a11403c0fac7c91ec45461Chris Lattner#include "magick/studio.h" 436db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner#include "magick/blob.h" 446db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner#include "magick/blob-private.h" 45afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "magick/cache.h" 466520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/color.h" 476520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/color-private.h" 486520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/colormap.h" 496520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/colorspace.h" 506520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/exception.h" 510cc8807029f577996a442b96d24c3346ed6de091Chris Lattner#include "magick/exception-private.h" 526520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/geometry.h" 536520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/image.h" 546520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/image-private.h" 550cc8807029f577996a442b96d24c3346ed6de091Chris Lattner#include "magick/list.h" 560cc8807029f577996a442b96d24c3346ed6de091Chris Lattner#include "magick/magick.h" 576520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/memory_.h" 586520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/monitor.h" 590cc8807029f577996a442b96d24c3346ed6de091Chris Lattner#include "magick/monitor-private.h" 600cc8807029f577996a442b96d24c3346ed6de091Chris Lattner#include "magick/pixel-private.h" 616520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/quantize.h" 626520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/quantum-private.h" 630cc8807029f577996a442b96d24c3346ed6de091Chris Lattner#include "magick/resize.h" 646520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/resource_.h" 656520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/splay-tree.h" 660cc8807029f577996a442b96d24c3346ed6de091Chris Lattner#include "magick/static.h" 670cc8807029f577996a442b96d24c3346ed6de091Chris Lattner#include "magick/string_.h" 686520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/module.h" 696520785dcd22012535934098942d57c07c7631c2Chris Lattner#include "magick/threshold.h" 700cc8807029f577996a442b96d24c3346ed6de091Chris Lattner#include "magick/utility.h" 710cc8807029f577996a442b96d24c3346ed6de091Chris Lattner 726520785dcd22012535934098942d57c07c7631c2Chris Lattner/* 736520785dcd22012535934098942d57c07c7631c2Chris Lattner Forward declarations. 740cc8807029f577996a442b96d24c3346ed6de091Chris Lattner*/ 756520785dcd22012535934098942d57c07c7631c2Chris Lattnerstatic MagickBooleanType 7644be25716628941b4cccccf56a28ee0ba2606850Chris Lattner WritePICONImage(const ImageInfo *,Image *), 776520785dcd22012535934098942d57c07c7631c2Chris Lattner WriteXPMImage(const ImageInfo *,Image *); 785da69c79f9c4490c6657c207430dfeb1060fc4ddChris Lattner 795da69c79f9c4490c6657c207430dfeb1060fc4ddChris Lattner/* 805da69c79f9c4490c6657c207430dfeb1060fc4ddChris Lattner%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 81efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner% % 82efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner% % 836db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner% % 846520785dcd22012535934098942d57c07c7631c2Chris Lattner% I s X P M % 8547ae4a1cee5eec5767a11403c0fac7c91ec45461Chris Lattner% % 866520785dcd22012535934098942d57c07c7631c2Chris Lattner% % 8710f22cb1a0f2755050218cd0e07221a0985c6b63Chris Lattner% % 8810f22cb1a0f2755050218cd0e07221a0985c6b63Chris Lattner%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 896520785dcd22012535934098942d57c07c7631c2Chris Lattner% 906520785dcd22012535934098942d57c07c7631c2Chris Lattner% IsXPM() returns MagickTrue if the image format type, identified by the 916520785dcd22012535934098942d57c07c7631c2Chris Lattner% magick string, is XPM. 92ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner% 93fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner% The format of the IsXPM method is: 94fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner% 95fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner% MagickBooleanType IsXPM(const unsigned char *magick,const size_t length) 96fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner% 97fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner% A description of each parameter follows: 98fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner% 99ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner% o magick: compare image format pattern against these bytes. or 100ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner% blob. 101ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner% 102ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner% o length: Specifies the length of the magick string. 103fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner% 10428b8ed90c75ce6c271500fa778fef252f267a5ffChris Lattner*/ 10528b8ed90c75ce6c271500fa778fef252f267a5ffChris Lattnerstatic MagickBooleanType IsXPM(const unsigned char *magick,const size_t length) 10628b8ed90c75ce6c271500fa778fef252f267a5ffChris Lattner{ 107dbe48dcaec69ff78e39e2d5faf4323ade6fffb04Chris Lattner if (length < 9) 108fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner return(MagickFalse); 109fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner if (LocaleNCompare((char *) magick+1,"* XPM *",7) == 0) 110fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner return(MagickTrue); 111fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner return(MagickFalse); 112fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner} 113c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner 114c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner/* 115c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 116c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner% % 117fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner% % 118a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner% % 119a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner% R e a d X P M I m a g e % 1207546c3884a400b72d10fc19f120c6798b294a39dChris Lattner% % 121fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner% % 122a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner% % 123a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 124ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner% 125be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner% ReadXPMImage() reads an X11 pixmap image file and returns it. It 126be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner% allocates the memory necessary for the new Image structure and returns a 1277546c3884a400b72d10fc19f120c6798b294a39dChris Lattner% pointer to the new image. 1287546c3884a400b72d10fc19f120c6798b294a39dChris Lattner% 1297546c3884a400b72d10fc19f120c6798b294a39dChris Lattner% The format of the ReadXPMImage method is: 1307546c3884a400b72d10fc19f120c6798b294a39dChris Lattner% 1317546c3884a400b72d10fc19f120c6798b294a39dChris Lattner% Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception) 1327546c3884a400b72d10fc19f120c6798b294a39dChris Lattner% 1337546c3884a400b72d10fc19f120c6798b294a39dChris Lattner% A description of each parameter follows: 134a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner% 135a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner% o image_info: the image info. 136a1cf1c8c87f10f12343ff6ae75f332390e7205abChris Lattner% 137a1cf1c8c87f10f12343ff6ae75f332390e7205abChris Lattner% o exception: return any errors or warnings in this structure. 138a1cf1c8c87f10f12343ff6ae75f332390e7205abChris Lattner% 139a1cf1c8c87f10f12343ff6ae75f332390e7205abChris Lattner*/ 140a1cf1c8c87f10f12343ff6ae75f332390e7205abChris Lattner 1417546c3884a400b72d10fc19f120c6798b294a39dChris Lattnerstatic int CompareXPMColor(const void *target,const void *source) 1427546c3884a400b72d10fc19f120c6798b294a39dChris Lattner{ 143a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner const char 144a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner *p, 145a269ec7b0a83d3b20730fd2d9f7c3ed5a552da90Chris Lattner *q; 146a269ec7b0a83d3b20730fd2d9f7c3ed5a552da90Chris Lattner 147a269ec7b0a83d3b20730fd2d9f7c3ed5a552da90Chris Lattner p=(const char *) target; 14890c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattner q=(const char *) source; 149a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner return(strcmp(p,q)); 150a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner} 15190c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattner 15290c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattnerstatic char *CopyXPMColor(char *destination,const char *source,size_t length) 15390c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattner{ 15490c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattner while (length-- && (*source != '\0')) 15590c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattner *destination++=(*source++); 156a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner *destination='\0'; 157a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner return(destination-length); 158a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner} 1597546c3884a400b72d10fc19f120c6798b294a39dChris Lattner 1607546c3884a400b72d10fc19f120c6798b294a39dChris Lattnerstatic char *NextXPMLine(char *p) 1617546c3884a400b72d10fc19f120c6798b294a39dChris Lattner{ 162be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner assert(p != (char*)NULL); 163be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner p=strchr(p,'\n'); 164be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner if (p != (char *) NULL) 165be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner p++; 166be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner return(p); 167be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner} 168be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner 169be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattnerstatic inline size_t MagickMin(const size_t x,const size_t y) 170be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner{ 171be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner if (x < y) 172be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner return(x); 173be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner return(y); 1745eda1f2f65941a24ef9a5a85addf4d90eb13fa9dChris Lattner} 1755eda1f2f65941a24ef9a5a85addf4d90eb13fa9dChris Lattner 1765eda1f2f65941a24ef9a5a85addf4d90eb13fa9dChris Lattnerstatic char *ParseXPMColor(char *color) 1775eda1f2f65941a24ef9a5a85addf4d90eb13fa9dChris Lattner{ 1785eda1f2f65941a24ef9a5a85addf4d90eb13fa9dChris Lattner#define NumberTargets 6 179be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner 180be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner register char 181be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner *p, 182be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner *r; 183be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner 184be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner register const char 185be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner *q; 186be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner 187be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner register ssize_t 188be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner i; 189be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner 190be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner static const char 191be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner *targets[NumberTargets] = { "c ", "g ", "g4 ", "m ", "b ", "s " }; 192be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner 193be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner for (i=0; i < NumberTargets; i++) 194be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner { 195fb4b96e77e2930bf3d0c148f1c3685b6a4434666Chris Lattner p=color; 196be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner for (q=targets[i]; *p != '\0'; p++) 197fb4b96e77e2930bf3d0c148f1c3685b6a4434666Chris Lattner { 198be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner if (*p == '\n') 199be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner break; 200be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner if (*p != *q) 201be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner continue; 202be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner if (isspace((int) ((unsigned char) (*(p-1)))) == 0) 203be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner continue; 204be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner r=p; 205fb4b96e77e2930bf3d0c148f1c3685b6a4434666Chris Lattner for ( ; ; ) 206fb4b96e77e2930bf3d0c148f1c3685b6a4434666Chris Lattner { 207be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner if (*q == '\0') 208be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner return(p); 209be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner if (*r++ != *q++) 2105e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner break; 2115e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner } 2125e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner q=targets[i]; 2135e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner } 2145e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner } 2155e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner return((char *) NULL); 2165e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner} 2175e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2185e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattnerstatic Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception) 2195e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner{ 2205e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner char 221b12914bfc0f76a7a48357162d5f4c39a1343e69bChris Lattner key[MaxTextExtent], 222b12914bfc0f76a7a48357162d5f4c39a1343e69bChris Lattner target[MaxTextExtent], 2235e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner *xpm_buffer; 2245e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2255e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner Image 2265e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner *image; 2275e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 228b12914bfc0f76a7a48357162d5f4c39a1343e69bChris Lattner ssize_t 2295e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner j, 2305e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner y; 2315e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2325e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner MagickBooleanType 2335e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner active, 2345e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner status; 2355e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2365e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner register char 2375e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner *p, 2385e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner *q, 2395e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner *next; 2405e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2415e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner register IndexPacket 2425e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner *indexes; 2435e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2445e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner register ssize_t 2455e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner i, 2465e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner x; 2475e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2485e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner register PixelPacket 2495e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner *r; 2505e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2515e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner size_t 2525e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner length; 2535e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2545e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner SplayTreeInfo 2555e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner *xpm_colors; 2565e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2575e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner ssize_t 2585e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner count; 2595e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2605e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner unsigned long 2615e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner colors, 2625e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner columns, 2635e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner rows, 2645e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner width; 2655e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner 2665e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner /* 2675e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner Open image file. 2685e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner */ 2695e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner assert(image_info != (const ImageInfo *) NULL); 2705e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner assert(image_info->signature == MagickSignature); 2715e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner if (image_info->debug != MagickFalse) 272891150f0b2a124a75c9f31516182ce864ae69ef8Chris Lattner (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 2735e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner image_info->filename); 274891150f0b2a124a75c9f31516182ce864ae69ef8Chris Lattner assert(exception != (ExceptionInfo *) NULL); 275891150f0b2a124a75c9f31516182ce864ae69ef8Chris Lattner assert(exception->signature == MagickSignature); 276891150f0b2a124a75c9f31516182ce864ae69ef8Chris Lattner image=AcquireImage(image_info); 277891150f0b2a124a75c9f31516182ce864ae69ef8Chris Lattner status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 2785e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner if (status == MagickFalse) 2795e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner { 280 image=DestroyImageList(image); 281 return((Image *) NULL); 282 } 283 /* 284 Read XPM file. 285 */ 286 length=MaxTextExtent; 287 xpm_buffer=(char *) AcquireQuantumMemory((size_t) length,sizeof(*xpm_buffer)); 288 p=xpm_buffer; 289 if (xpm_buffer != (char *) NULL) 290 while (ReadBlobString(image,p) != (char *) NULL) 291 { 292 if ((*p == '#') && ((p == xpm_buffer) || (*(p-1) == '\n'))) 293 continue; 294 if ((*p == '}') && (*(p+1) == ';')) 295 break; 296 p+=strlen(p); 297 if ((size_t) (p-xpm_buffer+MaxTextExtent) < length) 298 continue; 299 length<<=1; 300 xpm_buffer=(char *) ResizeQuantumMemory(xpm_buffer,length+MaxTextExtent, 301 sizeof(*xpm_buffer)); 302 if (xpm_buffer == (char *) NULL) 303 break; 304 p=xpm_buffer+strlen(xpm_buffer); 305 } 306 if (xpm_buffer == (char *) NULL) 307 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 308 /* 309 Remove comments. 310 */ 311 count=0; 312 for (p=xpm_buffer; *p != '\0'; p++) 313 { 314 if (*p != '"') 315 continue; 316 count=(ssize_t) sscanf(p+1,"%lu %lu %lu %lu",&columns,&rows,&colors,&width); 317 image->columns=columns; 318 image->rows=rows; 319 image->colors=colors; 320 if (count == 4) 321 break; 322 } 323 if ((count != 4) || (width > 10) || (image->columns == 0) || 324 (image->rows == 0) || (image->colors == 0)) 325 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 326 image->depth=16; 327 /* 328 Remove unquoted characters. 329 */ 330 i=0; 331 active=MagickFalse; 332 q=xpm_buffer; 333 while (*p != '\0') 334 { 335 if (*p++ == '"') 336 { 337 if (active != MagickFalse) 338 *q++='\n'; 339 active=active != MagickFalse ? MagickFalse : MagickTrue; 340 } 341 if (active != MagickFalse) 342 *q++=(*p); 343 } 344 *q='\0'; 345 /* 346 Initialize image structure. 347 */ 348 xpm_colors=NewSplayTree(CompareXPMColor,RelinquishMagickMemory, 349 (void *(*)(void *)) NULL); 350 if (AcquireImageColormap(image,image->colors) == MagickFalse) 351 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 352 /* 353 Read image colormap. 354 */ 355 i=1; 356 next=NextXPMLine(xpm_buffer); 357 for (j=0; (j < (ssize_t) image->colors) && (next != (char*) NULL); j++) 358 { 359 p=next; 360 next=NextXPMLine(p); 361 (void) CopyXPMColor(key,p,MagickMin((size_t) width,MaxTextExtent)); 362 status=AddValueToSplayTree(xpm_colors,ConstantString(key),(void *) j); 363 /* 364 Parse color. 365 */ 366 (void) CopyMagickString(target,"gray",MaxTextExtent); 367 q=ParseXPMColor(p+width); 368 if (q != (char *) NULL) 369 { 370 while ((isspace((int) ((unsigned char) *q)) == 0) && (*q != '\0')) 371 q++; 372 if (next != (char *) NULL) 373 (void) CopyXPMColor(target,q,MagickMin((size_t) (next-q), 374 MaxTextExtent)); 375 else 376 (void) CopyMagickString(target,q,MaxTextExtent); 377 q=ParseXPMColor(target); 378 if (q != (char *) NULL) 379 *q='\0'; 380 } 381 StripString(target); 382 if (LocaleCompare(target,"none") == 0) 383 { 384 image->storage_class=DirectClass; 385 image->matte=MagickTrue; 386 } 387 if (QueryColorDatabase(target,&image->colormap[j],exception) == MagickFalse) 388 break; 389 } 390 if (j < (ssize_t) image->colors) 391 ThrowReaderException(CorruptImageError,"CorruptImage"); 392 j=0; 393 if (image_info->ping == MagickFalse) 394 { 395 /* 396 Read image pixels. 397 */ 398 for (y=0; y < (ssize_t) image->rows; y++) 399 { 400 p=NextXPMLine(p); 401 if (p == (char *) NULL) 402 break; 403 r=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 404 if (r == (PixelPacket *) NULL) 405 break; 406 indexes=GetAuthenticIndexQueue(image); 407 for (x=0; x < (ssize_t) image->columns; x++) 408 { 409 (void) CopyXPMColor(key,p,(size_t) width); 410 j=(ssize_t) GetValueFromSplayTree(xpm_colors,key); 411 if (image->storage_class == PseudoClass) 412 indexes[x]=(IndexPacket) j; 413 *r=image->colormap[j]; 414 r++; 415 p+=width; 416 } 417 if (SyncAuthenticPixels(image,exception) == MagickFalse) 418 break; 419 } 420 if (y < (ssize_t) image->rows) 421 ThrowReaderException(CorruptImageError,"NotEnoughPixelData"); 422 } 423 /* 424 Relinquish resources. 425 */ 426 xpm_colors=DestroySplayTree(xpm_colors); 427 (void) CloseBlob(image); 428 return(GetFirstImageInList(image)); 429} 430 431/* 432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 433% % 434% % 435% % 436% R e g i s t e r X P M I m a g e % 437% % 438% % 439% % 440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 441% 442% RegisterXPMImage() adds attributes for the XPM image format to 443% the list of supported formats. The attributes include the image format 444% tag, a method to read and/or write the format, whether the format 445% supports the saving of more than one frame to the same file or blob, 446% whether the format supports native in-memory I/O, and a brief 447% description of the format. 448% 449% The format of the RegisterXPMImage method is: 450% 451% size_t RegisterXPMImage(void) 452% 453*/ 454ModuleExport size_t RegisterXPMImage(void) 455{ 456 MagickInfo 457 *entry; 458 459 entry=SetMagickInfo("PICON"); 460 entry->decoder=(DecodeImageHandler *) ReadXPMImage; 461 entry->encoder=(EncodeImageHandler *) WritePICONImage; 462 entry->adjoin=MagickFalse; 463 entry->description=ConstantString("Personal Icon"); 464 entry->module=ConstantString("XPM"); 465 (void) RegisterMagickInfo(entry); 466 entry=SetMagickInfo("PM"); 467 entry->decoder=(DecodeImageHandler *) ReadXPMImage; 468 entry->encoder=(EncodeImageHandler *) WriteXPMImage; 469 entry->adjoin=MagickFalse; 470 entry->stealth=MagickTrue; 471 entry->description=ConstantString("X Windows system pixmap (color)"); 472 entry->module=ConstantString("XPM"); 473 (void) RegisterMagickInfo(entry); 474 entry=SetMagickInfo("XPM"); 475 entry->decoder=(DecodeImageHandler *) ReadXPMImage; 476 entry->encoder=(EncodeImageHandler *) WriteXPMImage; 477 entry->magick=(IsImageFormatHandler *) IsXPM; 478 entry->adjoin=MagickFalse; 479 entry->description=ConstantString("X Windows system pixmap (color)"); 480 entry->module=ConstantString("XPM"); 481 (void) RegisterMagickInfo(entry); 482 return(MagickImageCoderSignature); 483} 484 485/* 486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 487% % 488% % 489% % 490% U n r e g i s t e r X P M I m a g e % 491% % 492% % 493% % 494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 495% 496% UnregisterXPMImage() removes format registrations made by the 497% XPM module from the list of supported formats. 498% 499% The format of the UnregisterXPMImage method is: 500% 501% UnregisterXPMImage(void) 502% 503*/ 504ModuleExport void UnregisterXPMImage(void) 505{ 506 (void) UnregisterMagickInfo("PICON"); 507 (void) UnregisterMagickInfo("PM"); 508 (void) UnregisterMagickInfo("XPM"); 509} 510 511/* 512%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 513% % 514% % 515% % 516% W r i t e P I C O N I m a g e % 517% % 518% % 519% % 520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 521% 522% Procedure WritePICONImage() writes an image to a file in the Personal Icon 523% format. 524% 525% The format of the WritePICONImage method is: 526% 527% MagickBooleanType WritePICONImage(const ImageInfo *image_info, 528% Image *image) 529% 530% A description of each parameter follows. 531% 532% o image_info: the image info. 533% 534% o image: The image. 535% 536*/ 537static MagickBooleanType WritePICONImage(const ImageInfo *image_info, 538 Image *image) 539{ 540#define ColormapExtent 155 541#define GraymapExtent 95 542#define PiconGeometry "48x48>" 543 544 static unsigned char 545 Colormap[]= 546 { 547 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x06, 0x00, 0x05, 0x00, 0xf4, 0x05, 548 0x00, 0x00, 0x00, 0x00, 0x2f, 0x4f, 0x4f, 0x70, 0x80, 0x90, 0x7e, 0x7e, 549 0x7e, 0xdc, 0xdc, 0xdc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 550 0xff, 0x1e, 0x90, 0xff, 0x87, 0xce, 0xeb, 0xe6, 0xe6, 0xfa, 0x00, 0xff, 551 0xff, 0x80, 0x00, 0x80, 0xb2, 0x22, 0x22, 0x2e, 0x8b, 0x57, 0x32, 0xcd, 552 0x32, 0x00, 0xff, 0x00, 0x98, 0xfb, 0x98, 0xff, 0x00, 0xff, 0xff, 0x00, 553 0x00, 0xff, 0x63, 0x47, 0xff, 0xa5, 0x00, 0xff, 0xd7, 0x00, 0xff, 0xff, 554 0x00, 0xee, 0x82, 0xee, 0xa0, 0x52, 0x2d, 0xcd, 0x85, 0x3f, 0xd2, 0xb4, 555 0x8c, 0xf5, 0xde, 0xb3, 0xff, 0xfa, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 556 0x00, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 557 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x05, 0x18, 0x20, 0x10, 0x08, 558 0x03, 0x51, 0x18, 0x07, 0x92, 0x28, 0x0b, 0xd3, 0x38, 0x0f, 0x14, 0x49, 559 0x13, 0x55, 0x59, 0x17, 0x96, 0x69, 0x1b, 0xd7, 0x85, 0x00, 0x3b, 560 }, 561 Graymap[]= 562 { 563 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x04, 0x00, 0xf3, 0x0f, 564 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x21, 0x21, 0x21, 0x33, 0x33, 565 0x33, 0x45, 0x45, 0x45, 0x54, 0x54, 0x54, 0x66, 0x66, 0x66, 0x78, 0x78, 566 0x78, 0x87, 0x87, 0x87, 0x99, 0x99, 0x99, 0xab, 0xab, 0xab, 0xba, 0xba, 567 0xba, 0xcc, 0xcc, 0xcc, 0xde, 0xde, 0xde, 0xed, 0xed, 0xed, 0xff, 0xff, 568 0xff, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 569 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x0c, 0x10, 0x04, 0x31, 570 0x48, 0x31, 0x07, 0x25, 0xb5, 0x58, 0x73, 0x4f, 0x04, 0x00, 0x3b, 571 }; 572 573#define MaxCixels 92 574 575 static const char 576 Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" 577 "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; 578 579 char 580 buffer[MaxTextExtent], 581 basename[MaxTextExtent], 582 name[MaxTextExtent], 583 symbol[MaxTextExtent]; 584 585 ExceptionInfo 586 *exception; 587 588 Image 589 *affinity_image, 590 *picon; 591 592 ImageInfo 593 *blob_info; 594 595 ssize_t 596 j, 597 k, 598 y; 599 600 MagickBooleanType 601 status, 602 transparent; 603 604 MagickPixelPacket 605 pixel; 606 607 QuantizeInfo 608 *quantize_info; 609 610 RectangleInfo 611 geometry; 612 613 register const IndexPacket 614 *indexes; 615 616 register const PixelPacket 617 *p; 618 619 register ssize_t 620 i, 621 x; 622 623 register PixelPacket 624 *q; 625 626 size_t 627 characters_per_pixel, 628 colors; 629 630 /* 631 Open output image file. 632 */ 633 assert(image_info != (const ImageInfo *) NULL); 634 assert(image_info->signature == MagickSignature); 635 assert(image != (Image *) NULL); 636 assert(image->signature == MagickSignature); 637 if (image->debug != MagickFalse) 638 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 639 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); 640 if (status == MagickFalse) 641 return(status); 642 if (image->colorspace != RGBColorspace) 643 (void) TransformImageColorspace(image,RGBColorspace); 644 SetGeometry(image,&geometry); 645 (void) ParseMetaGeometry(PiconGeometry,&geometry.x,&geometry.y, 646 &geometry.width,&geometry.height); 647 picon=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,1.0, 648 &image->exception); 649 blob_info=CloneImageInfo(image_info); 650 (void) AcquireUniqueFilename(blob_info->filename); 651 if ((image_info->type != TrueColorType) && 652 (IsGrayImage(image,&image->exception) != MagickFalse)) 653 affinity_image=BlobToImage(blob_info,Graymap,GraymapExtent, 654 &image->exception); 655 else 656 affinity_image=BlobToImage(blob_info,Colormap,ColormapExtent, 657 &image->exception); 658 (void) RelinquishUniqueFileResource(blob_info->filename); 659 blob_info=DestroyImageInfo(blob_info); 660 if ((picon == (Image *) NULL) || (affinity_image == (Image *) NULL)) 661 return(MagickFalse); 662 quantize_info=AcquireQuantizeInfo(image_info); 663 status=RemapImage(quantize_info,picon,affinity_image); 664 quantize_info=DestroyQuantizeInfo(quantize_info); 665 affinity_image=DestroyImage(affinity_image); 666 transparent=MagickFalse; 667 exception=(&image->exception); 668 if (picon->storage_class == PseudoClass) 669 { 670 (void) CompressImageColormap(picon); 671 if (picon->matte != MagickFalse) 672 transparent=MagickTrue; 673 } 674 else 675 { 676 /* 677 Convert DirectClass to PseudoClass picon. 678 */ 679 if (picon->matte != MagickFalse) 680 { 681 /* 682 Map all the transparent pixels. 683 */ 684 for (y=0; y < (ssize_t) picon->rows; y++) 685 { 686 q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception); 687 if (q == (PixelPacket *) NULL) 688 break; 689 for (x=0; x < (ssize_t) picon->columns; x++) 690 { 691 if (q->opacity == (Quantum) TransparentOpacity) 692 transparent=MagickTrue; 693 else 694 SetOpacityPixelComponent(q,OpaqueOpacity); 695 q++; 696 } 697 if (SyncAuthenticPixels(picon,exception) == MagickFalse) 698 break; 699 } 700 } 701 (void) SetImageType(picon,PaletteType); 702 } 703 colors=picon->colors; 704 if (transparent != MagickFalse) 705 { 706 register IndexPacket 707 *indexes; 708 709 colors++; 710 picon->colormap=(PixelPacket *) ResizeQuantumMemory((void **) 711 picon->colormap,(size_t) colors,sizeof(*picon->colormap)); 712 if (picon->colormap == (PixelPacket *) NULL) 713 ThrowWriterException(ResourceLimitError,"MemoryAllocationError"); 714 for (y=0; y < (ssize_t) picon->rows; y++) 715 { 716 q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception); 717 if (q == (PixelPacket *) NULL) 718 break; 719 indexes=GetAuthenticIndexQueue(picon); 720 for (x=0; x < (ssize_t) picon->columns; x++) 721 { 722 if (q->opacity == (Quantum) TransparentOpacity) 723 indexes[x]=(IndexPacket) picon->colors; 724 q++; 725 } 726 if (SyncAuthenticPixels(picon,exception) == MagickFalse) 727 break; 728 } 729 } 730 /* 731 Compute the character per pixel. 732 */ 733 characters_per_pixel=1; 734 for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels) 735 characters_per_pixel++; 736 /* 737 XPM header. 738 */ 739 (void) WriteBlobString(image,"/* XPM */\n"); 740 GetPathComponent(picon->filename,BasePath,basename); 741 (void) FormatMagickString(buffer,MaxTextExtent, 742 "static char *%s[] = {\n",basename); 743 (void) WriteBlobString(image,buffer); 744 (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n"); 745 (void) FormatMagickString(buffer,MaxTextExtent,"\"%lu %lu %lu %lu\",\n", 746 (unsigned long) picon->columns,(unsigned long) picon->rows,(unsigned long) 747 colors,(unsigned long) characters_per_pixel); 748 (void) WriteBlobString(image,buffer); 749 GetMagickPixelPacket(image,&pixel); 750 for (i=0; i < (ssize_t) colors; i++) 751 { 752 /* 753 Define XPM color. 754 */ 755 SetMagickPixelPacket(image,picon->colormap+i,(IndexPacket *) NULL,&pixel); 756 pixel.colorspace=RGBColorspace; 757 pixel.depth=8; 758 pixel.opacity=(MagickRealType) OpaqueOpacity; 759 (void) QueryMagickColorname(image,&pixel,XPMCompliance,name, 760 &image->exception); 761 if (transparent != MagickFalse) 762 { 763 if (i == (ssize_t) (colors-1)) 764 (void) CopyMagickString(name,"grey75",MaxTextExtent); 765 } 766 /* 767 Write XPM color. 768 */ 769 k=i % MaxCixels; 770 symbol[0]=Cixel[k]; 771 for (j=1; j < (ssize_t) characters_per_pixel; j++) 772 { 773 k=((i-k)/MaxCixels) % MaxCixels; 774 symbol[j]=Cixel[k]; 775 } 776 symbol[j]='\0'; 777 (void) FormatMagickString(buffer,MaxTextExtent,"\"%s c %s\",\n", 778 symbol,name); 779 (void) WriteBlobString(image,buffer); 780 } 781 /* 782 Define XPM pixels. 783 */ 784 (void) WriteBlobString(image,"/* pixels */\n"); 785 for (y=0; y < (ssize_t) picon->rows; y++) 786 { 787 p=GetVirtualPixels(picon,0,y,picon->columns,1,&picon->exception); 788 if (p == (const PixelPacket *) NULL) 789 break; 790 indexes=GetVirtualIndexQueue(picon); 791 (void) WriteBlobString(image,"\""); 792 for (x=0; x < (ssize_t) picon->columns; x++) 793 { 794 k=((ssize_t) indexes[x] % MaxCixels); 795 symbol[0]=Cixel[k]; 796 for (j=1; j < (ssize_t) characters_per_pixel; j++) 797 { 798 k=(((int) indexes[x]-k)/MaxCixels) % MaxCixels; 799 symbol[j]=Cixel[k]; 800 } 801 symbol[j]='\0'; 802 (void) CopyMagickString(buffer,symbol,MaxTextExtent); 803 (void) WriteBlobString(image,buffer); 804 } 805 (void) FormatMagickString(buffer,MaxTextExtent,"\"%s\n", 806 y == (ssize_t) (picon->rows-1) ? "" : ","); 807 (void) WriteBlobString(image,buffer); 808 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 809 picon->rows); 810 if (status == MagickFalse) 811 break; 812 } 813 picon=DestroyImage(picon); 814 (void) WriteBlobString(image,"};\n"); 815 (void) CloseBlob(image); 816 return(MagickTrue); 817} 818 819/* 820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 821% % 822% % 823% % 824% W r i t e X P M I m a g e % 825% % 826% % 827% % 828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 829% 830% Procedure WriteXPMImage() writes an image to a file in the X pixmap format. 831% 832% The format of the WriteXPMImage method is: 833% 834% MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image) 835% 836% A description of each parameter follows. 837% 838% o image_info: the image info. 839% 840% o image: The image. 841% 842% 843*/ 844static MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image) 845{ 846#define MaxCixels 92 847 848 static const char 849 Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" 850 "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; 851 852 char 853 buffer[MaxTextExtent], 854 basename[MaxTextExtent], 855 name[MaxTextExtent], 856 symbol[MaxTextExtent]; 857 858 ssize_t 859 j, 860 k, 861 opacity, 862 y; 863 864 MagickBooleanType 865 status; 866 867 MagickPixelPacket 868 pixel; 869 870 register const IndexPacket 871 *indexes; 872 873 register const PixelPacket 874 *p; 875 876 register ssize_t 877 i, 878 x; 879 880 size_t 881 characters_per_pixel; 882 883 /* 884 Open output image file. 885 */ 886 assert(image_info != (const ImageInfo *) NULL); 887 assert(image_info->signature == MagickSignature); 888 assert(image != (Image *) NULL); 889 assert(image->signature == MagickSignature); 890 if (image->debug != MagickFalse) 891 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 892 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); 893 if (status == MagickFalse) 894 return(status); 895 if (image->colorspace != RGBColorspace) 896 (void) TransformImageColorspace(image,RGBColorspace); 897 opacity=(-1); 898 if (image->matte == MagickFalse) 899 { 900 if ((image->storage_class == DirectClass) || (image->colors > 256)) 901 (void) SetImageType(image,PaletteType); 902 } 903 else 904 { 905 MagickRealType 906 alpha, 907 beta; 908 909 /* 910 Identify transparent colormap index. 911 */ 912 if ((image->storage_class == DirectClass) || (image->colors > 256)) 913 (void) SetImageType(image,PaletteBilevelMatteType); 914 for (i=0; i < (ssize_t) image->colors; i++) 915 if (image->colormap[i].opacity != OpaqueOpacity) 916 { 917 if (opacity < 0) 918 { 919 opacity=i; 920 continue; 921 } 922 alpha=(Quantum) TransparentOpacity-(MagickRealType) 923 image->colormap[i].opacity; 924 beta=(Quantum) TransparentOpacity-(MagickRealType) 925 image->colormap[opacity].opacity; 926 if (alpha < beta) 927 opacity=i; 928 } 929 if (opacity == -1) 930 { 931 (void) SetImageType(image,PaletteBilevelMatteType); 932 for (i=0; i < (ssize_t) image->colors; i++) 933 if (image->colormap[i].opacity != OpaqueOpacity) 934 { 935 if (opacity < 0) 936 { 937 opacity=i; 938 continue; 939 } 940 alpha=(Quantum) TransparentOpacity-(MagickRealType) 941 image->colormap[i].opacity; 942 beta=(Quantum) TransparentOpacity-(MagickRealType) 943 image->colormap[opacity].opacity; 944 if (alpha < beta) 945 opacity=i; 946 } 947 } 948 if (opacity >= 0) 949 { 950 image->colormap[opacity].red=image->transparent_color.red; 951 image->colormap[opacity].green=image->transparent_color.green; 952 image->colormap[opacity].blue=image->transparent_color.blue; 953 } 954 } 955 /* 956 Compute the character per pixel. 957 */ 958 characters_per_pixel=1; 959 for (k=MaxCixels; (ssize_t) image->colors > k; k*=MaxCixels) 960 characters_per_pixel++; 961 /* 962 XPM header. 963 */ 964 (void) WriteBlobString(image,"/* XPM */\n"); 965 GetPathComponent(image->filename,BasePath,basename); 966 if (isalnum((int) ((unsigned char) *basename)) == 0) 967 { 968 (void) FormatMagickString(buffer,MaxTextExtent,"xpm_%s",basename); 969 (void) CopyMagickString(basename,buffer,MaxTextExtent); 970 } 971 for (i=0; basename[i] != '\0'; i++) 972 if (isalpha((int) ((unsigned char) basename[i])) == 0) 973 basename[i]='_'; 974 (void) FormatMagickString(buffer,MaxTextExtent, 975 "static char *%s[] = {\n",basename); 976 (void) WriteBlobString(image,buffer); 977 (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n"); 978 (void) FormatMagickString(buffer,MaxTextExtent,"\"%lu %lu %lu %lu\",\n", 979 (unsigned long) image->columns,(unsigned long) image->rows,(unsigned long) 980 image->colors,(unsigned long) characters_per_pixel); 981 (void) WriteBlobString(image,buffer); 982 GetMagickPixelPacket(image,&pixel); 983 for (i=0; i < (ssize_t) image->colors; i++) 984 { 985 /* 986 Define XPM color. 987 */ 988 SetMagickPixelPacket(image,image->colormap+i,(IndexPacket *) NULL,&pixel); 989 pixel.colorspace=RGBColorspace; 990 pixel.depth=8; 991 pixel.opacity=(MagickRealType) OpaqueOpacity; 992 (void) QueryMagickColorname(image,&pixel,XPMCompliance,name, 993 &image->exception); 994 if (i == opacity) 995 (void) CopyMagickString(name,"None",MaxTextExtent); 996 /* 997 Write XPM color. 998 */ 999 k=i % MaxCixels; 1000 symbol[0]=Cixel[k]; 1001 for (j=1; j < (ssize_t) characters_per_pixel; j++) 1002 { 1003 k=((i-k)/MaxCixels) % MaxCixels; 1004 symbol[j]=Cixel[k]; 1005 } 1006 symbol[j]='\0'; 1007 (void) FormatMagickString(buffer,MaxTextExtent,"\"%s c %s\",\n",symbol, 1008 name); 1009 (void) WriteBlobString(image,buffer); 1010 } 1011 /* 1012 Define XPM pixels. 1013 */ 1014 (void) WriteBlobString(image,"/* pixels */\n"); 1015 for (y=0; y < (ssize_t) image->rows; y++) 1016 { 1017 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); 1018 if (p == (const PixelPacket *) NULL) 1019 break; 1020 indexes=GetVirtualIndexQueue(image); 1021 (void) WriteBlobString(image,"\""); 1022 for (x=0; x < (ssize_t) image->columns; x++) 1023 { 1024 k=((ssize_t) indexes[x] % MaxCixels); 1025 symbol[0]=Cixel[k]; 1026 for (j=1; j < (ssize_t) characters_per_pixel; j++) 1027 { 1028 k=(((int) indexes[x]-k)/MaxCixels) % MaxCixels; 1029 symbol[j]=Cixel[k]; 1030 } 1031 symbol[j]='\0'; 1032 (void) CopyMagickString(buffer,symbol,MaxTextExtent); 1033 (void) WriteBlobString(image,buffer); 1034 } 1035 (void) FormatMagickString(buffer,MaxTextExtent,"\"%s\n", 1036 (y == (ssize_t) (image->rows-1) ? "" : ",")); 1037 (void) WriteBlobString(image,buffer); 1038 if (image->previous == (Image *) NULL) 1039 { 1040 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1041 image->rows); 1042 if (status == MagickFalse) 1043 break; 1044 } 1045 } 1046 (void) WriteBlobString(image,"};\n"); 1047 (void) CloseBlob(image); 1048 return(MagickTrue); 1049} 1050