]> granicus.if.org Git - imagemagick/blob - coders/uyvy.c
(no commit message)
[imagemagick] / coders / uyvy.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                        U   U  Y   Y  V   V  Y   Y                           %
7 %                        U   U   Y Y   V   V   Y Y                            %
8 %                        U   U    Y    V   V    Y                             %
9 %                        U   U    Y     V V     Y                             %
10 %                         UUU     Y      V      Y                             %
11 %                                                                             %
12 %                                                                             %
13 %            Read/Write 16bit/pixel Interleaved YUV 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 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/blob-private.h"
45 #include "magick/cache.h"
46 #include "magick/color.h"
47 #include "magick/colorspace.h"
48 #include "magick/exception.h"
49 #include "magick/exception-private.h"
50 #include "magick/image.h"
51 #include "magick/image-private.h"
52 #include "magick/list.h"
53 #include "magick/magick.h"
54 #include "magick/memory_.h"
55 #include "magick/monitor.h"
56 #include "magick/monitor-private.h"
57 #include "magick/quantum-private.h"
58 #include "magick/static.h"
59 #include "magick/string_.h"
60 #include "magick/module.h"
61 \f
62 /*
63   Forward declarations.
64 */
65 static MagickBooleanType
66   WriteUYVYImage(const ImageInfo *,Image *);
67 \f
68 /*
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 %                                                                             %
71 %                                                                             %
72 %                                                                             %
73 %   R e a d U Y V Y I m a g e                                                 %
74 %                                                                             %
75 %                                                                             %
76 %                                                                             %
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 %
79 %  ReadUYVYImage() reads an image in the UYVY format and returns it.  It
80 %  allocates the memory necessary for the new Image structure and returns a
81 %  pointer to the new image.
82 %
83 %  The format of the ReadUYVYImage method is:
84 %
85 %      Image *ReadUYVYImage(const ImageInfo *image_info,
86 %        ExceptionInfo *exception)
87 %
88 %  A description of each parameter follows:
89 %
90 %    o image_info: the image info.
91 %
92 %    o exception: return any errors or warnings in this structure.
93 %
94 %
95 */
96 static Image *ReadUYVYImage(const ImageInfo *image_info,
97   ExceptionInfo *exception)
98 {
99   Image
100     *image;
101
102   long
103     y;
104
105   MagickBooleanType
106     status;
107
108   register long
109     x;
110
111   register PixelPacket
112     *q;
113
114   register long
115     i;
116
117   unsigned char
118     u,
119     v,
120     y1,
121     y2;
122
123   /*
124     Open image file.
125   */
126   assert(image_info != (const ImageInfo *) NULL);
127   assert(image_info->signature == MagickSignature);
128   if (image_info->debug != MagickFalse)
129     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
130       image_info->filename);
131   assert(exception != (ExceptionInfo *) NULL);
132   assert(exception->signature == MagickSignature);
133   image=AcquireImage(image_info);
134   if ((image->columns == 0) || (image->rows == 0))
135     ThrowReaderException(OptionError,"MustSpecifyImageSize");
136   if ((image->columns % 2) != 0)
137     image->columns++;
138   (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent);
139   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
140   if (status == MagickFalse)
141     return((Image *) NULL);
142   for (i=0; i < image->offset; i++)
143     if (ReadBlobByte(image) == EOF)
144       {
145         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
146           image->filename);
147         break;
148       }
149   image->depth=8;
150   if (image_info->ping != MagickFalse)
151     {
152       (void) CloseBlob(image);
153       return(GetFirstImageInList(image));
154     }
155   /*
156     Accumulate UYVY, then unpack into two pixels.
157   */
158   for (y=0; y < (long) image->rows; y++)
159   {
160     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
161     if (q == (PixelPacket *) NULL)
162       break;
163     for (x=0; x < (long) (image->columns >> 1); x++)
164     {
165       u=(unsigned char) ReadBlobByte(image);
166       y1=(unsigned char) ReadBlobByte(image);
167       v=(unsigned char) ReadBlobByte(image);
168       y2=(unsigned char) ReadBlobByte(image);
169       q->red=ScaleCharToQuantum(y1);
170       q->green=ScaleCharToQuantum(u);
171       q->blue=ScaleCharToQuantum(v);
172       q++;
173       q->red=ScaleCharToQuantum(y2);
174       q->green=ScaleCharToQuantum(u);
175       q->blue=ScaleCharToQuantum(v);
176       q++;
177     }
178     if (SyncAuthenticPixels(image,exception) == MagickFalse)
179       break;
180     status=SetImageProgress(image,LoadImageTag,y,image->rows);
181     if (status == MagickFalse)
182       break;
183   }
184   image->colorspace=YCbCrColorspace;
185   if (EOFBlob(image) != MagickFalse)
186     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
187       image->filename);
188   (void) CloseBlob(image);
189   return(GetFirstImageInList(image));
190 }
191 \f
192 /*
193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194 %                                                                             %
195 %                                                                             %
196 %                                                                             %
197 %   R e g i s t e r U Y V Y I m a g e                                         %
198 %                                                                             %
199 %                                                                             %
200 %                                                                             %
201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
202 %
203 %  RegisterUYVYImage() adds attributes for the UYVY image format to
204 %  the list of supported formats.  The attributes include the image format
205 %  tag, a method to read and/or write the format, whether the format
206 %  supports the saving of more than one frame to the same file or blob,
207 %  whether the format supports native in-memory I/O, and a brief
208 %  description of the format.
209 %
210 %  The format of the RegisterUYVYImage method is:
211 %
212 %      unsigned long RegisterUYVYImage(void)
213 %
214 */
215 ModuleExport unsigned long RegisterUYVYImage(void)
216 {
217   MagickInfo
218     *entry;
219
220   entry=SetMagickInfo("PAL");
221   entry->decoder=(DecodeImageHandler *) ReadUYVYImage;
222   entry->encoder=(EncodeImageHandler *) WriteUYVYImage;
223   entry->adjoin=MagickFalse;
224   entry->raw=MagickTrue;
225   entry->endian_support=MagickTrue;
226   entry->description=ConstantString("16bit/pixel interleaved YUV");
227   entry->module=ConstantString("UYVY");
228   (void) RegisterMagickInfo(entry);
229   entry=SetMagickInfo("UYVY");
230   entry->decoder=(DecodeImageHandler *) ReadUYVYImage;
231   entry->encoder=(EncodeImageHandler *) WriteUYVYImage;
232   entry->adjoin=MagickFalse;
233   entry->raw=MagickTrue;
234   entry->endian_support=MagickTrue;
235   entry->description=ConstantString("16bit/pixel interleaved YUV");
236   entry->module=ConstantString("UYVY");
237   (void) RegisterMagickInfo(entry);
238   return(MagickImageCoderSignature);
239 }
240 \f
241 /*
242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
243 %                                                                             %
244 %                                                                             %
245 %                                                                             %
246 %   U n r e g i s t e r U Y V Y I m a g e                                     %
247 %                                                                             %
248 %                                                                             %
249 %                                                                             %
250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
251 %
252 %  UnregisterUYVYImage() removes format registrations made by the
253 %  UYVY module from the list of supported formats.
254 %
255 %  The format of the UnregisterUYVYImage method is:
256 %
257 %      UnregisterUYVYImage(void)
258 %
259 */
260 ModuleExport void UnregisterUYVYImage(void)
261 {
262   (void) UnregisterMagickInfo("PAL");
263   (void) UnregisterMagickInfo("UYVY");
264 }
265 \f
266 /*
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268 %                                                                             %
269 %                                                                             %
270 %                                                                             %
271 %   W r i t e U Y V Y I m a g e                                               %
272 %                                                                             %
273 %                                                                             %
274 %                                                                             %
275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276 %
277 %  WriteUYVYImage() writes an image to a file in the digital UYVY
278 %  format.  This format, used by AccomWSD, is not dramatically higher quality
279 %  than the 12bit/pixel YUV format, but has better locality.
280 %
281 %  The format of the WriteUYVYImage method is:
282 %
283 %      MagickBooleanType WriteUYVYImage(const ImageInfo *image_info,
284 %        Image *image)
285 %
286 %  A description of each parameter follows.
287 %
288 %    o image_info: the image info.
289 %
290 %    o image:  The image.
291 %      Implicit assumption: number of columns is even.
292 %
293 */
294 static MagickBooleanType WriteUYVYImage(const ImageInfo *image_info,
295   Image *image)
296 {
297   MagickPixelPacket
298     pixel;
299
300   Image
301     *uyvy_image;
302
303   long
304     y;
305
306   MagickBooleanType
307     full,
308     status;
309
310   register const PixelPacket
311     *p;
312
313   register long
314     x;
315
316   /*
317     Open output image file.
318   */
319   assert(image_info != (const ImageInfo *) NULL);
320   assert(image_info->signature == MagickSignature);
321   assert(image != (Image *) NULL);
322   assert(image->signature == MagickSignature);
323   if (image->debug != MagickFalse)
324     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
325   if ((image->columns % 2) != 0)
326     image->columns++;
327   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
328   if (status == MagickFalse)
329     return(status);
330   /*
331     Accumulate two pixels, then output.
332   */
333   uyvy_image=CloneImage(image,0,0,MagickTrue,&image->exception);
334   if (uyvy_image == (Image *) NULL)
335     ThrowWriterException(ResourceLimitError,image->exception.reason);
336   (void) TransformImageColorspace(uyvy_image,YCbCrColorspace);
337   full=MagickFalse;
338   (void) ResetMagickMemory(&pixel,0,sizeof(MagickPixelPacket));
339   for (y=0; y < (long) image->rows; y++)
340   {
341     p=GetVirtualPixels(uyvy_image,0,y,image->columns,1,&image->exception);
342     if (p == (const PixelPacket *) NULL)
343       break;
344     for (x=0; x < (long) image->columns; x++)
345     {
346       if (full != MagickFalse)
347         {
348           pixel.green=(pixel.green+p->green)/2;
349           pixel.blue=(pixel.blue+p->blue)/2;
350           (void) WriteBlobByte(image,ScaleQuantumToChar((Quantum) pixel.green));
351           (void) WriteBlobByte(image,ScaleQuantumToChar((Quantum) pixel.red));
352           (void) WriteBlobByte(image,ScaleQuantumToChar((Quantum) pixel.blue));
353           (void) WriteBlobByte(image,ScaleQuantumToChar(p->red));
354         }
355       pixel.red=(double) p->red;
356       pixel.green=(double) p->green;
357       pixel.blue=(double) p->blue;
358       full=full == MagickFalse ? MagickTrue : MagickFalse;
359       p++;
360     }
361     status=SetImageProgress(image,LoadImageTag,y,image->rows);
362     if (status == MagickFalse)
363       break;
364   }
365   uyvy_image=DestroyImage(uyvy_image);
366   (void) CloseBlob(image);
367   return(MagickTrue);
368 }