/src/graphicsmagick/coders/mono.c
Line | Count | Source |
1 | | /* |
2 | | % Copyright (C) 2003-2025 GraphicsMagick Group |
3 | | % Copyright (C) 2002 ImageMagick Studio |
4 | | % Copyright 1991-1999 E. I. du Pont de Nemours and Company |
5 | | % |
6 | | % This program is covered by multiple licenses, which are described in |
7 | | % Copyright.txt. You should have received a copy of Copyright.txt with this |
8 | | % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. |
9 | | % |
10 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
11 | | % % |
12 | | % % |
13 | | % % |
14 | | % M M OOO N N OOO % |
15 | | % MM MM O O NN N O O % |
16 | | % M M M O O N N N O O % |
17 | | % M M O O N NN O O % |
18 | | % M M OOO N N OOO % |
19 | | % % |
20 | | % % |
21 | | % Read/Write Raw Bi-Level Bitmap Format. % |
22 | | % % |
23 | | % % |
24 | | % Software Design % |
25 | | % John Cristy % |
26 | | % July 1992 % |
27 | | % % |
28 | | % % |
29 | | % % |
30 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
31 | | % |
32 | | % |
33 | | */ |
34 | | |
35 | | /* |
36 | | Include declarations. |
37 | | */ |
38 | | #include "magick/studio.h" |
39 | | #include "magick/blob.h" |
40 | | #include "magick/colormap.h" |
41 | | #include "magick/magick.h" |
42 | | #include "magick/monitor.h" |
43 | | #include "magick/pixel_cache.h" |
44 | | #include "magick/utility.h" |
45 | | #include "magick/static.h" |
46 | | |
47 | | /* |
48 | | Forward declarations. |
49 | | */ |
50 | | static unsigned int |
51 | | WriteMONOImage(const ImageInfo *,Image *); |
52 | | |
53 | | /* |
54 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
55 | | % % |
56 | | % % |
57 | | % % |
58 | | % R e a d M O N O I m a g e % |
59 | | % % |
60 | | % % |
61 | | % % |
62 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
63 | | % |
64 | | % Method ReadMONOImage reads an image of raw bytes in LSB order and returns |
65 | | % it. It allocates the memory necessary for the new Image structure and |
66 | | % returns a pointer to the new image. |
67 | | % |
68 | | % The format of the ReadMONOImage method is: |
69 | | % |
70 | | % Image *ReadMONOImage(const ImageInfo *image_info, |
71 | | % ExceptionInfo *exception) |
72 | | % |
73 | | % A description of each parameter follows: |
74 | | % |
75 | | % o image: Method ReadMONOImage returns a pointer to the image after |
76 | | % reading. A null image is returned if there is a memory shortage or |
77 | | % if the image cannot be read. |
78 | | % |
79 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
80 | | % |
81 | | % o exception: return any errors or warnings in this structure. |
82 | | % |
83 | | % |
84 | | */ |
85 | | static Image *ReadMONOImage(const ImageInfo *image_info, |
86 | | ExceptionInfo *exception) |
87 | 23 | { |
88 | 23 | Image |
89 | 23 | *image; |
90 | | |
91 | 23 | long |
92 | 23 | y; |
93 | | |
94 | 23 | register IndexPacket |
95 | 23 | *indexes; |
96 | | |
97 | 23 | register long |
98 | 23 | x; |
99 | | |
100 | 23 | register PixelPacket |
101 | 23 | *q; |
102 | | |
103 | 23 | register long |
104 | 23 | i; |
105 | | |
106 | 23 | unsigned char |
107 | 23 | bit, |
108 | 23 | byte; |
109 | | |
110 | 23 | unsigned int |
111 | 23 | status; |
112 | | |
113 | | /* |
114 | | Open image file. |
115 | | */ |
116 | 23 | assert(image_info != (const ImageInfo *) NULL); |
117 | 23 | assert(image_info->signature == MagickSignature); |
118 | 23 | assert(exception != (ExceptionInfo *) NULL); |
119 | 23 | assert(exception->signature == MagickSignature); |
120 | 23 | image=AllocateImage(image_info); |
121 | 23 | if ((image->columns == 0) || (image->rows == 0)) |
122 | 23 | ThrowReaderException(OptionError,MustSpecifyImageSize,image); |
123 | 0 | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
124 | 0 | if (status == False) |
125 | 0 | ThrowReaderException(FileOpenError,UnableToOpenFile,image); |
126 | 0 | for (i=0; i < image->offset; i++) |
127 | 0 | { |
128 | 0 | if (EOF == ReadBlobByte(image)) |
129 | 0 | ThrowException(exception,CorruptImageError,UnexpectedEndOfFile, |
130 | 0 | image->filename); |
131 | 0 | } |
132 | | /* |
133 | | Initialize image colormap. |
134 | | */ |
135 | 0 | if (!AllocateImageColormap(image,2)) |
136 | 0 | ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); |
137 | 0 | if (image_info->ping) |
138 | 0 | { |
139 | 0 | CloseBlob(image); |
140 | 0 | StopTimer(&image->timer); |
141 | 0 | return(image); |
142 | 0 | } |
143 | | /* |
144 | | Convert bi-level image to pixel packets. |
145 | | */ |
146 | 0 | for (y=0; y < (long) image->rows; y++) |
147 | 0 | { |
148 | 0 | q=SetImagePixels(image,0,y,image->columns,1); |
149 | 0 | if (q == (PixelPacket *) NULL) |
150 | 0 | break; |
151 | 0 | indexes=AccessMutableIndexes(image); |
152 | 0 | bit=0U; |
153 | 0 | byte=0U; |
154 | 0 | for (x=0; x < (long) image->columns; x++) |
155 | 0 | { |
156 | 0 | if (bit == 0U) |
157 | 0 | byte=ReadBlobByte(image); |
158 | 0 | indexes[x]=(byte & 0x01U) ? 0x01U : 0x00U; |
159 | 0 | bit++; |
160 | 0 | if (bit == 8U) |
161 | 0 | bit=0U; |
162 | 0 | byte>>=1U; |
163 | 0 | } |
164 | 0 | if (!SyncImagePixels(image)) |
165 | 0 | break; |
166 | 0 | if (QuantumTick(y,image->rows)) |
167 | 0 | if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText, |
168 | 0 | image->filename, |
169 | 0 | image->columns,image->rows)) |
170 | 0 | break; |
171 | 0 | } |
172 | 0 | (void) SyncImage(image); |
173 | 0 | if (EOFBlob(image)) |
174 | 0 | ThrowException(exception,CorruptImageError,UnexpectedEndOfFile, |
175 | 0 | image->filename); |
176 | 0 | CloseBlob(image); |
177 | 0 | StopTimer(&image->timer); |
178 | 0 | return(image); |
179 | 0 | } |
180 | | |
181 | | /* |
182 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
183 | | % % |
184 | | % % |
185 | | % % |
186 | | % R e g i s t e r M O N O I m a g e % |
187 | | % % |
188 | | % % |
189 | | % % |
190 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
191 | | % |
192 | | % Method RegisterMONOImage adds attributes for the MONO image format to |
193 | | % the list of supported formats. The attributes include the image format |
194 | | % tag, a method to read and/or write the format, whether the format |
195 | | % supports the saving of more than one frame to the same file or blob, |
196 | | % whether the format supports native in-memory I/O, and a brief |
197 | | % description of the format. |
198 | | % |
199 | | % The format of the RegisterMONOImage method is: |
200 | | % |
201 | | % RegisterMONOImage(void) |
202 | | % |
203 | | */ |
204 | | ModuleExport void RegisterMONOImage(void) |
205 | 1 | { |
206 | 1 | MagickInfo |
207 | 1 | *entry; |
208 | | |
209 | 1 | entry=SetMagickInfo("MONO"); |
210 | 1 | entry->decoder=(DecoderHandler) ReadMONOImage; |
211 | 1 | entry->encoder=(EncoderHandler) WriteMONOImage; |
212 | 1 | entry->adjoin=False; |
213 | 1 | entry->description="Bi-level bitmap in least-significant-byte first order"; |
214 | 1 | entry->raw=True; |
215 | 1 | entry->module="MONO"; |
216 | 1 | (void) RegisterMagickInfo(entry); |
217 | 1 | } |
218 | | |
219 | | /* |
220 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
221 | | % % |
222 | | % % |
223 | | % % |
224 | | % U n r e g i s t e r M O N O I m a g e % |
225 | | % % |
226 | | % % |
227 | | % % |
228 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
229 | | % |
230 | | % Method UnregisterMONOImage removes format registrations made by the |
231 | | % MONO module from the list of supported formats. |
232 | | % |
233 | | % The format of the UnregisterMONOImage method is: |
234 | | % |
235 | | % UnregisterMONOImage(void) |
236 | | % |
237 | | */ |
238 | | ModuleExport void UnregisterMONOImage(void) |
239 | 0 | { |
240 | 0 | (void) UnregisterMagickInfo("MONO"); |
241 | 0 | } |
242 | | |
243 | | /* |
244 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
245 | | % % |
246 | | % % |
247 | | % % |
248 | | % W r i t e M O N O I m a g e % |
249 | | % % |
250 | | % % |
251 | | % % |
252 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
253 | | % |
254 | | % Method WriteMONOImage writes an image of raw bits in LSB order to a file. |
255 | | % |
256 | | % The format of the WriteMONOImage method is: |
257 | | % |
258 | | % unsigned int WriteMONOImage(const ImageInfo *image_info,Image *image) |
259 | | % |
260 | | % A description of each parameter follows. |
261 | | % |
262 | | % o status: Method WriteMONOImage return True if the image is written. |
263 | | % False is returned is there is a memory shortage or if the image file |
264 | | % fails to write. |
265 | | % |
266 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
267 | | % |
268 | | % o image: A pointer to an Image structure. |
269 | | % |
270 | | % |
271 | | */ |
272 | | static unsigned int WriteMONOImage(const ImageInfo *image_info,Image *image) |
273 | 0 | { |
274 | 0 | long |
275 | 0 | y; |
276 | |
|
277 | 0 | register const IndexPacket |
278 | 0 | *indexes; |
279 | |
|
280 | 0 | register const PixelPacket |
281 | 0 | *p; |
282 | |
|
283 | 0 | register long |
284 | 0 | x; |
285 | |
|
286 | 0 | unsigned char |
287 | 0 | bit, |
288 | 0 | byte, |
289 | 0 | polarity; |
290 | |
|
291 | 0 | unsigned int |
292 | 0 | status; |
293 | | |
294 | | /* |
295 | | Open output image file. |
296 | | */ |
297 | 0 | assert(image_info != (const ImageInfo *) NULL); |
298 | 0 | assert(image_info->signature == MagickSignature); |
299 | 0 | assert(image != (Image *) NULL); |
300 | 0 | assert(image->signature == MagickSignature); |
301 | 0 | status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); |
302 | 0 | if (status == False) |
303 | 0 | ThrowWriterException(FileOpenError,UnableToOpenFile,image); |
304 | 0 | (void) TransformColorspace(image,RGBColorspace); |
305 | | /* |
306 | | Convert image to a bi-level image. |
307 | | */ |
308 | 0 | (void) SetImageType(image,BilevelType); |
309 | 0 | polarity=PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2); |
310 | 0 | if (image->colors == 2) |
311 | 0 | polarity=PixelIntensityToQuantum(&image->colormap[0]) < |
312 | 0 | PixelIntensityToQuantum(&image->colormap[1]); |
313 | 0 | for (y=0; y < (long) image->rows; y++) |
314 | 0 | { |
315 | 0 | p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); |
316 | 0 | if (p == (const PixelPacket *) NULL) |
317 | 0 | break; |
318 | 0 | indexes=AccessImmutableIndexes(image); |
319 | 0 | bit=0; |
320 | 0 | byte=0; |
321 | 0 | for (x=0; x < (long) image->columns; x++) |
322 | 0 | { |
323 | 0 | byte>>=1; |
324 | 0 | if (indexes[x] == polarity) |
325 | 0 | byte|=0x80; |
326 | 0 | bit++; |
327 | 0 | if (bit == 8) |
328 | 0 | { |
329 | 0 | (void) WriteBlobByte(image,byte); |
330 | 0 | bit=0; |
331 | 0 | byte=0; |
332 | 0 | } |
333 | 0 | } |
334 | 0 | if (bit != 0) |
335 | 0 | (void) WriteBlobByte(image,byte >> (8-bit)); |
336 | 0 | if (QuantumTick(y,image->rows)) |
337 | 0 | if (!MagickMonitorFormatted(y,image->rows,&image->exception, |
338 | 0 | SaveImageText,image->filename, |
339 | 0 | image->columns,image->rows)) |
340 | 0 | break; |
341 | 0 | } |
342 | 0 | status &= CloseBlob(image); |
343 | 0 | return(status); |
344 | 0 | } |