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