]> granicus.if.org Git - imagemagick/blob - coders/cals.c
Removed png_write_chunk_from_profile()
[imagemagick] / coders / cals.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                         CCCC   AAA   L      SSSSS                           %
7 %                        C      A   A  L      SS                              %
8 %                        C      AAAAA  L       SSS                            %
9 %                        C      A   A  L         SS                           %
10 %                         CCCC  A   A  LLLLL  SSSSS                           %
11 %                                                                             %
12 %                                                                             %
13 %                 Read/Write CALS Raster Group 1 Image Format                 %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization      %
21 %  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 %    https://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 % The CALS raster format is a standard developed by the Computer Aided
37 % Acquisition and Logistics Support (CALS) office of the United States
38 % Department of Defense to standardize graphics data interchange for
39 % electronic publishing, especially in the areas of technical graphics,
40 % CAD/CAM, and image processing applications.
41 %
42 */
43 \f
44 /*
45   Include declarations.
46 */
47 #include "MagickCore/studio.h"
48 #include "MagickCore/blob.h"
49 #include "MagickCore/blob-private.h"
50 #include "MagickCore/cache.h"
51 #include "MagickCore/colorspace.h"
52 #include "MagickCore/constitute.h"
53 #include "MagickCore/exception.h"
54 #include "MagickCore/exception-private.h"
55 #include "MagickCore/geometry.h"
56 #include "MagickCore/image.h"
57 #include "MagickCore/image-private.h"
58 #include "MagickCore/list.h"
59 #include "MagickCore/magick.h"
60 #include "MagickCore/memory_.h"
61 #include "MagickCore/monitor.h"
62 #include "MagickCore/monitor-private.h"
63 #include "MagickCore/option.h"
64 #include "MagickCore/quantum-private.h"
65 #include "MagickCore/resource_.h"
66 #include "MagickCore/static.h"
67 #include "MagickCore/string_.h"
68 #include "MagickCore/module.h"
69 \f
70 #if defined(MAGICKCORE_TIFF_DELEGATE)
71 /*
72  Forward declarations.
73 */
74 static MagickBooleanType
75   WriteCALSImage(const ImageInfo *,Image *,ExceptionInfo *);
76 #endif
77 \f
78 /*
79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80 %                                                                             %
81 %                                                                             %
82 %                                                                             %
83 %   I s C A L S                                                               %
84 %                                                                             %
85 %                                                                             %
86 %                                                                             %
87 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88 %
89 %  IsCALS() returns MagickTrue if the image format type, identified by the
90 %  magick string, is CALS Raster Group 1.
91 %
92 %  The format of the IsCALS method is:
93 %
94 %      MagickBooleanType IsCALS(const unsigned char *magick,const size_t length)
95 %
96 %  A description of each parameter follows:
97 %
98 %    o magick: compare image format pattern against these bytes.
99 %
100 %    o length: Specifies the length of the magick string.
101 %
102 */
103 static MagickBooleanType IsCALS(const unsigned char *magick,const size_t length)
104 {
105   if (length < 128)
106     return(MagickFalse);
107   if (LocaleNCompare((const char *) magick,"version: MIL-STD-1840",21) == 0)
108     return(MagickTrue);
109   if (LocaleNCompare((const char *) magick,"srcdocid:",9) == 0)
110     return(MagickTrue);
111   if (LocaleNCompare((const char *) magick,"rorient:",8) == 0)
112     return(MagickTrue);
113   return(MagickFalse);
114 }
115 \f
116 /*
117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118 %                                                                             %
119 %                                                                             %
120 %                                                                             %
121 %   R e a d C A L S I m a g e                                                 %
122 %                                                                             %
123 %                                                                             %
124 %                                                                             %
125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126 %
127 %  ReadCALSImage() reads an CALS Raster Group 1 image format image file and
128 %  returns it.  It allocates the memory necessary for the new Image structure
129 %  and returns a pointer to the new image.
130 %
131 %  The format of the ReadCALSImage method is:
132 %
133 %      Image *ReadCALSImage(const ImageInfo *image_info,
134 %        ExceptionInfo *exception)
135 %
136 %  A description of each parameter follows:
137 %
138 %    o image_info: the image info.
139 %
140 %    o exception: return any errors or warnings in this structure.
141 %
142 */
143 static Image *ReadCALSImage(const ImageInfo *image_info,
144   ExceptionInfo *exception)
145 {
146   char
147     filename[MagickPathExtent],
148     header[MagickPathExtent],
149     message[MagickPathExtent];
150
151   FILE
152     *file;
153
154   Image
155     *image;
156
157   ImageInfo
158     *read_info;
159
160   int
161     c,
162     unique_file;
163
164   MagickBooleanType
165     status;
166
167   register ssize_t
168     i;
169
170   unsigned long
171     density,
172     direction,
173     height,
174     orientation,
175     pel_path,
176     type,
177     width;
178
179   /*
180     Open image file.
181   */
182   assert(image_info != (const ImageInfo *) NULL);
183   assert(image_info->signature == MagickCoreSignature);
184   if (image_info->debug != MagickFalse)
185     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
186       image_info->filename);
187   assert(exception != (ExceptionInfo *) NULL);
188   assert(exception->signature == MagickCoreSignature);
189   image=AcquireImage(image_info,exception);
190   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
191   if (status == MagickFalse)
192     {
193       image=DestroyImageList(image);
194       return((Image *) NULL);
195     }
196   /*
197     Read CALS header.
198   */
199   (void) ResetMagickMemory(header,0,sizeof(header));
200   density=0;
201   direction=0;
202   orientation=1;
203   pel_path=0;
204   type=1;
205   width=0;
206   height=0;
207   for (i=0; i < 16; i++)
208   {
209     if (ReadBlob(image,128,(unsigned char *) header) != 128)
210       break;
211     switch (*header)
212     {
213       case 'R':
214       case 'r':
215       {
216         if (LocaleNCompare(header,"rdensty:",8) == 0)
217           {
218             (void) sscanf(header+8,"%lu",&density);
219             break;
220           }
221         if (LocaleNCompare(header,"rpelcnt:",8) == 0)
222           {
223             (void) sscanf(header+8,"%lu,%lu",&width,&height);
224             break;
225           }
226         if (LocaleNCompare(header,"rorient:",8) == 0)
227           {
228             (void) sscanf(header+8,"%lu,%lu",&pel_path,&direction);
229             if (pel_path == 90)
230               orientation=5;
231             else
232               if (pel_path == 180)
233                 orientation=3;
234               else
235                 if (pel_path == 270)
236                   orientation=7;
237             if (direction == 90)
238               orientation++;
239             break;
240           }
241         if (LocaleNCompare(header,"rtype:",6) == 0)
242           {
243             (void) sscanf(header+6,"%lu",&type);
244             break;
245           }
246         break;
247       }
248     }
249   }
250   /*
251     Read CALS pixels.
252   */
253   file=(FILE *) NULL;
254   unique_file=AcquireUniqueFileResource(filename);
255   if (unique_file != -1)
256     file=fdopen(unique_file,"wb");
257   if ((unique_file == -1) || (file == (FILE *) NULL))
258     ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile");
259   while ((c=ReadBlobByte(image)) != EOF)
260     (void) fputc(c,file);
261   (void) fclose(file);
262   (void) CloseBlob(image);
263   image=DestroyImage(image);
264   read_info=CloneImageInfo(image_info);
265   SetImageInfoBlob(read_info,(void *) NULL,0);
266   (void) FormatLocaleString(read_info->filename,MagickPathExtent,"group4:%s",
267     filename);
268   (void) FormatLocaleString(message,MagickPathExtent,"%lux%lu",width,height);
269   (void) CloneString(&read_info->size,message);
270   (void) FormatLocaleString(message,MagickPathExtent,"%lu",density);
271   (void) CloneString(&read_info->density,message);
272   read_info->orientation=(OrientationType) orientation;
273   image=ReadImage(read_info,exception);
274   if (image != (Image *) NULL)
275     {
276       (void) CopyMagickString(image->filename,image_info->filename,
277         MagickPathExtent);
278       (void) CopyMagickString(image->magick_filename,image_info->filename,
279         MagickPathExtent);
280       (void) CopyMagickString(image->magick,"CALS",MagickPathExtent);
281     }
282   read_info=DestroyImageInfo(read_info);
283   (void) RelinquishUniqueFileResource(filename);
284   return(image);
285 }
286 \f
287 /*
288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289 %                                                                             %
290 %                                                                             %
291 %                                                                             %
292 %   R e g i s t e r C A L S I m a g e                                         %
293 %                                                                             %
294 %                                                                             %
295 %                                                                             %
296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297 %
298 %  RegisterCALSImage() adds attributes for the CALS Raster Group 1 image file
299 %  image format to the list of supported formats.  The attributes include the
300 %  image format tag, a method to read and/or write the format, whether the
301 %  format supports the saving of more than one frame to the same file or blob,
302 %  whether the format supports native in-memory I/O, and a brief description
303 %  of the format.
304 %
305 %  The format of the RegisterCALSImage method is:
306 %
307 %      size_t RegisterCALSImage(void)
308 %
309 */
310 ModuleExport size_t RegisterCALSImage(void)
311 {
312 #define CALSDescription  "Continuous Acquisition and Life-cycle Support Type 1"
313 #define CALSNote  "Specified in MIL-R-28002 and MIL-PRF-28002"
314
315   MagickInfo
316     *entry;
317
318   entry=AcquireMagickInfo("CALS","CAL",CALSDescription);
319   entry->decoder=(DecodeImageHandler *) ReadCALSImage;
320 #if defined(MAGICKCORE_TIFF_DELEGATE)
321   entry->encoder=(EncodeImageHandler *) WriteCALSImage;
322 #endif
323   entry->flags^=CoderAdjoinFlag;
324   entry->magick=(IsImageFormatHandler *) IsCALS;
325   entry->note=ConstantString(CALSNote);
326   (void) RegisterMagickInfo(entry);
327   entry=AcquireMagickInfo("CALS","CALS",CALSDescription);
328   entry->decoder=(DecodeImageHandler *) ReadCALSImage;
329 #if defined(MAGICKCORE_TIFF_DELEGATE)
330   entry->encoder=(EncodeImageHandler *) WriteCALSImage;
331 #endif
332   entry->flags^=CoderAdjoinFlag;
333   entry->magick=(IsImageFormatHandler *) IsCALS;
334   entry->note=ConstantString(CALSNote);
335   (void) RegisterMagickInfo(entry);
336   return(MagickImageCoderSignature);
337 }
338 \f
339 /*
340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341 %                                                                             %
342 %                                                                             %
343 %                                                                             %
344 %   U n r e g i s t e r C A L S I m a g e                                     %
345 %                                                                             %
346 %                                                                             %
347 %                                                                             %
348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349 %
350 %  UnregisterCALSImage() removes format registrations made by the
351 %  CALS module from the list of supported formats.
352 %
353 %  The format of the UnregisterCALSImage method is:
354 %
355 %      UnregisterCALSImage(void)
356 %
357 */
358 ModuleExport void UnregisterCALSImage(void)
359 {
360   (void) UnregisterMagickInfo("CAL");
361   (void) UnregisterMagickInfo("CALS");
362 }
363 \f
364 #if defined(MAGICKCORE_TIFF_DELEGATE)
365 /*
366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 %                                                                             %
368 %                                                                             %
369 %                                                                             %
370 %   W r i t e C A L S I m a g e                                               %
371 %                                                                             %
372 %                                                                             %
373 %                                                                             %
374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 %
376 %  WriteCALSImage() writes an image to a file in CALS Raster Group 1 image
377 %  format.
378 %
379 %  The format of the WriteCALSImage method is:
380 %
381 %      MagickBooleanType WriteCALSImage(const ImageInfo *image_info,
382 %        Image *image,ExceptionInfo *exception)
383 %
384 %  A description of each parameter follows.
385 %
386 %    o image_info: the image info.
387 %
388 %    o image:  The image.
389 %
390 %    o exception: return any errors or warnings in this structure.
391 %
392 */
393
394 static ssize_t WriteCALSRecord(Image *image,const char *data)
395 {
396   char
397     pad[128];
398
399   register const char
400     *p;
401
402   register ssize_t
403     i;
404
405   ssize_t
406     count;
407
408   i=0;
409   count=0;
410   if (data != (const char *) NULL)
411     {
412       p=data;
413       for (i=0; (i < 128) && (p[i] != '\0'); i++);
414       count=WriteBlob(image,(size_t) i,(const unsigned char *) data);
415     }
416   if (i < 128)
417     {
418       i=128-i;
419       (void) ResetMagickMemory(pad,' ',(size_t) i);
420       count=WriteBlob(image,(size_t) i,(const unsigned char *) pad);
421     }
422   return(count);
423 }
424
425 static MagickBooleanType WriteCALSImage(const ImageInfo *image_info,
426   Image *image,ExceptionInfo *exception)
427 {
428   char
429     header[129];
430
431   Image
432     *group4_image;
433
434   ImageInfo
435     *write_info;
436
437   MagickBooleanType
438     status;
439
440   register ssize_t
441     i;
442
443   size_t
444     density,
445     length,
446     orient_x,
447     orient_y;
448
449   ssize_t
450     count;
451
452   unsigned char
453     *group4;
454
455   /*
456     Open output image file.
457   */
458   assert(image_info != (const ImageInfo *) NULL);
459   assert(image_info->signature == MagickCoreSignature);
460   assert(image != (Image *) NULL);
461   assert(image->signature == MagickCoreSignature);
462   if (image->debug != MagickFalse)
463     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
464   assert(exception != (ExceptionInfo *) NULL);
465   assert(exception->signature == MagickCoreSignature);
466   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
467   if (status == MagickFalse)
468     return(status);
469   /*
470     Create standard CALS header.
471   */
472   count=WriteCALSRecord(image,"srcdocid: NONE");
473   (void) count;
474   count=WriteCALSRecord(image,"dstdocid: NONE");
475   count=WriteCALSRecord(image,"txtfilid: NONE");
476   count=WriteCALSRecord(image,"figid: NONE");
477   count=WriteCALSRecord(image,"srcgph: NONE");
478   count=WriteCALSRecord(image,"doccls: NONE");
479   count=WriteCALSRecord(image,"rtype: 1");
480   orient_x=0;
481   orient_y=0;
482   switch (image->orientation)
483   {
484     case TopRightOrientation:
485     {
486       orient_x=180;
487       orient_y=270;
488       break;
489     }
490     case BottomRightOrientation:
491     {
492       orient_x=180;
493       orient_y=90;
494       break;
495     }
496     case BottomLeftOrientation:
497     {
498       orient_y=90;
499       break;
500     }
501     case LeftTopOrientation:
502     {
503       orient_x=270;
504       break;
505     }
506     case RightTopOrientation:
507     {
508       orient_x=270;
509       orient_y=180;
510       break;
511     }
512     case RightBottomOrientation:
513     {
514       orient_x=90;
515       orient_y=180;
516       break;
517     }
518     case LeftBottomOrientation:
519     {
520       orient_x=90;
521       break;
522     }
523     default:
524     {
525       orient_y=270;
526       break;
527     }
528   }
529   (void) FormatLocaleString(header,sizeof(header),"rorient: %03ld,%03ld",
530     (long) orient_x,(long) orient_y);
531   count=WriteCALSRecord(image,header);
532   (void) FormatLocaleString(header,sizeof(header),"rpelcnt: %06lu,%06lu",
533     (unsigned long) image->columns,(unsigned long) image->rows);
534   count=WriteCALSRecord(image,header);  
535   density=200;
536   if (image_info->density != (char *) NULL)
537     {
538       GeometryInfo
539         geometry_info;
540
541       (void) ParseGeometry(image_info->density,&geometry_info);
542       density=(size_t) floor(geometry_info.rho+0.5);
543     }
544   (void) FormatLocaleString(header,sizeof(header),"rdensty: %04lu",
545     (unsigned long) density);
546   count=WriteCALSRecord(image,header);
547   count=WriteCALSRecord(image,"notes: NONE");
548   (void) ResetMagickMemory(header,' ',128);
549   for (i=0; i < 5; i++)
550     (void) WriteBlob(image,128,(unsigned char *) header);
551   /*
552     Write CALS pixels.
553   */
554   write_info=CloneImageInfo(image_info);
555   (void) CopyMagickString(write_info->filename,"GROUP4:",MagickPathExtent);
556   (void) CopyMagickString(write_info->magick,"GROUP4",MagickPathExtent);
557   group4_image=CloneImage(image,0,0,MagickTrue,exception);
558   if (group4_image == (Image *) NULL)
559     {
560       write_info=DestroyImageInfo(write_info);
561       (void) CloseBlob(image);
562       return(MagickFalse);
563     }
564   group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length,
565     exception);
566   group4_image=DestroyImage(group4_image);
567   if (group4 == (unsigned char *) NULL)
568     {
569       write_info=DestroyImageInfo(write_info);
570       (void) CloseBlob(image);
571       return(MagickFalse);
572     }
573   write_info=DestroyImageInfo(write_info);
574   if (WriteBlob(image,length,group4) != (ssize_t) length)
575     status=MagickFalse;
576   group4=(unsigned char *) RelinquishMagickMemory(group4);
577   (void) CloseBlob(image);
578   return(status);
579 }
580 #endif