/src/imagemagick/coders/farbfeld.c
Line | Count | Source |
1 | | /* |
2 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
3 | | % % |
4 | | % % |
5 | | % % |
6 | | % % |
7 | | % FFFFF AAA RRRR BBBB FFFFF EEEEE L DDDD % |
8 | | % F A A R R B B F E L D D % |
9 | | % FFF AAAAA RRRR BBBB FFF EEE L D D % |
10 | | % F A A R R B B F E L D D % |
11 | | % F A A R R BBBB F EEEEE LLLLL DDDD % |
12 | | % % |
13 | | % % |
14 | | % Support Farbfeld Image Format % |
15 | | % % |
16 | | % Software Design % |
17 | | % Dirk Lemstra % |
18 | | % November 2020 % |
19 | | % % |
20 | | % % |
21 | | % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization % |
22 | | % dedicated to making software imaging solutions freely available. % |
23 | | % % |
24 | | % You may not use this file except in compliance with the License. You may % |
25 | | % obtain a copy of the License at % |
26 | | % % |
27 | | % https://imagemagick.org/script/license.php % |
28 | | % % |
29 | | % Unless required by applicable law or agreed to in writing, software % |
30 | | % distributed under the License is distributed on an "AS IS" BASIS, % |
31 | | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
32 | | % See the License for the specific language governing permissions and % |
33 | | % limitations under the License. % |
34 | | % % |
35 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
36 | | % |
37 | | % |
38 | | */ |
39 | | |
40 | | /* |
41 | | Include declarations. |
42 | | */ |
43 | | #include "MagickCore/studio.h" |
44 | | #include "MagickCore/attribute.h" |
45 | | #include "MagickCore/blob.h" |
46 | | #include "MagickCore/blob-private.h" |
47 | | #include "MagickCore/cache.h" |
48 | | #include "MagickCore/color-private.h" |
49 | | #include "MagickCore/colormap.h" |
50 | | #include "MagickCore/colorspace.h" |
51 | | #include "MagickCore/colorspace-private.h" |
52 | | #include "MagickCore/exception.h" |
53 | | #include "MagickCore/exception-private.h" |
54 | | #include "MagickCore/image.h" |
55 | | #include "MagickCore/image-private.h" |
56 | | #include "MagickCore/list.h" |
57 | | #include "MagickCore/magick.h" |
58 | | #include "MagickCore/memory_.h" |
59 | | #include "MagickCore/monitor.h" |
60 | | #include "MagickCore/monitor-private.h" |
61 | | #include "MagickCore/quantum-private.h" |
62 | | #include "MagickCore/static.h" |
63 | | #include "MagickCore/string_.h" |
64 | | #include "MagickCore/module.h" |
65 | | |
66 | | /* |
67 | | Forward declarations. |
68 | | */ |
69 | | static MagickBooleanType |
70 | | WriteFARBFELDImage(const ImageInfo *,Image *,ExceptionInfo *); |
71 | | |
72 | | /* |
73 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
74 | | % % |
75 | | % % |
76 | | % % |
77 | | % I s F A R B F E L D % |
78 | | % % |
79 | | % % |
80 | | % % |
81 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
82 | | % |
83 | | % IsFARBFELD() returns MagickTrue if the image format type, identified by the |
84 | | % magick string, is Farbeld. |
85 | | % |
86 | | % The format of the IsFarbeld method is: |
87 | | % |
88 | | % MagickBooleanType IsFARBFELD(const unsigned char *magick, |
89 | | % const size_t extent) |
90 | | % |
91 | | % A description of each parameter follows: |
92 | | % |
93 | | % o magick: compare image format pattern against these bytes. |
94 | | % |
95 | | % o extent: Specifies the extent of the magick string. |
96 | | % |
97 | | */ |
98 | | static MagickBooleanType IsFARBFELD(const unsigned char *magick, |
99 | | const size_t extent) |
100 | 0 | { |
101 | 0 | if (extent < 8) |
102 | 0 | return(MagickFalse); |
103 | 0 | if (LocaleNCompare((char *) magick,"farbfeld",8) == 0) |
104 | 0 | return(MagickTrue); |
105 | 0 | return(MagickFalse); |
106 | 0 | } |
107 | | |
108 | | /* |
109 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
110 | | % % |
111 | | % % |
112 | | % % |
113 | | % R e a d F A R B F E L D I m a g e % |
114 | | % % |
115 | | % % |
116 | | % % |
117 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
118 | | % |
119 | | % ReadFARBFELDImage() reads an image of raw bits in LSB order and returns it. |
120 | | % It allocates the memory necessary for the new Image structure and returns |
121 | | % a pointer to the new image. |
122 | | % |
123 | | % The format of the ReadFARBFELDImage method is: |
124 | | % |
125 | | % Image *ReadFARBFELDImage(const ImageInfo *image_info, |
126 | | % ExceptionInfo *exception) |
127 | | % |
128 | | % A description of each parameter follows: |
129 | | % |
130 | | % o image_info: the image info. |
131 | | % |
132 | | % o exception: return any errors or warnings in this structure. |
133 | | % |
134 | | */ |
135 | | static Image *ReadFARBFELDImage(const ImageInfo *image_info, |
136 | | ExceptionInfo *exception) |
137 | 625 | { |
138 | 625 | Image |
139 | 625 | *image; |
140 | | |
141 | 625 | QuantumInfo |
142 | 625 | *quantum_info; |
143 | | |
144 | 625 | MagickBooleanType |
145 | 625 | status; |
146 | | |
147 | 625 | MagickSizeType |
148 | 625 | magic; |
149 | | |
150 | 625 | size_t |
151 | 625 | extent; |
152 | | |
153 | 625 | ssize_t |
154 | 625 | count, |
155 | 625 | y; |
156 | | |
157 | 625 | unsigned char |
158 | 625 | *pixels; |
159 | | |
160 | | /* |
161 | | Open image file. |
162 | | */ |
163 | 625 | assert(image_info != (const ImageInfo *) NULL); |
164 | 625 | assert(image_info->signature == MagickCoreSignature); |
165 | 625 | assert(exception != (ExceptionInfo *) NULL); |
166 | 625 | assert(exception->signature == MagickCoreSignature); |
167 | 625 | if (IsEventLogging() != MagickFalse) |
168 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", |
169 | 0 | image_info->filename); |
170 | 625 | image=AcquireImage(image_info,exception); |
171 | 625 | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
172 | 625 | if (status == MagickFalse) |
173 | 63 | { |
174 | 63 | image=DestroyImageList(image); |
175 | 63 | return((Image *) NULL); |
176 | 63 | } |
177 | 562 | image->depth=16; |
178 | 562 | image->endian=MSBEndian; |
179 | 562 | magic=ReadBlobLongLong(image); |
180 | 562 | if (magic != MagickULLConstant(7377303431559867492)) |
181 | 413 | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
182 | 413 | image->columns=(size_t) ReadBlobLong(image); |
183 | 413 | image->rows=(size_t) ReadBlobLong(image); |
184 | 413 | image->alpha_trait=BlendPixelTrait; |
185 | 413 | if (image_info->ping != MagickFalse) |
186 | 1 | { |
187 | 1 | (void) CloseBlob(image); |
188 | 1 | return(GetFirstImageInList(image)); |
189 | 1 | } |
190 | 412 | status=SetImageExtent(image,image->columns,image->rows,exception); |
191 | 412 | if (status == MagickFalse) |
192 | 126 | return(DestroyImageList(image)); |
193 | 286 | quantum_info=AcquireQuantumInfo(image_info,image); |
194 | 286 | if (quantum_info == (QuantumInfo *) NULL) |
195 | 286 | ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
196 | 286 | status=SetQuantumFormat(image,quantum_info,UnsignedQuantumFormat); |
197 | 286 | extent=GetQuantumExtent(image,quantum_info,RGBAQuantum); |
198 | 286 | pixels=GetQuantumPixels(quantum_info); |
199 | 17.6k | for (y=0; y < (ssize_t) image->rows; y++) |
200 | 17.5k | { |
201 | 17.5k | const void |
202 | 17.5k | *stream; |
203 | | |
204 | 17.5k | Quantum |
205 | 17.5k | *magick_restrict q; |
206 | | |
207 | 17.5k | q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); |
208 | 17.5k | if (q == (Quantum *) NULL) |
209 | 0 | break; |
210 | 17.5k | stream=ReadBlobStream(image,extent,pixels,&count); |
211 | 17.5k | if (count != (ssize_t) extent) |
212 | 133 | break; |
213 | 17.3k | (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info, |
214 | 17.3k | RGBAQuantum,(unsigned char *) stream,exception); |
215 | 17.3k | if (SyncAuthenticPixels(image,exception) == MagickFalse) |
216 | 0 | break; |
217 | 17.3k | if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse) |
218 | 0 | break; |
219 | 17.3k | } |
220 | 286 | SetQuantumImageType(image,RGBAQuantum); |
221 | 286 | quantum_info=DestroyQuantumInfo(quantum_info); |
222 | 286 | if (y < (ssize_t) image->rows) |
223 | 153 | ThrowReaderException(CorruptImageError,"UnableToReadImageData"); |
224 | 153 | if (EOFBlob(image) != MagickFalse) |
225 | 0 | ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", |
226 | 153 | image->filename); |
227 | 153 | if (CloseBlob(image) == MagickFalse) |
228 | 0 | status=MagickFalse; |
229 | 153 | if (status == MagickFalse) |
230 | 0 | return(DestroyImageList(image)); |
231 | 153 | return(GetFirstImageInList(image)); |
232 | 153 | } |
233 | | |
234 | | /* |
235 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
236 | | % % |
237 | | % % |
238 | | % % |
239 | | % R e g i s t e r F A R B F E L D I m a g e % |
240 | | % % |
241 | | % % |
242 | | % % |
243 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
244 | | % |
245 | | % RegisterFARBFELDImage() adds attributes for the FARBFELD image format to |
246 | | % the list of supported formats. The attributes include the image format |
247 | | % tag, a method to read and/or write the format, whether the format |
248 | | % supports the saving of more than one frame to the same file or blob, |
249 | | % whether the format supports native in-memory I/O, and a brief |
250 | | % description of the format. |
251 | | % |
252 | | % The format of the RegisterFARBFELDImage method is: |
253 | | % |
254 | | % size_t RegisterFARBFELDImage(void) |
255 | | % |
256 | | */ |
257 | | ModuleExport size_t RegisterFARBFELDImage(void) |
258 | 10 | { |
259 | 10 | MagickInfo |
260 | 10 | *entry; |
261 | | |
262 | 10 | entry=AcquireMagickInfo("FARBFELD","FARBFELD","Farbfeld"); |
263 | 10 | entry->decoder=(DecodeImageHandler *) ReadFARBFELDImage; |
264 | 10 | entry->encoder=(EncodeImageHandler *) WriteFARBFELDImage; |
265 | 10 | entry->magick=(IsImageFormatHandler *) IsFARBFELD; |
266 | 10 | entry->flags|=CoderRawSupportFlag; |
267 | 10 | entry->flags^=CoderAdjoinFlag; |
268 | 10 | (void) RegisterMagickInfo(entry); |
269 | 10 | entry=AcquireMagickInfo("FARBFELD","FF","Farbfeld"); |
270 | 10 | entry->decoder=(DecodeImageHandler *) ReadFARBFELDImage; |
271 | 10 | entry->encoder=(EncodeImageHandler *) WriteFARBFELDImage; |
272 | 10 | entry->magick=(IsImageFormatHandler *) IsFARBFELD; |
273 | 10 | entry->flags|=CoderRawSupportFlag; |
274 | 10 | entry->flags^=CoderAdjoinFlag; |
275 | 10 | (void) RegisterMagickInfo(entry); |
276 | 10 | return(MagickImageCoderSignature); |
277 | 10 | } |
278 | | |
279 | | /* |
280 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
281 | | % % |
282 | | % % |
283 | | % % |
284 | | % U n r e g i s t e r F A R B F E L D I m a g e % |
285 | | % % |
286 | | % % |
287 | | % % |
288 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
289 | | % |
290 | | % UnregisterFARBFELDImage() removes format registrations made by the |
291 | | % Farbfeld module from the list of supported formats. |
292 | | % |
293 | | % The format of the UnregisterFARBFELDImage method is: |
294 | | % |
295 | | % UnregisterFARBFELDImage(void) |
296 | | % |
297 | | */ |
298 | | ModuleExport void UnregisterFARBFELDImage(void) |
299 | 0 | { |
300 | 0 | (void) UnregisterMagickInfo("FARBFELD"); |
301 | 0 | } |
302 | | |
303 | | /* |
304 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
305 | | % % |
306 | | % % |
307 | | % % |
308 | | % W r i t e F A R B F E L D I m a g e % |
309 | | % % |
310 | | % % |
311 | | % % |
312 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
313 | | % |
314 | | % WriteFARBFELDImage() writes an image of raw bits in MSB order to a file. |
315 | | % |
316 | | % The format of the WriteFARBFELDImage method is: |
317 | | % |
318 | | % MagickBooleanType WriteFARBFELDImage(const ImageInfo *image_info, |
319 | | % Image *image,ExceptionInfo *exception) |
320 | | % |
321 | | % A description of each parameter follows. |
322 | | % |
323 | | % o image_info: the image info. |
324 | | % |
325 | | % o image: The image. |
326 | | % |
327 | | % o exception: return any errors or warnings in this structure. |
328 | | % |
329 | | */ |
330 | | static MagickBooleanType WriteFARBFELDImage(const ImageInfo *image_info, |
331 | | Image *image,ExceptionInfo *exception) |
332 | 153 | { |
333 | 153 | MagickBooleanType |
334 | 153 | status; |
335 | | |
336 | 153 | QuantumInfo |
337 | 153 | *quantum_info; |
338 | | |
339 | 153 | const Quantum |
340 | 153 | *p; |
341 | | |
342 | 153 | size_t |
343 | 153 | extent; |
344 | | |
345 | 153 | ssize_t |
346 | 153 | count, |
347 | 153 | y; |
348 | | |
349 | 153 | unsigned char |
350 | 153 | *pixels; |
351 | | |
352 | | /* |
353 | | Open output image file. |
354 | | */ |
355 | 153 | assert(image_info != (const ImageInfo *) NULL); |
356 | 153 | assert(image_info->signature == MagickCoreSignature); |
357 | 153 | assert(image != (Image *) NULL); |
358 | 153 | assert(image->signature == MagickCoreSignature); |
359 | 153 | assert(exception != (ExceptionInfo *) NULL); |
360 | 153 | assert(exception->signature == MagickCoreSignature); |
361 | 153 | if (IsEventLogging() != MagickFalse) |
362 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
363 | 153 | status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); |
364 | 153 | if (status == MagickFalse) |
365 | 0 | return(status); |
366 | 153 | image->endian=MSBEndian; |
367 | 153 | (void) WriteBlobLongLong(image,MagickULLConstant(7377303431559867492)); |
368 | 153 | (void) WriteBlobLong(image,(unsigned int) image->columns); |
369 | 153 | (void) WriteBlobLong(image,(unsigned int) image->rows); |
370 | 153 | image->depth=16; |
371 | 153 | quantum_info=AcquireQuantumInfo(image_info,image); |
372 | 153 | if (quantum_info == (QuantumInfo *) NULL) |
373 | 153 | ThrowWriterException(ImageError,"MemoryAllocationFailed"); |
374 | 153 | status=SetQuantumFormat(image,quantum_info,UnsignedQuantumFormat); |
375 | 153 | pixels=(unsigned char *) GetQuantumPixels(quantum_info); |
376 | 14.0k | for (y=0; y < (ssize_t) image->rows; y++) |
377 | 13.9k | { |
378 | 13.9k | p=GetVirtualPixels(image,0,y,image->columns,1,exception); |
379 | 13.9k | if (p == (const Quantum *) NULL) |
380 | 0 | break; |
381 | 13.9k | extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info, |
382 | 13.9k | RGBAQuantum,pixels,exception); |
383 | 13.9k | count=WriteBlob(image,extent,pixels); |
384 | 13.9k | if (count != (ssize_t) extent) |
385 | 0 | break; |
386 | 13.9k | status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, |
387 | 13.9k | image->rows); |
388 | 13.9k | if (status == MagickFalse) |
389 | 0 | break; |
390 | 13.9k | } |
391 | 153 | quantum_info=DestroyQuantumInfo(quantum_info); |
392 | 153 | if (y < (ssize_t) image->rows) |
393 | 153 | ThrowWriterException(CorruptImageError,"UnableToWriteImageData"); |
394 | 153 | if (CloseBlob(image) == MagickFalse) |
395 | 0 | status=MagickFalse; |
396 | 153 | return(status); |
397 | 153 | } |