blob: 318eb310ebaeee21d3b33f5ba82118a861fe675d [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% CCCC IIIII PPPP %
6% C I P P %
7% C I PPPP %
8% C I P %
9% CCCC IIIII P %
10% %
11% %
12% Read/Write Cisco IP Phone Image Format %
13% %
14% Software Design %
15% John Cristy %
16% April 2004 %
17% %
18% %
cristy16af1cb2009-12-11 21:38:29 +000019% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000020% dedicated to making software imaging solutions freely available. %
21% %
22% You may not use this file except in compliance with the License. You may %
23% obtain a copy of the License at %
24% %
25% http://www.imagemagick.org/script/license.php %
26% %
27% Unless required by applicable law or agreed to in writing, software %
28% distributed under the License is distributed on an "AS IS" BASIS, %
29% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30% See the License for the specific language governing permissions and %
31% limitations under the License. %
32% %
33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34%
35%
36*/
37
38/*
39 Include declarations.
40*/
41#include "magick/studio.h"
42#include "magick/blob.h"
43#include "magick/blob-private.h"
44#include "magick/cache.h"
45#include "magick/color-private.h"
46#include "magick/colorspace.h"
47#include "magick/constitute.h"
48#include "magick/exception.h"
49#include "magick/exception-private.h"
50#include "magick/image.h"
51#include "magick/image-private.h"
52#include "magick/list.h"
53#include "magick/magick.h"
54#include "magick/memory_.h"
55#include "magick/monitor.h"
56#include "magick/monitor-private.h"
57#include "magick/property.h"
58#include "magick/quantize.h"
59#include "magick/quantum-private.h"
60#include "magick/static.h"
61#include "magick/string_.h"
62#include "magick/module.h"
63#include "magick/utility.h"
64
65/*
66 Forward declarations.
67*/
68static MagickBooleanType
69 WriteCIPImage(const ImageInfo *,Image *);
70
71/*
72%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73% %
74% %
75% %
76% R e g i s t e r C I P I m a g e %
77% %
78% %
79% %
80%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81%
82% RegisterCIPImage() adds properties for the CIP IP phone image format to
83% the list of supported formats. The properties include the image format
84% tag, a method to read and/or write the format, whether the format
85% supports the saving of more than one frame to the same file or blob,
86% whether the format supports native in-memory I/O, and a brief
87% description of the format.
88%
89% The format of the RegisterCIPImage method is:
90%
cristybb503372010-05-27 20:51:26 +000091% size_t RegisterCIPImage(void)
cristy3ed852e2009-09-05 21:47:34 +000092%
93*/
cristybb503372010-05-27 20:51:26 +000094ModuleExport size_t RegisterCIPImage(void)
cristy3ed852e2009-09-05 21:47:34 +000095{
96 MagickInfo
97 *entry;
98
99 entry=SetMagickInfo("CIP");
100 entry->encoder=(EncodeImageHandler *) WriteCIPImage;
101 entry->adjoin=MagickFalse;
102 entry->description=ConstantString("Cisco IP phone image format");
103 entry->module=ConstantString("CIP");
104 (void) RegisterMagickInfo(entry);
105 return(MagickImageCoderSignature);
106}
107
108/*
109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110% %
111% %
112% %
113% U n r e g i s t e r C I P I m a g e %
114% %
115% %
116% %
117%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118%
119% UnregisterCIPImage() removes format registrations made by the
120% CIP module from the list of supported formats.
121%
122% The format of the UnregisterCIPImage method is:
123%
124% UnregisterCIPImage(void)
125%
126*/
127ModuleExport void UnregisterCIPImage(void)
128{
129 (void) UnregisterMagickInfo("CIP");
130}
131
132/*
133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134% %
135% %
136% %
137% W r i t e C I P I m a g e %
138% %
139% %
140% %
141%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142%
143% Procedure WriteCIPImage() writes an image to a file in the Cisco IP phone
144% image format.
145%
146% The format of the WriteCIPImage method is:
147%
148% MagickBooleanType WriteCIPImage(const ImageInfo *image_info,Image *image)
149%
150% A description of each parameter follows.
151%
152% o image_info: the image info.
153%
154% o image: The image.
155%
156*/
157
cristybb503372010-05-27 20:51:26 +0000158static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
cristy3ed852e2009-09-05 21:47:34 +0000159{
160 if (x < y)
161 return(x);
162 return(y);
163}
164
165static MagickBooleanType WriteCIPImage(const ImageInfo *image_info,Image *image)
166{
167 char
168 buffer[MaxTextExtent];
169
170 const char
171 *value;
172
cristybb503372010-05-27 20:51:26 +0000173 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000174 y;
175
176 MagickBooleanType
177 status;
178
179 register const PixelPacket
180 *p;
181
cristybb503372010-05-27 20:51:26 +0000182 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000183 i,
184 x;
185
186 unsigned char
187 byte;
188
189 /*
190 Open output image file.
191 */
192 assert(image_info != (const ImageInfo *) NULL);
193 assert(image_info->signature == MagickSignature);
194 assert(image != (Image *) NULL);
195 assert(image->signature == MagickSignature);
196 if (image->debug != MagickFalse)
197 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
198 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
199 if (status == MagickFalse)
200 return(status);
201 (void) WriteBlobString(image,"<CiscoIPPhoneImage>\n");
202 value=GetImageProperty(image,"label");
203 if (value != (const char *) NULL)
204 (void) FormatMagickString(buffer,MaxTextExtent,"<Title>%s</Title>\n",value);
205 else
206 {
207 char
208 basename[MaxTextExtent];
209
210 GetPathComponent(image->filename,BasePath,basename);
211 (void) FormatMagickString(buffer,MaxTextExtent,"<Title>%s</Title>\n",
212 basename);
213 }
214 (void) WriteBlobString(image,buffer);
cristye8c25f92010-06-03 00:53:06 +0000215 (void) FormatMagickString(buffer,MaxTextExtent,
216 "<LocationX>%.20g</LocationX>\n",(double) image->page.x);
cristy3ed852e2009-09-05 21:47:34 +0000217 (void) WriteBlobString(image,buffer);
cristye8c25f92010-06-03 00:53:06 +0000218 (void) FormatMagickString(buffer,MaxTextExtent,
219 "<LocationY>%.20g</LocationY>\n",(double) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +0000220 (void) WriteBlobString(image,buffer);
cristye8c25f92010-06-03 00:53:06 +0000221 (void) FormatMagickString(buffer,MaxTextExtent,"<Width>%.20g</Width>\n",
222 (double) (image->columns+(image->columns % 2)));
cristy3ed852e2009-09-05 21:47:34 +0000223 (void) WriteBlobString(image,buffer);
cristye8c25f92010-06-03 00:53:06 +0000224 (void) FormatMagickString(buffer,MaxTextExtent,"<Height>%.20g</Height>\n",
225 (double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000226 (void) WriteBlobString(image,buffer);
227 (void) FormatMagickString(buffer,MaxTextExtent,"<Depth>2</Depth>\n");
228 (void) WriteBlobString(image,buffer);
229 (void) WriteBlobString(image,"<Data>");
230 if (image->colorspace != RGBColorspace)
231 (void) TransformImageColorspace(image,RGBColorspace);
cristybb503372010-05-27 20:51:26 +0000232 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000233 {
234 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
235 if (p == (const PixelPacket *) NULL)
236 break;
cristybb503372010-05-27 20:51:26 +0000237 for (x=0; x < ((ssize_t) image->columns-3); x+=4)
cristy3ed852e2009-09-05 21:47:34 +0000238 {
239 byte=(unsigned char)
cristybb503372010-05-27 20:51:26 +0000240 ((((size_t) (4*PixelIntensityToQuantum(p+3)/QuantumRange) & 0x03) << 6) |
241 (((size_t) (4*PixelIntensityToQuantum(p+2)/QuantumRange) & 0x03) << 4) |
242 (((size_t) (4*PixelIntensityToQuantum(p+1)/QuantumRange) & 0x03) << 2) |
243 (((size_t) (4*PixelIntensityToQuantum(p+0)/QuantumRange) & 0x03) << 0));
cristy3ed852e2009-09-05 21:47:34 +0000244 (void) FormatMagickString(buffer,MaxTextExtent,"%02x",byte);
245 (void) WriteBlobString(image,buffer);
246 p+=4;
247 }
248 if ((image->columns % 4) != 0)
249 {
cristybb503372010-05-27 20:51:26 +0000250 i=(ssize_t) image->columns % 4;
cristy3ed852e2009-09-05 21:47:34 +0000251 byte=(unsigned char)
cristybb503372010-05-27 20:51:26 +0000252 ((((size_t) (4*PixelIntensityToQuantum(p+MagickMin(i,3))/QuantumRange) & 0x03) << 6) |
253 (((size_t) (4*PixelIntensityToQuantum(p+MagickMin(i,2))/QuantumRange) & 0x03) << 4) |
254 (((size_t) (4*PixelIntensityToQuantum(p+MagickMin(i,1))/QuantumRange) & 0x03) << 2) |
255 (((size_t) (4*PixelIntensityToQuantum(p+MagickMin(i,0))/QuantumRange) & 0x03) << 0));
cristy3ed852e2009-09-05 21:47:34 +0000256 (void) FormatMagickString(buffer,MaxTextExtent,"%02x",~byte);
257 (void) WriteBlobString(image,buffer);
258 }
cristycee97112010-05-28 00:44:52 +0000259 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
260 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000261 if (status == MagickFalse)
262 break;
263 }
264 (void) WriteBlobString(image,"</Data>\n");
265 (void) WriteBlobString(image,"</CiscoIPPhoneImage>\n");
266 (void) CloseBlob(image);
267 return(MagickTrue);
268}