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