Commit message: https://github.com/ImageMagick/ImageMagick/issues/1199
CVE: CVE-2018-16643
CWE: CWE-252
Vulnerability description: The functions ReadDCMImage in coders/dcm.c, ReadPWPImage in coders/pwp.c, ReadCALSImage in coders/cals.c, and ReadPICTImage in coders/pict.c in ImageMagick 7.0.8-4 do not check the return value of the fputc function, which allows remote attackers to cause a denial of service via a crafted image file.

Project: ImageMagick6
File: pwp.c

static Image *ReadPWPImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
  char
    filename[MaxTextExtent];

  FILE
    *file;

  Image
    *image,
    *next_image,
    *pwp_image;

  ImageInfo
    *read_info;

  int
    c,
    unique_file;

  MagickBooleanType
    status;

  register Image
    *p;

  register ssize_t
    i;

  size_t
    filesize,
    length;

  ssize_t
    count;

  unsigned char
    magick[MaxTextExtent];

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  image=AcquireImage(image_info);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImage(image);
      return((Image *) NULL);
    }
  pwp_image=image;
  memset(magick,0,sizeof(magick));
  count=ReadBlob(pwp_image,5,magick);
  if ((count != 5) || (LocaleNCompare((char *) magick,"SFW95",5) != 0))
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
  read_info=CloneImageInfo(image_info);
  (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
    (void *) NULL);
  SetImageInfoBlob(read_info,(void *) NULL,0);
  unique_file=AcquireUniqueFileResource(filename);
  (void) FormatLocaleString(read_info->filename,MagickPathExtent,"sfw:%s",
    filename);
  for ( ; ; )
  {
    (void) memset(magick,0,sizeof(magick));
    for (c=ReadBlobByte(pwp_image); c != EOF; c=ReadBlobByte(pwp_image))
    {
      for (i=0; i < 17; i++)
        magick[i]=magick[i+1];
      magick[17]=(unsigned char) c;
      if (LocaleNCompare((char *) (magick+12),"SFW94A",6) == 0)
        break;
    }
    if (c == EOF)
      {
        (void) RelinquishUniqueFileResource(filename);
        read_info=DestroyImageInfo(read_info);
        ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
      }
    if (LocaleNCompare((char *) (magick+12),"SFW94A",6) != 0)
      {
        (void) RelinquishUniqueFileResource(filename);
        read_info=DestroyImageInfo(read_info);
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
      }
    /*
      Dump SFW image to a temporary file.
    */
    file=(FILE *) NULL;
    if (unique_file != -1)
      file=fdopen(unique_file,"wb");
    if ((unique_file == -1) || (file == (FILE *) NULL))
      {
        (void) RelinquishUniqueFileResource(filename);
        read_info=DestroyImageInfo(read_info);
        ThrowFileException(exception,FileOpenError,"UnableToWriteFile",
          image->filename);
        image=DestroyImageList(image);
        return((Image *) NULL);
      }
    length=fwrite("SFW94A",1,6,file);
    (void) length;
    filesize=65535UL*magick[2]+256L*magick[1]+magick[0];
    for (i=0; i < (ssize_t) filesize; i++)
    {
      c=ReadBlobByte(pwp_image);
      if (c == EOF)
        break;
      (void) fputc(c,file);
    }
    (void) fclose(file);
    if (c == EOF)
      {
        (void) RelinquishUniqueFileResource(filename);
        read_info=DestroyImageInfo(read_info);
        ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
      }
    next_image=ReadImage(read_info,exception);
    if (next_image == (Image *) NULL)
      break;
    (void) FormatLocaleString(next_image->filename,MaxTextExtent,
      "slide_%02ld.sfw",(long) next_image->scene);
    if (image == (Image *) NULL)
      image=next_image;
    else
      {
        /*
          Link image into image list.
        */
        for (p=image; p->next != (Image *) NULL; p=GetNextImageInList(p)) ;
        next_image->previous=p;
        next_image->scene=p->scene+1;
        p->next=next_image;
      }
    if (image_info->number_scenes != 0)
      if (next_image->scene >= (image_info->scene+image_info->number_scenes-1))
        break;
    status=SetImageProgress(image,LoadImagesTag,TellBlob(pwp_image),
      GetBlobSize(pwp_image));
    if (status == MagickFalse)
      break;
  }
  if (unique_file != -1)
    (void) close(unique_file);
  (void) RelinquishUniqueFileResource(filename);
  read_info=DestroyImageInfo(read_info);
  if (image != (Image *) NULL)
    {
      if (EOFBlob(image) != MagickFalse)
        {
          char
            *message;

          message=GetExceptionMessage(errno);
          (void) ThrowMagickException(exception,GetMagickModule(),
            CorruptImageError,"UnexpectedEndOfFile","`%s': %s",image->filename,
            message);
          message=DestroyString(message);
        }
      (void) CloseBlob(image);
    }
  return(GetFirstImageInList(image));
}

Project: ImageMagick6
File: cals.c

static Image *ReadCALSImage(const ImageInfo *image_info,
  ExceptionInfo *exception)
{
  char
    filename[MaxTextExtent],
    header[129],
    message[MaxTextExtent];

  FILE
    *file;

  Image
    *image;

  ImageInfo
    *read_info;

  int
    c,
    unique_file;

  MagickBooleanType
    status;

  register ssize_t
    i;

  unsigned long
    density,
    direction,
    height,
    orientation,
    pel_path,
    type,
    width;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  image=AcquireImage(image_info);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Read CALS header.
  */
  (void) memset(header,0,sizeof(header));
  density=0;
  direction=0;
  orientation=1;
  pel_path=0;
  type=1;
  width=0;
  height=0;
  for (i=0; i < 16; i++)
  {
    if (ReadBlob(image,128,(unsigned char *) header) != 128)
      break;
    switch (*header)
    {
      case 'R':
      case 'r':
      {
        if (LocaleNCompare(header,"rdensty:",8) == 0)
          {
            (void) sscanf(header+8,"%lu",&density);
            break;
          }
        if (LocaleNCompare(header,"rpelcnt:",8) == 0)
          {
            (void) sscanf(header+8,"%lu,%lu",&width,&height);
            break;
          }
        if (LocaleNCompare(header,"rorient:",8) == 0)
          {
            (void) sscanf(header+8,"%lu,%lu",&pel_path,&direction);
            if (pel_path == 90)
              orientation=5;
            else
              if (pel_path == 180)
                orientation=3;
              else
                if (pel_path == 270)
                  orientation=7;
            if (direction == 90)
              orientation++;
            break;
          }
        if (LocaleNCompare(header,"rtype:",6) == 0)
          {
            (void) sscanf(header+6,"%lu",&type);
            break;
          }
        break;
      }
    }
  }
  /*
    Read CALS pixels.
  */
  file=(FILE *) NULL;
  unique_file=AcquireUniqueFileResource(filename);
  if (unique_file != -1)
    file=fdopen(unique_file,"wb");
  if ((unique_file == -1) || (file == (FILE *) NULL))
    ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile");
  while ((c=ReadBlobByte(image)) != EOF)
    (void) fputc(c,file);
  (void) fclose(file);
  (void) CloseBlob(image);
  image=DestroyImage(image);
  read_info=CloneImageInfo(image_info);
  SetImageInfoBlob(read_info,(void *) NULL,0);
  (void) FormatLocaleString(read_info->filename,MaxTextExtent,"group4:%s",
    filename);
  (void) FormatLocaleString(message,MaxTextExtent,"%lux%lu",width,height);
  read_info->size=ConstantString(message);
  (void) FormatLocaleString(message,MaxTextExtent,"%lu",density);
  read_info->density=ConstantString(message);
  read_info->orientation=(OrientationType) orientation;
  image=ReadImage(read_info,exception);
  if (image != (Image *) NULL)
    {
      (void) CopyMagickString(image->filename,image_info->filename,
        MaxTextExtent);
      (void) CopyMagickString(image->magick_filename,image_info->filename,
        MaxTextExtent);
      (void) CopyMagickString(image->magick,"CALS",MaxTextExtent);
    }
  read_info=DestroyImageInfo(read_info);
  (void) RelinquishUniqueFileResource(filename);
  return(image);
}

Project: ImageMagick6
File: pict.c

static Image *ReadPICTImage(const ImageInfo *image_info,
  ExceptionInfo *exception)
{
#define ThrowPICTException(exception,message) \
{ \
  if (tile_image != (Image *) NULL) \
    tile_image=DestroyImage(tile_image); \
  if (read_info != (ImageInfo *) NULL) \
    read_info=DestroyImageInfo(read_info); \
  ThrowReaderException((exception),(message)); \
}

  char
    geometry[MaxTextExtent],
    header_ole[4];

  Image
    *image,
    *tile_image;

  ImageInfo
    *read_info;

  IndexPacket
    index;

  int
    c,
    code;

  MagickBooleanType
    jpeg,
    status;

  PICTRectangle
    frame;

  PICTPixmap
    pixmap;

  register IndexPacket
    *indexes;

  register ssize_t
    x;

  register PixelPacket
    *q;

  register ssize_t
    i;

  size_t
    extent,
    length;

  ssize_t
    count,
    flags,
    j,
    version,
    y;

  StringInfo
    *profile;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  image=AcquireImage(image_info);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Read PICT header.
  */
  read_info=(ImageInfo *) NULL;
  tile_image=(Image *) NULL;
  pixmap.bits_per_pixel=0;
  pixmap.component_count=0;
  /*
    Skip header : 512 for standard PICT and 4, ie "PICT" for OLE2
  */
  header_ole[0]=ReadBlobByte(image);
  header_ole[1]=ReadBlobByte(image);
  header_ole[2]=ReadBlobByte(image);
  header_ole[3]=ReadBlobByte(image);
  if (!((header_ole[0] == 0x50) && (header_ole[1] == 0x49) &&
      (header_ole[2] == 0x43) && (header_ole[3] == 0x54)))
    for (i=0; i < 508; i++)
      if (ReadBlobByte(image) == EOF)
        break;
  (void) ReadBlobMSBShort(image);  /* skip picture size */
  if (ReadRectangle(image,&frame) == MagickFalse)
    ThrowPICTException(CorruptImageError,"ImproperImageHeader");
  while ((c=ReadBlobByte(image)) == 0) ;
  if (c != 0x11)
    ThrowPICTException(CorruptImageError,"ImproperImageHeader");
  version=(ssize_t) ReadBlobByte(image);
  if (version == 2)
    {
      c=ReadBlobByte(image);
      if (c != 0xff)
        ThrowPICTException(CorruptImageError,"ImproperImageHeader");
    }
  else
    if (version != 1)
      ThrowPICTException(CorruptImageError,"ImproperImageHeader");
  if ((frame.left < 0) || (frame.right < 0) || (frame.top < 0) ||
      (frame.bottom < 0) || (frame.left >= frame.right) ||
      (frame.top >= frame.bottom))
    ThrowPICTException(CorruptImageError,"ImproperImageHeader");
  /*
    Create black canvas.
  */
  flags=0;
  image->depth=8;
  image->columns=(unsigned int) (frame.right-frame.left);
  image->rows=(unsigned int) (frame.bottom-frame.top);
  image->x_resolution=DefaultResolution;
  image->y_resolution=DefaultResolution;
  image->units=UndefinedResolution;
  if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
    if (image->scene >= (image_info->scene+image_info->number_scenes-1))
      {
        (void) CloseBlob(image);
        return(GetFirstImageInList(image));
      }
  status=SetImageExtent(image,image->columns,image->rows);
  if (status != MagickFalse)
    status=ResetImagePixels(image,exception);
  if (status == MagickFalse)
    {
      InheritException(exception,&image->exception);
      return(DestroyImageList(image));
    }
  /*
    Interpret PICT opcodes.
  */
  jpeg=MagickFalse;
  for (code=0; EOFBlob(image) == MagickFalse; )
  {
    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
        break;
    if ((version == 1) || ((TellBlob(image) % 2) != 0))
      code=ReadBlobByte(image);
    if (version == 2)
      code=ReadBlobMSBSignedShort(image);
    if (code < 0)
      break;
    if (code == 0)
      continue;
    if (code > 0xa1)
      {
        if (image->debug != MagickFalse)
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%04X:",code);
      }
    else
      {
        if (image->debug != MagickFalse)
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
            "  %04X %s: %s",code,codes[code].name,codes[code].description);
        switch (code)
        {
          case 0x01:
          {
            /*
              Clipping rectangle.
            */
            length=ReadBlobMSBShort(image);
            if (length != 0x000a)
              {
                for (i=0; i < (ssize_t) (length-2); i++)
                  if (ReadBlobByte(image) == EOF)
                    break;
                break;
              }
            if (ReadRectangle(image,&frame) == MagickFalse)
              ThrowPICTException(CorruptImageError,"ImproperImageHeader");
            if (((frame.left & 0x8000) != 0) || ((frame.top & 0x8000) != 0))
              break;
            image->columns=(size_t) (frame.right-frame.left);
            image->rows=(size_t) (frame.bottom-frame.top);
            status=SetImageExtent(image,image->columns,image->rows);
            if (status != MagickFalse)
              status=ResetImagePixels(image,&image->exception);
            if (status == MagickFalse)
              {
                InheritException(exception,&image->exception);
                return(DestroyImageList(image));
              }
            break;
          }
          case 0x12:
          case 0x13:
          case 0x14:
          {
            ssize_t
              pattern;

            size_t
              height,
              width;

            /*
              Skip pattern definition.
            */
            pattern=(ssize_t) ReadBlobMSBShort(image);
            for (i=0; i < 8; i++)
              if (ReadBlobByte(image) == EOF)
                break;
            if (pattern == 2)
              {
                for (i=0; i < 5; i++)
                  if (ReadBlobByte(image) == EOF)
                    break;
                break;
              }
            if (pattern != 1)
              ThrowPICTException(CorruptImageError,"UnknownPatternType");
            length=ReadBlobMSBShort(image);
            if (ReadRectangle(image,&frame) == MagickFalse)
              ThrowPICTException(CorruptImageError,"ImproperImageHeader");
            if (ReadPixmap(image,&pixmap) == MagickFalse)
              ThrowPICTException(CorruptImageError,"ImproperImageHeader");
            image->depth=(size_t) pixmap.component_size;
            image->x_resolution=1.0*pixmap.horizontal_resolution;
            image->y_resolution=1.0*pixmap.vertical_resolution;
            image->units=PixelsPerInchResolution;
            (void) ReadBlobMSBLong(image);
            flags=(ssize_t) ReadBlobMSBShort(image);
            length=ReadBlobMSBShort(image);
            for (i=0; i <= (ssize_t) length; i++)
              (void) ReadBlobMSBLong(image);
            width=(size_t) (frame.bottom-frame.top);
            height=(size_t) (frame.right-frame.left);
            if (pixmap.bits_per_pixel <= 8)
              length&=0x7fff;
            if (pixmap.bits_per_pixel == 16)
              width<<=1;
            if (length == 0)
              length=width;
            if (length < 8)
              {
                for (i=0; i < (ssize_t) (length*height); i++)
                  if (ReadBlobByte(image) == EOF)
                    break;
              }
            else
              for (i=0; i < (ssize_t) height; i++)
              {
                if (EOFBlob(image) != MagickFalse)
                  break;
                if (length > 200)
                  {
                    for (j=0; j < (ssize_t) ReadBlobMSBShort(image); j++)
                      if (ReadBlobByte(image) == EOF)
                        break;
                  }
                else
                  for (j=0; j < (ssize_t) ReadBlobByte(image); j++)
                    if (ReadBlobByte(image) == EOF)
                      break;
              }
            break;
          }
          case 0x1b:
          {
            /*
              Initialize image background color.
            */
            image->background_color.red=(Quantum)
              ScaleShortToQuantum(ReadBlobMSBShort(image));
            image->background_color.green=(Quantum)
              ScaleShortToQuantum(ReadBlobMSBShort(image));
            image->background_color.blue=(Quantum)
              ScaleShortToQuantum(ReadBlobMSBShort(image));
            break;
          }
          case 0x70:
          case 0x71:
          case 0x72:
          case 0x73:
          case 0x74:
          case 0x75:
          case 0x76:
          case 0x77:
          {
            /*
              Skip polygon or region.
            */
            length=ReadBlobMSBShort(image);
            for (i=0; i < (ssize_t) (length-2); i++)
              if (ReadBlobByte(image) == EOF)
                break;
            break;
          }
          case 0x90:
          case 0x91:
          case 0x98:
          case 0x99:
          case 0x9a:
          case 0x9b:
          {
            ssize_t
              bytes_per_line;

            PICTRectangle
              source,
              destination;

            register unsigned char
              *p;

            size_t
              j;

            unsigned char
              *pixels;

            /*
              Pixmap clipped by a rectangle.
            */
            bytes_per_line=0;
            if ((code != 0x9a) && (code != 0x9b))
              bytes_per_line=(ssize_t) ReadBlobMSBShort(image);
            else
              {
                (void) ReadBlobMSBShort(image);
                (void) ReadBlobMSBShort(image);
                (void) ReadBlobMSBShort(image);
              }
            if (ReadRectangle(image,&frame) == MagickFalse)
              ThrowPICTException(CorruptImageError,"ImproperImageHeader");
            /*
              Initialize tile image.
            */
            tile_image=CloneImage(image,(size_t) (frame.right-frame.left),
              (size_t) (frame.bottom-frame.top),MagickTrue,exception);
            if (tile_image == (Image *) NULL)
              ThrowPICTException(CorruptImageError,"ImproperImageHeader");
            if ((code == 0x9a) || (code == 0x9b) ||
                ((bytes_per_line & 0x8000) != 0))
              {
                if (ReadPixmap(image,&pixmap) == MagickFalse)
                  ThrowPICTException(CorruptImageError,"ImproperImageHeader");
                tile_image->depth=(size_t) pixmap.component_size;
                tile_image->matte=pixmap.component_count == 4 ?
                  MagickTrue : MagickFalse;
                tile_image->x_resolution=(double) pixmap.horizontal_resolution;
                tile_image->y_resolution=(double) pixmap.vertical_resolution;
                tile_image->units=PixelsPerInchResolution;
                if (tile_image->matte != MagickFalse)
                  (void) SetImageAlphaChannel(tile_image,OpaqueAlphaChannel);
              }
            if ((code != 0x9a) && (code != 0x9b))
              {
                /*
                  Initialize colormap.
                */
                tile_image->colors=2;
                if ((bytes_per_line & 0x8000) != 0)
                  {
                    (void) ReadBlobMSBLong(image);
                    flags=(ssize_t) ReadBlobMSBShort(image);
                    tile_image->colors=1UL*ReadBlobMSBShort(image)+1;
                  }
                status=AcquireImageColormap(tile_image,tile_image->colors);
                if (status == MagickFalse)
                  ThrowPICTException(ResourceLimitError,
                    "MemoryAllocationFailed");
                if ((bytes_per_line & 0x8000) != 0)
                  {
                    for (i=0; i < (ssize_t) tile_image->colors; i++)
                    {
                      j=ReadBlobMSBShort(image) % tile_image->colors;
                      if ((flags & 0x8000) != 0)
                        j=(size_t) i;
                      tile_image->colormap[j].red=(Quantum)
                        ScaleShortToQuantum(ReadBlobMSBShort(image));
                      tile_image->colormap[j].green=(Quantum)
                        ScaleShortToQuantum(ReadBlobMSBShort(image));
                      tile_image->colormap[j].blue=(Quantum)
                        ScaleShortToQuantum(ReadBlobMSBShort(image));
                    }
                  }
                else
                  {
                    for (i=0; i < (ssize_t) tile_image->colors; i++)
                    {
                      tile_image->colormap[i].red=(Quantum) (QuantumRange-
                        tile_image->colormap[i].red);
                      tile_image->colormap[i].green=(Quantum) (QuantumRange-
                        tile_image->colormap[i].green);
                      tile_image->colormap[i].blue=(Quantum) (QuantumRange-
                        tile_image->colormap[i].blue);
                    }
                  }
              }
            if (EOFBlob(image) != MagickFalse)
              ThrowPICTException(CorruptImageError,
                "InsufficientImageDataInFile");
            if (ReadRectangle(image,&source) == MagickFalse)
              ThrowPICTException(CorruptImageError,"ImproperImageHeader");
            if (ReadRectangle(image,&destination) == MagickFalse)
              ThrowPICTException(CorruptImageError,"ImproperImageHeader");
            (void) ReadBlobMSBShort(image);
            if ((code == 0x91) || (code == 0x99) || (code == 0x9b))
              {
                /*
                  Skip region.
                */
                length=ReadBlobMSBShort(image);
                for (i=0; i < (ssize_t) (length-2); i++)
                  if (ReadBlobByte(image) == EOF)
                    break;
              }
            if ((code != 0x9a) && (code != 0x9b) &&
                (bytes_per_line & 0x8000) == 0)
              pixels=DecodeImage(image,tile_image,(size_t) bytes_per_line,1,
                &extent);
            else
              pixels=DecodeImage(image,tile_image,(unsigned int) bytes_per_line,
                (unsigned int) pixmap.bits_per_pixel,&extent);
            if (pixels == (unsigned char *) NULL)
              ThrowPICTException(CorruptImageError,"UnableToUncompressImage");
            /*
              Convert PICT tile image to pixel packets.
            */
            p=pixels;
            for (y=0; y < (ssize_t) tile_image->rows; y++)
            {
              if (p > (pixels+extent+image->columns))
                {
                  pixels=(unsigned char *) RelinquishMagickMemory(pixels);
                  ThrowPICTException(CorruptImageError,"NotEnoughPixelData");
                }
              q=QueueAuthenticPixels(tile_image,0,y,tile_image->columns,1,
                exception);
              if (q == (PixelPacket *) NULL)
                break;
              indexes=GetAuthenticIndexQueue(tile_image);
              for (x=0; x < (ssize_t) tile_image->columns; x++)
              {
                if (tile_image->storage_class == PseudoClass)
                  {
                    index=ConstrainColormapIndex(tile_image,*p);
                    SetPixelIndex(indexes+x,index);
                    SetPixelRed(q,
                      tile_image->colormap[(ssize_t) index].red);
                    SetPixelGreen(q,
                      tile_image->colormap[(ssize_t) index].green);
                    SetPixelBlue(q,
                      tile_image->colormap[(ssize_t) index].blue);
                  }
                else
                  {
                    if (pixmap.bits_per_pixel == 16)
                      {
                        i=(ssize_t) (*p++);
                        j=(*p);
                        SetPixelRed(q,ScaleCharToQuantum(
                          (unsigned char) ((i & 0x7c) << 1)));
                        SetPixelGreen(q,ScaleCharToQuantum(
                          (unsigned char) (((i & 0x03) << 6) |
                          ((j & 0xe0) >> 2))));
                        SetPixelBlue(q,ScaleCharToQuantum(
                          (unsigned char) ((j & 0x1f) << 3)));
                      }
                    else
                      if (tile_image->matte == MagickFalse)
                        {
                          if (p > (pixels+extent+2*image->columns))
                            ThrowPICTException(CorruptImageError,
                              "NotEnoughPixelData");
                          SetPixelRed(q,ScaleCharToQuantum(*p));
                          SetPixelGreen(q,ScaleCharToQuantum(
                            *(p+tile_image->columns)));
                          SetPixelBlue(q,ScaleCharToQuantum(
                            *(p+2*tile_image->columns)));
                        }
                      else
                        {
                          if (p > (pixels+extent+3*image->columns))
                            ThrowPICTException(CorruptImageError,
                              "NotEnoughPixelData");
                          SetPixelAlpha(q,ScaleCharToQuantum(*p));
                          SetPixelRed(q,ScaleCharToQuantum(
                            *(p+tile_image->columns)));
                          SetPixelGreen(q,ScaleCharToQuantum(
                            *(p+2*tile_image->columns)));
                          SetPixelBlue(q,ScaleCharToQuantum(
                            *(p+3*tile_image->columns)));
                        }
                  }
                p++;
                q++;
              }
              if (SyncAuthenticPixels(tile_image,exception) == MagickFalse)
                break;
              if ((tile_image->storage_class == DirectClass) &&
                  (pixmap.bits_per_pixel != 16))
                {
                  p+=(pixmap.component_count-1)*tile_image->columns;
                  if (p < pixels)
                    break;
                }
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                tile_image->rows);
              if (status == MagickFalse)
                break;
            }
            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
            if ((jpeg == MagickFalse) && (EOFBlob(image) == MagickFalse))
              if ((code == 0x9a) || (code == 0x9b) ||
                  ((bytes_per_line & 0x8000) != 0))
                (void) CompositeImage(image,CopyCompositeOp,tile_image,
                  (ssize_t) destination.left,(ssize_t) destination.top);
            tile_image=DestroyImage(tile_image);
            break;
          }
          case 0xa1:
          {
            unsigned char
              *info;

            size_t
              type;

            /*
              Comment.
            */
            type=ReadBlobMSBShort(image);
            length=ReadBlobMSBShort(image);
            if (length == 0)
              break;
            (void) ReadBlobMSBLong(image);
            length-=MagickMin(length,4);
            if (length == 0)
              break;
            info=(unsigned char *) AcquireQuantumMemory(length,sizeof(*info));
            if (info == (unsigned char *) NULL)
              break;
            count=ReadBlob(image,length,info);
            if (count != (ssize_t) length)
              {
                info=(unsigned char *) RelinquishMagickMemory(info);
                ThrowPICTException(ResourceLimitError,"UnableToReadImageData");
              }
            switch (type)
            {
              case 0xe0:
              {
                profile=BlobToStringInfo((const void *) NULL,length);
                SetStringInfoDatum(profile,info);
                status=SetImageProfile(image,"icc",profile);
                profile=DestroyStringInfo(profile);
                if (status == MagickFalse)
                  {
                    info=(unsigned char *) RelinquishMagickMemory(info);
                    ThrowPICTException(ResourceLimitError,
                      "MemoryAllocationFailed");
                  }
                break;
              }
              case 0x1f2:
              {
                profile=BlobToStringInfo((const void *) NULL,length);
                SetStringInfoDatum(profile,info);
                status=SetImageProfile(image,"iptc",profile);
                if (status == MagickFalse)
                  {
                    info=(unsigned char *) RelinquishMagickMemory(info);
                    ThrowPICTException(ResourceLimitError,
                      "MemoryAllocationFailed");
                  }
                profile=DestroyStringInfo(profile);
                break;
              }
              default:
                break;
            }
            info=(unsigned char *) RelinquishMagickMemory(info);
            break;
          }
          default:
          {
            /*
              Skip to next op code.
            */
            if (codes[code].length == -1)
              (void) ReadBlobMSBShort(image);
            else
              for (i=0; i < (ssize_t) codes[code].length; i++)
                if (ReadBlobByte(image) == EOF)
                  break;
          }
        }
      }
    if (code == 0xc00)
      {
        /*
          Skip header.
        */
        for (i=0; i < 24; i++)
          if (ReadBlobByte(image) == EOF)
            break;
        continue;
      }
    if (((code >= 0xb0) && (code <= 0xcf)) ||
        ((code >= 0x8000) && (code <= 0x80ff)))
      continue;
    if (code == 0x8200)
      {
        char
          filename[MaxTextExtent];

        FILE
          *file;

        int
          unique_file;

        /*
          Embedded JPEG.
        */
        jpeg=MagickTrue;
        read_info=CloneImageInfo(image_info);
        SetImageInfoBlob(read_info,(void *) NULL,0);
        file=(FILE *) NULL;
        unique_file=AcquireUniqueFileResource(filename);
        (void) FormatLocaleString(read_info->filename,MaxTextExtent,"jpeg:%s",
          filename);
        if (unique_file != -1)
          file=fdopen(unique_file,"wb");
        if ((unique_file == -1) || (file == (FILE *) NULL))
          {
            (void) RelinquishUniqueFileResource(read_info->filename);
            (void) CopyMagickString(image->filename,read_info->filename,
              MaxTextExtent);
            ThrowPICTException(FileOpenError,"UnableToCreateTemporaryFile");
          }
        length=ReadBlobMSBLong(image);
        if (length > 154)
          {
            for (i=0; i < 6; i++)
              (void) ReadBlobMSBLong(image);
            if (ReadRectangle(image,&frame) == MagickFalse)
              {
                (void) fclose(file);
                (void) RelinquishUniqueFileResource(read_info->filename);
                ThrowPICTException(CorruptImageError,"ImproperImageHeader");
              }
            for (i=0; i < 122; i++)
              if (ReadBlobByte(image) == EOF)
                break;
            for (i=0; i < (ssize_t) (length-154); i++)
            {
              c=ReadBlobByte(image);
              if (c == EOF)
                break;
              (void) fputc(c,file);
            }
          }
        (void) fclose(file);
        (void) close(unique_file);
        tile_image=ReadImage(read_info,exception);
        (void) RelinquishUniqueFileResource(filename);
        read_info=DestroyImageInfo(read_info);
        if (tile_image == (Image *) NULL)
          continue;
        (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g",
          (double) MagickMax(image->columns,tile_image->columns),
          (double) MagickMax(image->rows,tile_image->rows));
        (void) SetImageExtent(image,
          MagickMax(image->columns,tile_image->columns),
          MagickMax(image->rows,tile_image->rows));
        (void) TransformImageColorspace(image,tile_image->colorspace);
        (void) CompositeImage(image,CopyCompositeOp,tile_image,(ssize_t)
          frame.left,(ssize_t) frame.right);
        image->compression=tile_image->compression;
        tile_image=DestroyImage(tile_image);
        continue;
      }
    if ((code == 0xff) || (code == 0xffff))
      break;
    if (((code >= 0xd0) && (code <= 0xfe)) ||
        ((code >= 0x8100) && (code <= 0xffff)))
      {
        /*
          Skip reserved.
        */
        length=ReadBlobMSBShort(image);
        for (i=0; i < (ssize_t) length; i++)
          if (ReadBlobByte(image) == EOF)
            break;
        continue;
      }
    if ((code >= 0x100) && (code <= 0x7fff))
      {
        /*
          Skip reserved.
        */
        length=(size_t) ((code >> 7) & 0xff);
        for (i=0; i < (ssize_t) length; i++)
          if (ReadBlobByte(image) == EOF)
            break;
        continue;
      }
  }
  (void) CloseBlob(image);
  return(GetFirstImageInList(image));
}

Project: ImageMagick6
File: dcm.c

static Image *ReadDCMImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
#define ThrowDCMException(exception,message) \
{ \
  if (info.scale != (Quantum *) NULL) \
    info.scale=(Quantum *) RelinquishMagickMemory(info.scale); \
  if (data != (unsigned char *) NULL) \
    data=(unsigned char *) RelinquishMagickMemory(data); \
  if (graymap != (int *) NULL) \
    graymap=(int *) RelinquishMagickMemory(graymap); \
  if (bluemap != (int *) NULL) \
    bluemap=(int *) RelinquishMagickMemory(bluemap); \
  if (greenmap != (int *) NULL) \
    greenmap=(int *) RelinquishMagickMemory(greenmap); \
  if (redmap != (int *) NULL) \
    redmap=(int *) RelinquishMagickMemory(redmap); \
  if (stream_info->offsets != (ssize_t *) NULL) \
    stream_info->offsets=(ssize_t *) RelinquishMagickMemory( \
      stream_info->offsets); \
  if (stream_info != (DCMStreamInfo *) NULL) \
    stream_info=(DCMStreamInfo *) RelinquishMagickMemory(stream_info); \
  ThrowReaderException((exception),(message)); \
}

  char
    explicit_vr[MaxTextExtent],
    implicit_vr[MaxTextExtent],
    magick[MaxTextExtent],
    photometric[MaxTextExtent];

  DCMInfo
    info;

  DCMStreamInfo
    *stream_info;

  Image
    *image;

  int
    *bluemap,
    datum,
    *greenmap,
    *graymap,
    *redmap;

  MagickBooleanType
    explicit_file,
    explicit_retry,
    use_explicit;

  MagickOffsetType
    offset;

  register unsigned char
    *p;

  register ssize_t
    i;

  size_t
    colors,
    height,
    length,
    number_scenes,
    quantum,
    status,
    width;

  ssize_t
    count,
    scene;

  unsigned char
    *data;

  unsigned short
    group,
    element;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  image=AcquireImage(image_info);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    return(DestroyImageList(image));
  image->depth=8UL;
  image->endian=LSBEndian;
  /*
    Read DCM preamble.
  */
  (void) memset(&info,0,sizeof(info));
  data=(unsigned char *) NULL;
  graymap=(int *) NULL;
  redmap=(int *) NULL;
  greenmap=(int *) NULL;
  bluemap=(int *) NULL;
  stream_info=(DCMStreamInfo *) AcquireMagickMemory(sizeof(*stream_info));
  if (stream_info == (DCMStreamInfo *) NULL)
    ThrowDCMException(ResourceLimitError,"MemoryAllocationFailed");
  (void) memset(stream_info,0,sizeof(*stream_info));
  count=ReadBlob(image,128,(unsigned char *) magick);
  if (count != 128)
    ThrowDCMException(CorruptImageError,"ImproperImageHeader");
  count=ReadBlob(image,4,(unsigned char *) magick);
  if ((count != 4) || (LocaleNCompare(magick,"DICM",4) != 0))
    {
      offset=SeekBlob(image,0L,SEEK_SET);
      if (offset < 0)
        ThrowDCMException(CorruptImageError,"ImproperImageHeader");
    }
  /*
    Read DCM Medical image.
  */
  (void) CopyMagickString(photometric,"MONOCHROME1 ",MaxTextExtent);
  info.bits_allocated=8;
  info.bytes_per_pixel=1;
  info.depth=8;
  info.mask=0xffff;
  info.max_value=255UL;
  info.samples_per_pixel=1;
  info.signed_data=(~0UL);
  info.rescale_slope=1.0;
  data=(unsigned char *) NULL;
  element=0;
  explicit_vr[2]='\0';
  explicit_file=MagickFalse;
  colors=0;
  redmap=(int *) NULL;
  greenmap=(int *) NULL;
  bluemap=(int *) NULL;
  graymap=(int *) NULL;
  height=0;
  number_scenes=1;
  use_explicit=MagickFalse;
  explicit_retry = MagickFalse;
  width=0;
  while (TellBlob(image) < (MagickOffsetType) GetBlobSize(image))
  {
    for (group=0; (group != 0x7FE0) || (element != 0x0010) ; )
    {
      /*
        Read a group.
      */
      image->offset=(ssize_t) TellBlob(image);
      group=ReadBlobLSBShort(image);
      element=ReadBlobLSBShort(image);
      if ((group == 0xfffc) && (element == 0xfffc))
        break;
      if ((group != 0x0002) && (image->endian == MSBEndian))
        {
          group=(unsigned short) ((group << 8) | ((group >> 8) & 0xFF));
          element=(unsigned short) ((element << 8) | ((element >> 8) & 0xFF));
        }
      quantum=0;
      /*
        Find corresponding VR for this group and element.
      */
      for (i=0; dicom_info[i].group < 0xffff; i++)
        if ((group == dicom_info[i].group) &&
            (element == dicom_info[i].element))
          break;
      (void) CopyMagickString(implicit_vr,dicom_info[i].vr,MaxTextExtent);
      count=ReadBlob(image,2,(unsigned char *) explicit_vr);
      if (count != 2)
        ThrowDCMException(CorruptImageError,"ImproperImageHeader");
      /*
        Check for "explicitness", but meta-file headers always explicit.
      */
      if ((explicit_file == MagickFalse) && (group != 0x0002))
        explicit_file=(isupper((unsigned char) *explicit_vr) != MagickFalse) &&
          (isupper((unsigned char) *(explicit_vr+1)) != MagickFalse) ?
          MagickTrue : MagickFalse;
      use_explicit=((group == 0x0002) && (explicit_retry == MagickFalse)) ||
        (explicit_file != MagickFalse) ? MagickTrue : MagickFalse;
      if ((use_explicit != MagickFalse) && (strncmp(implicit_vr,"xs",2) == 0))
        (void) CopyMagickString(implicit_vr,explicit_vr,MaxTextExtent);
      if ((use_explicit == MagickFalse) || (strncmp(implicit_vr,"!!",2) == 0))
        {
          offset=SeekBlob(image,(MagickOffsetType) -2,SEEK_CUR);
          if (offset < 0)
            ThrowDCMException(CorruptImageError,"ImproperImageHeader");
          quantum=4;
        }
      else
        {
          /*
            Assume explicit type.
          */
          quantum=2;
          if ((strncmp(explicit_vr,"OB",2) == 0) ||
              (strncmp(explicit_vr,"UN",2) == 0) ||
              (strncmp(explicit_vr,"OW",2) == 0) ||
              (strncmp(explicit_vr,"SQ",2) == 0))
            {
              (void) ReadBlobLSBShort(image);
              quantum=4;
            }
        }
      datum=0;
      if (quantum == 4)
        {
          if (group == 0x0002)
            datum=ReadBlobLSBSignedLong(image);
          else
            datum=ReadBlobSignedLong(image);
        }
      else
        if (quantum == 2)
          {
            if (group == 0x0002)
              datum=ReadBlobLSBSignedShort(image);
            else
              datum=ReadBlobSignedShort(image);
          }
      quantum=0;
      length=1;
      if (datum != 0)
        {
          if ((strncmp(implicit_vr,"OW",2) == 0) ||
              (strncmp(implicit_vr,"SS",2) == 0) ||
              (strncmp(implicit_vr,"US",2) == 0))
            quantum=2;
          else
            if ((strncmp(implicit_vr,"FL",2) == 0) ||
                (strncmp(implicit_vr,"OF",2) == 0) ||
                (strncmp(implicit_vr,"SL",2) == 0) ||
                (strncmp(implicit_vr,"UL",2) == 0))
              quantum=4;
            else
              if (strncmp(implicit_vr,"FD",2) == 0)
                quantum=8;
              else
                quantum=1;
          if (datum != ~0)
            length=(size_t) datum/quantum;
          else
            {
              /*
                Sequence and item of undefined length.
              */
              quantum=0;
              length=0;
            }
        }
      if (image_info->verbose != MagickFalse)
        {
          /*
            Display Dicom info.
          */
          if (use_explicit == MagickFalse)
            explicit_vr[0]='\0';
          for (i=0; dicom_info[i].description != (char *) NULL; i++)
            if ((group == dicom_info[i].group) &&
                (element == dicom_info[i].element))
              break;
          (void) FormatLocaleFile(stdout,"0x%04lX %4ld %s-%s (0x%04lx,0x%04lx)",
            (unsigned long) image->offset,(long) length,implicit_vr,explicit_vr,
            (unsigned long) group,(unsigned long) element);
          if (dicom_info[i].description != (char *) NULL)
            (void) FormatLocaleFile(stdout," %s",dicom_info[i].description);
          (void) FormatLocaleFile(stdout,": ");
        }
      if ((group == 0x7FE0) && (element == 0x0010))
        {
          if (image_info->verbose != MagickFalse)
            (void) FormatLocaleFile(stdout,"\n");
          break;
        }
      /*
        Allocate space and read an array.
      */
      data=(unsigned char *) NULL;
      if ((length == 1) && (quantum == 1))
        datum=ReadBlobByte(image);
      else
        if ((length == 1) && (quantum == 2))
          {
            if (group == 0x0002)
              datum=ReadBlobLSBSignedShort(image);
            else
              datum=ReadBlobSignedShort(image);
          }
        else
          if ((length == 1) && (quantum == 4))
            {
              if (group == 0x0002)
                datum=ReadBlobLSBSignedLong(image);
              else
                datum=ReadBlobSignedLong(image);
            }
          else
            if ((quantum != 0) && (length != 0))
              {
                if (length > (size_t) GetBlobSize(image))
                  ThrowDCMException(CorruptImageError,
                    "InsufficientImageDataInFile");
                if (~length >= 1)
                  data=(unsigned char *) AcquireQuantumMemory(length+1,quantum*
                    sizeof(*data));
                if (data == (unsigned char *) NULL)
                  ThrowDCMException(ResourceLimitError,
                    "MemoryAllocationFailed");
                count=ReadBlob(image,(size_t) quantum*length,data);
                if (count != (ssize_t) (quantum*length))
                  {
                    if (image_info->verbose != MagickFalse)
                      (void) FormatLocaleFile(stdout,"count=%d quantum=%d "
                        "length=%d group=%d\n",(int) count,(int) quantum,(int)
                        length,(int) group);
                     ThrowDCMException(CorruptImageError,
                       "InsufficientImageDataInFile");
                  }
                data[length*quantum]='\0';
              }
      if ((((unsigned int) group << 16) | element) == 0xFFFEE0DD)
        {
          if (data != (unsigned char *) NULL)
            data=(unsigned char *) RelinquishMagickMemory(data);
          continue;
        }
      switch (group)
      {
        case 0x0002:
        {
          switch (element)
          {
            case 0x0010:
            {
              char
                transfer_syntax[MaxTextExtent];

              /*
                Transfer Syntax.
              */
              if ((datum == 0) && (explicit_retry == MagickFalse))
                {
                  explicit_retry=MagickTrue;
                  (void) SeekBlob(image,(MagickOffsetType) 0,SEEK_SET);
                  group=0;
                  element=0;
                  if (image_info->verbose != MagickFalse)
                    (void) FormatLocaleFile(stdout,
                      "Corrupted image - trying explicit format\n");
                  break;
                }
              *transfer_syntax='\0';
              if (data != (unsigned char *) NULL)
                (void) CopyMagickString(transfer_syntax,(char *) data,
                  MaxTextExtent);
              if (image_info->verbose != MagickFalse)
                (void) FormatLocaleFile(stdout,"transfer_syntax=%s\n",
                  (const char *) transfer_syntax);
              if (strncmp(transfer_syntax,"1.2.840.10008.1.2",17) == 0)
                {
                  int
                    count,
                    subtype,
                    type;

                  type=1;
                  subtype=0;
                  if (strlen(transfer_syntax) > 17)
                    {
                      count=sscanf(transfer_syntax+17,".%d.%d",&type,&subtype);
                      if (count < 1)
                        ThrowDCMException(CorruptImageError,
                          "ImproperImageHeader");
                    }
                  switch (type)
                  {
                    case 1:
                    {
                      image->endian=LSBEndian;
                      break;
                    }
                    case 2:
                    {
                      image->endian=MSBEndian;
                      break;
                    }
                    case 4:
                    {
                      if ((subtype >= 80) && (subtype <= 81))
                        image->compression=JPEGCompression;
                      else
                        if ((subtype >= 90) && (subtype <= 93))
                          image->compression=JPEG2000Compression;
                        else
                          image->compression=JPEGCompression;
                      break;
                    }
                    case 5:
                    {
                      image->compression=RLECompression;
                      break;
                    }
                  }
                }
              break;
            }
            default:
              break;
          }
          break;
        }
        case 0x0028:
        {
          switch (element)
          {
            case 0x0002:
            {
              /*
                Samples per pixel.
              */
              info.samples_per_pixel=(size_t) datum;
              if ((info.samples_per_pixel == 0) || (info.samples_per_pixel > 4))
                ThrowDCMException(CorruptImageError,"ImproperImageHeader");
              break;
            }
            case 0x0004:
            {
              /*
                Photometric interpretation.
              */
              if (data == (unsigned char *) NULL)
                break;
              for (i=0; i < (ssize_t) MagickMin(length,MaxTextExtent-1); i++)
                photometric[i]=(char) data[i];
              photometric[i]='\0';
              info.polarity=LocaleCompare(photometric,"MONOCHROME1 ") == 0 ?
                MagickTrue : MagickFalse;
              break;
            }
            case 0x0006:
            {
              /*
                Planar configuration.
              */
              if (datum == 1)
                image->interlace=PlaneInterlace;
              break;
            }
            case 0x0008:
            {
              /*
                Number of frames.
              */
              if (data == (unsigned char *) NULL)
                break;
              number_scenes=StringToUnsignedLong((char *) data);
              break;
            }
            case 0x0010:
            {
              /*
                Image rows.
              */
              height=(size_t) datum;
              break;
            }
            case 0x0011:
            {
              /*
                Image columns.
              */
              width=(size_t) datum;
              break;
            }
            case 0x0100:
            {
              /*
                Bits allocated.
              */
              info.bits_allocated=(size_t) datum;
              info.bytes_per_pixel=1;
              if (datum > 8)
                info.bytes_per_pixel=2;
              info.depth=info.bits_allocated;
              if ((info.depth == 0) || (info.depth > 32))
                ThrowDCMException(CorruptImageError,"ImproperImageHeader");
              info.max_value=(1UL << info.bits_allocated)-1;
              image->depth=info.depth;
              break;
            }
            case 0x0101:
            {
              /*
                Bits stored.
              */
              info.significant_bits=(size_t) datum;
              info.bytes_per_pixel=1;
              if (info.significant_bits > 8)
                info.bytes_per_pixel=2;
              info.depth=info.significant_bits;
              if ((info.depth == 0) || (info.depth > 16))
                ThrowDCMException(CorruptImageError,"ImproperImageHeader");
              info.max_value=(1UL << info.significant_bits)-1;
              info.mask=(size_t) GetQuantumRange(info.significant_bits);
              image->depth=info.depth;
              break;
            }
            case 0x0102:
            {
              /*
                High bit.
              */
              break;
            }
            case 0x0103:
            {
              /*
                Pixel representation.
              */
              info.signed_data=(size_t) datum;
              break;
            }
            case 0x1050:
            {
              /*
                Visible pixel range: center.
              */
              if (data != (unsigned char *) NULL)
                info.window_center=StringToDouble((char *) data,
                  (char **) NULL);
              break;
            }
            case 0x1051:
            {
              /*
                Visible pixel range: width.
              */
              if (data != (unsigned char *) NULL)
                info.window_width=StringToDouble((char *) data,
                  (char **) NULL);
              break;
            }
            case 0x1052:
            {
              /*
                Rescale intercept
              */
              if (data != (unsigned char *) NULL)
                info.rescale_intercept=StringToDouble((char *) data,
                  (char **) NULL);
              break;
            }
            case 0x1053:
            {
              /*
                Rescale slope
              */
              if (data != (unsigned char *) NULL)
                info.rescale_slope=StringToDouble((char *) data,
                  (char **) NULL);
              break;
            }
            case 0x1200:
            case 0x3006:
            {
              /*
                Populate graymap.
              */
              if (data == (unsigned char *) NULL)
                break;
              colors=(size_t) (length/info.bytes_per_pixel);
              datum=(int) colors;
              if (graymap != (int *) NULL)
                graymap=(int *) RelinquishMagickMemory(graymap);
              graymap=(int *) AcquireQuantumMemory(MagickMax(colors,65536),
                sizeof(*graymap));
              if (graymap == (int *) NULL)
                ThrowDCMException(ResourceLimitError,"MemoryAllocationFailed");
              (void) memset(graymap,0,MagickMax(colors,65536)*
                sizeof(*graymap));
              for (i=0; i < (ssize_t) colors; i++)
                if (info.bytes_per_pixel == 1)
                  graymap[i]=(int) data[i];
                else
                  graymap[i]=(int) ((short *) data)[i];
              break;
            }
            case 0x1201:
            {
              unsigned short
                index;

              /*
                Populate redmap.
              */
              if (data == (unsigned char *) NULL)
                break;
              colors=(size_t) (length/2);
              datum=(int) colors;
              if (redmap != (int *) NULL)
                redmap=(int *) RelinquishMagickMemory(redmap);
              redmap=(int *) AcquireQuantumMemory(MagickMax(colors,65536),
                sizeof(*redmap));
              if (redmap == (int *) NULL)
                ThrowDCMException(ResourceLimitError,"MemoryAllocationFailed");
              (void) memset(redmap,0,MagickMax(colors,65536)*
                sizeof(*redmap));
              p=data;
              for (i=0; i < (ssize_t) colors; i++)
              {
                if (image->endian == MSBEndian)
                  index=(unsigned short) ((*p << 8) | *(p+1));
                else
                  index=(unsigned short) (*p | (*(p+1) << 8));
                redmap[i]=(int) index;
                p+=2;
              }
              break;
            }
            case 0x1202:
            {
              unsigned short
                index;

              /*
                Populate greenmap.
              */
              if (data == (unsigned char *) NULL)
                break;
              colors=(size_t) (length/2);
              datum=(int) colors;
              if (greenmap != (int *) NULL)
                greenmap=(int *) RelinquishMagickMemory(greenmap);
              greenmap=(int *) AcquireQuantumMemory(MagickMax(colors,65536),
                sizeof(*greenmap));
              if (greenmap == (int *) NULL)
                ThrowDCMException(ResourceLimitError,"MemoryAllocationFailed");
              (void) memset(greenmap,0,MagickMax(colors,65536)*
                sizeof(*greenmap));
              p=data;
              for (i=0; i < (ssize_t) colors; i++)
              {
                if (image->endian == MSBEndian)
                  index=(unsigned short) ((*p << 8) | *(p+1));
                else
                  index=(unsigned short) (*p | (*(p+1) << 8));
                greenmap[i]=(int) index;
                p+=2;
              }
              break;
            }
            case 0x1203:
            {
              unsigned short
                index;

              /*
                Populate bluemap.
              */
              if (data == (unsigned char *) NULL)
                break;
              colors=(size_t) (length/2);
              datum=(int) colors;
              if (bluemap != (int *) NULL)
                bluemap=(int *) RelinquishMagickMemory(bluemap);
              bluemap=(int *) AcquireQuantumMemory(MagickMax(colors,65536),
                sizeof(*bluemap));
              if (bluemap == (int *) NULL)
                ThrowDCMException(ResourceLimitError,"MemoryAllocationFailed");
              (void) memset(bluemap,0,MagickMax(colors,65536)*
                sizeof(*bluemap));
              p=data;
              for (i=0; i < (ssize_t) colors; i++)
              {
                if (image->endian == MSBEndian)
                  index=(unsigned short) ((*p << 8) | *(p+1));
                else
                  index=(unsigned short) (*p | (*(p+1) << 8));
                bluemap[i]=(int) index;
                p+=2;
              }
              break;
            }
            default:
              break;
          }
          break;
        }
        case 0x2050:
        {
          switch (element)
          {
            case 0x0020:
            {
              if ((data != (unsigned char *) NULL) &&
                  (strncmp((char *) data,"INVERSE",7) == 0))
                info.polarity=MagickTrue;
              break;
            }
            default:
              break;
          }
          break;
        }
        default:
          break;
      }
      if (data != (unsigned char *) NULL)
        {
          char
            *attribute;

          for (i=0; dicom_info[i].description != (char *) NULL; i++)
            if ((group == dicom_info[i].group) &&
                (element == dicom_info[i].element))
              break;
          if (dicom_info[i].description != (char *) NULL)
            {
              attribute=AcquireString("dcm:");
              (void) ConcatenateString(&attribute,dicom_info[i].description);
              for (i=0; i < (ssize_t) MagickMax(length,4); i++)
                if (isprint((int) data[i]) == MagickFalse)
                  break;
              if ((i == (ssize_t) length) || (length > 4))
                {
                  (void) SubstituteString(&attribute," ","");
                  (void) SetImageProperty(image,attribute,(char *) data);
                }
              attribute=DestroyString(attribute);
            }
        }
      if (image_info->verbose != MagickFalse)
        {
          if (data == (unsigned char *) NULL)
            (void) FormatLocaleFile(stdout,"%d\n",datum);
          else
            {
              /*
                Display group data.
              */
              for (i=0; i < (ssize_t) MagickMax(length,4); i++)
                if (isprint((int) data[i]) == MagickFalse)
                  break;
              if ((i != (ssize_t) length) && (length <= 4))
                {
                  ssize_t
                    j;

                  datum=0;
                  for (j=(ssize_t) length-1; j >= 0; j--)
                    datum=(256*datum+data[j]);
                  (void) FormatLocaleFile(stdout,"%d",datum);
                }
              else
                for (i=0; i < (ssize_t) length; i++)
                  if (isprint((int) data[i]) != MagickFalse)
                    (void) FormatLocaleFile(stdout,"%c",data[i]);
                  else
                    (void) FormatLocaleFile(stdout,"%c",'.');
              (void) FormatLocaleFile(stdout,"\n");
            }
        }
      if (data != (unsigned char *) NULL)
        data=(unsigned char *) RelinquishMagickMemory(data);
      if (EOFBlob(image) != MagickFalse)
        {
          ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
            image->filename);
          break;
        }
    }
    if ((group == 0xfffc) && (element == 0xfffc))
      {
        Image
          *last;

        last=RemoveLastImageFromList(&image);
        if (last != (Image *) NULL)
          last=DestroyImage(last);
        break;
      }
    if ((width == 0) || (height == 0))
      ThrowDCMException(CorruptImageError,"ImproperImageHeader");
    image->columns=(size_t) width;
    image->rows=(size_t) height;
    if (info.signed_data == 0xffff)
      info.signed_data=(size_t) (info.significant_bits == 16 ? 1 : 0);
    if ((image->compression == JPEGCompression) ||
        (image->compression == JPEG2000Compression))
      {
        Image
          *images;

        ImageInfo
          *read_info;

        int
          c;

        size_t
          length;

        /*
          Read offset table.
        */
        for (i=0; i < (ssize_t) stream_info->remaining; i++)
          if (ReadBlobByte(image) == EOF)
            break;
        (void) (((ssize_t) ReadBlobLSBShort(image) << 16) |
          ReadBlobLSBShort(image));
        length=(size_t) ReadBlobLSBLong(image);
        if (length > (size_t) GetBlobSize(image))
          ThrowDCMException(CorruptImageError,"InsufficientImageDataInFile");
        stream_info->offset_count=length >> 2;
        if (stream_info->offset_count != 0)
          {
            MagickOffsetType
              offset;

            if (stream_info->offsets != (ssize_t *) NULL)
              stream_info->offsets=(ssize_t *) RelinquishMagickMemory(
                stream_info->offsets);
            stream_info->offsets=(ssize_t *) AcquireQuantumMemory(
              stream_info->offset_count,sizeof(*stream_info->offsets));
            if (stream_info->offsets == (ssize_t *) NULL)
              ThrowDCMException(ResourceLimitError,"MemoryAllocationFailed");
            for (i=0; i < (ssize_t) stream_info->offset_count; i++)
              stream_info->offsets[i]=(ssize_t) ReadBlobLSBSignedLong(image);
            offset=TellBlob(image);
            for (i=0; i < (ssize_t) stream_info->offset_count; i++)
              stream_info->offsets[i]+=offset;
          }
        /*
          Handle non-native image formats.
        */
        read_info=CloneImageInfo(image_info);
        SetImageInfoBlob(read_info,(void *) NULL,0);
        images=NewImageList();
        for (scene=0; scene < (ssize_t) number_scenes; scene++)
        {
          char
            filename[MaxTextExtent];

          const char
            *property;

          FILE
            *file;

          Image
            *jpeg_image;

          int
            unique_file;

          unsigned int
            tag;

          tag=((unsigned int) ReadBlobLSBShort(image) << 16) |
            ReadBlobLSBShort(image);
          length=(size_t) ReadBlobLSBLong(image);
          if (tag == 0xFFFEE0DD)
            break; /* sequence delimiter tag */
          if (tag != 0xFFFEE000)
            {
              read_info=DestroyImageInfo(read_info);
              ThrowDCMException(CorruptImageError,"ImproperImageHeader");
            }
          file=(FILE *) NULL;
          unique_file=AcquireUniqueFileResource(filename);
          if (unique_file != -1)
            file=fdopen(unique_file,"wb");
          if (file == (FILE *) NULL)
            {
              (void) RelinquishUniqueFileResource(filename);
              ThrowFileException(exception,FileOpenError,
                "UnableToCreateTemporaryFile",filename);
              break;
            }
          for (c=EOF; length != 0; length--)
          {
            c=ReadBlobByte(image);
            if (c == EOF)
              {
                ThrowFileException(exception,CorruptImageError,
                  "UnexpectedEndOfFile",image->filename);
                break;
              }
            (void) fputc(c,file);
          }
          (void) fclose(file);
          if (c == EOF)
            break;
          (void) FormatLocaleString(read_info->filename,MaxTextExtent,"jpeg:%s",
            filename);
          if (image->compression == JPEG2000Compression)
            (void) FormatLocaleString(read_info->filename,MaxTextExtent,
              "j2k:%s",filename);
          jpeg_image=ReadImage(read_info,exception);
          if (jpeg_image != (Image *) NULL)
            {
              ResetImagePropertyIterator(image);
              property=GetNextImageProperty(image);
              while (property != (const char *) NULL)
              {
                (void) SetImageProperty(jpeg_image,property,
                  GetImageProperty(image,property));
                property=GetNextImageProperty(image);
              }
              AppendImageToList(&images,jpeg_image);
            }
          (void) RelinquishUniqueFileResource(filename);
        }
        read_info=DestroyImageInfo(read_info);
        if (stream_info->offsets != (ssize_t *) NULL)
          stream_info->offsets=(ssize_t *)
            RelinquishMagickMemory(stream_info->offsets);
        stream_info=(DCMStreamInfo *) RelinquishMagickMemory(stream_info);
        if (info.scale != (Quantum *) NULL)
          info.scale=(Quantum *) RelinquishMagickMemory(info.scale);
        if (graymap != (int *) NULL)
          graymap=(int *) RelinquishMagickMemory(graymap);
        if (bluemap != (int *) NULL)
          bluemap=(int *) RelinquishMagickMemory(bluemap);
        if (greenmap != (int *) NULL)
          greenmap=(int *) RelinquishMagickMemory(greenmap);
        if (redmap != (int *) NULL)
          redmap=(int *) RelinquishMagickMemory(redmap);
        image=DestroyImageList(image);
        return(GetFirstImageInList(images));
      }
    if (info.depth != (1UL*MAGICKCORE_QUANTUM_DEPTH))
      {
        QuantumAny
          range;

        size_t
          length;

        /*
          Compute pixel scaling table.
        */
        length=(size_t) (GetQuantumRange(info.depth)+1);
        if (length > (size_t) GetBlobSize(image))
          ThrowDCMException(CorruptImageError,"InsufficientImageDataInFile");
        if (info.scale != (Quantum *) NULL) 
          info.scale=(Quantum *) RelinquishMagickMemory(info.scale);
        info.scale=(Quantum *) AcquireQuantumMemory(MagickMax(length,256),
          sizeof(*info.scale));
        if (info.scale == (Quantum *) NULL)
          ThrowDCMException(ResourceLimitError,"MemoryAllocationFailed");
        (void) memset(info.scale,0,MagickMax(length,256)*
          sizeof(*info.scale));
        range=GetQuantumRange(info.depth);
        for (i=0; i <= (ssize_t) GetQuantumRange(info.depth); i++)
          info.scale[i]=ScaleAnyToQuantum((size_t) i,range);
      }
    if (image->compression == RLECompression)
      {
        size_t
          length;

        unsigned int
          tag;

        /*
          Read RLE offset table.
        */
        for (i=0; i < (ssize_t) stream_info->remaining; i++)
        {
          int
            c;

          c=ReadBlobByte(image);
          if (c == EOF)
            break;
        }
        tag=((unsigned int) ReadBlobLSBShort(image) << 16) |
          ReadBlobLSBShort(image);
        (void) tag;
        length=(size_t) ReadBlobLSBLong(image);
        if (length > (size_t) GetBlobSize(image))
          ThrowDCMException(CorruptImageError,"InsufficientImageDataInFile");
        stream_info->offset_count=length >> 2;
        if (stream_info->offset_count != 0)
          {
            MagickOffsetType
              offset;

            stream_info->offsets=(ssize_t *) AcquireQuantumMemory(
              stream_info->offset_count,sizeof(*stream_info->offsets));
            if (stream_info->offsets == (ssize_t *) NULL)
              ThrowDCMException(ResourceLimitError,"MemoryAllocationFailed");
            for (i=0; i < (ssize_t) stream_info->offset_count; i++)
            {
              stream_info->offsets[i]=(ssize_t) ReadBlobLSBSignedLong(image);
              if (EOFBlob(image) != MagickFalse)
                break;
            }
            offset=TellBlob(image)+8;
            for (i=0; i < (ssize_t) stream_info->offset_count; i++)
              stream_info->offsets[i]+=offset;
          }
      }
    for (scene=0; scene < (ssize_t) number_scenes; scene++)
    {
      if (image_info->ping != MagickFalse)
        break;
      image->columns=(size_t) width;
      image->rows=(size_t) height;
      image->depth=info.depth;
      status=SetImageExtent(image,image->columns,image->rows);
      if (status == MagickFalse)
        {
          InheritException(exception,&image->exception);
          break;
        }
      image->colorspace=RGBColorspace;
      (void) SetImageBackgroundColor(image);
      if ((image->colormap == (PixelPacket *) NULL) &&
          (info.samples_per_pixel == 1))
        {
          int
            index;

          size_t
            one;

          one=1;
          if (colors == 0)
            colors=one << info.depth;
          if (AcquireImageColormap(image,colors) == MagickFalse)
            ThrowDCMException(ResourceLimitError,"MemoryAllocationFailed");
          if (redmap != (int *) NULL)
            for (i=0; i < (ssize_t) colors; i++)
            {
              index=redmap[i];
              if ((info.scale != (Quantum *) NULL) && (index >= 0) &&
                  (index <= (int) info.max_value))
                index=(int) info.scale[index];
              image->colormap[i].red=(Quantum) index;
            }
          if (greenmap != (int *) NULL)
            for (i=0; i < (ssize_t) colors; i++)
            {
              index=greenmap[i];
              if ((info.scale != (Quantum *) NULL) && (index >= 0) &&
                  (index <= (int) info.max_value))
                index=(int) info.scale[index];
              image->colormap[i].green=(Quantum) index;
            }
          if (bluemap != (int *) NULL)
            for (i=0; i < (ssize_t) colors; i++)
            {
              index=bluemap[i];
              if ((info.scale != (Quantum *) NULL) && (index >= 0) &&
                  (index <= (int) info.max_value))
                index=(int) info.scale[index];
              image->colormap[i].blue=(Quantum) index;
            }
          if (graymap != (int *) NULL)
            for (i=0; i < (ssize_t) colors; i++)
            {
              index=graymap[i];
              if ((info.scale != (Quantum *) NULL) && (index >= 0) &&
                  (index <= (int) info.max_value))
                index=(int) info.scale[index];
              image->colormap[i].red=(Quantum) index;
              image->colormap[i].green=(Quantum) index;
              image->colormap[i].blue=(Quantum) index;
            }
        }
      if (image->compression == RLECompression)
        {
          unsigned int
            tag;

          /*
            Read RLE segment table.
          */
          for (i=0; i < (ssize_t) stream_info->remaining; i++)
          {
            int
              c;

            c=ReadBlobByte(image);
            if (c == EOF)
              break;
          }
          tag=((unsigned int) ReadBlobLSBShort(image) << 16) |
            ReadBlobLSBShort(image);
          stream_info->remaining=(size_t) ReadBlobLSBLong(image);
          if ((tag != 0xFFFEE000) || (stream_info->remaining <= 64) ||
              (EOFBlob(image) != MagickFalse))
            {
              if (stream_info->offsets != (ssize_t *) NULL)
                stream_info->offsets=(ssize_t *)
                  RelinquishMagickMemory(stream_info->offsets);
              ThrowDCMException(CorruptImageError,"ImproperImageHeader");
            }
          stream_info->count=0;
          stream_info->segment_count=ReadBlobLSBLong(image);
          for (i=0; i < 15; i++)
            stream_info->segments[i]=(ssize_t) ReadBlobLSBSignedLong(image);
          stream_info->remaining-=64;
          if (stream_info->segment_count > 1)
            {
              info.bytes_per_pixel=1;
              info.depth=8;
              if (stream_info->offset_count > 0)
                (void) SeekBlob(image,(MagickOffsetType)
                  stream_info->offsets[0]+stream_info->segments[0],SEEK_SET);
            }
        }
      if ((info.samples_per_pixel > 1) && (image->interlace == PlaneInterlace))
        {
          register ssize_t
            x;

          register PixelPacket
            *q;

          ssize_t
            y;

          /*
            Convert Planar RGB DCM Medical image to pixel packets.
          */
          for (i=0; i < (ssize_t) info.samples_per_pixel; i++)
          {
            for (y=0; y < (ssize_t) image->rows; y++)
            {
              q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
              if (q == (PixelPacket *) NULL)
                break;
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                switch ((int) i)
                {
                  case 0:
                  {
                    SetPixelRed(q,ScaleCharToQuantum((unsigned char)
                      ReadDCMByte(stream_info,image)));
                    break;
                  }
                  case 1:
                  {
                    SetPixelGreen(q,ScaleCharToQuantum((unsigned char)
                      ReadDCMByte(stream_info,image)));
                    break;
                  }
                  case 2:
                  {
                    SetPixelBlue(q,ScaleCharToQuantum((unsigned char)
                      ReadDCMByte(stream_info,image)));
                    break;
                  }
                  case 3:
                  {
                    SetPixelAlpha(q,ScaleCharToQuantum((unsigned char)
                      ReadDCMByte(stream_info,image)));
                    break;
                  }
                  default:
                    break;
                }
                q++;
              }
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
                break;
              if (image->previous == (Image *) NULL)
                {
                  status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                    y,image->rows);
                  if (status == MagickFalse)
                    break;
                }
            }
          }
        }
      else
        {
          const char
            *option;

          /*
            Convert DCM Medical image to pixel packets.
          */
          option=GetImageOption(image_info,"dcm:display-range");
          if (option != (const char *) NULL)
            {
              if (LocaleCompare(option,"reset") == 0)
                info.window_width=0;
            }
          option=GetImageOption(image_info,"dcm:window");
          if (option != (char *) NULL)
            {
              GeometryInfo
                geometry_info;

              MagickStatusType
                flags;

              flags=ParseGeometry(option,&geometry_info);
              if (flags & RhoValue)
                info.window_center=geometry_info.rho;
              if (flags & SigmaValue)
                info.window_width=geometry_info.sigma;
              info.rescale=MagickTrue;
            }
          option=GetImageOption(image_info,"dcm:rescale");
          if (option != (char *) NULL)
            info.rescale=IsStringTrue(option);
          if ((info.window_center != 0) && (info.window_width == 0))
            info.window_width=info.window_center;
          status=ReadDCMPixels(image,&info,stream_info,MagickTrue,exception);
          if ((status != MagickFalse) && (stream_info->segment_count > 1))
            {
              if (stream_info->offset_count > 0)
                (void) SeekBlob(image,(MagickOffsetType)
                  stream_info->offsets[0]+stream_info->segments[1],SEEK_SET);
              (void) ReadDCMPixels(image,&info,stream_info,MagickFalse,
                exception);
            }
        }
      if (SetImageGray(image,exception) != MagickFalse)
        (void) SetImageColorspace(image,GRAYColorspace);
      if (EOFBlob(image) != MagickFalse)
        {
          ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
            image->filename);
          break;
        }
      /*
        Proceed to next image.
      */
      if (image_info->number_scenes != 0)
        if (image->scene >= (image_info->scene+image_info->number_scenes-1))
          break;
      if (scene < (ssize_t) (number_scenes-1))
        {
          /*
            Allocate next image structure.
          */
          AcquireNextImage(image_info,image);
          if (GetNextImageInList(image) == (Image *) NULL)
            {
              status=MagickFalse;
              break;
            }
          image=SyncNextImageInList(image);
          status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
            GetBlobSize(image));
          if (status == MagickFalse)
            break;
        }
    }
    if (TellBlob(image) < (MagickOffsetType) GetBlobSize(image))
      {
        /*
          Allocate next image structure.
        */
        AcquireNextImage(image_info,image);
        if (GetNextImageInList(image) == (Image *) NULL)
          {
            status=MagickFalse;
            break;
          }
        image=SyncNextImageInList(image);
        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
          GetBlobSize(image));
        if (status == MagickFalse)
          break;
     }
  }
  /*
    Free resources.
  */
  if (stream_info->offsets != (ssize_t *) NULL)
    stream_info->offsets=(ssize_t *)
      RelinquishMagickMemory(stream_info->offsets);
  stream_info=(DCMStreamInfo *) RelinquishMagickMemory(stream_info);
  if (info.scale != (Quantum *) NULL)
    info.scale=(Quantum *) RelinquishMagickMemory(info.scale);
  if (graymap != (int *) NULL)
    graymap=(int *) RelinquishMagickMemory(graymap);
  if (bluemap != (int *) NULL)
    bluemap=(int *) RelinquishMagickMemory(bluemap);
  if (greenmap != (int *) NULL)
    greenmap=(int *) RelinquishMagickMemory(greenmap);
  if (redmap != (int *) NULL)
    redmap=(int *) RelinquishMagickMemory(redmap);
  (void) CloseBlob(image);
  if (status == MagickFalse)
    return(DestroyImageList(image));
  return(GetFirstImageInList(image));
}