]> 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 Image Format                         %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2009 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/image.h"
55 #include "magick/image-private.h"
56 #include "magick/list.h"
57 #include "magick/magick.h"
58 #include "magick/memory_.h"
59 #include "magick/monitor.h"
60 #include "magick/monitor-private.h"
61 #include "magick/quantum-private.h"
62 #include "magick/resource_.h"
63 #include "magick/static.h"
64 #include "magick/string_.h"
65 #include "magick/module.h"
66 \f
67 /*
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 %                                                                             %
70 %                                                                             %
71 %                                                                             %
72 %   I s C A L S                                                               %
73 %                                                                             %
74 %                                                                             %
75 %                                                                             %
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 %
78 %  IsCALS() returns MagickTrue if the image format type, identified by the
79 %  magick string, is CALS.
80 %
81 %  The format of the IsCALS method is:
82 %
83 %      MagickBooleanType IsCALS(const unsigned char *magick,const size_t length)
84 %
85 %  A description of each parameter follows:
86 %
87 %    o magick: compare image format pattern against these bytes.
88 %
89 %    o length: Specifies the length of the magick string.
90 %
91 */
92 static MagickBooleanType IsCALS(const unsigned char *magick,const size_t length)
93 {
94   if (length < 128)
95     return(MagickFalse);
96   if (LocaleNCompare((char *) magick,"version: MIL-STD-1840",21) == 0)
97     return(MagickTrue);
98   if (LocaleNCompare((char *) magick,"srcdocid:",9) == 0)
99     return(MagickTrue);
100   if (LocaleNCompare((char *) magick,"rorient:",8) == 0)
101     return(MagickTrue);
102   return(MagickFalse);
103 }
104 \f
105 /*
106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107 %                                                                             %
108 %                                                                             %
109 %                                                                             %
110 %   R e a d C A L S I m a g e                                                 %
111 %                                                                             %
112 %                                                                             %
113 %                                                                             %
114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115 %
116 %  ReadCALSImage() reads an Automated Interchange of Technical Information,
117 %  MIL-STD-1840A image file and returns it.  It allocates the memory necessary
118 %  for the new Image structure and returns a pointer to the new image.
119 %
120 %  The format of the ReadCALSImage method is:
121 %
122 %      Image *ReadCALSImage(const ImageInfo *image_info,
123 %        ExceptionInfo *exception)
124 %
125 %  A description of each parameter follows:
126 %
127 %    o image_info: the image info.
128 %
129 %    o exception: return any errors or warnings in this structure.
130 %
131 */
132
133 static inline size_t WriteCALSLSBLong(FILE *file,const unsigned int value)
134 {
135   unsigned char
136     buffer[4];
137
138   buffer[0]=(unsigned char) value;
139   buffer[1]=(unsigned char) (value >> 8);
140   buffer[2]=(unsigned char) (value >> 16);
141   buffer[3]=(unsigned char) (value >> 24);
142   return(fwrite(buffer,1,4,file));
143 }
144
145 static Image *ReadCALSImage(const ImageInfo *image_info,
146   ExceptionInfo *exception)
147 {
148   char
149     filename[MaxTextExtent],
150     header[129];
151
152   FILE
153     *file;
154
155   Image
156     *image;
157
158   ImageInfo
159     *read_info;
160
161   int
162     c,
163     unique_file;
164
165   MagickBooleanType
166     status;
167
168   register long
169     i;
170
171   size_t
172     length;
173
174   ssize_t
175     offset,
176     strip_offset;
177
178   unsigned int
179     density,
180     direction,
181     height,
182     orientation,
183     pel_path,
184     type,
185     width;
186
187   /*
188     Open image file.
189   */
190   assert(image_info != (const ImageInfo *) NULL);
191   assert(image_info->signature == MagickSignature);
192   if (image_info->debug != MagickFalse)
193     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
194       image_info->filename);
195   assert(exception != (ExceptionInfo *) NULL);
196   assert(exception->signature == MagickSignature);
197   image=AcquireImage(image_info);
198   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
199   if (status == MagickFalse)
200     {
201       image=DestroyImageList(image);
202       return((Image *) NULL);
203     }
204   /*
205     Read CALS header.
206   */
207   (void) ResetMagickMemory(header,0,sizeof(header));
208   density=0;
209   direction=0;
210   orientation=1;
211   pel_path=0;
212   type=1;
213   width=0;
214   height=0;
215   for (i=0; i < 16; i++)
216   {
217     if (ReadBlob(image,128,(unsigned char *) header) != 128)
218       break;
219     switch (*header)
220     {
221       case 'R':
222       case 'r':
223       {
224         if (LocaleNCompare(header,"rdensty:",8) == 0)
225           {
226             (void) sscanf(header+8,"%u",&density);
227             break;
228           }
229         if (LocaleNCompare(header,"rpelcnt:",8) == 0)
230           {
231             (void) sscanf(header+8,"%u,%u",&width,&height);
232             break;
233           }
234         if (LocaleNCompare(header,"rorient:",8) == 0)
235           {
236             (void) sscanf(header+8,"%u,%u",&pel_path,&direction);
237             if (pel_path == 90)
238               orientation=5;
239             else
240               if (pel_path == 90)
241                 orientation=3;
242               else
243                 if (pel_path == 270)
244                   orientation=7;
245             if (direction == 90)
246               orientation++;
247             break;
248           }
249         if (LocaleNCompare(header,"rtype:",6) == 0)
250           {
251             (void) sscanf(header+6,"%u",&type);
252             break;
253           }
254         break;
255       }
256     }
257   }
258   if ((width == 0) || (height == 0) || (type == 0))
259     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
260   /*
261     Write CALS facsimile document wrapped as a TIFF image file.
262   */
263   file=(FILE *) NULL;
264   unique_file=AcquireUniqueFileResource(filename);
265   if (unique_file != -1)
266     file=fdopen(unique_file,"wb");
267   if ((unique_file == -1) || (file == (FILE *) NULL))
268     ThrowReaderException(FileOpenError,"UnableToCreateTemporaryFile");
269   length=fwrite("\111\111\052\000\010\000\000\000\016\000",1,10,file);
270   length=fwrite("\376\000\003\000\001\000\000\000\000\000\000\000",1,12,file);
271   length=fwrite("\000\001\004\000\001\000\000\000",1,8,file);
272   length=WriteCALSLSBLong(file,width);
273   length=fwrite("\001\001\004\000\001\000\000\000",1,8,file);
274   length=WriteCALSLSBLong(file,height);
275   length=fwrite("\002\001\003\000\001\000\000\000\001\000\000\000",1,12,file);
276   length=fwrite("\003\001\003\000\001\000\000\000\004\000\000\000",1,12,file);
277   length=fwrite("\006\001\003\000\001\000\000\000\000\000\000\000",1,12,file);
278   length=fwrite("\021\001\003\000\001\000\000\000",1,8,file);
279   strip_offset=10+(12*14)+4+8;
280   length=WriteCALSLSBLong(file,(unsigned int) strip_offset);
281   length=fwrite("\022\001\003\000\001\000\000\000",1,8,file);
282   length=WriteCALSLSBLong(file,orientation);
283   length=fwrite("\025\001\003\000\001\000\000\000\001\000\000\000",1,12,file);
284   length=fwrite("\026\001\004\000\001\000\000\000",1,8,file);
285   length=WriteCALSLSBLong(file,width);
286   length=fwrite("\027\001\004\000\001\000\000\000\000\000\000\000",1,12,file);
287   offset=(ssize_t) ftell(file)-4;
288   length=fwrite("\032\001\005\000\001\000\000\000",1,8,file);
289   length=WriteCALSLSBLong(file,(unsigned int) (strip_offset-8));
290   length=fwrite("\033\001\005\000\001\000\000\000",1,8,file);
291   length=WriteCALSLSBLong(file,(unsigned int) (strip_offset-8));
292   length=fwrite("\050\001\003\000\001\000\000\000\002\000\000\000",1,12,file);
293   length=fwrite("\000\000\000\000",1,4,file);
294   length=WriteCALSLSBLong(file,density);
295   length=WriteCALSLSBLong(file,1);
296   for (length=0; (c=ReadBlobByte(image)) != EOF; length++)
297     (void) fputc(c,file);
298   (void) CloseBlob(image);
299   image=DestroyImage(image);
300   offset=(ssize_t) fseek(file,(long) offset,SEEK_SET);
301   length=WriteCALSLSBLong(file,(unsigned int) length);
302   (void) fclose(file);
303   /*
304     Read TIFF image.
305   */
306   read_info=CloneImageInfo(image_info);
307   SetImageInfoBlob(read_info,(void *) NULL,0);
308   (void) FormatMagickString(read_info->filename,MaxTextExtent,"tiff:%.1024s",
309     filename);
310   image=ReadImage(read_info,exception);
311   read_info=DestroyImageInfo(read_info);
312   (void) RelinquishUniqueFileResource(filename);
313   if (image == (Image *) NULL)
314     return(image);
315   return(GetFirstImageInList(image));
316 }
317 \f
318 /*
319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
320 %                                                                             %
321 %                                                                             %
322 %                                                                             %
323 %   R e g i s t e r C A L S I m a g e                                         %
324 %                                                                             %
325 %                                                                             %
326 %                                                                             %
327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328 %
329 %  RegisterCALSImage() adds attributes for the CALS X image format to the list
330 %  of supported formats.  The attributes include the image format tag, a
331 %  method to read and/or write the format, whether the format supports the
332 %  saving of more than one frame to the same file or blob, whether the format
333 %  supports native in-memory I/O, and a brief description of the format.
334 %
335 %  The format of the RegisterCALSImage method is:
336 %
337 %      unsigned long RegisterCALSImage(void)
338 %
339 */
340 ModuleExport unsigned long RegisterCALSImage(void)
341 {
342   MagickInfo
343     *entry;
344
345   entry=SetMagickInfo("CALS");
346   entry->decoder=(DecodeImageHandler *) ReadCALSImage;
347   entry->adjoin=MagickFalse;
348   entry->magick=(IsImageFormatHandler *) IsCALS;
349   entry->description=ConstantString("Automated Interchange of Technical "
350     "Information, MIL-STD-1840A");
351   entry->module=ConstantString("CALS");
352   (void) RegisterMagickInfo(entry);
353   return(MagickImageCoderSignature);
354 }
355 \f
356 /*
357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
358 %                                                                             %
359 %                                                                             %
360 %                                                                             %
361 %   U n r e g i s t e r C A L S I m a g e                                     %
362 %                                                                             %
363 %                                                                             %
364 %                                                                             %
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 %
367 %  UnregisterCALSImage() removes format registrations made by the
368 %  CALS module from the list of supported formats.
369 %
370 %  The format of the UnregisterCALSImage method is:
371 %
372 %      UnregisterCALSImage(void)
373 %
374 */
375 ModuleExport void UnregisterCALSImage(void)
376 {
377   (void) UnregisterMagickInfo("CALS");
378 }