blob: 8c6c5dcbcd0db5aa940e0d0fdb7aea7f3400b688 [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 %
cristyde984cd2013-12-01 14:49:27 +000015% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000016% April 2004 %
17% %
18% %
Cristy7ce65e72015-12-12 18:03:16 -050019% Copyright 1999-2016 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*/
cristy4c08aed2011-07-01 19:47:50 +000041#include "MagickCore/studio.h"
42#include "MagickCore/blob.h"
43#include "MagickCore/blob-private.h"
44#include "MagickCore/cache.h"
45#include "MagickCore/color-private.h"
46#include "MagickCore/colorspace.h"
cristy510d06a2011-07-06 23:43:54 +000047#include "MagickCore/colorspace-private.h"
cristy4c08aed2011-07-01 19:47:50 +000048#include "MagickCore/constitute.h"
49#include "MagickCore/exception.h"
50#include "MagickCore/exception-private.h"
51#include "MagickCore/image.h"
52#include "MagickCore/image-private.h"
53#include "MagickCore/list.h"
54#include "MagickCore/magick.h"
55#include "MagickCore/memory_.h"
56#include "MagickCore/monitor.h"
57#include "MagickCore/monitor-private.h"
58#include "MagickCore/pixel-accessor.h"
59#include "MagickCore/property.h"
60#include "MagickCore/quantize.h"
61#include "MagickCore/quantum-private.h"
62#include "MagickCore/static.h"
63#include "MagickCore/string_.h"
64#include "MagickCore/module.h"
65#include "MagickCore/utility.h"
cristy3ed852e2009-09-05 21:47:34 +000066
67/*
68 Forward declarations.
69*/
70static MagickBooleanType
cristy1e178e72011-08-28 19:44:34 +000071 WriteCIPImage(const ImageInfo *,Image *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +000072
73/*
74%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75% %
76% %
77% %
78% R e g i s t e r C I P I m a g e %
79% %
80% %
81% %
82%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83%
84% RegisterCIPImage() adds properties for the CIP IP phone image format to
85% the list of supported formats. The properties include the image format
86% tag, a method to read and/or write the format, whether the format
87% supports the saving of more than one frame to the same file or blob,
88% whether the format supports native in-memory I/O, and a brief
89% description of the format.
90%
91% The format of the RegisterCIPImage method is:
92%
cristybb503372010-05-27 20:51:26 +000093% size_t RegisterCIPImage(void)
cristy3ed852e2009-09-05 21:47:34 +000094%
95*/
cristybb503372010-05-27 20:51:26 +000096ModuleExport size_t RegisterCIPImage(void)
cristy3ed852e2009-09-05 21:47:34 +000097{
98 MagickInfo
99 *entry;
100
dirk06b627a2015-04-06 18:59:17 +0000101 entry=AcquireMagickInfo("CIP","CIP","Cisco IP phone image format");
cristy3ed852e2009-09-05 21:47:34 +0000102 entry->encoder=(EncodeImageHandler *) WriteCIPImage;
dirk08e9a112015-02-22 01:51:41 +0000103 entry->flags^=CoderAdjoinFlag;
cristy3ed852e2009-09-05 21:47:34 +0000104 (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%
cristy1e178e72011-08-28 19:44:34 +0000148% MagickBooleanType WriteCIPImage(const ImageInfo *image_info,
149% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000150%
151% A description of each parameter follows.
152%
153% o image_info: the image info.
154%
155% o image: The image.
156%
cristy1e178e72011-08-28 19:44:34 +0000157% o exception: return any errors or warnings in this structure.
158%
cristy3ed852e2009-09-05 21:47:34 +0000159*/
cristy1e178e72011-08-28 19:44:34 +0000160static MagickBooleanType WriteCIPImage(const ImageInfo *image_info,Image *image,
161 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000162{
163 char
cristy151b66d2015-04-15 10:50:31 +0000164 buffer[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000165
166 const char
167 *value;
168
cristy3ed852e2009-09-05 21:47:34 +0000169 MagickBooleanType
170 status;
171
cristy4c08aed2011-07-01 19:47:50 +0000172 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +0000173 *p;
174
cristybb503372010-05-27 20:51:26 +0000175 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000176 i,
177 x;
178
cristy4e82e512011-04-24 01:33:42 +0000179 ssize_t
180 y;
181
cristy3ed852e2009-09-05 21:47:34 +0000182 unsigned char
183 byte;
184
185 /*
186 Open output image file.
187 */
188 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000189 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000190 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000191 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000192 if (image->debug != MagickFalse)
193 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +0000194 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000195 assert(exception->signature == MagickCoreSignature);
cristy1e178e72011-08-28 19:44:34 +0000196 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +0000197 if (status == MagickFalse)
198 return(status);
199 (void) WriteBlobString(image,"<CiscoIPPhoneImage>\n");
cristyd15e6592011-10-15 00:13:06 +0000200 value=GetImageProperty(image,"label",exception);
cristy3ed852e2009-09-05 21:47:34 +0000201 if (value != (const char *) NULL)
cristy151b66d2015-04-15 10:50:31 +0000202 (void) FormatLocaleString(buffer,MagickPathExtent,"<Title>%s</Title>\n",value);
cristy3ed852e2009-09-05 21:47:34 +0000203 else
204 {
205 char
cristy151b66d2015-04-15 10:50:31 +0000206 basename[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000207
208 GetPathComponent(image->filename,BasePath,basename);
cristy151b66d2015-04-15 10:50:31 +0000209 (void) FormatLocaleString(buffer,MagickPathExtent,"<Title>%s</Title>\n",
cristy3ed852e2009-09-05 21:47:34 +0000210 basename);
211 }
212 (void) WriteBlobString(image,buffer);
cristy151b66d2015-04-15 10:50:31 +0000213 (void) FormatLocaleString(buffer,MagickPathExtent,
cristye8c25f92010-06-03 00:53:06 +0000214 "<LocationX>%.20g</LocationX>\n",(double) image->page.x);
cristy3ed852e2009-09-05 21:47:34 +0000215 (void) WriteBlobString(image,buffer);
cristy151b66d2015-04-15 10:50:31 +0000216 (void) FormatLocaleString(buffer,MagickPathExtent,
cristye8c25f92010-06-03 00:53:06 +0000217 "<LocationY>%.20g</LocationY>\n",(double) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +0000218 (void) WriteBlobString(image,buffer);
cristy151b66d2015-04-15 10:50:31 +0000219 (void) FormatLocaleString(buffer,MagickPathExtent,"<Width>%.20g</Width>\n",
cristye8c25f92010-06-03 00:53:06 +0000220 (double) (image->columns+(image->columns % 2)));
cristy3ed852e2009-09-05 21:47:34 +0000221 (void) WriteBlobString(image,buffer);
cristy151b66d2015-04-15 10:50:31 +0000222 (void) FormatLocaleString(buffer,MagickPathExtent,"<Height>%.20g</Height>\n",
cristye8c25f92010-06-03 00:53:06 +0000223 (double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000224 (void) WriteBlobString(image,buffer);
cristy151b66d2015-04-15 10:50:31 +0000225 (void) FormatLocaleString(buffer,MagickPathExtent,"<Depth>2</Depth>\n");
cristy3ed852e2009-09-05 21:47:34 +0000226 (void) WriteBlobString(image,buffer);
227 (void) WriteBlobString(image,"<Data>");
cristyaf8d3912014-02-21 14:50:33 +0000228 (void) TransformImageColorspace(image,sRGBColorspace,exception);
cristybb503372010-05-27 20:51:26 +0000229 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000230 {
cristy1e178e72011-08-28 19:44:34 +0000231 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000232 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000233 break;
cristybb503372010-05-27 20:51:26 +0000234 for (x=0; x < ((ssize_t) image->columns-3); x+=4)
cristy3ed852e2009-09-05 21:47:34 +0000235 {
236 byte=(unsigned char)
cristy91607422013-07-03 00:14:54 +0000237 ((((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+3))/QuantumRange) & 0x03) << 6) |
238 (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+2))/QuantumRange) & 0x03) << 4) |
239 (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+1))/QuantumRange) & 0x03) << 2) |
240 (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+0))/QuantumRange) & 0x03) << 0));
cristy151b66d2015-04-15 10:50:31 +0000241 (void) FormatLocaleString(buffer,MagickPathExtent,"%02x",byte);
cristy3ed852e2009-09-05 21:47:34 +0000242 (void) WriteBlobString(image,buffer);
243 p+=4;
244 }
245 if ((image->columns % 4) != 0)
246 {
cristybb503372010-05-27 20:51:26 +0000247 i=(ssize_t) image->columns % 4;
cristy3ed852e2009-09-05 21:47:34 +0000248 byte=(unsigned char)
cristy91607422013-07-03 00:14:54 +0000249 ((((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+MagickMin(i,3)))/QuantumRange) & 0x03) << 6) |
250 (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+MagickMin(i,2)))/QuantumRange) & 0x03) << 4) |
251 (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+MagickMin(i,1)))/QuantumRange) & 0x03) << 2) |
252 (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+MagickMin(i,0)))/QuantumRange) & 0x03) << 0));
cristy151b66d2015-04-15 10:50:31 +0000253 (void) FormatLocaleString(buffer,MagickPathExtent,"%02x",~byte);
cristy3ed852e2009-09-05 21:47:34 +0000254 (void) WriteBlobString(image,buffer);
255 }
cristycee97112010-05-28 00:44:52 +0000256 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
cristy4e82e512011-04-24 01:33:42 +0000257 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000258 if (status == MagickFalse)
259 break;
260 }
261 (void) WriteBlobString(image,"</Data>\n");
262 (void) WriteBlobString(image,"</CiscoIPPhoneImage>\n");
263 (void) CloseBlob(image);
264 return(MagickTrue);
265}