root / ImageMagick / trunk / coders / gray.c

Revision 12033, 14.9 kB (checked in by cristy, 6 weeks ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                         GGGG  RRRR    AAA   Y   Y                           %
7%                        G      R   R  A   A   Y Y                            %
8%                        G  GG  RRRR   AAAAA    Y                             %
9%                        G   G  R R    A   A    Y                             %
10%                         GGG   R  R   A   A    Y                             %
11%                                                                             %
12%                                                                             %
13%                    Read/Write RAW Gray Image Format.                        %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                 July 1992                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2008 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%
37*/
38
39/*
40  Include declarations.
41*/
42#include "magick/studio.h"
43#include "magick/blob.h"
44#include "magick/blob-private.h"
45#include "magick/colorspace.h"
46#include "magick/constitute.h"
47#include "magick/exception.h"
48#include "magick/exception-private.h"
49#include "magick/image.h"
50#include "magick/image-private.h"
51#include "magick/list.h"
52#include "magick/magick.h"
53#include "magick/memory_.h"
54#include "magick/monitor.h"
55#include "magick/monitor-private.h"
56#include "magick/pixel.h"
57#include "magick/pixel-private.h"
58#include "magick/quantum-private.h"
59#include "magick/static.h"
60#include "magick/statistic.h"
61#include "magick/string_.h"
62#include "magick/module.h"
63
64/*
65  Forward declarations.
66*/
67static MagickBooleanType
68  WriteGRAYImage(const ImageInfo *,Image *);
69
70/*
71%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72%                                                                             %
73%                                                                             %
74%                                                                             %
75%   R e a d G R A Y I m a g e                                                 %
76%                                                                             %
77%                                                                             %
78%                                                                             %
79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80%
81%  ReadGRAYImage() reads an image of raw grayscale samples and returns
82%  it.  It allocates the memory necessary for the new Image structure and
83%   returns a pointer to the new image.
84%
85%  The format of the ReadGRAYImage method is:
86%
87%      Image *ReadGRAYImage(const ImageInfo *image_info,
88%        ExceptionInfo *exception)
89%
90%  A description of each parameter follows:
91%
92%    o image_info: the image info.
93%
94%    o exception: return any errors or warnings in this structure.
95%
96*/
97static Image *ReadGRAYImage(const ImageInfo *image_info,
98  ExceptionInfo *exception)
99{
100  Image
101    *canvas_image,
102    *image;
103
104  long
105    y;
106
107  MagickBooleanType
108    status;
109
110  QuantumInfo
111    *quantum_info;
112
113  QuantumType
114    quantum_type;
115
116  register const PixelPacket
117    *p;
118
119  register long
120    i,
121    x;
122
123  register PixelPacket
124    *q;
125
126  ssize_t
127    count;
128
129  size_t
130    length;
131
132  unsigned char
133    *pixels;
134
135  /*
136    Open image file.
137  */
138  assert(image_info != (const ImageInfo *) NULL);
139  assert(image_info->signature == MagickSignature);
140  if (image_info->debug != MagickFalse)
141    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
142      image_info->filename);
143  assert(exception != (ExceptionInfo *) NULL);
144  assert(exception->signature == MagickSignature);
145  image=AcquireImage(image_info);
146  if ((image->columns == 0) || (image->rows == 0))
147    ThrowReaderException(OptionError,"MustSpecifyImageSize");
148  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
149  if (status == MagickFalse)
150    {
151      image=DestroyImageList(image);
152      return((Image *) NULL);
153    }
154  for (i=0; i < image->offset; i++)
155    if (ReadBlobByte(image) == EOF)
156      {
157        ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
158          image->filename);
159        break;
160      }
161  /*
162    Create virtual canvas to support cropping (i.e. image.gray[100x100+10+20]).
163  */
164  canvas_image=CloneImage(image,image->extract_info.width,1,MagickTrue,
165    exception);
166  (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod);
167  quantum_type=GrayQuantum;
168  quantum_info=AcquireQuantumInfo(image_info,canvas_image);
169  pixels=GetQuantumPixels(quantum_info);
170  if (image_info->number_scenes != 0)
171    while (image->scene < image_info->scene)
172    {
173      /*
174        Skip to next image.
175      */
176      image->scene++;
177      length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
178      for (y=0; y < (long) image->rows; y++)
179      {
180        count=ReadBlob(image,length,pixels);
181        if (count != (ssize_t) length)
182          break;
183      }
184    }
185  do
186  {
187    /*
188      Read pixels to virtual canvas image then push to image.
189    */
190    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
191      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
192        break;
193    if ((SetImageExtent(image,0,0) == MagickFalse) ||
194        (SetImageExtent(canvas_image,0,0) == MagickFalse))
195      break;
196    length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
197    count=ReadBlob(image,length,pixels);
198    if (count != (ssize_t) length)
199      break;
200    for (y=0; y < (long) image->extract_info.height; y++)
201    {
202      q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
203      if (q == (PixelPacket *) NULL)
204        break;
205      length=ImportQuantumPixels(canvas_image,quantum_info,quantum_type,pixels);
206      if (SyncImagePixels(canvas_image) == MagickFalse)
207        break;
208      count=ReadBlob(image,length,pixels);
209      if (((y-image->extract_info.y) >= 0) &&
210          ((y-image->extract_info.y) < (long) image->rows))
211        {
212          p=AcquireImagePixels(canvas_image,canvas_image->extract_info.x,0,
213            image->columns,1,exception);
214          q=SetImagePixels(image,0,y-image->extract_info.y,image->columns,1);
215          if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
216            break;
217          for (x=0; x < (long) image->columns; x++)
218          {
219            q->red=p->red;
220            q->green=p->green;
221            q->blue=p->blue;
222            p++;
223            q++;
224          }
225          if (SyncImagePixels(image) == MagickFalse)
226            break;
227        }
228      if (image->previous == (Image *) NULL)
229        {
230          status=SetImageProgress(image,LoadImageTag,y,image->rows);
231          if (status == MagickFalse)
232            break;
233        }
234    }
235    SetQuantumImageType(image,quantum_type);
236    /*
237      Proceed to next image.
238    */
239    if (image_info->number_scenes != 0)
240      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
241        break;
242    if (count == (ssize_t) length)
243      {
244        /*
245          Allocate next image structure.
246        */
247        AcquireNextImage(image_info,image);
248        if (GetNextImageInList(image) == (Image *) NULL)
249          {
250            image=DestroyImageList(image);
251            return((Image *) NULL);
252          }
253        image=SyncNextImageInList(image);
254        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
255          GetBlobSize(image));
256        if (status == MagickFalse)
257          break;
258      }
259  } while (count == (ssize_t) length);
260  quantum_info=DestroyQuantumInfo(quantum_info);
261  InheritException(exception,&canvas_image->exception);
262  canvas_image=DestroyImage(canvas_image);
263  (void) CloseBlob(image);
264  return(GetFirstImageInList(image));
265}
266
267/*
268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269%                                                                             %
270%                                                                             %
271%                                                                             %
272%   R e g i s t e r G R A Y I m a g e                                         %
273%                                                                             %
274%                                                                             %
275%                                                                             %
276%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277%
278%  RegisterGRAYImage() adds attributes for the GRAY image format to
279%  the list of supported formats.  The attributes include the image format
280%  tag, a method to read and/or write the format, whether the format
281%  supports the saving of more than one frame to the same file or blob,
282%  whether the format supports native in-memory I/O, and a brief
283%  description of the format.
284%
285%  The format of the RegisterGRAYImage method is:
286%
287%      unsigned long RegisterGRAYImage(void)
288%
289*/
290ModuleExport unsigned long RegisterGRAYImage(void)
291{
292  MagickInfo
293    *entry;
294
295  entry=SetMagickInfo("GRAY");
296  entry->decoder=(DecodeImageHandler *) ReadGRAYImage;
297  entry->encoder=(EncodeImageHandler *) WriteGRAYImage;
298  entry->raw=MagickTrue;
299  entry->endian_support=MagickTrue;
300  entry->description=ConstantString("Raw gray samples");
301  entry->module=ConstantString("GRAY");
302  (void) RegisterMagickInfo(entry);
303  return(MagickImageCoderSignature);
304}
305
306/*
307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308%                                                                             %
309%                                                                             %
310%                                                                             %
311%   U n r e g i s t e r G R A Y I m a g e                                     %
312%                                                                             %
313%                                                                             %
314%                                                                             %
315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316%
317%  UnregisterGRAYImage() removes format registrations made by the
318%  GRAY module from the list of supported formats.
319%
320%  The format of the UnregisterGRAYImage method is:
321%
322%      UnregisterGRAYImage(void)
323%
324*/
325ModuleExport void UnregisterGRAYImage(void)
326{
327  (void) UnregisterMagickInfo("GRAY");
328}
329
330/*
331%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332%                                                                             %
333%                                                                             %
334%                                                                             %
335%   W r i t e G R A Y I m a g e                                               %
336%                                                                             %
337%                                                                             %
338%                                                                             %
339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340%
341%  WriteGRAYImage() writes an image to a file as gray scale intensity
342%  values.
343%
344%  The format of the WriteGRAYImage method is:
345%
346%      MagickBooleanType WriteGRAYImage(const ImageInfo *image_info,
347%        Image *image)
348%
349%  A description of each parameter follows.
350%
351%    o image_info: the image info.
352%
353%    o image:  The image.
354%
355*/
356static MagickBooleanType WriteGRAYImage(const ImageInfo *image_info,
357  Image *image)
358{
359  long
360    y;
361
362  MagickBooleanType
363    status;
364
365  MagickOffsetType
366    scene;
367
368  QuantumInfo
369    *quantum_info;
370
371  QuantumType
372    quantum_type;
373
374  register const PixelPacket
375    *p;
376
377  ssize_t
378    count;
379
380  size_t
381    length;
382
383  unsigned char
384    *pixels;
385
386  /*
387    Open output image file.
388  */
389  assert(image_info != (const ImageInfo *) NULL);
390  assert(image_info->signature == MagickSignature);
391  assert(image != (Image *) NULL);
392  assert(image->signature == MagickSignature);
393  if (image->debug != MagickFalse)
394    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
395  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
396  if (status == MagickFalse)
397    return(status);
398  scene=0;
399  do
400  {
401    /*
402      Write grayscale pixels.
403    */
404    if (image->colorspace != RGBColorspace)
405      (void) SetImageColorspace(image,RGBColorspace);
406    quantum_type=GrayQuantum;
407    quantum_info=AcquireQuantumInfo(image_info,image);
408    pixels=GetQuantumPixels(quantum_info);
409    for (y=0; y < (long) image->rows; y++)
410    {
411      p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
412      if (p == (const PixelPacket *) NULL)
413        break;
414      length=ExportQuantumPixels(image,quantum_info,quantum_type,pixels);
415      count=WriteBlob(image,length,pixels);
416      if (count != (ssize_t) length)
417        break;
418      if (image->previous == (Image *) NULL)
419        {
420          status=SetImageProgress(image,SaveImageTag,y,image->rows);
421          if (status == MagickFalse)
422            break;
423        }
424    }
425    quantum_info=DestroyQuantumInfo(quantum_info);
426    if (GetNextImageInList(image) == (Image *) NULL)
427      break;
428    image=SyncNextImageInList(image);
429    status=SetImageProgress(image,SaveImagesTag,scene++,
430      GetImageListLength(image));
431    if (status == MagickFalse)
432      break;
433  } while (image_info->adjoin != MagickFalse);
434  (void) CloseBlob(image);
435  return(MagickTrue);
436}
Note: See TracBrowser for help on using the browser.