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