blob: 9c7f00f368fe097ca2bfee28c1a158a16bcef55b [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"
46#include "magick/colorspace.h"
47#include "magick/exception.h"
48#include "magick/exception-private.h"
49#include "magick/image.h"
50#include "magick/image-private.h"
51#include "magick/list.h"
52#include "magick/magick.h"
53#include "magick/memory_.h"
54#include "magick/monitor.h"
55#include "magick/monitor-private.h"
56#include "magick/quantum-private.h"
57#include "magick/static.h"
58#include "magick/string_.h"
59#include "magick/module.h"
60
61/*
62 Forward declarations.
63*/
64static MagickBooleanType
65 WriteWBMPImage(const ImageInfo *,Image *);
66
67/*
68%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69% %
70% %
71% %
72% R e a d W B M P I m a g e %
73% %
74% %
75% %
76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77%
78% ReadWBMPImage() reads a WBMP (level 0) image file and returns it. It
79% allocates the memory necessary for the new Image structure and returns a
80% pointer to the new image.
81%
82% ReadWBMPImage was contributed by Milan Votava <votava@mageo.cz>.
83%
84% The format of the ReadWBMPImage method is:
85%
86% Image *ReadWBMPImage(const ImageInfo *image_info,
87% ExceptionInfo *exception)
88%
89% A description of each parameter follows:
90%
91% o image_info: the image info.
92%
93% o exception: return any errors or warnings in this structure.
94%
95*/
96
97static MagickBooleanType WBMPReadInteger(Image *image,unsigned long *value)
98{
99 int
100 byte;
101
102 *value=0;
103 do
104 {
105 byte=ReadBlobByte(image);
106 if (byte == EOF)
107 return(MagickFalse);
108 *value<<=7;
109 *value|=(unsigned int) (byte & 0x7f);
110 } while (byte & 0x80);
111 return(MagickTrue);
112}
113
114static Image *ReadWBMPImage(const ImageInfo *image_info,
115 ExceptionInfo *exception)
116{
117 Image
118 *image;
119
120 int
121 byte;
122
123 long
124 y;
125
126 MagickBooleanType
127 status;
128
129 register IndexPacket
130 *indexes;
131
132 register long
133 x;
134
135 register PixelPacket
136 *q;
137
138 register long
139 i;
140
141 unsigned char
142 bit;
143
144 unsigned short
145 header;
146
147 /*
148 Open image file.
149 */
150 assert(image_info != (const ImageInfo *) NULL);
151 assert(image_info->signature == MagickSignature);
152 if (image_info->debug != MagickFalse)
153 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
154 image_info->filename);
155 assert(exception != (ExceptionInfo *) NULL);
156 assert(exception->signature == MagickSignature);
157 image=AcquireImage(image_info);
158 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
159 if (status == MagickFalse)
160 {
161 image=DestroyImageList(image);
162 return((Image *) NULL);
163 }
164 if (ReadBlob(image,2,(unsigned char *) &header) == 0)
165 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
166 if (header != 0)
167 ThrowReaderException(CoderError,"OnlyLevelZerofilesSupported");
168 /*
169 Initialize image structure.
170 */
171 if (WBMPReadInteger(image,&image->columns) == MagickFalse)
172 ThrowReaderException(CorruptImageError,"CorruptWBMPimage");
173 if (WBMPReadInteger(image,&image->rows) == MagickFalse)
174 ThrowReaderException(CorruptImageError,"CorruptWBMPimage");
175 if ((image->columns == 0) || (image->rows == 0))
176 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
177 for (i=0; i < image->offset; i++)
178 if (ReadBlobByte(image) == EOF)
179 {
180 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
181 image->filename);
182 break;
183 }
184 if (AcquireImageColormap(image,2) == MagickFalse)
185 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
186 if (image_info->ping != MagickFalse)
187 {
188 (void) CloseBlob(image);
189 return(GetFirstImageInList(image));
190 }
191 /*
192 Convert bi-level image to pixel packets.
193 */
194 for (y=0; y < (long) image->rows; y++)
195 {
196 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
197 if (q == (PixelPacket *) NULL)
198 break;
199 indexes=GetAuthenticIndexQueue(image);
200 bit=0;
201 byte=0;
202 for (x=0; x < (long) image->columns; x++)
203 {
204 if (bit == 0)
205 {
206 byte=ReadBlobByte(image);
207 if (byte == EOF)
208 ThrowReaderException(CorruptImageError,"CorruptImage");
209 }
210 indexes[x]=(IndexPacket) ((byte & (0x01 << (7-bit))) ? 1 : 0);
211 bit++;
212 if (bit == 8)
213 bit=0;
214 }
215 if (SyncAuthenticPixels(image,exception) == MagickFalse)
216 break;
217 status=SetImageProgress(image,LoadImageTag,y,image->rows);
218 if (status == MagickFalse)
219 break;
220 }
221 (void) SyncImage(image);
222 if (EOFBlob(image) != MagickFalse)
223 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
224 image->filename);
225 (void) CloseBlob(image);
226 return(GetFirstImageInList(image));
227}
228
229/*
230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231% %
232% %
233% %
234% R e g i s t e r W B M P I m a g e %
235% %
236% %
237% %
238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239%
240% RegisterWBMPImage() adds attributes for the WBMP image format to
241% the list of supported formats. The attributes include the image format
242% tag, a method to read and/or write the format, whether the format
243% supports the saving of more than one frame to the same file or blob,
244% whether the format supports native in-memory I/O, and a brief
245% description of the format.
246%
247% The format of the RegisterWBMPImage method is:
248%
249% unsigned long RegisterWBMPImage(void)
250%
251*/
252ModuleExport unsigned long RegisterWBMPImage(void)
253{
254 MagickInfo
255 *entry;
256
257 entry=SetMagickInfo("WBMP");
258 entry->decoder=(DecodeImageHandler *) ReadWBMPImage;
259 entry->encoder=(EncodeImageHandler *) WriteWBMPImage;
260 entry->adjoin=MagickFalse;
261 entry->description=ConstantString("Wireless Bitmap (level 0) image");
262 entry->module=ConstantString("WBMP");
263 (void) RegisterMagickInfo(entry);
264 return(MagickImageCoderSignature);
265}
266
267/*
268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269% %
270% %
271% %
272% U n r e g i s t e r W B M P I m a g e %
273% %
274% %
275% %
276%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277%
278% UnregisterWBMPImage() removes format registrations made by the
279% WBMP module from the list of supported formats.
280%
281% The format of the UnregisterWBMPImage method is:
282%
283% UnregisterWBMPImage(void)
284%
285*/
286ModuleExport void UnregisterWBMPImage(void)
287{
288 (void) UnregisterMagickInfo("WBMP");
289}
290
291/*
292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293% %
294% %
295% %
296% W r i t e W B M P I m a g e %
297% %
298% %
299% %
300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301%
302% WriteWBMPImage() writes an image to a file in the Wireless Bitmap
303% (level 0) image format.
304%
305% WriteWBMPImage was contributed by Milan Votava <votava@mageo.cz>.
306%
307% The format of the WriteWBMPImage method is:
308%
309% MagickBooleanType WriteWBMPImage(const ImageInfo *image_info,
310% Image *image)
311%
312% A description of each parameter follows.
313%
314% o image_info: the image info.
315%
316% o image: The image.
317%
318%
319*/
320
321static void WBMPWriteInteger(Image *image,const unsigned long value)
322{
323 int
324 bits,
325 flag,
326 n;
327
328 register long
329 i;
330
331 unsigned char
332 buffer[5],
333 octet;
334
335 n=1;
336 bits=28;
337 flag=MagickFalse;
338 for (i=4; i >= 0; i--)
339 {
340 octet=(unsigned char) ((value >> bits) & 0x7f);
341 if ((flag == 0) && (octet != 0))
342 {
343 flag=MagickTrue;
344 n=i+1;
345 }
346 buffer[4-i]=octet | (i && (flag || octet))*(0x01 << 7);
347 bits-=7;
348 }
349 (void) WriteBlob(image,(size_t) n,buffer+5-n);
350}
351
352static MagickBooleanType WriteWBMPImage(const ImageInfo *image_info,
353 Image *image)
354{
355 long
356 y;
357
358 MagickBooleanType
359 status;
360
361 register const IndexPacket
362 *indexes;
363
364 register const PixelPacket
365 *p;
366
367 register long
368 x;
369
370 unsigned char
371 bit,
372 byte;
373
374 /*
375 Open output image file.
376 */
377 assert(image_info != (const ImageInfo *) NULL);
378 assert(image_info->signature == MagickSignature);
379 assert(image != (Image *) NULL);
380 assert(image->signature == MagickSignature);
381 if (image->debug != MagickFalse)
382 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
383 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
384 if (status == MagickFalse)
385 return(status);
386 if (image->colorspace != RGBColorspace)
387 (void) TransformImageColorspace(image,RGBColorspace);
388 /*
389 Convert image to a bi-level image.
390 */
391 (void) SetImageType(image,BilevelType);
392 (void) WriteBlobMSBShort(image,0);
393 WBMPWriteInteger(image,image->columns);
394 WBMPWriteInteger(image,image->rows);
395 for (y=0; y < (long) image->rows; y++)
396 {
397 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
398 if (p == (const PixelPacket *) NULL)
399 break;
400 indexes=GetVirtualIndexQueue(image);
401 bit=0;
402 byte=0;
403 for (x=0; x < (long) image->columns; x++)
404 {
405 if (PixelIntensity(p) >= ((MagickRealType) QuantumRange/2.0))
406 byte|=0x1 << (7-bit);
407 bit++;
408 if (bit == 8)
409 {
410 (void) WriteBlobByte(image,byte);
411 bit=0;
412 byte=0;
413 }
414 p++;
415 }
416 if (bit != 0)
417 (void) WriteBlobByte(image,byte);
418 status=SetImageProgress(image,SaveImageTag,y,image->rows);
419 if (status == MagickFalse)
420 break;
421 }
422 (void) CloseBlob(image);
423 return(MagickTrue);
424}