root/ImageMagick/trunk/coders/cals.c

Revision 199, 18.4 KB (checked in by cristy, 2 months ago)
Line 
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-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
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
69/*
70 Forward declarations.
71*/
72static MagickBooleanType
73  WriteCALSImage(const ImageInfo *,Image *);
74
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*/
100static 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
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*/
140static 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
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*/
307ModuleExport 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 Image"
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
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*/
366ModuleExport void UnregisterCALSImage(void)
367{
368  (void) UnregisterMagickInfo("CAL");
369  (void) UnregisterMagickInfo("CALS");
370}
371
372/*
373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374%                                                                             %
375%                                                                             %
376%                                                                             %
377%   W r i t e C A L S I m a g e                                               %
378%                                                                             %
379%                                                                             %
380%                                                                             %
381%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
382%
383%  WriteCALSImage() writes an image to a file in CALS Raster Group 1 image
384%  format.
385%
386%  The format of the WriteCALSImage method is:
387%
388%      MagickBooleanType WriteCALSImage(const ImageInfo *image_info,
389%        Image *image)
390%
391%  A description of each parameter follows.
392%
393%    o image_info: the image info.
394%
395%    o image:  The image.
396%
397*/
398
399static ssize_t WriteCALSRecord(Image *image,const char *data)
400{
401  char
402    pad[128];
403
404  ssize_t
405    count;
406
407  register const char
408    *p;
409
410  register long
411    i;
412
413  i=0;
414  if (data != (const char *) NULL)
415    {
416      p=data;
417      for (i=0; (i < 128) && (p[i] != '\0'); i++);
418      count=WriteBlob(image,(size_t) i,(const unsigned char *) data);
419    }
420  if (i < 128)
421    {
422      i=128-i;
423      (void) ResetMagickMemory(pad,' ',(const size_t) i);
424      count=WriteBlob(image,(size_t) i,(const unsigned char *) pad);
425    }
426  return(count);
427}
428
429static MagickBooleanType WriteCALSImage(const ImageInfo *image_info,
430  Image *image)
431{
432  char
433    header[129];
434
435  Image
436    *group4_image;
437
438  ImageInfo
439    *write_info;
440
441  MagickBooleanType
442    status;
443
444  register long
445    i;
446
447  ssize_t
448    count;
449
450  size_t
451    length;
452
453  unsigned char
454    *group4;
455
456  unsigned long
457    density,
458    orient_x,
459    orient_y;
460
461  /*
462    Open output image file.
463  */
464  assert(image_info != (const ImageInfo *) NULL);
465  assert(image_info->signature == MagickSignature);
466  assert(image != (Image *) NULL);
467  assert(image->signature == MagickSignature);
468  if (image->debug != MagickFalse)
469    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
470  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
471  if (status == MagickFalse)
472    return(status);
473  /*
474    Create standard CALS header.
475  */
476  count=WriteCALSRecord(image,"srcdocid: NONE");
477  count=WriteCALSRecord(image,"dstdocid: NONE");
478  count=WriteCALSRecord(image,"txtfilid: NONE");
479  count=WriteCALSRecord(image,"figid: NONE");
480  count=WriteCALSRecord(image,"srcgph: NONE");
481  count=WriteCALSRecord(image,"docls: NONE");
482  count=WriteCALSRecord(image,"rtype: 1");
483  orient_x=0;
484  orient_y=0;
485  switch (image->orientation)
486  {
487    case TopRightOrientation:
488    {
489      orient_x=180;
490      orient_y=270;
491      break;
492    }
493    case BottomRightOrientation:
494    {
495      orient_x=180;
496      orient_y=90;
497      break;
498    }
499    case BottomLeftOrientation:
500    {
501      orient_y=90;
502      break;
503    }
504    case LeftTopOrientation:
505    {
506      orient_x=270;
507      break;
508    }
509    case RightTopOrientation:
510    {
511      orient_x=270;
512      orient_y=180;
513      break;
514    }
515    case RightBottomOrientation:
516    {
517      orient_x=90;
518      orient_y=180;
519      break;
520    }
521    case LeftBottomOrientation:
522    {
523      orient_x=90;
524      break;
525    }
526    default:
527    {
528      orient_y=270;
529    }
530  }
531  (void) FormatMagickString(header,MaxTextExtent,"rorient: %03ld,%03ld",
532    orient_x,orient_y);
533  count=WriteCALSRecord(image,header);
534  (void) FormatMagickString(header,MaxTextExtent,"rpelcnt: %06lu,%06lu",
535    image->columns,image->rows);
536  count=WriteCALSRecord(image,header); 
537  density=200;
538  if (image_info->density != (char *) NULL)
539    {
540      GeometryInfo
541        geometry_info;
542
543      (void) ParseGeometry(image_info->density,&geometry_info);
544      density=(unsigned long) (geometry_info.rho+0.5);
545    }
546  (void) FormatMagickString(header,MaxTextExtent,"rdensty: %04lu",density);
547  count=WriteCALSRecord(image,header);
548  count=WriteCALSRecord(image,"notes: NONE");
549  (void) ResetMagickMemory(header,' ',128);
550  for (i=0; i < 5; i++)
551    (void) WriteBlob(image,128,(unsigned char *) header);
552  /*
553    Write CALS pixels.
554  */
555  write_info=CloneImageInfo(image_info);
556  (void) CopyMagickString(write_info->filename,"GROUP4:",MaxTextExtent);
557  (void) CopyMagickString(write_info->magick,"GROUP4",MaxTextExtent);
558  group4_image=CloneImage(image,0,0,MagickTrue,&image->exception);
559  if (group4_image == (Image *) NULL)
560    {
561      (void) CloseBlob(image);
562      return(MagickFalse);
563    }
564  group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length,
565    &image->exception);
566  group4_image=DestroyImage(group4_image);
567  if (group4 == (unsigned char *) NULL)
568    {
569      (void) CloseBlob(image);
570      return(MagickFalse);
571    }
572  write_info=DestroyImageInfo(write_info);
573  if (WriteBlob(image,length,group4) != (ssize_t) length)
574    status=MagickFalse;
575  group4=(unsigned char *) RelinquishMagickMemory(group4);
576  (void) CloseBlob(image);
577  return(status);
578}
Note: See TracBrowser for help on using the browser.