/src/imagemagick/coders/fl32.c
Line | Count | Source |
1 | | /* |
2 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
3 | | % % |
4 | | % % |
5 | | % % |
6 | | % % |
7 | | % FFFFF L IIIII FFFFF % |
8 | | % F L I F % |
9 | | % FFF L I FFF % |
10 | | % F L I F % |
11 | | % F LLLLL IIIII F % |
12 | | % % |
13 | | % % |
14 | | % Support FilmLight Image Format % |
15 | | % % |
16 | | % Software Design % |
17 | | % Cristy % |
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 | | WriteFL32Image(const ImageInfo *,Image *,ExceptionInfo *); |
71 | | |
72 | | /* |
73 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
74 | | % % |
75 | | % % |
76 | | % % |
77 | | % I s F L 3 2 % |
78 | | % % |
79 | | % % |
80 | | % % |
81 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
82 | | % |
83 | | % IsFL32() returns MagickTrue if the image format type, identified by the |
84 | | % magick string, is FL32. |
85 | | % |
86 | | % The format of the IsFL32 method is: |
87 | | % |
88 | | % MagickBooleanType IsFL32(const unsigned char *magick,const size_t extent) |
89 | | % |
90 | | % A description of each parameter follows: |
91 | | % |
92 | | % o magick: compare image format pattern against these bytes. |
93 | | % |
94 | | % o extent: Specifies the extent of the magick string. |
95 | | % |
96 | | */ |
97 | | static MagickBooleanType IsFL32(const unsigned char *magick,const size_t extent) |
98 | 0 | { |
99 | 0 | if (extent < 4) |
100 | 0 | return(MagickFalse); |
101 | 0 | if (LocaleNCompare((char *) magick,"FL32",4) == 0) |
102 | 0 | return(MagickTrue); |
103 | 0 | return(MagickFalse); |
104 | 0 | } |
105 | | |
106 | | /* |
107 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
108 | | % % |
109 | | % % |
110 | | % % |
111 | | % R e a d F L 3 2 I m a g e % |
112 | | % % |
113 | | % % |
114 | | % % |
115 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
116 | | % |
117 | | % ReadFL32Image() reads an image of raw bits in LSB order and returns it. |
118 | | % It allocates the memory necessary for the new Image structure and returns |
119 | | % a pointer to the new image. |
120 | | % |
121 | | % The format of the ReadFL32Image method is: |
122 | | % |
123 | | % Image *ReadFL32Image(const ImageInfo *image_info, |
124 | | % ExceptionInfo *exception) |
125 | | % |
126 | | % A description of each parameter follows: |
127 | | % |
128 | | % o image_info: the image info. |
129 | | % |
130 | | % o exception: return any errors or warnings in this structure. |
131 | | % |
132 | | */ |
133 | | static Image *ReadFL32Image(const ImageInfo *image_info, |
134 | | ExceptionInfo *exception) |
135 | 1.18k | { |
136 | 1.18k | Image |
137 | 1.18k | *image; |
138 | | |
139 | 1.18k | MagickBooleanType |
140 | 1.18k | status; |
141 | | |
142 | 1.18k | QuantumInfo |
143 | 1.18k | *quantum_info; |
144 | | |
145 | 1.18k | QuantumType |
146 | 1.18k | quantum_type; |
147 | | |
148 | 1.18k | size_t |
149 | 1.18k | extent; |
150 | | |
151 | 1.18k | ssize_t |
152 | 1.18k | count, |
153 | 1.18k | y; |
154 | | |
155 | 1.18k | unsigned char |
156 | 1.18k | *pixels; |
157 | | |
158 | 1.18k | unsigned int |
159 | 1.18k | magic; |
160 | | |
161 | | /* |
162 | | Open image file. |
163 | | */ |
164 | 1.18k | assert(image_info != (const ImageInfo *) NULL); |
165 | 1.18k | assert(image_info->signature == MagickCoreSignature); |
166 | 1.18k | assert(exception != (ExceptionInfo *) NULL); |
167 | 1.18k | assert(exception->signature == MagickCoreSignature); |
168 | 1.18k | if (IsEventLogging() != MagickFalse) |
169 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", |
170 | 0 | image_info->filename); |
171 | 1.18k | image=AcquireImage(image_info,exception); |
172 | 1.18k | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
173 | 1.18k | if (status == MagickFalse) |
174 | 300 | { |
175 | 300 | image=DestroyImageList(image); |
176 | 300 | return((Image *) NULL); |
177 | 300 | } |
178 | 883 | magic=ReadBlobLSBLong(image); |
179 | 883 | if (magic != 842222662) |
180 | 676 | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
181 | 676 | image->depth=32; |
182 | 676 | image->endian=LSBEndian; |
183 | 676 | image->rows=(size_t) ReadBlobLSBLong(image); |
184 | 676 | image->columns=(size_t) ReadBlobLSBLong(image); |
185 | 676 | image->number_channels=(size_t) ReadBlobLSBLong(image); |
186 | 676 | if ((image->columns == 0) || (image->rows == 0) || |
187 | 664 | (image->number_channels == 0) || |
188 | 622 | (image->number_channels >= MaxPixelChannels)) |
189 | 557 | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
190 | 557 | switch (image->number_channels) |
191 | 557 | { |
192 | 210 | case 1: |
193 | 210 | { |
194 | 210 | quantum_type=GrayQuantum; |
195 | 210 | image->colorspace=GRAYColorspace; |
196 | 210 | break; |
197 | 0 | } |
198 | 62 | case 2: |
199 | 62 | { |
200 | 62 | image->alpha_trait=BlendPixelTrait; |
201 | 62 | image->colorspace=GRAYColorspace; |
202 | 62 | quantum_type=GrayAlphaQuantum; |
203 | 62 | break; |
204 | 0 | } |
205 | 7 | case 3: |
206 | 7 | { |
207 | 7 | image->colorspace=sRGBColorspace; |
208 | 7 | quantum_type=RGBQuantum; |
209 | 7 | break; |
210 | 0 | } |
211 | 86 | case 4: |
212 | 86 | { |
213 | 86 | image->colorspace=sRGBColorspace; |
214 | 86 | image->alpha_trait=BlendPixelTrait; |
215 | 86 | quantum_type=RGBAQuantum; |
216 | 86 | break; |
217 | 0 | } |
218 | 192 | default: |
219 | 192 | { |
220 | 192 | image->number_meta_channels=image->number_channels-3; |
221 | 192 | quantum_type=RGBQuantum; |
222 | 192 | break; |
223 | 0 | } |
224 | 557 | } |
225 | 557 | if (image_info->ping != MagickFalse) |
226 | 16 | { |
227 | 16 | (void) CloseBlob(image); |
228 | 16 | return(GetFirstImageInList(image)); |
229 | 16 | } |
230 | 541 | status=SetImageExtent(image,image->columns,image->rows,exception); |
231 | 541 | if (status == MagickFalse) |
232 | 93 | return(DestroyImageList(image)); |
233 | | /* |
234 | | Convert FL32 image to pixel packets. |
235 | | */ |
236 | 448 | quantum_info=AcquireQuantumInfo(image_info,image); |
237 | 448 | if (quantum_info == (QuantumInfo *) NULL) |
238 | 448 | ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
239 | 448 | status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat); |
240 | 448 | extent=GetQuantumExtent(image,quantum_info,quantum_type); |
241 | 448 | pixels=GetQuantumPixels(quantum_info); |
242 | 21.5k | for (y=0; y < (ssize_t) image->rows; y++) |
243 | 21.3k | { |
244 | 21.3k | const void |
245 | 21.3k | *stream; |
246 | | |
247 | 21.3k | Quantum |
248 | 21.3k | *magick_restrict q; |
249 | | |
250 | 21.3k | q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); |
251 | 21.3k | if (q == (Quantum *) NULL) |
252 | 0 | break; |
253 | 21.3k | stream=ReadBlobStream(image,extent,pixels,&count); |
254 | 21.3k | if (count != (ssize_t) extent) |
255 | 234 | break; |
256 | 21.1k | (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info, |
257 | 21.1k | quantum_type,(unsigned char *) stream,exception); |
258 | 21.1k | if (SyncAuthenticPixels(image,exception) == MagickFalse) |
259 | 0 | break; |
260 | 21.1k | if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse) |
261 | 0 | break; |
262 | 21.1k | } |
263 | 448 | SetQuantumImageType(image,quantum_type); |
264 | 448 | quantum_info=DestroyQuantumInfo(quantum_info); |
265 | 448 | if (y < (ssize_t) image->rows) |
266 | 234 | ThrowReaderException(CorruptImageError,"UnableToReadImageData"); |
267 | 214 | if (EOFBlob(image) != MagickFalse) |
268 | 0 | ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", |
269 | 214 | image->filename); |
270 | 214 | if (CloseBlob(image) == MagickFalse) |
271 | 0 | status=MagickFalse; |
272 | 214 | if (status == MagickFalse) |
273 | 0 | return(DestroyImageList(image)); |
274 | 214 | return(GetFirstImageInList(image)); |
275 | 214 | } |
276 | | |
277 | | /* |
278 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
279 | | % % |
280 | | % % |
281 | | % % |
282 | | % R e g i s t e r F L 3 2 I m a g e % |
283 | | % % |
284 | | % % |
285 | | % % |
286 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
287 | | % |
288 | | % RegisterFL32Image() adds attributes for the FL32 image format to |
289 | | % the list of supported formats. The attributes include the image format |
290 | | % tag, a method to read and/or write the format, whether the format |
291 | | % supports the saving of more than one frame to the same file or blob, |
292 | | % whether the format supports native in-memory I/O, and a brief |
293 | | % description of the format. |
294 | | % |
295 | | % The format of the RegisterFL32Image method is: |
296 | | % |
297 | | % size_t RegisterFL32Image(void) |
298 | | % |
299 | | */ |
300 | | ModuleExport size_t RegisterFL32Image(void) |
301 | 10 | { |
302 | 10 | MagickInfo |
303 | 10 | *entry; |
304 | | |
305 | 10 | entry=AcquireMagickInfo("FL32","FL32","FilmLight"); |
306 | 10 | entry->decoder=(DecodeImageHandler *) ReadFL32Image; |
307 | 10 | entry->encoder=(EncodeImageHandler *) WriteFL32Image; |
308 | 10 | entry->magick=(IsImageFormatHandler *) IsFL32; |
309 | 10 | entry->flags|=CoderRawSupportFlag; |
310 | 10 | entry->flags^=CoderAdjoinFlag; |
311 | 10 | (void) RegisterMagickInfo(entry); |
312 | 10 | return(MagickImageCoderSignature); |
313 | 10 | } |
314 | | |
315 | | /* |
316 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
317 | | % % |
318 | | % % |
319 | | % % |
320 | | % U n r e g i s t e r F L 3 2 I m a g e % |
321 | | % % |
322 | | % % |
323 | | % % |
324 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
325 | | % |
326 | | % UnregisterFL32Image() removes format registrations made by the |
327 | | % FL32 module from the list of supported formats. |
328 | | % |
329 | | % The format of the UnregisterFL32Image method is: |
330 | | % |
331 | | % UnregisterFL32Image(void) |
332 | | % |
333 | | */ |
334 | | ModuleExport void UnregisterFL32Image(void) |
335 | 0 | { |
336 | 0 | (void) UnregisterMagickInfo("FL32"); |
337 | 0 | } |
338 | | |
339 | | /* |
340 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
341 | | % % |
342 | | % % |
343 | | % % |
344 | | % W r i t e F L 3 2 I m a g e % |
345 | | % % |
346 | | % % |
347 | | % % |
348 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
349 | | % |
350 | | % WriteFL32Image() writes an image of raw bits in LSB order to a file. |
351 | | % |
352 | | % The format of the WriteFL32Image method is: |
353 | | % |
354 | | % MagickBooleanType WriteFL32Image(const ImageInfo *image_info, |
355 | | % Image *image,ExceptionInfo *exception) |
356 | | % |
357 | | % A description of each parameter follows. |
358 | | % |
359 | | % o image_info: the image info. |
360 | | % |
361 | | % o image: The image. |
362 | | % |
363 | | % o exception: return any errors or warnings in this structure. |
364 | | % |
365 | | */ |
366 | | static MagickBooleanType WriteFL32Image(const ImageInfo *image_info, |
367 | | Image *image,ExceptionInfo *exception) |
368 | 214 | { |
369 | 214 | const Quantum |
370 | 214 | *p; |
371 | | |
372 | 214 | MagickBooleanType |
373 | 214 | status; |
374 | | |
375 | 214 | QuantumInfo |
376 | 214 | *quantum_info; |
377 | | |
378 | 214 | QuantumType |
379 | 214 | quantum_type; |
380 | | |
381 | 214 | size_t |
382 | 214 | channels, |
383 | 214 | extent; |
384 | | |
385 | 214 | ssize_t |
386 | 214 | count, |
387 | 214 | y; |
388 | | |
389 | 214 | unsigned char |
390 | 214 | *pixels; |
391 | | |
392 | | /* |
393 | | Open output image file. |
394 | | */ |
395 | 214 | assert(image_info != (const ImageInfo *) NULL); |
396 | 214 | assert(image_info->signature == MagickCoreSignature); |
397 | 214 | assert(image != (Image *) NULL); |
398 | 214 | assert(image->signature == MagickCoreSignature); |
399 | 214 | assert(exception != (ExceptionInfo *) NULL); |
400 | 214 | assert(exception->signature == MagickCoreSignature); |
401 | 214 | if (IsEventLogging() != MagickFalse) |
402 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
403 | 214 | status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); |
404 | 214 | if (status == MagickFalse) |
405 | 0 | return(status); |
406 | 214 | if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) |
407 | 0 | (void) TransformImageColorspace(image,sRGBColorspace,exception); |
408 | 214 | (void) WriteBlobLSBLong(image,842222662U); |
409 | 214 | (void) WriteBlobLSBLong(image,(unsigned int) image->rows); |
410 | 214 | (void) WriteBlobLSBLong(image,(unsigned int) image->columns); |
411 | 214 | image->endian=LSBEndian; |
412 | 214 | image->depth=32; |
413 | 214 | channels=GetImageChannels(image); |
414 | 214 | switch (channels) |
415 | 214 | { |
416 | 113 | case 1: |
417 | 113 | { |
418 | 113 | quantum_type=GrayQuantum; |
419 | 113 | break; |
420 | 0 | } |
421 | 30 | case 2: |
422 | 30 | { |
423 | 30 | if (image->alpha_trait != UndefinedPixelTrait) |
424 | 30 | { |
425 | 30 | quantum_type=GrayAlphaQuantum; |
426 | 30 | break; |
427 | 30 | } |
428 | 0 | quantum_type=GrayQuantum; |
429 | 0 | channels=1; |
430 | 0 | break; |
431 | 30 | } |
432 | 33 | case 4: |
433 | 33 | { |
434 | 33 | if (image->alpha_trait != UndefinedPixelTrait) |
435 | 33 | { |
436 | 33 | quantum_type=RGBAQuantum; |
437 | 33 | break; |
438 | 33 | } |
439 | 0 | quantum_type=RGBQuantum; |
440 | 0 | channels=3; |
441 | 0 | break; |
442 | 33 | } |
443 | 38 | default: |
444 | 38 | { |
445 | 38 | quantum_type=RGBQuantum; |
446 | 38 | channels=3; |
447 | 38 | break; |
448 | 33 | } |
449 | 214 | } |
450 | 214 | (void) WriteBlobLSBLong(image,(unsigned int) channels); |
451 | 214 | quantum_info=AcquireQuantumInfo(image_info,image); |
452 | 214 | if (quantum_info == (QuantumInfo *) NULL) |
453 | 214 | ThrowWriterException(ImageError,"MemoryAllocationFailed"); |
454 | 214 | status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat); |
455 | 214 | pixels=(unsigned char *) GetQuantumPixels(quantum_info); |
456 | 13.7k | for (y=0; y < (ssize_t) image->rows; y++) |
457 | 13.5k | { |
458 | 13.5k | p=GetVirtualPixels(image,0,y,image->columns,1,exception); |
459 | 13.5k | if (p == (const Quantum *) NULL) |
460 | 0 | break; |
461 | 13.5k | extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info, |
462 | 13.5k | quantum_type,pixels,exception); |
463 | 13.5k | count=WriteBlob(image,extent,pixels); |
464 | 13.5k | if (count != (ssize_t) extent) |
465 | 0 | break; |
466 | 13.5k | status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, |
467 | 13.5k | image->rows); |
468 | 13.5k | if (status == MagickFalse) |
469 | 0 | break; |
470 | 13.5k | } |
471 | 214 | quantum_info=DestroyQuantumInfo(quantum_info); |
472 | 214 | if (y < (ssize_t) image->rows) |
473 | 214 | ThrowWriterException(CorruptImageError,"UnableToWriteImageData"); |
474 | 214 | if (CloseBlob(image) == MagickFalse) |
475 | 0 | status=MagickFalse; |
476 | 214 | return(status); |
477 | 214 | } |