blob: 791801e8535e7943103f055618f2552b433ce377 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% W W BBBB M M PPPP %
7% W W B B MM MM P P %
8% W W W BBBB M M M PPPP %
9% WW WW B B M M P %
10% W W BBBB M M P %
11% %
12% %
13% Read/Write Wireless Bitmap (level 0) Image Format %
14% %
15% Software Design %
16% John Cristy %
17% January 2000 %
18% %
19% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
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"
cristye7e40552010-04-24 21:34:22 +000046#include "magick/colormap.h"
cristy3ed852e2009-09-05 21:47:34 +000047#include "magick/colorspace.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/quantum-private.h"
58#include "magick/static.h"
59#include "magick/string_.h"
60#include "magick/module.h"
61
62/*
63 Forward declarations.
64*/
65static MagickBooleanType
66 WriteWBMPImage(const ImageInfo *,Image *);
67
68/*
69%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70% %
71% %
72% %
73% R e a d W B M P I m a g e %
74% %
75% %
76% %
77%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78%
79% ReadWBMPImage() reads a WBMP (level 0) image file and returns it. It
80% allocates the memory necessary for the new Image structure and returns a
81% pointer to the new image.
82%
83% ReadWBMPImage was contributed by Milan Votava <votava@mageo.cz>.
84%
85% The format of the ReadWBMPImage method is:
86%
87% Image *ReadWBMPImage(const ImageInfo *image_info,
88% ExceptionInfo *exception)
89%
90% A description of each parameter follows:
91%
92% o image_info: the image info.
93%
94% o exception: return any errors or warnings in this structure.
95%
96*/
97
cristybb503372010-05-27 20:51:26 +000098static MagickBooleanType WBMPReadInteger(Image *image,size_t *value)
cristy3ed852e2009-09-05 21:47:34 +000099{
100 int
101 byte;
102
103 *value=0;
104 do
105 {
106 byte=ReadBlobByte(image);
107 if (byte == EOF)
108 return(MagickFalse);
109 *value<<=7;
110 *value|=(unsigned int) (byte & 0x7f);
111 } while (byte & 0x80);
112 return(MagickTrue);
113}
114
115static Image *ReadWBMPImage(const ImageInfo *image_info,
116 ExceptionInfo *exception)
117{
118 Image
119 *image;
120
121 int
122 byte;
123
cristybb503372010-05-27 20:51:26 +0000124 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000125 y;
126
127 MagickBooleanType
128 status;
129
130 register IndexPacket
131 *indexes;
132
cristybb503372010-05-27 20:51:26 +0000133 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000134 x;
135
136 register PixelPacket
137 *q;
138
cristybb503372010-05-27 20:51:26 +0000139 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000140 i;
141
142 unsigned char
143 bit;
144
145 unsigned short
146 header;
147
148 /*
149 Open image file.
150 */
151 assert(image_info != (const ImageInfo *) NULL);
152 assert(image_info->signature == MagickSignature);
153 if (image_info->debug != MagickFalse)
154 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
155 image_info->filename);
156 assert(exception != (ExceptionInfo *) NULL);
157 assert(exception->signature == MagickSignature);
158 image=AcquireImage(image_info);
159 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
160 if (status == MagickFalse)
161 {
162 image=DestroyImageList(image);
163 return((Image *) NULL);
164 }
165 if (ReadBlob(image,2,(unsigned char *) &header) == 0)
166 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
167 if (header != 0)
168 ThrowReaderException(CoderError,"OnlyLevelZerofilesSupported");
169 /*
170 Initialize image structure.
171 */
172 if (WBMPReadInteger(image,&image->columns) == MagickFalse)
173 ThrowReaderException(CorruptImageError,"CorruptWBMPimage");
174 if (WBMPReadInteger(image,&image->rows) == MagickFalse)
175 ThrowReaderException(CorruptImageError,"CorruptWBMPimage");
176 if ((image->columns == 0) || (image->rows == 0))
177 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
178 for (i=0; i < image->offset; i++)
179 if (ReadBlobByte(image) == EOF)
180 {
181 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
182 image->filename);
183 break;
184 }
185 if (AcquireImageColormap(image,2) == MagickFalse)
186 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
187 if (image_info->ping != MagickFalse)
188 {
189 (void) CloseBlob(image);
190 return(GetFirstImageInList(image));
191 }
192 /*
193 Convert bi-level image to pixel packets.
194 */
cristybb503372010-05-27 20:51:26 +0000195 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000196 {
197 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
198 if (q == (PixelPacket *) NULL)
199 break;
200 indexes=GetAuthenticIndexQueue(image);
201 bit=0;
202 byte=0;
cristybb503372010-05-27 20:51:26 +0000203 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000204 {
205 if (bit == 0)
206 {
207 byte=ReadBlobByte(image);
208 if (byte == EOF)
209 ThrowReaderException(CorruptImageError,"CorruptImage");
210 }
211 indexes[x]=(IndexPacket) ((byte & (0x01 << (7-bit))) ? 1 : 0);
212 bit++;
213 if (bit == 8)
214 bit=0;
215 }
216 if (SyncAuthenticPixels(image,exception) == MagickFalse)
217 break;
218 status=SetImageProgress(image,LoadImageTag,y,image->rows);
219 if (status == MagickFalse)
220 break;
221 }
222 (void) SyncImage(image);
223 if (EOFBlob(image) != MagickFalse)
224 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
225 image->filename);
226 (void) CloseBlob(image);
227 return(GetFirstImageInList(image));
228}
229
230/*
231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232% %
233% %
234% %
235% R e g i s t e r W B M P I m a g e %
236% %
237% %
238% %
239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240%
241% RegisterWBMPImage() adds attributes for the WBMP image format to
242% the list of supported formats. The attributes include the image format
243% tag, a method to read and/or write the format, whether the format
244% supports the saving of more than one frame to the same file or blob,
245% whether the format supports native in-memory I/O, and a brief
246% description of the format.
247%
248% The format of the RegisterWBMPImage method is:
249%
cristybb503372010-05-27 20:51:26 +0000250% size_t RegisterWBMPImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000251%
252*/
cristybb503372010-05-27 20:51:26 +0000253ModuleExport size_t RegisterWBMPImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000254{
255 MagickInfo
256 *entry;
257
258 entry=SetMagickInfo("WBMP");
259 entry->decoder=(DecodeImageHandler *) ReadWBMPImage;
260 entry->encoder=(EncodeImageHandler *) WriteWBMPImage;
261 entry->adjoin=MagickFalse;
262 entry->description=ConstantString("Wireless Bitmap (level 0) image");
263 entry->module=ConstantString("WBMP");
264 (void) RegisterMagickInfo(entry);
265 return(MagickImageCoderSignature);
266}
267
268/*
269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270% %
271% %
272% %
273% U n r e g i s t e r W B M P I m a g e %
274% %
275% %
276% %
277%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278%
279% UnregisterWBMPImage() removes format registrations made by the
280% WBMP module from the list of supported formats.
281%
282% The format of the UnregisterWBMPImage method is:
283%
284% UnregisterWBMPImage(void)
285%
286*/
287ModuleExport void UnregisterWBMPImage(void)
288{
289 (void) UnregisterMagickInfo("WBMP");
290}
291
292/*
293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294% %
295% %
296% %
297% W r i t e W B M P I m a g e %
298% %
299% %
300% %
301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302%
303% WriteWBMPImage() writes an image to a file in the Wireless Bitmap
304% (level 0) image format.
305%
306% WriteWBMPImage was contributed by Milan Votava <votava@mageo.cz>.
307%
308% The format of the WriteWBMPImage method is:
309%
310% MagickBooleanType WriteWBMPImage(const ImageInfo *image_info,
311% Image *image)
312%
313% A description of each parameter follows.
314%
315% o image_info: the image info.
316%
317% o image: The image.
318%
319%
320*/
321
cristybb503372010-05-27 20:51:26 +0000322static void WBMPWriteInteger(Image *image,const size_t value)
cristy3ed852e2009-09-05 21:47:34 +0000323{
324 int
325 bits,
326 flag,
327 n;
328
cristybb503372010-05-27 20:51:26 +0000329 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000330 i;
331
332 unsigned char
333 buffer[5],
334 octet;
335
336 n=1;
337 bits=28;
338 flag=MagickFalse;
339 for (i=4; i >= 0; i--)
340 {
341 octet=(unsigned char) ((value >> bits) & 0x7f);
342 if ((flag == 0) && (octet != 0))
343 {
344 flag=MagickTrue;
345 n=i+1;
346 }
347 buffer[4-i]=octet | (i && (flag || octet))*(0x01 << 7);
348 bits-=7;
349 }
350 (void) WriteBlob(image,(size_t) n,buffer+5-n);
351}
352
353static MagickBooleanType WriteWBMPImage(const ImageInfo *image_info,
354 Image *image)
355{
cristybb503372010-05-27 20:51:26 +0000356 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000357 y;
358
359 MagickBooleanType
360 status;
361
362 register const IndexPacket
363 *indexes;
364
365 register const PixelPacket
366 *p;
367
cristybb503372010-05-27 20:51:26 +0000368 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000369 x;
370
371 unsigned char
372 bit,
373 byte;
374
375 /*
376 Open output image file.
377 */
378 assert(image_info != (const ImageInfo *) NULL);
379 assert(image_info->signature == MagickSignature);
380 assert(image != (Image *) NULL);
381 assert(image->signature == MagickSignature);
382 if (image->debug != MagickFalse)
383 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
384 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
385 if (status == MagickFalse)
386 return(status);
387 if (image->colorspace != RGBColorspace)
388 (void) TransformImageColorspace(image,RGBColorspace);
389 /*
390 Convert image to a bi-level image.
391 */
392 (void) SetImageType(image,BilevelType);
393 (void) WriteBlobMSBShort(image,0);
394 WBMPWriteInteger(image,image->columns);
395 WBMPWriteInteger(image,image->rows);
cristybb503372010-05-27 20:51:26 +0000396 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000397 {
398 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
399 if (p == (const PixelPacket *) NULL)
400 break;
401 indexes=GetVirtualIndexQueue(image);
402 bit=0;
403 byte=0;
cristybb503372010-05-27 20:51:26 +0000404 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000405 {
406 if (PixelIntensity(p) >= ((MagickRealType) QuantumRange/2.0))
407 byte|=0x1 << (7-bit);
408 bit++;
409 if (bit == 8)
410 {
411 (void) WriteBlobByte(image,byte);
412 bit=0;
413 byte=0;
414 }
415 p++;
416 }
417 if (bit != 0)
418 (void) WriteBlobByte(image,byte);
419 status=SetImageProgress(image,SaveImageTag,y,image->rows);
420 if (status == MagickFalse)
421 break;
422 }
423 (void) CloseBlob(image);
424 return(MagickTrue);
425}