blob: c2c021b570975ab3902f716c6b498e1b41834cf2 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% OOO TTTTT BBBB %
7% O O T B B %
8% O O T BBBB %
9% O O T B B %
10% OOO T BBBB %
11% %
12% %
13% Read/Write On-The-Air 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 WriteOTBImage(const ImageInfo *,Image *);
66
67/*
68%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69% %
70% %
71% %
72% R e a d O T B I m a g e %
73% %
74% %
75% %
76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77%
78% ReadOTBImage() reads a on-the-air (level 0) bitmap 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% The format of the ReadOTBImage method is:
83%
84% Image *ReadOTBImage(const ImageInfo *image_info,ExceptionInfo *exception)
85%
86% A description of each parameter follows:
87%
88% o image_info: the image info.
89%
90% o exception: return any errors or warnings in this structure.
91%
92%
93*/
94static Image *ReadOTBImage(const ImageInfo *image_info,ExceptionInfo *exception)
95{
96#define GetBit(a,i) (((a) >> (i)) & 1L)
97
98 Image
99 *image;
100
101 int
102 byte;
103
104 long
105 y;
106
107 MagickBooleanType
108 status;
109
110 register IndexPacket
111 *indexes;
112
113 register long
114 x;
115
116 register PixelPacket
117 *q;
118
119 unsigned char
120 bit,
121 info,
122 depth;
123
124 /*
125 Open image file.
126 */
127 assert(image_info != (const ImageInfo *) NULL);
128 assert(image_info->signature == MagickSignature);
129 if (image_info->debug != MagickFalse)
130 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
131 image_info->filename);
132 assert(exception != (ExceptionInfo *) NULL);
133 assert(exception->signature == MagickSignature);
134 image=AcquireImage(image_info);
135 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
136 if (status == MagickFalse)
137 {
138 image=DestroyImageList(image);
139 return((Image *) NULL);
140 }
141 /*
142 Initialize image structure.
143 */
144 info=(unsigned char) ReadBlobByte(image);
145 if (GetBit(info,4) == 0)
146 {
147 image->columns=(unsigned long) ReadBlobByte(image);
148 image->rows=(unsigned long) ReadBlobByte(image);
149 }
150 else
151 {
152 image->columns=(unsigned long) ReadBlobMSBShort(image);
153 image->rows=(unsigned long) ReadBlobMSBShort(image);
154 }
155 if ((image->columns == 0) || (image->rows == 0))
156 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
157 depth=(unsigned char) ReadBlobByte(image);
158 if (depth != 1)
159 ThrowReaderException(CoderError,"OnlyLevelZerofilesSupported");
160 if (AcquireImageColormap(image,2) == MagickFalse)
161 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
162 if (image_info->ping != MagickFalse)
163 {
164 (void) CloseBlob(image);
165 return(GetFirstImageInList(image));
166 }
167 /*
168 Convert bi-level image to pixel packets.
169 */
170 for (y=0; y < (long) image->rows; y++)
171 {
172 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
173 if (q == (PixelPacket *) NULL)
174 break;
175 indexes=GetAuthenticIndexQueue(image);
176 bit=0;
177 byte=0;
178 for (x=0; x < (long) image->columns; x++)
179 {
180 if (bit == 0)
181 {
182 byte=ReadBlobByte(image);
183 if (byte == EOF)
184 ThrowReaderException(CorruptImageError,"CorruptImage");
185 }
186 indexes[x]=(IndexPacket) ((byte & (0x01 << (7-bit))) ? 0x00 : 0x01);
187 bit++;
188 if (bit == 8)
189 bit=0;
190 }
191 if (SyncAuthenticPixels(image,exception) == MagickFalse)
192 break;
193 if (image->previous == (Image *) NULL)
194 {
195 status=SetImageProgress(image,LoadImageTag,y,image->rows);
196 if (status == MagickFalse)
197 break;
198 }
199 }
200 (void) SyncImage(image);
201 if (EOFBlob(image) != MagickFalse)
202 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
203 image->filename);
204 (void) CloseBlob(image);
205 return(GetFirstImageInList(image));
206}
207
208/*
209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210% %
211% %
212% %
213% R e g i s t e r O T B I m a g e %
214% %
215% %
216% %
217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218%
219% RegisterOTBImage() adds attributes for the OTB image format to
220% the list of supported formats. The attributes include the image format
221% tag, a method to read and/or write the format, whether the format
222% supports the saving of more than one frame to the same file or blob,
223% whether the format supports native in-memory I/O, and a brief
224% description of the format.
225%
226% The format of the RegisterOTBImage method is:
227%
228% unsigned long RegisterOTBImage(void)
229%
230*/
231ModuleExport unsigned long RegisterOTBImage(void)
232{
233 MagickInfo
234 *entry;
235
236 entry=SetMagickInfo("OTB");
237 entry->decoder=(DecodeImageHandler *) ReadOTBImage;
238 entry->encoder=(EncodeImageHandler *) WriteOTBImage;
239 entry->adjoin=MagickFalse;
240 entry->description=ConstantString("On-the-air bitmap");
241 entry->module=ConstantString("OTB");
242 (void) RegisterMagickInfo(entry);
243 return(MagickImageCoderSignature);
244}
245
246/*
247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248% %
249% %
250% %
251% U n r e g i s t e r O T B I m a g e %
252% %
253% %
254% %
255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256%
257% UnregisterOTBImage() removes format registrations made by the
258% OTB module from the list of supported formats.
259%
260% The format of the UnregisterOTBImage method is:
261%
262% UnregisterOTBImage(void)
263%
264*/
265ModuleExport void UnregisterOTBImage(void)
266{
267 (void) UnregisterMagickInfo("OTB");
268}
269
270/*
271%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272% %
273% %
274% %
275% W r i t e O T B I m a g e %
276% %
277% %
278% %
279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280%
281% WriteOTBImage() writes an image to a file in the On-the-air Bitmap
282% (level 0) image format.
283%
284% The format of the WriteOTBImage method is:
285%
286% MagickBooleanType WriteOTBImage(const ImageInfo *image_info,Image *image)
287%
288% A description of each parameter follows.
289%
290% o image_info: the image info.
291%
292% o image: The image.
293%
294%
295*/
296static MagickBooleanType WriteOTBImage(const ImageInfo *image_info,Image *image)
297{
298#define SetBit(a,i,set) \
299 a=(unsigned char) ((set) ? (a) | (1L << (i)) : (a) & ~(1L << (i)))
300
301 long
302 y;
303
304 MagickBooleanType
305 status;
306
307 register const PixelPacket
308 *p;
309
310 register long
311 x;
312
313 unsigned char
314 bit,
315 byte,
316 info;
317
318 /*
319 Open output image file.
320 */
321 assert(image_info != (const ImageInfo *) NULL);
322 assert(image_info->signature == MagickSignature);
323 assert(image != (Image *) NULL);
324 assert(image->signature == MagickSignature);
325 if (image->debug != MagickFalse)
326 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
327 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
328 if (status == MagickFalse)
329 return(status);
330 if (image->colorspace != RGBColorspace)
331 (void) TransformImageColorspace(image,RGBColorspace);
332 /*
333 Convert image to a bi-level image.
334 */
335 (void) SetImageType(image,BilevelType);
336 info=0;
337 if ((image->columns >= 256) || (image->rows >= 256))
338 SetBit(info,4,1);
339 (void) WriteBlobByte(image,info);
340 if ((image->columns >= 256) || (image->rows >= 256))
341 {
342 (void) WriteBlobMSBShort(image,(unsigned short) image->columns);
343 (void) WriteBlobMSBShort(image,(unsigned short) image->rows);
344 }
345 else
346 {
347 (void) WriteBlobByte(image,(unsigned char) image->columns);
348 (void) WriteBlobByte(image,(unsigned char) image->rows);
349 }
350 (void) WriteBlobByte(image,1); /* depth */
351 for (y=0; y < (long) image->rows; y++)
352 {
353 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
354 if (p == (const PixelPacket *) NULL)
355 break;
356 bit=0;
357 byte=0;
358 for (x=0; x < (long) image->columns; x++)
359 {
360 if (PixelIntensity(p) < ((Quantum) QuantumRange/2.0))
361 byte|=0x1 << (7-bit);
362 bit++;
363 if (bit == 8)
364 {
365 (void) WriteBlobByte(image,byte);
366 bit=0;
367 byte=0;
368 }
369 p++;
370 }
371 if (bit != 0)
372 (void) WriteBlobByte(image,byte);
373 if (image->previous == (Image *) NULL)
374 {
375 status=SetImageProgress(image,SaveImageTag,y,image->rows);
376 if (status == MagickFalse)
377 break;
378 }
379 }
380 (void) CloseBlob(image);
381 return(MagickTrue);
382}