/src/graphicsmagick/coders/cals.c
Line | Count | Source |
1 | | /* |
2 | | % Copyright (C) 2009-2026 GraphicsMagick Group |
3 | | % |
4 | | % This program is covered by multiple licenses, which are described in |
5 | | % Copyright.txt. You should have received a copy of Copyright.txt with this |
6 | | % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. |
7 | | % |
8 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
9 | | % % |
10 | | % % |
11 | | % % |
12 | | % CCCC AAA L SSSSS % |
13 | | % C A A L SS % |
14 | | % C AAAAA L SSS % |
15 | | % C A A L SS % |
16 | | % CCCC A A LLLLL SSSSS % |
17 | | % % |
18 | | % % |
19 | | % Read/Write CALS (CALS type 1) format % |
20 | | % % |
21 | | % % |
22 | | % Software Design % |
23 | | % John Sergeant % |
24 | | % May 2009 % |
25 | | % % |
26 | | % % |
27 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
28 | | % |
29 | | % |
30 | | */ |
31 | | |
32 | | /* |
33 | | Include declarations. |
34 | | */ |
35 | | #include "magick/studio.h" |
36 | | #include "magick/attribute.h" |
37 | | #include "magick/blob.h" |
38 | | #include "magick/compress.h" |
39 | | #include "magick/constitute.h" |
40 | | #include "magick/log.h" |
41 | | #include "magick/magick.h" |
42 | | #include "magick/monitor.h" |
43 | | #include "magick/tempfile.h" |
44 | | #include "magick/utility.h" |
45 | | #include "magick/static.h" |
46 | | /* |
47 | | Write an unsigned long to file with Intel/LSB ordering |
48 | | */ |
49 | | static void CALS_WriteIntelULong(FILE *file,unsigned long ul) |
50 | 25.2k | { |
51 | 25.2k | fputc((unsigned char)ul,file); |
52 | 25.2k | fputc((unsigned char)(ul >> 8),file); |
53 | 25.2k | fputc((unsigned char)(ul >> 16),file); |
54 | 25.2k | fputc((unsigned char)(ul >> 24),file); |
55 | 25.2k | } |
56 | | |
57 | | /* |
58 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
59 | | % % |
60 | | % % |
61 | | % % |
62 | | % I s C A L S % |
63 | | % % |
64 | | % % |
65 | | % % |
66 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
67 | | % |
68 | | % Method IsCALS returns MagickTrue if the image format type, identified by the |
69 | | % magick string, is CAL. |
70 | | % |
71 | | % The format of the IsCALS method is: |
72 | | % |
73 | | % unsigned int IsCALS(const unsigned char *magick,const size_t length) |
74 | | % |
75 | | % A description of each parameter follows: |
76 | | % |
77 | | % o status: Method IsCALS returns MagickTrue if the image format type is CAL. |
78 | | % |
79 | | % o magick: This string is generally the first few bytes of an image file |
80 | | % or blob. |
81 | | % |
82 | | % o length: Specifies the length of the magick string. |
83 | | % |
84 | | % |
85 | | */ |
86 | | static MagickBool IsCALS(const unsigned char *magick,const size_t length) |
87 | 0 | { |
88 | 0 | if (length < 132) |
89 | 0 | return(MagickFalse); |
90 | 0 | if (LocaleNCompare((char *) (magick),"version: MIL-STD-1840",21) == 0) |
91 | 0 | return(MagickTrue); |
92 | 0 | if (LocaleNCompare((char *) (magick),"srcdocid:",9) == 0) |
93 | 0 | return(MagickTrue); |
94 | 0 | if (LocaleNCompare((char *) (magick),"rorient:",8) == 0) |
95 | 0 | return(MagickTrue); |
96 | 0 | return(MagickFalse); |
97 | 0 | } |
98 | | |
99 | | /* |
100 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
101 | | % % |
102 | | % % |
103 | | % % |
104 | | % R e a d C A L S I m a g e % |
105 | | % % |
106 | | % % |
107 | | % % |
108 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
109 | | % |
110 | | % Method ReadCALSImage reads a CALS type 1 image file and returns it. It |
111 | | % allocates the memory necessary for the new Image structure and returns a |
112 | | % pointer to the new image. |
113 | | % |
114 | | % The format of the ReadCALSImage method is: |
115 | | % |
116 | | % Image *ReadCALSImage(const ImageInfo *image_info,ExceptionInfo *exception) |
117 | | % |
118 | | % A description of each parameter follows: |
119 | | % |
120 | | % o image: Method ReadCALSImage returns a pointer to the image after |
121 | | % reading. A null image is returned if there is a memory shortage or |
122 | | % if the image cannot be read. |
123 | | % |
124 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
125 | | % |
126 | | % o exception: return any errors or warnings in this structure. |
127 | | % |
128 | | % |
129 | | */ |
130 | | static Image *ReadCALSImage(const ImageInfo *image_info,ExceptionInfo *exception) |
131 | 6.68k | { |
132 | 6.68k | Image |
133 | 6.68k | *image; |
134 | | |
135 | 6.68k | long |
136 | 6.68k | y; |
137 | | |
138 | 6.68k | char |
139 | 6.68k | record[129]; |
140 | | |
141 | 6.68k | unsigned long |
142 | 6.68k | status, |
143 | 6.68k | width, |
144 | 6.68k | height, |
145 | 6.68k | rtype, |
146 | 6.68k | orient, |
147 | 6.68k | density; |
148 | | |
149 | 6.68k | char |
150 | 6.68k | filename[MaxTextExtent]; |
151 | | |
152 | 6.68k | FILE |
153 | 6.68k | *file; |
154 | | |
155 | 6.68k | TimerInfo |
156 | 6.68k | timer; |
157 | | |
158 | 6.68k | unsigned long |
159 | 6.68k | byte_count_pos, |
160 | 6.68k | strip_off_pos, |
161 | 6.68k | flen; |
162 | | |
163 | 6.68k | int |
164 | 6.68k | c; |
165 | | |
166 | 6.68k | ImageInfo |
167 | 6.68k | *clone_info; |
168 | | |
169 | 6.68k | MagickPassFail |
170 | 6.68k | file_write_status; |
171 | | |
172 | | /* |
173 | | Open image file. |
174 | | */ |
175 | 6.68k | assert(image_info != (const ImageInfo *) NULL); |
176 | 6.68k | assert(image_info->signature == MagickSignature); |
177 | 6.68k | assert(exception != (ExceptionInfo *) NULL); |
178 | 6.68k | assert(exception->signature == MagickSignature); |
179 | 6.68k | GetTimerInfo(&timer); |
180 | 6.68k | image=AllocateImage(image_info); |
181 | 6.68k | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
182 | 6.68k | if (status == MagickFail) |
183 | 6.68k | ThrowReaderException(FileOpenError,UnableToOpenFile,image); |
184 | | |
185 | | /* |
186 | | Scan CAL header, record by record, looking for mandatory fields |
187 | | */ |
188 | 6.68k | rtype = 1; |
189 | 6.68k | width = height = 0; |
190 | 6.68k | orient = 1; |
191 | 6.68k | density = 200; |
192 | 6.68k | record[128]=0; |
193 | 42.1k | for (y = 0; y < 16; y++) |
194 | 40.0k | { |
195 | 40.0k | if (ReadBlob(image,128,(char *) record) != 128) |
196 | 4.53k | break; |
197 | 35.5k | if (LocaleNCompare(record,"rtype:",6) == 0) |
198 | 130 | { /* rtype */ |
199 | 130 | if (sscanf(record+6,"%ld",&rtype) != 1) |
200 | 1 | { |
201 | 1 | rtype = 0; |
202 | 1 | break; |
203 | 1 | } |
204 | 130 | } |
205 | 35.3k | else |
206 | 35.3k | if (LocaleNCompare(record,"rorient:",8) == 0) |
207 | 459 | { /* rorient */ |
208 | 459 | unsigned long |
209 | 459 | pel_path_rot, |
210 | 459 | line_rot; |
211 | | |
212 | 459 | pel_path_rot = line_rot = 0; |
213 | 459 | if (sscanf(record+8,"%ld,%ld",&pel_path_rot,&line_rot) != 2) |
214 | 5 | { |
215 | 5 | orient = 0; |
216 | 5 | break; |
217 | 5 | } |
218 | 454 | switch (pel_path_rot) |
219 | 454 | { |
220 | 48 | case 90: |
221 | 48 | orient = 5; |
222 | 48 | break; |
223 | 54 | case 180: |
224 | 54 | orient = 3; |
225 | 54 | break; |
226 | 102 | case 270: |
227 | 102 | orient = 7; |
228 | 102 | break; |
229 | 250 | default: |
230 | 250 | orient = 1; |
231 | 454 | } |
232 | 454 | if (line_rot == 90) orient++; |
233 | 454 | } |
234 | 34.9k | else |
235 | 34.9k | if (LocaleNCompare(record,"rpelcnt:",8) == 0) |
236 | 2.78k | { /* replcnt */ |
237 | 2.78k | if (sscanf(record+8,"%ld,%ld",&width,&height) != 2) |
238 | 3 | { |
239 | 3 | width = 0; |
240 | 3 | height = 0; |
241 | 3 | break; |
242 | 3 | } |
243 | 2.78k | } |
244 | 32.1k | else |
245 | 32.1k | if (LocaleNCompare(record,"rdensty:",8) == 0) |
246 | 333 | { /* rdensty */ |
247 | 333 | if (sscanf(record+8,"%ld",&density) != 1) |
248 | 3 | { |
249 | 3 | density = 0; |
250 | 3 | break; |
251 | 3 | } |
252 | 330 | if (!density) density = 200; |
253 | 330 | } |
254 | 35.5k | } |
255 | 6.68k | if ((!width) || (!height) || (rtype != 1) || (!orient) || (!density) ) |
256 | 4.15k | ThrowReaderException(CorruptImageError,ImproperImageHeader,image); |
257 | | |
258 | 2.52k | (void) LogMagickEvent(CoderEvent,GetMagickModule(), |
259 | 2.52k | "Dimensions %lux%lu",width,height); |
260 | | |
261 | | /* Create TIFF wrapper to handle file data using TIFF library */ |
262 | 2.52k | file=AcquireTemporaryFileStream(filename,BinaryFileIOMode); |
263 | 2.52k | if (file == (FILE *) NULL) |
264 | 2.52k | ThrowReaderTemporaryFileException(filename); |
265 | 2.52k | file_write_status=MagickFail; |
266 | 2.52k | do |
267 | 2.52k | { |
268 | | /* Intel TIFF with IFD at offset 8 - IFD has 14 records */ |
269 | 2.52k | fwrite("\111\111\052\000\010\000\000\000\016\000",1,10,file); |
270 | | /* New sub image - normal type */ |
271 | 2.52k | fwrite("\376\000\003\000\001\000\000\000\000\000\000\000",1,12,file); |
272 | | /* Image width */ |
273 | 2.52k | fwrite("\000\001\004\000\001\000\000\000",1,8,file); |
274 | 2.52k | CALS_WriteIntelULong(file,width); |
275 | | /* Image height */ |
276 | 2.52k | fwrite("\001\001\004\000\001\000\000\000",1,8,file); |
277 | 2.52k | CALS_WriteIntelULong(file,height); |
278 | | /* 1 bit per sample */ |
279 | 2.52k | fwrite("\002\001\003\000\001\000\000\000\001\000\000\000",1,12,file); |
280 | | /* CCITT Group 4 compression */ |
281 | 2.52k | fwrite("\003\001\003\000\001\000\000\000\004\000\000\000",1,12,file); |
282 | | /* Photometric interpretation MAX BLACK */ |
283 | 2.52k | fwrite("\006\001\003\000\001\000\000\000\000\000\000\000",1,12,file); |
284 | | /* Strip offset */ |
285 | 2.52k | fwrite("\021\001\003\000\001\000\000\000",1,8,file); |
286 | 2.52k | strip_off_pos = 10 + (12 * 14) + 4 + 8; |
287 | 2.52k | CALS_WriteIntelULong(file,strip_off_pos); |
288 | | /* Orientation */ |
289 | 2.52k | fwrite("\022\001\003\000\001\000\000\000",1,8,file); |
290 | 2.52k | CALS_WriteIntelULong(file,orient); |
291 | | /* 1 sample per pixel */ |
292 | 2.52k | fwrite("\025\001\003\000\001\000\000\000\001\000\000\000",1,12,file); |
293 | | /* Rows per strip (same as height) */ |
294 | 2.52k | fwrite("\026\001\004\000\001\000\000\000",1,8,file); |
295 | 2.52k | CALS_WriteIntelULong(file,height); |
296 | | /* Strip byte count */ |
297 | 2.52k | fwrite("\027\001\004\000\001\000\000\000\000\000\000\000",1,12,file); |
298 | 2.52k | byte_count_pos = ftell(file)-4; |
299 | | /* X resolution */ |
300 | 2.52k | fwrite("\032\001\005\000\001\000\000\000",1,8,file); |
301 | 2.52k | CALS_WriteIntelULong(file,strip_off_pos-8); |
302 | | /* Y resolution */ |
303 | 2.52k | fwrite("\033\001\005\000\001\000\000\000",1,8,file); |
304 | 2.52k | CALS_WriteIntelULong(file,strip_off_pos-8); |
305 | | /* Resolution unit is inch */ |
306 | 2.52k | fwrite("\050\001\003\000\001\000\000\000\002\000\000\000",1,12,file); |
307 | | /* Offset to next IFD ie end of images */ |
308 | 2.52k | fwrite("\000\000\000\000",1,4,file); |
309 | | /* Write X/Y resolution as rational data */ |
310 | 2.52k | CALS_WriteIntelULong(file,density); |
311 | 2.52k | CALS_WriteIntelULong(file,1); |
312 | | |
313 | | /* Copy image stream data */ |
314 | 2.52k | flen = 0; |
315 | 2.52k | c=ReadBlobByte(image); |
316 | 27.6M | while (c != EOF) |
317 | 27.6M | { |
318 | 27.6M | flen++; |
319 | 27.6M | (void) fputc(c,file); |
320 | 27.6M | c=ReadBlobByte(image); |
321 | 27.6M | } |
322 | | |
323 | | /* Return to correct location and output strip byte count */ |
324 | 2.52k | if (fseek(file,byte_count_pos,SEEK_SET) != 0) |
325 | 0 | break; |
326 | 2.52k | CALS_WriteIntelULong(file,flen); |
327 | 2.52k | fflush(file); |
328 | 2.52k | if (ferror(file)) |
329 | 0 | break; |
330 | 2.52k | file_write_status=MagickPass; |
331 | 2.52k | } while (0); |
332 | 2.52k | (void) fclose(file); |
333 | 2.52k | if (file_write_status != MagickPass) |
334 | 0 | { |
335 | 0 | (void) LiberateTemporaryFile(filename); |
336 | 0 | ThrowReaderException(CoderError,UnableToWriteTemporaryFile,image); |
337 | 0 | } |
338 | 2.52k | CloseBlob(image); |
339 | 2.52k | DestroyImage(image); |
340 | 2.52k | clone_info=CloneImageInfo((ImageInfo *) NULL); |
341 | 2.52k | MagickFormatString(clone_info->filename,sizeof(clone_info->filename),"tiff:%.1024s",filename); |
342 | 2.52k | image=ReadImage(clone_info,exception); |
343 | 2.52k | (void) LiberateTemporaryFile(filename); |
344 | 2.52k | DestroyImageInfo(clone_info); |
345 | 2.52k | if (image != (Image *) NULL) |
346 | 1.89k | { |
347 | 1.89k | (void) strlcpy(image->filename,image_info->filename, |
348 | 1.89k | sizeof(image->filename)); |
349 | 1.89k | (void) strlcpy(image->magick_filename,image_info->filename, |
350 | 1.89k | sizeof(image->magick_filename)); |
351 | 1.89k | (void) strlcpy(image->magick,"CALS",sizeof(image->magick)); |
352 | 1.89k | StopTimer(&timer); |
353 | 1.89k | image->timer=timer; |
354 | 1.89k | } |
355 | 626 | else |
356 | 626 | { |
357 | 626 | DestroyImage(image); |
358 | 626 | image = (Image *) NULL; |
359 | 626 | } |
360 | 2.52k | return(image); |
361 | 2.52k | } |
362 | | |
363 | | /* |
364 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
365 | | % % |
366 | | % % |
367 | | % % |
368 | | % W r i t e C A L S I m a g e % |
369 | | % % |
370 | | % % |
371 | | % % |
372 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
373 | | % |
374 | | % Method WriteCALSImage writes an image in the CALS type I image format |
375 | | % |
376 | | % The format of the WriteCALSImage method is: |
377 | | % |
378 | | % unsigned int WriteCALSImage(const ImageInfo *image_info,Image *image) |
379 | | % |
380 | | % A description of each parameter follows. |
381 | | % |
382 | | % o status: Method WriteCALSImage return MagickTrue if the image is written. |
383 | | % MagickFail is returned is there is a memory shortage or if the image file |
384 | | % fails to write. |
385 | | % |
386 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
387 | | % |
388 | | % o image: A pointer to an Image structure. |
389 | | % |
390 | | % |
391 | | % |
392 | | */ |
393 | | static void WriteCALSRecord(Image *image,const char *data) |
394 | 18.6k | { |
395 | 18.6k | int |
396 | 18.6k | i; |
397 | | |
398 | 18.6k | const char |
399 | 18.6k | *p; |
400 | | |
401 | 18.6k | char |
402 | 18.6k | pad[128]; |
403 | | |
404 | 18.6k | i = 0; |
405 | 18.6k | if (data) |
406 | 18.6k | { |
407 | | /* Limit output to 128 chars */ |
408 | 18.6k | p=data; |
409 | 265k | while ((i < 128) && (p[i])) i++; |
410 | 18.6k | WriteBlob(image,i,data); |
411 | 18.6k | } |
412 | 18.6k | if (i < 128) |
413 | 18.6k | { |
414 | | /* Pad record to 128 characters using trailing spaces */ |
415 | 18.6k | i=128-i; |
416 | 18.6k | memset(pad,' ',i); |
417 | 18.6k | WriteBlob(image,i,pad); |
418 | 18.6k | } |
419 | 18.6k | } |
420 | | |
421 | | static MagickPassFail WriteCALSImage(const ImageInfo *image_info,Image *image) |
422 | 1.69k | { |
423 | 1.69k | char |
424 | 1.69k | buffer[MaxTextExtent]; |
425 | | |
426 | 1.69k | int |
427 | 1.69k | i; |
428 | | |
429 | 1.69k | long |
430 | 1.69k | sans; |
431 | | |
432 | 1.69k | unsigned long |
433 | 1.69k | density; |
434 | | |
435 | 1.69k | int |
436 | 1.69k | orx, |
437 | 1.69k | ory; |
438 | | |
439 | 1.69k | MagickPassFail |
440 | 1.69k | status=MagickPass; |
441 | | |
442 | | /* |
443 | | Validate input image |
444 | | */ |
445 | 1.69k | assert(image_info != (const ImageInfo *) NULL); |
446 | 1.69k | assert(image_info->signature == MagickSignature); |
447 | 1.69k | assert(image != (Image *) NULL); |
448 | 1.69k | assert(image->signature == MagickSignature); |
449 | | |
450 | | /* |
451 | | Open output image file. |
452 | | */ |
453 | 1.69k | if (OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception) == MagickFail) |
454 | 1.69k | ThrowWriterException(FileOpenError,UnableToOpenFile,image); |
455 | | |
456 | | /* |
457 | | Create standard header |
458 | | */ |
459 | 1.69k | WriteCALSRecord(image,"srcdocid: NONE"); |
460 | 1.69k | WriteCALSRecord(image,"dstdocid: NONE"); |
461 | 1.69k | WriteCALSRecord(image,"txtfilid: NONE"); |
462 | 1.69k | WriteCALSRecord(image,"figid: NONE"); |
463 | 1.69k | WriteCALSRecord(image,"srcgph: NONE"); |
464 | 1.69k | WriteCALSRecord(image,"docls: NONE"); |
465 | 1.69k | WriteCALSRecord(image,"rtype: 1"); |
466 | | /* orientation based on input or default of upright */ |
467 | 1.69k | switch (image->orientation) |
468 | 1.69k | { |
469 | 1 | case TopRightOrientation: |
470 | 1 | orx=180; |
471 | 1 | ory=270; |
472 | 1 | break; |
473 | 13 | case BottomRightOrientation: |
474 | 13 | orx=180; |
475 | 13 | ory=90; |
476 | 13 | break; |
477 | 0 | case BottomLeftOrientation: |
478 | 0 | orx=0; |
479 | 0 | ory=90; |
480 | 0 | break; |
481 | 3 | case LeftTopOrientation: |
482 | 3 | orx=270; |
483 | 3 | ory=0; |
484 | 3 | break; |
485 | 2 | case RightTopOrientation: |
486 | 2 | orx=270; |
487 | 2 | ory=180; |
488 | 2 | break; |
489 | 58 | case RightBottomOrientation: |
490 | 58 | orx=90; |
491 | 58 | ory=180; |
492 | 58 | break; |
493 | 0 | case LeftBottomOrientation: |
494 | 0 | orx=90; |
495 | 0 | ory=0; |
496 | 0 | break; |
497 | 1.61k | default: |
498 | 1.61k | orx=0; |
499 | 1.61k | ory=270; |
500 | 1.69k | } |
501 | 1.69k | MagickFormatString(buffer,sizeof(buffer),"rorient: %03d,%03d",orx,ory); |
502 | 1.69k | WriteCALSRecord(image,buffer); |
503 | | /* pixel counts based on columns/rows of input */ |
504 | 1.69k | MagickFormatString(buffer,sizeof(buffer),"rpelcnt: %06ld,%06ld",image->columns,image->rows); |
505 | 1.69k | WriteCALSRecord(image,buffer); |
506 | | /* density based on input density or default of 200 */ |
507 | 1.69k | density=200; |
508 | 1.69k | if (image_info->density != (char *) NULL) |
509 | 0 | (void) GetGeometry(image_info->density,&sans,&sans,&density,&density); |
510 | 1.69k | MagickFormatString(buffer,sizeof(buffer),"rdensty: %04ld",density); |
511 | 1.69k | WriteCALSRecord(image,buffer); |
512 | 1.69k | WriteCALSRecord(image,"notes: NONE"); |
513 | | |
514 | | /* |
515 | | Pad header to make 16 records / 2048 bytes |
516 | | */ |
517 | 1.69k | memset(buffer,' ',128); |
518 | 10.1k | for (i = 0; i < 5; i++) |
519 | 8.46k | if (WriteBlob(image,128,buffer) != 128) |
520 | 0 | status=MagickFail; |
521 | | |
522 | | /* |
523 | | Encode data to Group 4 |
524 | | */ |
525 | 1.69k | if (MagickFail != status) |
526 | 1.69k | { |
527 | 1.69k | unsigned char |
528 | 1.69k | *blob; |
529 | | |
530 | 1.69k | size_t |
531 | 1.69k | blob_length; |
532 | | |
533 | 1.69k | blob=ImageToHuffman2DBlob(image,image_info,&blob_length,&image->exception); |
534 | 1.69k | if (blob == (unsigned char *) NULL) |
535 | 0 | status=MagickFail; |
536 | | |
537 | 1.69k | if (MagickFail != status) |
538 | 1.69k | { |
539 | 1.69k | if (WriteBlob(image,blob_length,blob) != blob_length) |
540 | 0 | status=MagickFail; |
541 | 1.69k | } |
542 | 1.69k | MagickFreeMemory(blob); |
543 | 1.69k | } |
544 | | |
545 | | /* |
546 | | Close output file and return image |
547 | | */ |
548 | 1.69k | status &= CloseBlob(image); |
549 | 1.69k | return status; |
550 | 1.69k | } |
551 | | |
552 | | /* |
553 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
554 | | % % |
555 | | % % |
556 | | % % |
557 | | % R e g i s t e r C A L S I m a g e % |
558 | | % % |
559 | | % % |
560 | | % % |
561 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
562 | | % |
563 | | % Method RegisterCALSImage adds attributes for the CALS image format to |
564 | | % the list of supported formats. The attributes include the image format |
565 | | % tag, a method to read and/or write the format, whether the format |
566 | | % supports the saving of more than one frame to the same file or blob, |
567 | | % whether the format supports native in-memory I/O, and a brief |
568 | | % description of the format. |
569 | | % |
570 | | % The format of the RegisterCALSImage method is: |
571 | | % |
572 | | % RegisterCALSImage(void) |
573 | | % |
574 | | */ |
575 | | ModuleExport void RegisterCALSImage(void) |
576 | 4 | { |
577 | 4 | MagickInfo |
578 | 4 | *entry; |
579 | | |
580 | 4 | const char |
581 | 4 | *description = "Continuous Acquisition and Life-cycle Support Type 1 image", |
582 | 4 | *module = "CALS", |
583 | 4 | *note = "Specified in MIL-R-28002 and MIL-PRF-28002"; |
584 | | |
585 | 4 | entry=SetMagickInfo("CAL"); |
586 | 4 | entry->decoder=(DecoderHandler) ReadCALSImage; |
587 | 4 | entry->encoder=(EncoderHandler) WriteCALSImage; |
588 | 4 | entry->magick=(MagickHandler) IsCALS; |
589 | 4 | entry->adjoin=MagickFalse; |
590 | 4 | entry->seekable_stream=MagickTrue; |
591 | 4 | entry->description=description; |
592 | 4 | entry->note=note; |
593 | 4 | entry->module=module; |
594 | 4 | entry->stealth=MagickTrue; /* Don't list in '-list format' output */ |
595 | 4 | (void) RegisterMagickInfo(entry); |
596 | | |
597 | 4 | entry=SetMagickInfo("CALS"); |
598 | 4 | entry->decoder=(DecoderHandler) ReadCALSImage; |
599 | 4 | entry->encoder=(EncoderHandler) WriteCALSImage; |
600 | 4 | entry->magick=(MagickHandler) IsCALS; |
601 | 4 | entry->adjoin=MagickFalse; |
602 | 4 | entry->seekable_stream=MagickTrue; |
603 | 4 | entry->description=description; |
604 | 4 | entry->note=note; |
605 | 4 | entry->module=module; |
606 | 4 | (void) RegisterMagickInfo(entry); |
607 | 4 | } |
608 | | |
609 | | /* |
610 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
611 | | % % |
612 | | % % |
613 | | % % |
614 | | % U n r e g i s t e r C A L S I m a g e % |
615 | | % % |
616 | | % % |
617 | | % % |
618 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
619 | | % |
620 | | % Method UnregisterCALSImage removes format registrations made by the |
621 | | % CAL module from the list of supported formats. |
622 | | % |
623 | | % The format of the UnregisterCALSImage method is: |
624 | | % |
625 | | % UnregisterCALSImage(void) |
626 | | % |
627 | | */ |
628 | | ModuleExport void UnregisterCALSImage(void) |
629 | 0 | { |
630 | 0 | (void) UnregisterMagickInfo("CAL"); |
631 | 0 | (void) UnregisterMagickInfo("CALS"); |
632 | 0 | } |