Пример #1
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%     C y c l e C o l o r m a p I m a g e                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  CycleColormap() displaces an image's colormap by a given number of
%  positions.  If you cycle the colormap a number of times you can produce
%  a psychodelic effect.
%
%  WARNING: this assumes an images colormap is in a well know and defined
%  order. Currently Imagemagick has no way of setting that order.
%
%  The format of the CycleColormapImage method is:
%
%      MagickBooleanType CycleColormapImage(Image *image,const ssize_t displace,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image: the image.
%
%    o displace:  displace the colormap this amount.
%
%    o exception: return any errors or warnings in this structure.
%
*/
MagickExport MagickBooleanType CycleColormapImage(Image *image,
  const ssize_t displace,ExceptionInfo *exception)
{
  CacheView
    *image_view;

  MagickBooleanType
    status;

  ssize_t
    y;

  assert(image != (Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  if (image->storage_class == DirectClass)
    (void) SetImageType(image,PaletteType,exception);
  status=MagickTrue;
  image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) \
    magick_threads(image,image,1,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register ssize_t
      x;

    register Quantum
      *restrict q;

    ssize_t
      index;

    if (status == MagickFalse)
      continue;
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if (q == (Quantum *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      index=(ssize_t) (GetPixelIndex(image,q)+displace) % image->colors;
      if (index < 0)
        index+=(ssize_t) image->colors;
      SetPixelIndex(image,(Quantum) index,q);
      SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
      q+=GetPixelChannels(image);
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
  }
  image_view=DestroyCacheView(image_view);
  return(status);
}
Пример #2
0
RGBQUAD CxDib::GetPixelColor(long x,long y)
{
	RGBQUAD rgb={0,0,0,0};
	if ((hDib==NULL)||(x<0)||(y<0)||
		(x>=m_bi.biWidth)||(y>=m_bi.biHeight)) return rgb;
	if (m_nColors) return GetPaletteIndex(GetPixelIndex(x,y));
	else {
		BYTE* iDst = GetBits()+(m_bi.biHeight - y)*m_LineWidth + x*sizeof(RGBQUAD);
		rgb.rgbBlue = *iDst++;
		rgb.rgbGreen= *iDst++;
		rgb.rgbRed =*iDst;
		return rgb;
	}
}
Пример #3
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   G e t I m a g e T o t a l I n k D e n s i t y                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  GetImageTotalInkDensity() returns the total ink density for a CMYK image.
%  Total Ink Density (TID) is determined by adding the CMYK values in the
%  darkest shadow area in an image.
%
%  The format of the GetImageTotalInkDensity method is:
%
%      double GetImageTotalInkDensity(const Image *image)
%
%  A description of each parameter follows:
%
%    o image: the image.
%
*/
MagickExport double GetImageTotalInkDensity(Image *image)
{
  CacheView
    *image_view;

  double
    total_ink_density;

  ExceptionInfo
    *exception;

  MagickBooleanType
    status;

  ssize_t
    y;

  assert(image != (Image *) NULL);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  assert(image->signature == MagickSignature);
  if (image->colorspace != CMYKColorspace)
    {
      (void) ThrowMagickException(&image->exception,GetMagickModule(),
        ImageError,"ColorSeparatedImageRequired","`%s'",image->filename);
      return(0.0);
    }
  status=MagickTrue;
  total_ink_density=0.0;
  exception=(&image->exception);
  image_view=AcquireVirtualCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status) \
    dynamic_number_threads(image,image->columns,image->rows,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    double
      density;

    register const IndexPacket
      *indexes;

    register const PixelPacket
      *p;

    register ssize_t
      x;

    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
    if (p == (const PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewVirtualIndexQueue(image_view);
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      density=(double) GetPixelRed(p)+GetPixelGreen(p)+
        GetPixelBlue(p)+GetPixelIndex(indexes+x);
      if (density > total_ink_density)
#if defined(MAGICKCORE_OPENMP_SUPPORT)
        #pragma omp critical (MagickCore_GetImageTotalInkDensity)
#endif
        {
          if (density > total_ink_density)
            total_ink_density=density;
        }
      p++;
    }
  }
  image_view=DestroyCacheView(image_view);
  if (status == MagickFalse)
    total_ink_density=0.0;
  return(total_ink_density);
}
Пример #4
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   W r i t e S I X E L I m a g e                                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  WriteSIXELImage() writes an image to a file in the X pixmap format.
%
%  The format of the WriteSIXELImage method is:
%
%      MagickBooleanType WriteSIXELImage(const ImageInfo *image_info,
%        Image *image,ExceptionInfo *exception)
%
%  A description of each parameter follows.
%
%    o image_info: the image info.
%
%    o image:  The image.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static MagickBooleanType WriteSIXELImage(const ImageInfo *image_info,Image *image)
{
  ExceptionInfo
    *exception;

  MagickBooleanType
    status;

  register const IndexPacket
    *indexes;

  register ssize_t
    i,
    x;

  ssize_t
    opacity,
    y;

  sixel_output_t
    *output;

  unsigned char
    sixel_palette[256 * 3],
    *sixel_pixels;

  /*
    Open output image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  exception=(&image->exception);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
  if (status == MagickFalse)
    return(status);
  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
    (void) TransformImageColorspace(image,sRGBColorspace);
  opacity=(-1);
  if (image->matte == MagickFalse)
    {
      if ((image->storage_class == DirectClass) || (image->colors > 256))
        (void) SetImageType(image,PaletteType);
    }
  else
    {
      MagickRealType
        alpha,
        beta;

      /*
        Identify transparent colormap index.
      */
      if ((image->storage_class == DirectClass) || (image->colors > 256))
        (void) SetImageType(image,PaletteBilevelMatteType);
      for (i=0; i < (ssize_t) image->colors; i++)
        if (image->colormap[i].opacity != OpaqueOpacity)
          {
            if (opacity < 0)
              {
                opacity=i;
                continue;
              }
            alpha=(MagickRealType) image->colormap[i].opacity;
            beta=(MagickRealType) image->colormap[opacity].opacity;
            if (alpha > beta)
              opacity=i;
          }
      if (opacity == -1)
        {
          (void) SetImageType(image,PaletteBilevelMatteType);
          for (i=0; i < (ssize_t) image->colors; i++)
            if (image->colormap[i].opacity != OpaqueOpacity)
              {
                if (opacity < 0)
                  {
                    opacity=i;
                    continue;
                  }
                alpha=(MagickRealType) image->colormap[i].opacity;
                beta=(MagickRealType) image->colormap[opacity].opacity;
                if (alpha > beta)
                  opacity=i;
              }
        }
      if (opacity >= 0)
        {
          image->colormap[opacity].red=image->transparent_color.red;
          image->colormap[opacity].green=image->transparent_color.green;
          image->colormap[opacity].blue=image->transparent_color.blue;
        }
    }
  /*
    SIXEL header.
  */
  for (i=0; i < (ssize_t) image->colors; i++)
  {
    sixel_palette[i * 3 + 0] = ScaleQuantumToChar(image->colormap[i].red);
    sixel_palette[i * 3 + 1] = ScaleQuantumToChar(image->colormap[i].green);
    sixel_palette[i * 3 + 2] = ScaleQuantumToChar(image->colormap[i].blue);
  }

  /*
    Define SIXEL pixels.
  */
  output = sixel_output_create(image);
  sixel_pixels =(unsigned char *) AcquireQuantumMemory(image->columns * image->rows,1);
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    (void) GetVirtualPixels(image,0,y,image->columns,1,exception);
    indexes=GetVirtualIndexQueue(image);
    for (x=0; x < (ssize_t) image->columns; x++)
      sixel_pixels[y * image->columns + x] = (unsigned char) ((ssize_t) GetPixelIndex(indexes + x));
  }
  status = sixel_encode_impl(sixel_pixels, image->columns, image->rows,
                          sixel_palette, image->colors, -1,
                          output);
  sixel_pixels =(unsigned char *) RelinquishMagickMemory(sixel_pixels);
  output = (sixel_output_t *) RelinquishMagickMemory(output);
  (void) CloseBlob(image);
  return(status);
}
Пример #5
0
bool CxImageTIF::EncodeBody(TIFF *m_tif, bool multipage, int page, int pagecount)
{
    uint32 height=head.biHeight;
    uint32 width=head.biWidth;
    uint16 bitcount=head.biBitCount;
    uint16 bitspersample;
    uint16 samplesperpixel;
    uint16 photometric=0;
    uint16 compression;
//	uint16 pitch;
//	int line;
    uint32 x, y;

    samplesperpixel = ((bitcount == 24) || (bitcount == 32)) ? (BYTE)3 : (BYTE)1;
#if CXIMAGE_SUPPORT_ALPHA
    if (bitcount==24 && AlphaIsValid()) { bitcount=32; samplesperpixel=4; }
#endif //CXIMAGE_SUPPORT_ALPHA

    bitspersample = bitcount / samplesperpixel;

    //set the PHOTOMETRIC tag
    RGBQUAD *rgb = GetPalette();
    switch (bitcount) {
        case 1:
            if (CompareColors(&rgb[0],&rgb[1])<0) {
                /* <abe> some viewers do not handle PHOTOMETRIC_MINISBLACK:
                 * let's transform the image in PHOTOMETRIC_MINISWHITE
                 */
                //invert the colors
                RGBQUAD tempRGB=GetPaletteColor(0);
                SetPaletteColor(0,GetPaletteColor(1));
                SetPaletteColor(1,tempRGB);
                //invert the pixels
                BYTE *iSrc=info.pImage;
                for (unsigned long i=0;i<head.biSizeImage;i++){
                    *iSrc=(BYTE)~(*(iSrc));
                    iSrc++;
                }
                photometric = PHOTOMETRIC_MINISWHITE;
                //photometric = PHOTOMETRIC_MINISBLACK;
            } else {
                photometric = PHOTOMETRIC_MINISWHITE;
            }
            break;
        case 4:	// Check if the DIB has a color or a greyscale palette
        case 8:
            photometric = PHOTOMETRIC_MINISBLACK; //default to gray scale
            for (x = 0; x < head.biClrUsed; x++) {
                if ((rgb->rgbRed != x)||(rgb->rgbRed != rgb->rgbGreen)||(rgb->rgbRed != rgb->rgbBlue)){
                    photometric = PHOTOMETRIC_PALETTE;
                    break;
                }
                rgb++;
            }
            break;
        case 24:
        case 32:
            photometric = PHOTOMETRIC_RGB;			
            break;
    }

#if CXIMAGE_SUPPORT_ALPHA
    if (AlphaIsValid() && bitcount==8) samplesperpixel=2; //8bpp + alpha layer
#endif //CXIMAGE_SUPPORT_ALPHA

//	line = CalculateLine(width, bitspersample * samplesperpixel);
//	pitch = (uint16)CalculatePitch(line);

    //prepare the palette struct
    RGBQUAD pal[256];
    if (GetPalette()){
        BYTE b;
        memcpy(pal,GetPalette(),GetPaletteSize());
        for(WORD a=0;a<head.biClrUsed;a++){	//swap blue and red components
            b=pal[a].rgbBlue; pal[a].rgbBlue=pal[a].rgbRed; pal[a].rgbRed=b;
        }
    }

    // handle standard width/height/bpp stuff
    TIFFSetField(m_tif, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(m_tif, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
    TIFFSetField(m_tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
    TIFFSetField(m_tif, TIFFTAG_PHOTOMETRIC, photometric);
    TIFFSetField(m_tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);	// single image plane 
    TIFFSetField(m_tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);

    uint32 rowsperstrip = TIFFDefaultStripSize(m_tif, (uint32) -1);  //<REC> gives better compression
    TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);

    // handle metrics
    TIFFSetField(m_tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
    TIFFSetField(m_tif, TIFFTAG_XRESOLUTION, (float)info.xDPI);
    TIFFSetField(m_tif, TIFFTAG_YRESOLUTION, (float)info.yDPI);
//	TIFFSetField(m_tif, TIFFTAG_XPOSITION, (float)info.xOffset);
//	TIFFSetField(m_tif, TIFFTAG_YPOSITION, (float)info.yOffset);

    // multi-paging - Thanks to Abe <God(dot)bless(at)marihuana(dot)com>
    if (multipage)
    {
        char page_number[20];
        sprintf(page_number, "Page %d", page);

        TIFFSetField(m_tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
        TIFFSetField(m_tif, TIFFTAG_PAGENUMBER, page,pagecount);
        TIFFSetField(m_tif, TIFFTAG_PAGENAME, page_number);
    } else {
        TIFFSetField(m_tif, TIFFTAG_SUBFILETYPE, 0);
    }

    // palettes (image colormaps are automatically scaled to 16-bits)
    if (photometric == PHOTOMETRIC_PALETTE) {
        uint16 *r, *g, *b;
        r = (uint16 *) _TIFFmalloc(sizeof(uint16) * 3 * 256);
        g = r + 256;
        b = g + 256;

        for (int i = 255; i >= 0; i--) {
            b[i] = (uint16)SCALE((uint16)pal[i].rgbRed);
            g[i] = (uint16)SCALE((uint16)pal[i].rgbGreen);
            r[i] = (uint16)SCALE((uint16)pal[i].rgbBlue);
        }

        TIFFSetField(m_tif, TIFFTAG_COLORMAP, r, g, b);
        _TIFFfree(r);
    }

    // compression
    if (GetCodecOption(CXIMAGE_FORMAT_TIF)) {
        compression = (WORD)GetCodecOption(CXIMAGE_FORMAT_TIF);
    } else {
        switch (bitcount) {
            case 1 :
                compression = COMPRESSION_CCITTFAX4;
                break;
            case 4 :
            case 8 :
                compression = COMPRESSION_LZW;
                break;
            case 24 :
            case 32 :
                compression = COMPRESSION_JPEG;
                break;
            default :
                compression = COMPRESSION_NONE;
                break;
        }
    }
    TIFFSetField(m_tif, TIFFTAG_COMPRESSION, compression);

    switch (compression) {
    case COMPRESSION_JPEG:
        TIFFSetField(m_tif, TIFFTAG_JPEGQUALITY, info.nQuality);
        TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, ((7+rowsperstrip)>>3)<<3);
        break;
    case COMPRESSION_LZW:
        if (bitcount>=8) TIFFSetField(m_tif, TIFFTAG_PREDICTOR, 2);
        break;
    }

    // read the DIB lines from bottom to top and save them in the TIF

    BYTE *bits;
    switch(bitcount) {				
        case 1 :
        case 4 :
        case 8 :
        {
            if (samplesperpixel==1){
                for (y = 0; y < height; y++) {
                    bits= info.pImage + (height - y - 1)*info.dwEffWidth;
                    if (TIFFWriteScanline(m_tif,bits, y, 0)==-1) return false;
                }
            }
#if CXIMAGE_SUPPORT_ALPHA
            else { //8bpp + alpha layer
                bits = (BYTE*)malloc(2*width);
                if (!bits) return false;
                for (y = 0; y < height; y++) {
                    for (x=0;x<width;x++){
                        bits[2*x]=GetPixelIndex(x,height - y - 1);
                        bits[2*x+1]=AlphaGet(x,height - y - 1);
                    }
                    if (TIFFWriteScanline(m_tif,bits, y, 0)==-1) {
                        free(bits);
                        return false;
                    }
                }
                free(bits);
            }
#endif //CXIMAGE_SUPPORT_ALPHA
            break;
        }				
        case 24:
        {
            BYTE *buffer = (BYTE *)malloc(info.dwEffWidth);
            if (!buffer) return false;
            for (y = 0; y < height; y++) {
                // get a pointer to the scanline
                memcpy(buffer, info.pImage + (height - y - 1)*info.dwEffWidth, info.dwEffWidth);
                // TIFFs store color data RGB instead of BGR
                BYTE *pBuf = buffer;
                for (x = 0; x < width; x++) {
                    BYTE tmp = pBuf[0];
                    pBuf[0] = pBuf[2];
                    pBuf[2] = tmp;
                    pBuf += 3;
                }
                // write the scanline to disc
                if (TIFFWriteScanline(m_tif, buffer, y, 0)==-1){
                    free(buffer);
                    return false;
                }
            }
            free(buffer);
            break;
        }				
        case 32 :
        {
#if CXIMAGE_SUPPORT_ALPHA
            BYTE *buffer = (BYTE *)malloc((info.dwEffWidth*4)/3);
            if (!buffer) return false;
            for (y = 0; y < height; y++) {
                // get a pointer to the scanline
                memcpy(buffer, info.pImage + (height - y - 1)*info.dwEffWidth, info.dwEffWidth);
                // TIFFs store color data RGB instead of BGR
                BYTE *pSrc = buffer + 3 * width;
                BYTE *pDst = buffer + 4 * width;
                for (x = 0; x < width; x++) {
                    pDst-=4;
                    pSrc-=3;
                    pDst[3] = AlphaGet(width-x-1,height-y-1);
                    pDst[2] = pSrc[0];
                    pDst[1] = pSrc[1];
                    pDst[0] = pSrc[2];
                }
                // write the scanline to disc
                if (TIFFWriteScanline(m_tif, buffer, y, 0)==-1){
                    free(buffer);
                    return false;
                }
            }
            free(buffer);
#endif //CXIMAGE_SUPPORT_ALPHA
            break;
        }				
    }
    return true;
}
Пример #6
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   W r i t e X P M I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  WriteXPMImage() writes an image to a file in the X pixmap format.
%
%  The format of the WriteXPMImage method is:
%
%      MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image)
%
%  A description of each parameter follows.
%
%    o image_info: the image info.
%
%    o image:  The image.
%
*/
static MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image)
{
#define MaxCixels  92

  static const char
    Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk"
                         "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";

  char
    buffer[MaxTextExtent],
    basename[MaxTextExtent],
    name[MaxTextExtent],
    symbol[MaxTextExtent];

  ExceptionInfo
    *exception;

  MagickBooleanType
    status;

  MagickPixelPacket
    pixel;

  register const IndexPacket
    *indexes;

  register const PixelPacket
    *p;

  register ssize_t
    i,
    x;

  size_t
    characters_per_pixel;

  ssize_t
    j,
    k,
    opacity,
    y;

  /*
    Open output image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  exception=(&image->exception);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
  if (status == MagickFalse)
    return(status);
  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
    (void) TransformImageColorspace(image,sRGBColorspace);
  opacity=(-1);
  if (image->matte == MagickFalse)
    {
      if ((image->storage_class == DirectClass) || (image->colors > 256))
        (void) SetImageType(image,PaletteType);
    }
  else
    {
      MagickRealType
        alpha,
        beta;

      /*
        Identify transparent colormap index.
      */
      if ((image->storage_class == DirectClass) || (image->colors > 256))
        (void) SetImageType(image,PaletteBilevelMatteType);
      for (i=0; i < (ssize_t) image->colors; i++)
        if (image->colormap[i].opacity != OpaqueOpacity)
          {
            if (opacity < 0)
              {
                opacity=i;
                continue;
              }
            alpha=(Quantum) TransparentOpacity-(MagickRealType)
              image->colormap[i].opacity;
            beta=(Quantum) TransparentOpacity-(MagickRealType)
              image->colormap[opacity].opacity;
            if (alpha < beta)
              opacity=i;
          }
      if (opacity == -1)
        {
          (void) SetImageType(image,PaletteBilevelMatteType);
          for (i=0; i < (ssize_t) image->colors; i++)
            if (image->colormap[i].opacity != OpaqueOpacity)
              {
                if (opacity < 0)
                  {
                    opacity=i;
                    continue;
                  }
                alpha=(Quantum) TransparentOpacity-(MagickRealType)
                  image->colormap[i].opacity;
                beta=(Quantum) TransparentOpacity-(MagickRealType)
                  image->colormap[opacity].opacity;
                if (alpha < beta)
                  opacity=i;
              }
        }
      if (opacity >= 0)
        {
          image->colormap[opacity].red=image->transparent_color.red;
          image->colormap[opacity].green=image->transparent_color.green;
          image->colormap[opacity].blue=image->transparent_color.blue;
        }
    }
  /*
    Compute the character per pixel.
  */
  characters_per_pixel=1;
  for (k=MaxCixels; (ssize_t) image->colors > k; k*=MaxCixels)
    characters_per_pixel++;
  /*
    XPM header.
  */
  (void) WriteBlobString(image,"/* XPM */\n");
  GetPathComponent(image->filename,BasePath,basename);
  if (isalnum((int) ((unsigned char) *basename)) == 0)
    {
      (void) FormatLocaleString(buffer,MaxTextExtent,"xpm_%s",basename);
      (void) CopyMagickString(basename,buffer,MaxTextExtent);
    }
  if (isalpha((int) ((unsigned char) basename[0])) == 0)
    basename[0]='_';
  for (i=1; basename[i] != '\0'; i++)
    if (isalnum((int) ((unsigned char) basename[i])) == 0)
      basename[i]='_';
  (void) FormatLocaleString(buffer,MaxTextExtent,
    "static char *%s[] = {\n",basename);
  (void) WriteBlobString(image,buffer);
  (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n");
  (void) FormatLocaleString(buffer,MaxTextExtent,
    "\"%.20g %.20g %.20g %.20g \",\n",(double) image->columns,(double)
    image->rows,(double) image->colors,(double) characters_per_pixel);
  (void) WriteBlobString(image,buffer);
  GetMagickPixelPacket(image,&pixel);
  for (i=0; i < (ssize_t) image->colors; i++)
  {
    /*
      Define XPM color.
    */
    SetMagickPixelPacket(image,image->colormap+i,(IndexPacket *) NULL,&pixel);
    pixel.colorspace=sRGBColorspace;
    pixel.depth=8;
    pixel.opacity=(MagickRealType) OpaqueOpacity;
    (void) QueryMagickColorname(image,&pixel,XPMCompliance,name,exception);
    if (i == opacity)
      (void) CopyMagickString(name,"None",MaxTextExtent);
    /*
      Write XPM color.
    */
    k=i % MaxCixels;
    symbol[0]=Cixel[k];
    for (j=1; j < (ssize_t) characters_per_pixel; j++)
    {
      k=((i-k)/MaxCixels) % MaxCixels;
      symbol[j]=Cixel[k];
    }
    symbol[j]='\0';
    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s c %s\",\n",symbol,
      name);
    (void) WriteBlobString(image,buffer);
  }
  /*
    Define XPM pixels.
  */
  (void) WriteBlobString(image,"/* pixels */\n");
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
    if (p == (const PixelPacket *) NULL)
      break;
    indexes=GetVirtualIndexQueue(image);
    (void) WriteBlobString(image,"\"");
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      k=((ssize_t) GetPixelIndex(indexes+x) % MaxCixels);
      symbol[0]=Cixel[k];
      for (j=1; j < (ssize_t) characters_per_pixel; j++)
      {
        k=(((int) GetPixelIndex(indexes+x)-k)/MaxCixels) % MaxCixels;
        symbol[j]=Cixel[k];
      }
      symbol[j]='\0';
      (void) CopyMagickString(buffer,symbol,MaxTextExtent);
      (void) WriteBlobString(image,buffer);
    }
    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s\n",
      (y == (ssize_t) (image->rows-1) ? "" : ","));
    (void) WriteBlobString(image,buffer);
    if (image->previous == (Image *) NULL)
      {
        status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
          image->rows);
        if (status == MagickFalse)
          break;
      }
  }
  (void) WriteBlobString(image,"};\n");
  (void) CloseBlob(image);
  return(MagickTrue);
}
Пример #7
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d V I F F I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadVIFFImage() reads a Khoros Visualization image file and returns
%  it.  It allocates the memory necessary for the new Image structure and
%  returns a pointer to the new image.
%
%  The format of the ReadVIFFImage method is:
%
%      Image *ReadVIFFImage(const ImageInfo *image_info,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image: Method ReadVIFFImage returns a pointer to the image after
%      reading.  A null image is returned if there is a memory shortage or if
%      the image cannot be read.
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadVIFFImage(const ImageInfo *image_info,
                            ExceptionInfo *exception)
{
#define VFF_CM_genericRGB  15
#define VFF_CM_ntscRGB  1
#define VFF_CM_NONE  0
#define VFF_DEP_DECORDER  0x4
#define VFF_DEP_NSORDER  0x8
#define VFF_DES_RAW  0
#define VFF_LOC_IMPLICIT  1
#define VFF_MAPTYP_NONE  0
#define VFF_MAPTYP_1_BYTE  1
#define VFF_MAPTYP_2_BYTE  2
#define VFF_MAPTYP_4_BYTE  4
#define VFF_MAPTYP_FLOAT  5
#define VFF_MAPTYP_DOUBLE  7
#define VFF_MS_NONE  0
#define VFF_MS_ONEPERBAND  1
#define VFF_MS_SHARED  3
#define VFF_TYP_BIT  0
#define VFF_TYP_1_BYTE  1
#define VFF_TYP_2_BYTE  2
#define VFF_TYP_4_BYTE  4
#define VFF_TYP_FLOAT  5
#define VFF_TYP_DOUBLE  9

    typedef struct _ViffInfo
    {
        unsigned char
        identifier,
        file_type,
        release,
        version,
        machine_dependency,
        reserve[3];

        char
        comment[512];

        unsigned int
        rows,
        columns,
        subrows;

        int
        x_offset,
        y_offset;

        float
        x_bits_per_pixel,
        y_bits_per_pixel;

        unsigned int
        location_type,
        location_dimension,
        number_of_images,
        number_data_bands,
        data_storage_type,
        data_encode_scheme,
        map_scheme,
        map_storage_type,
        map_rows,
        map_columns,
        map_subrows,
        map_enable,
        maps_per_cycle,
        color_space_model;
    } ViffInfo;

    double
    min_value,
    scale_factor,
    value;

    Image
    *image;

    int
    bit;

    MagickBooleanType
    status;

    MagickSizeType
    number_pixels;

    register ssize_t
    x;

    register Quantum
    *q;

    register ssize_t
    i;

    register unsigned char
    *p;

    size_t
    bytes_per_pixel,
    lsb_first,
    max_packets,
    quantum;

    ssize_t
    count,
    y;

    unsigned char
    buffer[7],
           *viff_pixels;

    ViffInfo
    viff_info;

    /*
      Open image file.
    */
    assert(image_info != (const ImageInfo *) NULL);
    assert(image_info->signature == MagickSignature);
    if (image_info->debug != MagickFalse)
        (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
                              image_info->filename);
    assert(exception != (ExceptionInfo *) NULL);
    assert(exception->signature == MagickSignature);
    image=AcquireImage(image_info,exception);
    status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    if (status == MagickFalse)
    {
        image=DestroyImageList(image);
        return((Image *) NULL);
    }
    /*
      Read VIFF header (1024 bytes).
    */
    count=ReadBlob(image,1,&viff_info.identifier);
    do
    {
        /*
          Verify VIFF identifier.
        */
        if ((count == 0) || ((unsigned char) viff_info.identifier != 0xab))
            ThrowReaderException(CorruptImageError,"NotAVIFFImage");
        /*
          Initialize VIFF image.
        */
        count=ReadBlob(image,7,buffer);
        viff_info.file_type=buffer[0];
        viff_info.release=buffer[1];
        viff_info.version=buffer[2];
        viff_info.machine_dependency=buffer[3];
        count=ReadBlob(image,512,(unsigned char *) viff_info.comment);
        viff_info.comment[511]='\0';
        if (strlen(viff_info.comment) > 4)
            (void) SetImageProperty(image,"comment",viff_info.comment,exception);
        if ((viff_info.machine_dependency == VFF_DEP_DECORDER) ||
                (viff_info.machine_dependency == VFF_DEP_NSORDER))
        {
            viff_info.rows=ReadBlobLSBLong(image);
            viff_info.columns=ReadBlobLSBLong(image);
            viff_info.subrows=ReadBlobLSBLong(image);
            viff_info.x_offset=(int) ReadBlobLSBLong(image);
            viff_info.y_offset=(int) ReadBlobLSBLong(image);
            viff_info.x_bits_per_pixel=(float) ReadBlobLSBLong(image);
            viff_info.y_bits_per_pixel=(float) ReadBlobLSBLong(image);
            viff_info.location_type=ReadBlobLSBLong(image);
            viff_info.location_dimension=ReadBlobLSBLong(image);
            viff_info.number_of_images=ReadBlobLSBLong(image);
            viff_info.number_data_bands=ReadBlobLSBLong(image);
            viff_info.data_storage_type=ReadBlobLSBLong(image);
            viff_info.data_encode_scheme=ReadBlobLSBLong(image);
            viff_info.map_scheme=ReadBlobLSBLong(image);
            viff_info.map_storage_type=ReadBlobLSBLong(image);
            viff_info.map_rows=ReadBlobLSBLong(image);
            viff_info.map_columns=ReadBlobLSBLong(image);
            viff_info.map_subrows=ReadBlobLSBLong(image);
            viff_info.map_enable=ReadBlobLSBLong(image);
            viff_info.maps_per_cycle=ReadBlobLSBLong(image);
            viff_info.color_space_model=ReadBlobLSBLong(image);
        }
        else
        {
            viff_info.rows=ReadBlobMSBLong(image);
            viff_info.columns=ReadBlobMSBLong(image);
            viff_info.subrows=ReadBlobMSBLong(image);
            viff_info.x_offset=(int) ReadBlobMSBLong(image);
            viff_info.y_offset=(int) ReadBlobMSBLong(image);
            viff_info.x_bits_per_pixel=(float) ReadBlobMSBLong(image);
            viff_info.y_bits_per_pixel=(float) ReadBlobMSBLong(image);
            viff_info.location_type=ReadBlobMSBLong(image);
            viff_info.location_dimension=ReadBlobMSBLong(image);
            viff_info.number_of_images=ReadBlobMSBLong(image);
            viff_info.number_data_bands=ReadBlobMSBLong(image);
            viff_info.data_storage_type=ReadBlobMSBLong(image);
            viff_info.data_encode_scheme=ReadBlobMSBLong(image);
            viff_info.map_scheme=ReadBlobMSBLong(image);
            viff_info.map_storage_type=ReadBlobMSBLong(image);
            viff_info.map_rows=ReadBlobMSBLong(image);
            viff_info.map_columns=ReadBlobMSBLong(image);
            viff_info.map_subrows=ReadBlobMSBLong(image);
            viff_info.map_enable=ReadBlobMSBLong(image);
            viff_info.maps_per_cycle=ReadBlobMSBLong(image);
            viff_info.color_space_model=ReadBlobMSBLong(image);
        }
        for (i=0; i < 420; i++)
            (void) ReadBlobByte(image);
        image->columns=viff_info.rows;
        image->rows=viff_info.columns;
        image->depth=viff_info.x_bits_per_pixel <= 8 ? 8UL :
                     MAGICKCORE_QUANTUM_DEPTH;
        /*
          Verify that we can read this VIFF image.
        */
        number_pixels=(MagickSizeType) viff_info.columns*viff_info.rows;
        if (number_pixels != (size_t) number_pixels)
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        if (number_pixels == 0)
            ThrowReaderException(CoderError,"ImageColumnOrRowSizeIsNotSupported");
        if ((viff_info.number_data_bands < 1) || (viff_info.number_data_bands > 4))
            ThrowReaderException(CorruptImageError,"ImproperImageHeader");
        if ((viff_info.data_storage_type != VFF_TYP_BIT) &&
                (viff_info.data_storage_type != VFF_TYP_1_BYTE) &&
                (viff_info.data_storage_type != VFF_TYP_2_BYTE) &&
                (viff_info.data_storage_type != VFF_TYP_4_BYTE) &&
                (viff_info.data_storage_type != VFF_TYP_FLOAT) &&
                (viff_info.data_storage_type != VFF_TYP_DOUBLE))
            ThrowReaderException(CoderError,"DataStorageTypeIsNotSupported");
        if (viff_info.data_encode_scheme != VFF_DES_RAW)
            ThrowReaderException(CoderError,"DataEncodingSchemeIsNotSupported");
        if ((viff_info.map_storage_type != VFF_MAPTYP_NONE) &&
                (viff_info.map_storage_type != VFF_MAPTYP_1_BYTE) &&
                (viff_info.map_storage_type != VFF_MAPTYP_2_BYTE) &&
                (viff_info.map_storage_type != VFF_MAPTYP_4_BYTE) &&
                (viff_info.map_storage_type != VFF_MAPTYP_FLOAT) &&
                (viff_info.map_storage_type != VFF_MAPTYP_DOUBLE))
            ThrowReaderException(CoderError,"MapStorageTypeIsNotSupported");
        if ((viff_info.color_space_model != VFF_CM_NONE) &&
                (viff_info.color_space_model != VFF_CM_ntscRGB) &&
                (viff_info.color_space_model != VFF_CM_genericRGB))
            ThrowReaderException(CoderError,"ColorspaceModelIsNotSupported");
        if (viff_info.location_type != VFF_LOC_IMPLICIT)
            ThrowReaderException(CoderError,"LocationTypeIsNotSupported");
        if (viff_info.number_of_images != 1)
            ThrowReaderException(CoderError,"NumberOfImagesIsNotSupported");
        if (viff_info.map_rows == 0)
            viff_info.map_scheme=VFF_MS_NONE;
        switch ((int) viff_info.map_scheme)
        {
        case VFF_MS_NONE:
        {
            if (viff_info.number_data_bands < 3)
            {
                /*
                  Create linear color ramp.
                */
                image->colors=image->depth <= 8 ? 256UL : 65536UL;
                if (viff_info.data_storage_type == VFF_TYP_BIT)
                    image->colors=2;
                if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
                    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
            }
            break;
        }
        case VFF_MS_ONEPERBAND:
        case VFF_MS_SHARED:
        {
            unsigned char
            *viff_colormap;

            /*
              Allocate VIFF colormap.
            */
            switch ((int) viff_info.map_storage_type)
            {
            case VFF_MAPTYP_1_BYTE:
                bytes_per_pixel=1;
                break;
            case VFF_MAPTYP_2_BYTE:
                bytes_per_pixel=2;
                break;
            case VFF_MAPTYP_4_BYTE:
                bytes_per_pixel=4;
                break;
            case VFF_MAPTYP_FLOAT:
                bytes_per_pixel=4;
                break;
            case VFF_MAPTYP_DOUBLE:
                bytes_per_pixel=8;
                break;
            default:
                bytes_per_pixel=1;
                break;
            }
            image->colors=viff_info.map_columns;
            if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
                ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
            viff_colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
                          viff_info.map_rows*bytes_per_pixel*sizeof(*viff_colormap));
            if (viff_colormap == (unsigned char *) NULL)
                ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
            /*
              Read VIFF raster colormap.
            */
            count=ReadBlob(image,bytes_per_pixel*image->colors*viff_info.map_rows,
                           viff_colormap);
            lsb_first=1;
            if (*(char *) &lsb_first &&
                    ((viff_info.machine_dependency != VFF_DEP_DECORDER) &&
                     (viff_info.machine_dependency != VFF_DEP_NSORDER)))
                switch ((int) viff_info.map_storage_type)
                {
                case VFF_MAPTYP_2_BYTE:
                {
                    MSBOrderShort(viff_colormap,(bytes_per_pixel*image->colors*
                                                 viff_info.map_rows));
                    break;
                }
                case VFF_MAPTYP_4_BYTE:
                case VFF_MAPTYP_FLOAT:
                {
                    MSBOrderLong(viff_colormap,(bytes_per_pixel*image->colors*
                                                viff_info.map_rows));
                    break;
                }
                default:
                    break;
                }
            for (i=0; i < (ssize_t) (viff_info.map_rows*image->colors); i++)
            {
                switch ((int) viff_info.map_storage_type)
                {
                case VFF_MAPTYP_2_BYTE:
                    value=1.0*((short *) viff_colormap)[i];
                    break;
                case VFF_MAPTYP_4_BYTE:
                    value=1.0*((int *) viff_colormap)[i];
                    break;
                case VFF_MAPTYP_FLOAT:
                    value=((float *) viff_colormap)[i];
                    break;
                case VFF_MAPTYP_DOUBLE:
                    value=((double *) viff_colormap)[i];
                    break;
                default:
                    value=1.0*viff_colormap[i];
                    break;
                }
                if (i < (ssize_t) image->colors)
                {
                    image->colormap[i].red=ScaleCharToQuantum((unsigned char) value);
                    image->colormap[i].green=
                        ScaleCharToQuantum((unsigned char) value);
                    image->colormap[i].blue=ScaleCharToQuantum((unsigned char) value);
                }
                else if (i < (ssize_t) (2*image->colors))
                    image->colormap[i % image->colors].green=
                        ScaleCharToQuantum((unsigned char) value);
                else if (i < (ssize_t) (3*image->colors))
                    image->colormap[i % image->colors].blue=
                        ScaleCharToQuantum((unsigned char) value);
            }
            viff_colormap=(unsigned char *) RelinquishMagickMemory(viff_colormap);
            break;
        }
        default:
            ThrowReaderException(CoderError,"ColormapTypeNotSupported");
        }
        /*
          Initialize image structure.
        */
        image->alpha_trait=viff_info.number_data_bands == 4 ? BlendPixelTrait :
                           UndefinedPixelTrait;
        image->storage_class=(viff_info.number_data_bands < 3 ? PseudoClass :
                              DirectClass);
        image->columns=viff_info.rows;
        image->rows=viff_info.columns;
        if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
            if (image->scene >= (image_info->scene+image_info->number_scenes-1))
                break;
        /*
          Allocate VIFF pixels.
        */
        switch ((int) viff_info.data_storage_type)
        {
        case VFF_TYP_2_BYTE:
            bytes_per_pixel=2;
            break;
        case VFF_TYP_4_BYTE:
            bytes_per_pixel=4;
            break;
        case VFF_TYP_FLOAT:
            bytes_per_pixel=4;
            break;
        case VFF_TYP_DOUBLE:
            bytes_per_pixel=8;
            break;
        default:
            bytes_per_pixel=1;
            break;
        }
        if (viff_info.data_storage_type == VFF_TYP_BIT)
            max_packets=((image->columns+7UL) >> 3UL)*image->rows;
        else
            max_packets=(size_t) (number_pixels*viff_info.number_data_bands);
        viff_pixels=(unsigned char *) AcquireQuantumMemory(max_packets,
                    bytes_per_pixel*sizeof(*viff_pixels));
        if (viff_pixels == (unsigned char *) NULL)
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        count=ReadBlob(image,bytes_per_pixel*max_packets,viff_pixels);
        lsb_first=1;
        if (*(char *) &lsb_first &&
                ((viff_info.machine_dependency != VFF_DEP_DECORDER) &&
                 (viff_info.machine_dependency != VFF_DEP_NSORDER)))
            switch ((int) viff_info.data_storage_type)
            {
            case VFF_TYP_2_BYTE:
            {
                MSBOrderShort(viff_pixels,bytes_per_pixel*max_packets);
                break;
            }
            case VFF_TYP_4_BYTE:
            case VFF_TYP_FLOAT:
            {
                MSBOrderLong(viff_pixels,bytes_per_pixel*max_packets);
                break;
            }
            default:
                break;
            }
        min_value=0.0;
        scale_factor=1.0;
        if ((viff_info.data_storage_type != VFF_TYP_1_BYTE) &&
                (viff_info.map_scheme == VFF_MS_NONE))
        {
            double
            max_value;

            /*
              Determine scale factor.
            */
            switch ((int) viff_info.data_storage_type)
            {
            case VFF_TYP_2_BYTE:
                value=1.0*((short *) viff_pixels)[0];
                break;
            case VFF_TYP_4_BYTE:
                value=1.0*((int *) viff_pixels)[0];
                break;
            case VFF_TYP_FLOAT:
                value=((float *) viff_pixels)[0];
                break;
            case VFF_TYP_DOUBLE:
                value=((double *) viff_pixels)[0];
                break;
            default:
                value=1.0*viff_pixels[0];
                break;
            }
            max_value=value;
            min_value=value;
            for (i=0; i < (ssize_t) max_packets; i++)
            {
                switch ((int) viff_info.data_storage_type)
                {
                case VFF_TYP_2_BYTE:
                    value=1.0*((short *) viff_pixels)[i];
                    break;
                case VFF_TYP_4_BYTE:
                    value=1.0*((int *) viff_pixels)[i];
                    break;
                case VFF_TYP_FLOAT:
                    value=((float *) viff_pixels)[i];
                    break;
                case VFF_TYP_DOUBLE:
                    value=((double *) viff_pixels)[i];
                    break;
                default:
                    value=1.0*viff_pixels[i];
                    break;
                }
                if (value > max_value)
                    max_value=value;
                else if (value < min_value)
                    min_value=value;
            }
            if ((min_value == 0) && (max_value == 0))
                scale_factor=0;
            else if (min_value == max_value)
            {
                scale_factor=(double) QuantumRange/min_value;
                min_value=0;
            }
            else
                scale_factor=(double) QuantumRange/(max_value-min_value);
        }
        /*
          Convert pixels to Quantum size.
        */
        p=(unsigned char *) viff_pixels;
        for (i=0; i < (ssize_t) max_packets; i++)
        {
            switch ((int) viff_info.data_storage_type)
            {
            case VFF_TYP_2_BYTE:
                value=1.0*((short *) viff_pixels)[i];
                break;
            case VFF_TYP_4_BYTE:
                value=1.0*((int *) viff_pixels)[i];
                break;
            case VFF_TYP_FLOAT:
                value=((float *) viff_pixels)[i];
                break;
            case VFF_TYP_DOUBLE:
                value=((double *) viff_pixels)[i];
                break;
            default:
                value=1.0*viff_pixels[i];
                break;
            }
            if (viff_info.map_scheme == VFF_MS_NONE)
            {
                value=(value-min_value)*scale_factor;
                if (value > QuantumRange)
                    value=QuantumRange;
                else if (value < 0)
                    value=0;
            }
            *p=(unsigned char) value;
            p++;
        }
        /*
          Convert VIFF raster image to pixel packets.
        */
        p=(unsigned char *) viff_pixels;
        if (viff_info.data_storage_type == VFF_TYP_BIT)
        {
            /*
              Convert bitmap scanline.
            */
            (void) SetImageType(image,BilevelType,exception);
            (void) SetImageType(image,PaletteType,exception);
            for (y=0; y < (ssize_t) image->rows; y++)
            {
                q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
                if (q == (Quantum *) NULL)
                    break;
                for (x=0; x < (ssize_t) (image->columns-7); x+=8)
                {
                    for (bit=0; bit < 8; bit++)
                    {
                        if (GetPixelLuma(image,q) < (QuantumRange/2.0))
                        {
                            quantum=(size_t) GetPixelIndex(image,q);
                            quantum|=0x01;
                            SetPixelIndex(image,quantum,q);
                        }
                        q+=GetPixelChannels(image);
                    }
                    p++;
                }
                if ((image->columns % 8) != 0)
                {
                    for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)
                        if (GetPixelLuma(image,q) < (QuantumRange/2.0))
                        {
                            quantum=(size_t) GetPixelIndex(image,q);
                            quantum|=0x01;
                            SetPixelIndex(image,quantum,q);
                            q+=GetPixelChannels(image);
                        }
                    p++;
                }
                if (SyncAuthenticPixels(image,exception) == MagickFalse)
                    break;
                if (image->previous == (Image *) NULL)
                {
                    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                                            image->rows);
                    if (status == MagickFalse)
                        break;
                }
            }
        }
        else if (image->storage_class == PseudoClass)
            for (y=0; y < (ssize_t) image->rows; y++)
            {
                q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
                if (q == (Quantum *) NULL)
                    break;
                for (x=0; x < (ssize_t) image->columns; x++)
                {
                    SetPixelIndex(image,*p++,q);
                    q+=GetPixelChannels(image);
                }
                if (SyncAuthenticPixels(image,exception) == MagickFalse)
                    break;
                if (image->previous == (Image *) NULL)
                {
                    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                                            image->rows);
                    if (status == MagickFalse)
                        break;
                }
            }
        else
        {
            /*
              Convert DirectColor scanline.
            */
            number_pixels=(MagickSizeType) image->columns*image->rows;
            for (y=0; y < (ssize_t) image->rows; y++)
            {
                q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
                if (q == (Quantum *) NULL)
                    break;
                for (x=0; x < (ssize_t) image->columns; x++)
                {
                    SetPixelRed(image,ScaleCharToQuantum(*p),q);
                    SetPixelGreen(image,ScaleCharToQuantum(*(p+number_pixels)),q);
                    SetPixelBlue(image,ScaleCharToQuantum(*(p+2*number_pixels)),q);
                    if (image->colors != 0)
                    {
                        SetPixelRed(image,image->colormap[(ssize_t)
                                                          GetPixelRed(image,q)].red,q);
                        SetPixelGreen(image,image->colormap[(ssize_t)
                                                            GetPixelGreen(image,q)].green,q);
                        SetPixelBlue(image,image->colormap[(ssize_t)
                                                           GetPixelBlue(image,q)].blue,q);
                    }
                    SetPixelAlpha(image,image->alpha_trait == BlendPixelTrait ?
                                  ScaleCharToQuantum(*(p+number_pixels*3)) : OpaqueAlpha,q);
                    p++;
                    q+=GetPixelChannels(image);
                }
                if (SyncAuthenticPixels(image,exception) == MagickFalse)
                    break;
                if (image->previous == (Image *) NULL)
                {
                    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                                            image->rows);
                    if (status == MagickFalse)
                        break;
                }
            }
        }
        viff_pixels=(unsigned char *) RelinquishMagickMemory(viff_pixels);
        if (image->storage_class == PseudoClass)
            (void) SyncImage(image,exception);
        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;
        count=ReadBlob(image,1,&viff_info.identifier);
        if ((count != 0) && (viff_info.identifier == 0xab))
        {
            /*
              Allocate next image structure.
            */
            AcquireNextImage(image_info,image,exception);
            if (GetNextImageInList(image) == (Image *) NULL)
            {
                image=DestroyImageList(image);
                return((Image *) NULL);
            }
            image=SyncNextImageInList(image);
            status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
                                    GetBlobSize(image));
            if (status == MagickFalse)
                break;
        }
    } while ((count != 0) && (viff_info.identifier == 0xab));
Пример #8
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   W r i t e U I L I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Procedure WriteUILImage() writes an image to a file in the X-Motif UIL table
%  format.
%
%  The format of the WriteUILImage method is:
%
%      MagickBooleanType WriteUILImage(const ImageInfo *image_info,
%        Image *image,ExceptionInfo *exception)
%
%  A description of each parameter follows.
%
%    o image_info: the image info.
%
%    o image:  The image.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static MagickBooleanType WriteUILImage(const ImageInfo *image_info,Image *image,
                                       ExceptionInfo *exception)
{
#define MaxCixels  92

    char
    basename[MagickPathExtent],
             buffer[MagickPathExtent],
             name[MagickPathExtent],
             *symbol;

    int
    j;

    MagickBooleanType
    status,
    transparent;

    MagickSizeType
    number_pixels;

    PixelInfo
    pixel;

    register const Quantum
    *p;

    register ssize_t
    i,
    x;

    size_t
    characters_per_pixel,
    colors;

    ssize_t
    k,
    y;

    static const char
    Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk"
                         "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";

    /*
      Open output image file.
    */
    assert(image_info != (const ImageInfo *) NULL);
    assert(image_info->signature == MagickCoreSignature);
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
        (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    assert(exception != (ExceptionInfo *) NULL);
    assert(exception->signature == MagickCoreSignature);
    status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
    if (status == MagickFalse)
        return(status);
    (void) TransformImageColorspace(image,sRGBColorspace,exception);
    transparent=MagickFalse;
    i=0;
    p=(const Quantum *) NULL;
    if (image->storage_class == PseudoClass)
        colors=image->colors;
    else
    {
        unsigned char
        *matte_image;

        /*
          Convert DirectClass to PseudoClass image.
        */
        matte_image=(unsigned char *) NULL;
        if (image->alpha_trait != UndefinedPixelTrait)
        {
            /*
              Map all the transparent pixels.
            */
            number_pixels=(MagickSizeType) image->columns*image->rows;
            if (number_pixels != ((MagickSizeType) (size_t) number_pixels))
                ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
            matte_image=(unsigned char *) AcquireQuantumMemory(image->columns,
                        image->rows*sizeof(*matte_image));
            if (matte_image == (unsigned char *) NULL)
                ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
            for (y=0; y < (ssize_t) image->rows; y++)
            {
                p=GetVirtualPixels(image,0,y,image->columns,1,exception);
                if (p == (const Quantum *) NULL)
                    break;
                for (x=0; x < (ssize_t) image->columns; x++)
                {
                    matte_image[i]=(unsigned char) (GetPixelAlpha(image,p) ==
                                                    (Quantum) TransparentAlpha ? 1 : 0);
                    if (matte_image[i] != 0)
                        transparent=MagickTrue;
                    i++;
                    p+=GetPixelChannels(image);
                }
            }
        }
        (void) SetImageType(image,PaletteType,exception);
        colors=image->colors;
        if (transparent != MagickFalse)
        {
            register Quantum
            *q;

            colors++;
            for (y=0; y < (ssize_t) image->rows; y++)
            {
                q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
                if (q == (Quantum *) NULL)
                    break;
                for (x=0; x < (ssize_t) image->columns; x++)
                {
                    if (matte_image[i] != 0)
                        SetPixelIndex(image,(Quantum) image->colors,q);
                    q+=GetPixelChannels(image);
                }
            }
        }
        if (matte_image != (unsigned char *) NULL)
            matte_image=(unsigned char *) RelinquishMagickMemory(matte_image);
    }
    /*
      Compute the character per pixel.
    */
    characters_per_pixel=1;
    for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels)
        characters_per_pixel++;
    /*
      UIL header.
    */
    symbol=AcquireString("");
    (void) WriteBlobString(image,"/* UIL */\n");
    GetPathComponent(image->filename,BasePath,basename);
    (void) FormatLocaleString(buffer,MagickPathExtent,
                              "value\n  %s_ct : color_table(\n",basename);
    (void) WriteBlobString(image,buffer);
    GetPixelInfo(image,&pixel);
    for (i=0; i < (ssize_t) colors; i++)
    {
        /*
          Define UIL color.
        */
        pixel=image->colormap[i];
        pixel.colorspace=sRGBColorspace;
        pixel.depth=8;
        pixel.alpha=(double) OpaqueAlpha;
        GetColorTuple(&pixel,MagickTrue,name);
        if (transparent != MagickFalse)
            if (i == (ssize_t) (colors-1))
                (void) CopyMagickString(name,"None",MagickPathExtent);
        /*
          Write UIL color.
        */
        k=i % MaxCixels;
        symbol[0]=Cixel[k];
        for (j=1; j < (int) characters_per_pixel; j++)
        {
            k=((i-k)/MaxCixels) % MaxCixels;
            symbol[j]=Cixel[k];
        }
        symbol[j]='\0';
        (void) SubstituteString(&symbol,"'","''");
        if (LocaleCompare(name,"None") == 0)
            (void) FormatLocaleString(buffer,MagickPathExtent,
                                      "    background color = '%s'",symbol);
        else
            (void) FormatLocaleString(buffer,MagickPathExtent,
                                      "    color('%s',%s) = '%s'",name,
                                      GetPixelInfoIntensity(image,image->colormap+i) <
                                      (QuantumRange/2.0) ? "background" : "foreground",symbol);
        (void) WriteBlobString(image,buffer);
        (void) FormatLocaleString(buffer,MagickPathExtent,"%s",
                                  (i == (ssize_t) (colors-1) ? ");\n" : ",\n"));
        (void) WriteBlobString(image,buffer);
    }
    /*
      Define UIL pixels.
    */
    GetPathComponent(image->filename,BasePath,basename);
    (void) FormatLocaleString(buffer,MagickPathExtent,
                              "  %s_icon : icon(color_table = %s_ct,\n",basename,basename);
    (void) WriteBlobString(image,buffer);
    for (y=0; y < (ssize_t) image->rows; y++)
    {
        p=GetVirtualPixels(image,0,y,image->columns,1,exception);
        if (p == (const Quantum *) NULL)
            break;
        (void) WriteBlobString(image,"    \"");
        for (x=0; x < (ssize_t) image->columns; x++)
        {
            k=((ssize_t) GetPixelIndex(image,p) % MaxCixels);
            symbol[0]=Cixel[k];
            for (j=1; j < (int) characters_per_pixel; j++)
            {
                k=(((int) GetPixelIndex(image,p)-k)/MaxCixels) %
                  MaxCixels;
                symbol[j]=Cixel[k];
            }
            symbol[j]='\0';
            (void) CopyMagickString(buffer,symbol,MagickPathExtent);
            (void) WriteBlobString(image,buffer);
            p+=GetPixelChannels(image);
        }
        (void) FormatLocaleString(buffer,MagickPathExtent,"\"%s\n",
                                  (y == (ssize_t) (image->rows-1) ? ");" : ","));
        (void) WriteBlobString(image,buffer);
        status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
                                image->rows);
        if (status == MagickFalse)
            break;
    }
    symbol=DestroyString(symbol);
    (void) CloseBlob(image);
    return(MagickTrue);
}
Пример #9
0
static MagickBooleanType ForwardFourierTransform(FourierInfo *fourier_info,
  const Image *image,double *magnitude,double *phase,ExceptionInfo *exception)
{
  CacheView
    *image_view;

  double
    n,
    *source;

  fftw_complex
    *fourier;

  fftw_plan
    fftw_r2c_plan;

  register const IndexPacket
    *indexes;

  register const PixelPacket
    *p;

  register ssize_t
    i,
    x;

  ssize_t
    y;

  /*
    Generate the forward Fourier transform.
  */
  source=(double *) AcquireQuantumMemory((size_t) fourier_info->height,
    fourier_info->width*sizeof(*source));
  if (source == (double *) NULL)
    {
      (void) ThrowMagickException(exception,GetMagickModule(),
        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
      return(MagickFalse);
    }
  ResetMagickMemory(source,0,fourier_info->height*fourier_info->width*
    sizeof(*source));
  i=0L;
  image_view=AcquireVirtualCacheView(image,exception);
  for (y=0L; y < (ssize_t) fourier_info->height; y++)
  {
    p=GetCacheViewVirtualPixels(image_view,0L,y,fourier_info->width,1UL,
      exception);
    if (p == (const PixelPacket *) NULL)
      break;
    indexes=GetCacheViewVirtualIndexQueue(image_view);
    for (x=0L; x < (ssize_t) fourier_info->width; x++)
    {
      switch (fourier_info->channel)
      {
        case RedChannel:
        default:
        {
          source[i]=QuantumScale*GetPixelRed(p);
          break;
        }
        case GreenChannel:
        {
          source[i]=QuantumScale*GetPixelGreen(p);
          break;
        }
        case BlueChannel:
        {
          source[i]=QuantumScale*GetPixelBlue(p);
          break;
        }
        case OpacityChannel:
        {
          source[i]=QuantumScale*GetPixelOpacity(p);
          break;
        }
        case IndexChannel:
        {
          source[i]=QuantumScale*GetPixelIndex(indexes+x);
          break;
        }
        case GrayChannels:
        {
          source[i]=QuantumScale*GetPixelGray(p);
          break;
        }
      }
      i++;
      p++;
    }
  }
  image_view=DestroyCacheView(image_view);
  fourier=(fftw_complex *) AcquireQuantumMemory((size_t) fourier_info->height,
    fourier_info->center*sizeof(*fourier));
  if (fourier == (fftw_complex *) NULL)
    {
      (void) ThrowMagickException(exception,GetMagickModule(),
        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
      source=(double *) RelinquishMagickMemory(source);
      return(MagickFalse);
    }
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp critical (MagickCore_ForwardFourierTransform)
#endif
  fftw_r2c_plan=fftw_plan_dft_r2c_2d(fourier_info->width,fourier_info->width,
    source,fourier,FFTW_ESTIMATE);
  fftw_execute(fftw_r2c_plan);
  fftw_destroy_plan(fftw_r2c_plan);
  source=(double *) RelinquishMagickMemory(source);
  /*
    Normalize Fourier transform.
  */
  n=(double) fourier_info->width*(double) fourier_info->width;
  i=0L;
  for (y=0L; y < (ssize_t) fourier_info->height; y++)
    for (x=0L; x < (ssize_t) fourier_info->center; x++)
    {
#if defined(MAGICKCORE_HAVE_COMPLEX_H)
      fourier[i]/=n;
#else
      fourier[i][0]/=n;
      fourier[i][1]/=n;
#endif
      i++;
    }
  /*
    Generate magnitude and phase (or real and imaginary).
  */
  i=0L;
  if (fourier_info->modulus != MagickFalse)
    for (y=0L; y < (ssize_t) fourier_info->height; y++)
      for (x=0L; x < (ssize_t) fourier_info->center; x++)
      {
        magnitude[i]=cabs(fourier[i]);
        phase[i]=carg(fourier[i]);
        i++;
      }
  else
    for (y=0L; y < (ssize_t) fourier_info->height; y++)
      for (x=0L; x < (ssize_t) fourier_info->center; x++)
      {
        magnitude[i]=creal(fourier[i]);
        phase[i]=cimag(fourier[i]);
        i++;
      }
  fourier=(fftw_complex *) RelinquishMagickMemory(fourier);
  return(MagickTrue);
}
Пример #10
0
static MagickBooleanType WriteVIPSImage(const ImageInfo *image_info,
  Image *image)
{
  const char
    *metadata;

  MagickBooleanType
    status;

  register const IndexPacket
    *indexes;

  register const PixelPacket
    *p;

  register ssize_t
    x;

  ssize_t
    y;

  unsigned int
    channels;

  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);

  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
  if (status == MagickFalse)
    return(status);
  if (image->endian == LSBEndian)
    (void) WriteBlobLSBLong(image,VIPS_MAGIC_LSB);
  else
    (void) WriteBlobLSBLong(image,VIPS_MAGIC_MSB);
  (void) WriteBlobLong(image,(unsigned int) image->columns);
  (void) WriteBlobLong(image,(unsigned int) image->rows);
  (void) SetImageStorageClass(image,DirectClass);
  channels=image->matte ? 4 : 3;
  if (SetImageGray(image,&image->exception) != MagickFalse)
    channels=image->matte ? 2 : 1;
  else if (image->colorspace == CMYKColorspace)
    channels=image->matte ? 5 : 4;
  (void) WriteBlobLong(image,channels);
  (void) WriteBlobLong(image,0);
  if (image->depth == 16)
    (void) WriteBlobLong(image,(unsigned int) VIPSBandFormatUSHORT);
  else
    {
      image->depth=8;
      (void) WriteBlobLong(image,(unsigned int) VIPSBandFormatUCHAR);
    }
  (void) WriteBlobLong(image,VIPSCodingNONE);
  switch(image->colorspace)
  {
    case CMYKColorspace:
      (void) WriteBlobLong(image,VIPSTypeCMYK);
      break;
    case GRAYColorspace:
      if (image->depth == 16)
        (void) WriteBlobLong(image, VIPSTypeGREY16);
      else
        (void) WriteBlobLong(image, VIPSTypeB_W);
      break;
    case RGBColorspace:
      if (image->depth == 16)
        (void) WriteBlobLong(image, VIPSTypeRGB16);
      else
        (void) WriteBlobLong(image, VIPSTypeRGB);
      break;
    default:
    case sRGBColorspace:
      (void) SetImageColorspace(image,sRGBColorspace);
      (void) WriteBlobLong(image,VIPSTypesRGB);
      break;
  }
  if (image->units == PixelsPerCentimeterResolution)
    {
      (void) WriteBlobFloat(image,(image->x_resolution / 10));
      (void) WriteBlobFloat(image,(image->y_resolution / 10));
    }
  else if (image->units == PixelsPerInchResolution)
    {
      (void) WriteBlobFloat(image,(image->x_resolution / 25.4));
      (void) WriteBlobFloat(image,(image->y_resolution / 25.4));
    }
  else
    {
      (void) WriteBlobLong(image,0);
      (void) WriteBlobLong(image,0);
    }
  /*
    Legacy, Offsets, Future
  */
  for (y=0; y < 24; y++)
    (void) WriteBlobByte(image,0);
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
    if (p == (const PixelPacket *) NULL)
      break;
    indexes=GetVirtualIndexQueue(image);
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      WriteVIPSPixel(image,GetPixelRed(p));
      if (channels == 2)
        WriteVIPSPixel(image,GetPixelAlpha(p));
      else
        {
          WriteVIPSPixel(image,GetPixelGreen(p));
          WriteVIPSPixel(image,GetPixelBlue(p));
          if (channels >= 4)
            {
              if (image->colorspace == CMYKColorspace)
                WriteVIPSPixel(image,GetPixelIndex(indexes+x));
              else
                WriteVIPSPixel(image,GetPixelAlpha(p));
            }
          else if (channels == 5)
            {
               WriteVIPSPixel(image,GetPixelIndex(indexes+x));
               WriteVIPSPixel(image,GetPixelAlpha(p));
            }
        }
      p++;
    }
  }
  metadata=GetImageProperty(image,"vips:metadata");
  if (metadata != (const char*) NULL)
    WriteBlobString(image,metadata);
  (void) CloseBlob(image);
  return(status);
}
Пример #11
0
MagickExport ChannelFeatures *GetImageChannelFeatures(const Image *image,
  const size_t distance,ExceptionInfo *exception)
{
  typedef struct _ChannelStatistics
  {
    DoublePixelPacket
      direction[4];  /* horizontal, vertical, left and right diagonals */
  } ChannelStatistics;

  CacheView
    *image_view;

  ChannelFeatures
    *channel_features;

  ChannelStatistics
    **cooccurrence,
    correlation,
    *density_x,
    *density_xy,
    *density_y,
    entropy_x,
    entropy_xy,
    entropy_xy1,
    entropy_xy2,
    entropy_y,
    mean,
    **Q,
    *sum,
    sum_squares,
    variance;

  LongPixelPacket
    gray,
    *grays;

  MagickBooleanType
    status;

  register ssize_t
    i;

  size_t
    length;

  ssize_t
    y;

  unsigned int
    number_grays;

  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  if ((image->columns < (distance+1)) || (image->rows < (distance+1)))
    return((ChannelFeatures *) NULL);
  length=CompositeChannels+1UL;
  channel_features=(ChannelFeatures *) AcquireQuantumMemory(length,
    sizeof(*channel_features));
  if (channel_features == (ChannelFeatures *) NULL)
    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
  (void) ResetMagickMemory(channel_features,0,length*
    sizeof(*channel_features));
  /*
    Form grays.
  */
  grays=(LongPixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*grays));
  if (grays == (LongPixelPacket *) NULL)
    {
      channel_features=(ChannelFeatures *) RelinquishMagickMemory(
        channel_features);
      (void) ThrowMagickException(exception,GetMagickModule(),
        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
      return(channel_features);
    }
  for (i=0; i <= (ssize_t) MaxMap; i++)
  {
    grays[i].red=(~0U);
    grays[i].green=(~0U);
    grays[i].blue=(~0U);
    grays[i].opacity=(~0U);
    grays[i].index=(~0U);
  }
  status=MagickTrue;
  image_view=AcquireCacheView(image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register const IndexPacket
      *restrict indexes;

    register const PixelPacket
      *restrict p;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
    if (p == (const PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewVirtualIndexQueue(image_view);
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      grays[ScaleQuantumToMap(GetPixelRed(p))].red=
        ScaleQuantumToMap(GetPixelRed(p));
      grays[ScaleQuantumToMap(GetPixelGreen(p))].green=
        ScaleQuantumToMap(GetPixelGreen(p));
      grays[ScaleQuantumToMap(GetPixelBlue(p))].blue=
        ScaleQuantumToMap(GetPixelBlue(p));
      if (image->colorspace == CMYKColorspace)
        grays[ScaleQuantumToMap(GetPixelIndex(indexes+x))].index=
          ScaleQuantumToMap(GetPixelIndex(indexes+x));
      if (image->matte != MagickFalse)
        grays[ScaleQuantumToMap(GetPixelOpacity(p))].opacity=
          ScaleQuantumToMap(GetPixelOpacity(p));
      p++;
    }
  }
  image_view=DestroyCacheView(image_view);
  if (status == MagickFalse)
    {
      grays=(LongPixelPacket *) RelinquishMagickMemory(grays);
      channel_features=(ChannelFeatures *) RelinquishMagickMemory(
        channel_features);
      return(channel_features);
    }
  (void) ResetMagickMemory(&gray,0,sizeof(gray));
  for (i=0; i <= (ssize_t) MaxMap; i++)
  {
    if (grays[i].red != ~0U)
      grays[(ssize_t) gray.red++].red=grays[i].red;
    if (grays[i].green != ~0U)
      grays[(ssize_t) gray.green++].green=grays[i].green;
    if (grays[i].blue != ~0U)
      grays[(ssize_t) gray.blue++].blue=grays[i].blue;
    if (image->colorspace == CMYKColorspace)
      if (grays[i].index != ~0U)
        grays[(ssize_t) gray.index++].index=grays[i].index;
    if (image->matte != MagickFalse)
      if (grays[i].opacity != ~0U)
        grays[(ssize_t) gray.opacity++].opacity=grays[i].opacity;
  }
  /*
    Allocate spatial dependence matrix.
  */
  number_grays=gray.red;
  if (gray.green > number_grays)
    number_grays=gray.green;
  if (gray.blue > number_grays)
    number_grays=gray.blue;
  if (image->colorspace == CMYKColorspace)
    if (gray.index > number_grays)
      number_grays=gray.index;
  if (image->matte != MagickFalse)
    if (gray.opacity > number_grays)
      number_grays=gray.opacity;
  cooccurrence=(ChannelStatistics **) AcquireQuantumMemory(number_grays,
    sizeof(*cooccurrence));
  density_x=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1),
    sizeof(*density_x));
  density_xy=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1),
    sizeof(*density_xy));
  density_y=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1),
    sizeof(*density_y));
  Q=(ChannelStatistics **) AcquireQuantumMemory(number_grays,sizeof(*Q));
  sum=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(*sum));
  if ((cooccurrence == (ChannelStatistics **) NULL) ||
      (density_x == (ChannelStatistics *) NULL) ||
      (density_xy == (ChannelStatistics *) NULL) ||
      (density_y == (ChannelStatistics *) NULL) ||
      (Q == (ChannelStatistics **) NULL) ||
      (sum == (ChannelStatistics *) NULL))
    {
      if (Q != (ChannelStatistics **) NULL)
        {
          for (i=0; i < (ssize_t) number_grays; i++)
            Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]);
          Q=(ChannelStatistics **) RelinquishMagickMemory(Q);
        }
      if (sum != (ChannelStatistics *) NULL)
        sum=(ChannelStatistics *) RelinquishMagickMemory(sum);
      if (density_y != (ChannelStatistics *) NULL)
        density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y);
      if (density_xy != (ChannelStatistics *) NULL)
        density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy);
      if (density_x != (ChannelStatistics *) NULL)
        density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x);
      if (cooccurrence != (ChannelStatistics **) NULL)
        {
          for (i=0; i < (ssize_t) number_grays; i++)
            cooccurrence[i]=(ChannelStatistics *)
              RelinquishMagickMemory(cooccurrence[i]);
          cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(
            cooccurrence);
        }
      grays=(LongPixelPacket *) RelinquishMagickMemory(grays);
      channel_features=(ChannelFeatures *) RelinquishMagickMemory(
        channel_features);
      (void) ThrowMagickException(exception,GetMagickModule(),
        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
      return(channel_features);
    }
  (void) ResetMagickMemory(&correlation,0,sizeof(correlation));
  (void) ResetMagickMemory(density_x,0,2*(number_grays+1)*sizeof(*density_x));
  (void) ResetMagickMemory(density_xy,0,2*(number_grays+1)*sizeof(*density_xy));
  (void) ResetMagickMemory(density_y,0,2*(number_grays+1)*sizeof(*density_y));
  (void) ResetMagickMemory(&mean,0,sizeof(mean));
  (void) ResetMagickMemory(sum,0,number_grays*sizeof(*sum));
  (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares));
  (void) ResetMagickMemory(density_xy,0,2*number_grays*sizeof(*density_xy));
  (void) ResetMagickMemory(&entropy_x,0,sizeof(entropy_x));
  (void) ResetMagickMemory(&entropy_xy,0,sizeof(entropy_xy));
  (void) ResetMagickMemory(&entropy_xy1,0,sizeof(entropy_xy1));
  (void) ResetMagickMemory(&entropy_xy2,0,sizeof(entropy_xy2));
  (void) ResetMagickMemory(&entropy_y,0,sizeof(entropy_y));
  (void) ResetMagickMemory(&variance,0,sizeof(variance));
  for (i=0; i < (ssize_t) number_grays; i++)
  {
    cooccurrence[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,
      sizeof(**cooccurrence));
    Q[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(**Q));
    if ((cooccurrence[i] == (ChannelStatistics *) NULL) ||
        (Q[i] == (ChannelStatistics *) NULL))
      break;
    (void) ResetMagickMemory(cooccurrence[i],0,number_grays*
      sizeof(**cooccurrence));
    (void) ResetMagickMemory(Q[i],0,number_grays*sizeof(**Q));
  }
  if (i < (ssize_t) number_grays)
    {
      for (i--; i >= 0; i--)
      {
        if (Q[i] != (ChannelStatistics *) NULL)
          Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]);
        if (cooccurrence[i] != (ChannelStatistics *) NULL)
          cooccurrence[i]=(ChannelStatistics *)
            RelinquishMagickMemory(cooccurrence[i]);
      }
      Q=(ChannelStatistics **) RelinquishMagickMemory(Q);
      cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence);
      sum=(ChannelStatistics *) RelinquishMagickMemory(sum);
      density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y);
      density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy);
      density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x);
      grays=(LongPixelPacket *) RelinquishMagickMemory(grays);
      channel_features=(ChannelFeatures *) RelinquishMagickMemory(
        channel_features);
      (void) ThrowMagickException(exception,GetMagickModule(),
        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
      return(channel_features);
    }
  /*
    Initialize spatial dependence matrix.
  */
  status=MagickTrue;
  image_view=AcquireCacheView(image);
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register const IndexPacket
      *restrict indexes;

    register const PixelPacket
      *restrict p;

    register ssize_t
      x;

    ssize_t
      i,
      offset,
      u,
      v;

    if (status == MagickFalse)
      continue;
    p=GetCacheViewVirtualPixels(image_view,-(ssize_t) distance,y,image->columns+
      2*distance,distance+2,exception);
    if (p == (const PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewVirtualIndexQueue(image_view);
    p+=distance;
    indexes+=distance;
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      for (i=0; i < 4; i++)
      {
        switch (i)
        {
          case 0:
          default:
          {
            /*
              Horizontal adjacency.
            */
            offset=(ssize_t) distance;
            break;
          }
          case 1:
          {
            /*
              Vertical adjacency.
            */
            offset=(ssize_t) (image->columns+2*distance);
            break;
          }
          case 2:
          {
            /*
              Right diagonal adjacency.
            */
            offset=(ssize_t) ((image->columns+2*distance)-distance);
            break;
          }
          case 3:
          {
            /*
              Left diagonal adjacency.
            */
            offset=(ssize_t) ((image->columns+2*distance)+distance);
            break;
          }
        }
        u=0;
        v=0;
        while (grays[u].red != ScaleQuantumToMap(GetPixelRed(p)))
          u++;
        while (grays[v].red != ScaleQuantumToMap(GetPixelRed(p+offset)))
          v++;
        cooccurrence[u][v].direction[i].red++;
        cooccurrence[v][u].direction[i].red++;
        u=0;
        v=0;
        while (grays[u].green != ScaleQuantumToMap(GetPixelGreen(p)))
          u++;
        while (grays[v].green != ScaleQuantumToMap(GetPixelGreen(p+offset)))
          v++;
        cooccurrence[u][v].direction[i].green++;
        cooccurrence[v][u].direction[i].green++;
        u=0;
        v=0;
        while (grays[u].blue != ScaleQuantumToMap(GetPixelBlue(p)))
          u++;
        while (grays[v].blue != ScaleQuantumToMap((p+offset)->blue))
          v++;
        cooccurrence[u][v].direction[i].blue++;
        cooccurrence[v][u].direction[i].blue++;
        if (image->colorspace == CMYKColorspace)
          {
            u=0;
            v=0;
            while (grays[u].index != ScaleQuantumToMap(GetPixelIndex(indexes+x)))
              u++;
            while (grays[v].index != ScaleQuantumToMap(GetPixelIndex(indexes+x+offset)))
              v++;
            cooccurrence[u][v].direction[i].index++;
            cooccurrence[v][u].direction[i].index++;
          }
        if (image->matte != MagickFalse)
          {
            u=0;
            v=0;
            while (grays[u].opacity != ScaleQuantumToMap(GetPixelOpacity(p)))
              u++;
            while (grays[v].opacity != ScaleQuantumToMap((p+offset)->opacity))
              v++;
            cooccurrence[u][v].direction[i].opacity++;
            cooccurrence[v][u].direction[i].opacity++;
          }
      }
      p++;
    }
  }
  grays=(LongPixelPacket *) RelinquishMagickMemory(grays);
  image_view=DestroyCacheView(image_view);
  if (status == MagickFalse)
    {
      for (i=0; i < (ssize_t) number_grays; i++)
        cooccurrence[i]=(ChannelStatistics *)
          RelinquishMagickMemory(cooccurrence[i]);
      cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence);
      channel_features=(ChannelFeatures *) RelinquishMagickMemory(
        channel_features);
      (void) ThrowMagickException(exception,GetMagickModule(),
        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
      return(channel_features);
    }
  /*
    Normalize spatial dependence matrix.
  */
  for (i=0; i < 4; i++)
  {
    double
      normalize;

    register ssize_t
      y;

    switch (i)
    {
      case 0:
      default:
      {
        /*
          Horizontal adjacency.
        */
        normalize=2.0*image->rows*(image->columns-distance);
        break;
      }
      case 1:
      {
        /*
          Vertical adjacency.
        */
        normalize=2.0*(image->rows-distance)*image->columns;
        break;
      }
      case 2:
      {
        /*
          Right diagonal adjacency.
        */
        normalize=2.0*(image->rows-distance)*(image->columns-distance);
        break;
      }
      case 3:
      {
        /*
          Left diagonal adjacency.
        */
        normalize=2.0*(image->rows-distance)*(image->columns-distance);
        break;
      }
    }
    normalize=1.0/(fabs((double) normalize) <= MagickEpsilon ? 1.0 : normalize);
    for (y=0; y < (ssize_t) number_grays; y++)
    {
      register ssize_t
        x;

      for (x=0; x < (ssize_t) number_grays; x++)
      {
        cooccurrence[x][y].direction[i].red*=normalize;
        cooccurrence[x][y].direction[i].green*=normalize;
        cooccurrence[x][y].direction[i].blue*=normalize;
        if (image->colorspace == CMYKColorspace)
          cooccurrence[x][y].direction[i].index*=normalize;
        if (image->matte != MagickFalse)
          cooccurrence[x][y].direction[i].opacity*=normalize;
      }
    }
  }
  /*
    Compute texture features.
  */
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status)
#endif
  for (i=0; i < 4; i++)
  {
    register ssize_t
      y;

    for (y=0; y < (ssize_t) number_grays; y++)
    {
      register ssize_t
        x;

      for (x=0; x < (ssize_t) number_grays; x++)
      {
        /*
          Angular second moment:  measure of homogeneity of the image.
        */
        channel_features[RedChannel].angular_second_moment[i]+=
          cooccurrence[x][y].direction[i].red*
          cooccurrence[x][y].direction[i].red;
        channel_features[GreenChannel].angular_second_moment[i]+=
          cooccurrence[x][y].direction[i].green*
          cooccurrence[x][y].direction[i].green;
        channel_features[BlueChannel].angular_second_moment[i]+=
          cooccurrence[x][y].direction[i].blue*
          cooccurrence[x][y].direction[i].blue;
        if (image->colorspace == CMYKColorspace)
          channel_features[BlackChannel].angular_second_moment[i]+=
            cooccurrence[x][y].direction[i].index*
            cooccurrence[x][y].direction[i].index;
        if (image->matte != MagickFalse)
          channel_features[OpacityChannel].angular_second_moment[i]+=
            cooccurrence[x][y].direction[i].opacity*
            cooccurrence[x][y].direction[i].opacity;
        /*
          Correlation: measure of linear-dependencies in the image.
        */
        sum[y].direction[i].red+=cooccurrence[x][y].direction[i].red;
        sum[y].direction[i].green+=cooccurrence[x][y].direction[i].green;
        sum[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
        if (image->colorspace == CMYKColorspace)
          sum[y].direction[i].index+=cooccurrence[x][y].direction[i].index;
        if (image->matte != MagickFalse)
          sum[y].direction[i].opacity+=cooccurrence[x][y].direction[i].opacity;
        correlation.direction[i].red+=x*y*cooccurrence[x][y].direction[i].red;
        correlation.direction[i].green+=x*y*
          cooccurrence[x][y].direction[i].green;
        correlation.direction[i].blue+=x*y*
          cooccurrence[x][y].direction[i].blue;
        if (image->colorspace == CMYKColorspace)
          correlation.direction[i].index+=x*y*
            cooccurrence[x][y].direction[i].index;
        if (image->matte != MagickFalse)
          correlation.direction[i].opacity+=x*y*
            cooccurrence[x][y].direction[i].opacity;
        /*
          Inverse Difference Moment.
        */
        channel_features[RedChannel].inverse_difference_moment[i]+=
          cooccurrence[x][y].direction[i].red/((y-x)*(y-x)+1);
        channel_features[GreenChannel].inverse_difference_moment[i]+=
          cooccurrence[x][y].direction[i].green/((y-x)*(y-x)+1);
        channel_features[BlueChannel].inverse_difference_moment[i]+=
          cooccurrence[x][y].direction[i].blue/((y-x)*(y-x)+1);
        if (image->colorspace == CMYKColorspace)
          channel_features[IndexChannel].inverse_difference_moment[i]+=
            cooccurrence[x][y].direction[i].index/((y-x)*(y-x)+1);
        if (image->matte != MagickFalse)
          channel_features[OpacityChannel].inverse_difference_moment[i]+=
            cooccurrence[x][y].direction[i].opacity/((y-x)*(y-x)+1);
        /*
          Sum average.
        */
        density_xy[y+x+2].direction[i].red+=
          cooccurrence[x][y].direction[i].red;
        density_xy[y+x+2].direction[i].green+=
          cooccurrence[x][y].direction[i].green;
        density_xy[y+x+2].direction[i].blue+=
          cooccurrence[x][y].direction[i].blue;
        if (image->colorspace == CMYKColorspace)
          density_xy[y+x+2].direction[i].index+=
            cooccurrence[x][y].direction[i].index;
        if (image->matte != MagickFalse)
          density_xy[y+x+2].direction[i].opacity+=
            cooccurrence[x][y].direction[i].opacity;
        /*
          Entropy.
        */
        channel_features[RedChannel].entropy[i]-=
          cooccurrence[x][y].direction[i].red*
          log10(cooccurrence[x][y].direction[i].red+MagickEpsilon);
        channel_features[GreenChannel].entropy[i]-=
          cooccurrence[x][y].direction[i].green*
          log10(cooccurrence[x][y].direction[i].green+MagickEpsilon);
        channel_features[BlueChannel].entropy[i]-=
          cooccurrence[x][y].direction[i].blue*
          log10(cooccurrence[x][y].direction[i].blue+MagickEpsilon);
        if (image->colorspace == CMYKColorspace)
          channel_features[IndexChannel].entropy[i]-=
            cooccurrence[x][y].direction[i].index*
            log10(cooccurrence[x][y].direction[i].index+MagickEpsilon);
        if (image->matte != MagickFalse)
          channel_features[OpacityChannel].entropy[i]-=
            cooccurrence[x][y].direction[i].opacity*
            log10(cooccurrence[x][y].direction[i].opacity+MagickEpsilon);
        /*
          Information Measures of Correlation.
        */
        density_x[x].direction[i].red+=cooccurrence[x][y].direction[i].red;
        density_x[x].direction[i].green+=cooccurrence[x][y].direction[i].green;
        density_x[x].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
        if (image->colorspace == CMYKColorspace)
          density_x[x].direction[i].index+=
            cooccurrence[x][y].direction[i].index;
        if (image->matte != MagickFalse)
          density_x[x].direction[i].opacity+=
            cooccurrence[x][y].direction[i].opacity;
        density_y[y].direction[i].red+=cooccurrence[x][y].direction[i].red;
        density_y[y].direction[i].green+=cooccurrence[x][y].direction[i].green;
        density_y[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
        if (image->colorspace == CMYKColorspace)
          density_y[y].direction[i].index+=
            cooccurrence[x][y].direction[i].index;
        if (image->matte != MagickFalse)
          density_y[y].direction[i].opacity+=
            cooccurrence[x][y].direction[i].opacity;
      }
      mean.direction[i].red+=y*sum[y].direction[i].red;
      sum_squares.direction[i].red+=y*y*sum[y].direction[i].red;
      mean.direction[i].green+=y*sum[y].direction[i].green;
      sum_squares.direction[i].green+=y*y*sum[y].direction[i].green;
      mean.direction[i].blue+=y*sum[y].direction[i].blue;
      sum_squares.direction[i].blue+=y*y*sum[y].direction[i].blue;
      if (image->colorspace == CMYKColorspace)
        {
          mean.direction[i].index+=y*sum[y].direction[i].index;
          sum_squares.direction[i].index+=y*y*sum[y].direction[i].index;
        }
      if (image->matte != MagickFalse)
        {
          mean.direction[i].opacity+=y*sum[y].direction[i].opacity;
          sum_squares.direction[i].opacity+=y*y*sum[y].direction[i].opacity;
        }
    }
    /*
      Correlation: measure of linear-dependencies in the image.
    */
    channel_features[RedChannel].correlation[i]=
      (correlation.direction[i].red-mean.direction[i].red*
      mean.direction[i].red)/(sqrt(sum_squares.direction[i].red-
      (mean.direction[i].red*mean.direction[i].red))*sqrt(
      sum_squares.direction[i].red-(mean.direction[i].red*
      mean.direction[i].red)));
    channel_features[GreenChannel].correlation[i]=
      (correlation.direction[i].green-mean.direction[i].green*
      mean.direction[i].green)/(sqrt(sum_squares.direction[i].green-
      (mean.direction[i].green*mean.direction[i].green))*sqrt(
      sum_squares.direction[i].green-(mean.direction[i].green*
      mean.direction[i].green)));
    channel_features[BlueChannel].correlation[i]=
      (correlation.direction[i].blue-mean.direction[i].blue*
      mean.direction[i].blue)/(sqrt(sum_squares.direction[i].blue-
      (mean.direction[i].blue*mean.direction[i].blue))*sqrt(
      sum_squares.direction[i].blue-(mean.direction[i].blue*
      mean.direction[i].blue)));
    if (image->colorspace == CMYKColorspace)
      channel_features[IndexChannel].correlation[i]=
        (correlation.direction[i].index-mean.direction[i].index*
        mean.direction[i].index)/(sqrt(sum_squares.direction[i].index-
        (mean.direction[i].index*mean.direction[i].index))*sqrt(
        sum_squares.direction[i].index-(mean.direction[i].index*
        mean.direction[i].index)));
    if (image->matte != MagickFalse)
      channel_features[OpacityChannel].correlation[i]=
        (correlation.direction[i].opacity-mean.direction[i].opacity*
        mean.direction[i].opacity)/(sqrt(sum_squares.direction[i].opacity-
        (mean.direction[i].opacity*mean.direction[i].opacity))*sqrt(
        sum_squares.direction[i].opacity-(mean.direction[i].opacity*
        mean.direction[i].opacity)));
  }
  /*
    Compute more texture features.
  */
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status)
#endif
  for (i=0; i < 4; i++)
  {
    register ssize_t
      x;

    for (x=2; x < (ssize_t) (2*number_grays); x++)
    {
      /*
        Sum average.
      */
      channel_features[RedChannel].sum_average[i]+=
        x*density_xy[x].direction[i].red;
      channel_features[GreenChannel].sum_average[i]+=
        x*density_xy[x].direction[i].green;
      channel_features[BlueChannel].sum_average[i]+=
        x*density_xy[x].direction[i].blue;
      if (image->colorspace == CMYKColorspace)
        channel_features[IndexChannel].sum_average[i]+=
          x*density_xy[x].direction[i].index;
      if (image->matte != MagickFalse)
        channel_features[OpacityChannel].sum_average[i]+=
          x*density_xy[x].direction[i].opacity;
      /*
        Sum entropy.
      */
      channel_features[RedChannel].sum_entropy[i]-=
        density_xy[x].direction[i].red*
        log10(density_xy[x].direction[i].red+MagickEpsilon);
      channel_features[GreenChannel].sum_entropy[i]-=
        density_xy[x].direction[i].green*
        log10(density_xy[x].direction[i].green+MagickEpsilon);
      channel_features[BlueChannel].sum_entropy[i]-=
        density_xy[x].direction[i].blue*
        log10(density_xy[x].direction[i].blue+MagickEpsilon);
      if (image->colorspace == CMYKColorspace)
        channel_features[IndexChannel].sum_entropy[i]-=
          density_xy[x].direction[i].index*
          log10(density_xy[x].direction[i].index+MagickEpsilon);
      if (image->matte != MagickFalse)
        channel_features[OpacityChannel].sum_entropy[i]-=
          density_xy[x].direction[i].opacity*
          log10(density_xy[x].direction[i].opacity+MagickEpsilon);
      /*
        Sum variance.
      */
      channel_features[RedChannel].sum_variance[i]+=
        (x-channel_features[RedChannel].sum_entropy[i])*
        (x-channel_features[RedChannel].sum_entropy[i])*
        density_xy[x].direction[i].red;
      channel_features[GreenChannel].sum_variance[i]+=
        (x-channel_features[GreenChannel].sum_entropy[i])*
        (x-channel_features[GreenChannel].sum_entropy[i])*
        density_xy[x].direction[i].green;
      channel_features[BlueChannel].sum_variance[i]+=
        (x-channel_features[BlueChannel].sum_entropy[i])*
        (x-channel_features[BlueChannel].sum_entropy[i])*
        density_xy[x].direction[i].blue;
      if (image->colorspace == CMYKColorspace)
        channel_features[IndexChannel].sum_variance[i]+=
          (x-channel_features[IndexChannel].sum_entropy[i])*
          (x-channel_features[IndexChannel].sum_entropy[i])*
          density_xy[x].direction[i].index;
      if (image->matte != MagickFalse)
        channel_features[OpacityChannel].sum_variance[i]+=
          (x-channel_features[OpacityChannel].sum_entropy[i])*
          (x-channel_features[OpacityChannel].sum_entropy[i])*
          density_xy[x].direction[i].opacity;
    }
  }
  /*
    Compute more texture features.
  */
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status)
#endif
  for (i=0; i < 4; i++)
  {
    register ssize_t
      y;

    for (y=0; y < (ssize_t) number_grays; y++)
    {
      register ssize_t
        x;

      for (x=0; x < (ssize_t) number_grays; x++)
      {
        /*
          Sum of Squares: Variance
        */
        variance.direction[i].red+=(y-mean.direction[i].red+1)*
          (y-mean.direction[i].red+1)*cooccurrence[x][y].direction[i].red;
        variance.direction[i].green+=(y-mean.direction[i].green+1)*
          (y-mean.direction[i].green+1)*cooccurrence[x][y].direction[i].green;
        variance.direction[i].blue+=(y-mean.direction[i].blue+1)*
          (y-mean.direction[i].blue+1)*cooccurrence[x][y].direction[i].blue;
        if (image->colorspace == CMYKColorspace)
          variance.direction[i].index+=(y-mean.direction[i].index+1)*
            (y-mean.direction[i].index+1)*cooccurrence[x][y].direction[i].index;
        if (image->matte != MagickFalse)
          variance.direction[i].opacity+=(y-mean.direction[i].opacity+1)*
            (y-mean.direction[i].opacity+1)*
            cooccurrence[x][y].direction[i].opacity;
        /*
          Sum average / Difference Variance.
        */
        density_xy[MagickAbsoluteValue(y-x)].direction[i].red+=
          cooccurrence[x][y].direction[i].red;
        density_xy[MagickAbsoluteValue(y-x)].direction[i].green+=
          cooccurrence[x][y].direction[i].green;
        density_xy[MagickAbsoluteValue(y-x)].direction[i].blue+=
          cooccurrence[x][y].direction[i].blue;
        if (image->colorspace == CMYKColorspace)
          density_xy[MagickAbsoluteValue(y-x)].direction[i].index+=
            cooccurrence[x][y].direction[i].index;
        if (image->matte != MagickFalse)
          density_xy[MagickAbsoluteValue(y-x)].direction[i].opacity+=
            cooccurrence[x][y].direction[i].opacity;
        /*
          Information Measures of Correlation.
        */
        entropy_xy.direction[i].red-=cooccurrence[x][y].direction[i].red*
          log10(cooccurrence[x][y].direction[i].red+MagickEpsilon);
        entropy_xy.direction[i].green-=cooccurrence[x][y].direction[i].green*
          log10(cooccurrence[x][y].direction[i].green+MagickEpsilon);
        entropy_xy.direction[i].blue-=cooccurrence[x][y].direction[i].blue*
          log10(cooccurrence[x][y].direction[i].blue+MagickEpsilon);
        if (image->colorspace == CMYKColorspace)
          entropy_xy.direction[i].index-=cooccurrence[x][y].direction[i].index*
            log10(cooccurrence[x][y].direction[i].index+MagickEpsilon);
        if (image->matte != MagickFalse)
          entropy_xy.direction[i].opacity-=
            cooccurrence[x][y].direction[i].opacity*log10(
            cooccurrence[x][y].direction[i].opacity+MagickEpsilon);
        entropy_xy1.direction[i].red-=(cooccurrence[x][y].direction[i].red*
          log10(density_x[x].direction[i].red*density_y[y].direction[i].red+
          MagickEpsilon));
        entropy_xy1.direction[i].green-=(cooccurrence[x][y].direction[i].green*
          log10(density_x[x].direction[i].green*density_y[y].direction[i].green+
          MagickEpsilon));
        entropy_xy1.direction[i].blue-=(cooccurrence[x][y].direction[i].blue*
          log10(density_x[x].direction[i].blue*density_y[y].direction[i].blue+
          MagickEpsilon));
        if (image->colorspace == CMYKColorspace)
          entropy_xy1.direction[i].index-=(
            cooccurrence[x][y].direction[i].index*log10(
            density_x[x].direction[i].index*density_y[y].direction[i].index+
            MagickEpsilon));
        if (image->matte != MagickFalse)
          entropy_xy1.direction[i].opacity-=(
            cooccurrence[x][y].direction[i].opacity*log10(
            density_x[x].direction[i].opacity*density_y[y].direction[i].opacity+
            MagickEpsilon));
        entropy_xy2.direction[i].red-=(density_x[x].direction[i].red*
          density_y[y].direction[i].red*log10(density_x[x].direction[i].red*
          density_y[y].direction[i].red+MagickEpsilon));
        entropy_xy2.direction[i].green-=(density_x[x].direction[i].green*
          density_y[y].direction[i].green*log10(density_x[x].direction[i].green*
          density_y[y].direction[i].green+MagickEpsilon));
        entropy_xy2.direction[i].blue-=(density_x[x].direction[i].blue*
          density_y[y].direction[i].blue*log10(density_x[x].direction[i].blue*
          density_y[y].direction[i].blue+MagickEpsilon));
        if (image->colorspace == CMYKColorspace)
          entropy_xy2.direction[i].index-=(density_x[x].direction[i].index*
            density_y[y].direction[i].index*log10(
            density_x[x].direction[i].index*density_y[y].direction[i].index+
            MagickEpsilon));
        if (image->matte != MagickFalse)
          entropy_xy2.direction[i].opacity-=(density_x[x].direction[i].opacity*
            density_y[y].direction[i].opacity*log10(
            density_x[x].direction[i].opacity*density_y[y].direction[i].opacity+
            MagickEpsilon));
      }
    }
    channel_features[RedChannel].variance_sum_of_squares[i]=
      variance.direction[i].red;
    channel_features[GreenChannel].variance_sum_of_squares[i]=
      variance.direction[i].green;
    channel_features[BlueChannel].variance_sum_of_squares[i]=
      variance.direction[i].blue;
    if (image->colorspace == CMYKColorspace)
      channel_features[RedChannel].variance_sum_of_squares[i]=
        variance.direction[i].index;
    if (image->matte != MagickFalse)
      channel_features[RedChannel].variance_sum_of_squares[i]=
        variance.direction[i].opacity;
  }
  /*
    Compute more texture features.
  */
  (void) ResetMagickMemory(&variance,0,sizeof(variance));
  (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares));
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status)
#endif
  for (i=0; i < 4; i++)
  {
    register ssize_t
      x;

    for (x=0; x < (ssize_t) number_grays; x++)
    {
      /*
        Difference variance.
      */
      variance.direction[i].red+=density_xy[x].direction[i].red;
      variance.direction[i].green+=density_xy[x].direction[i].green;
      variance.direction[i].blue+=density_xy[x].direction[i].blue;
      if (image->colorspace == CMYKColorspace)
        variance.direction[i].index+=density_xy[x].direction[i].index;
      if (image->matte != MagickFalse)
        variance.direction[i].opacity+=density_xy[x].direction[i].opacity;
      sum_squares.direction[i].red+=density_xy[x].direction[i].red*
        density_xy[x].direction[i].red;
      sum_squares.direction[i].green+=density_xy[x].direction[i].green*
        density_xy[x].direction[i].green;
      sum_squares.direction[i].blue+=density_xy[x].direction[i].blue*
        density_xy[x].direction[i].blue;
      if (image->colorspace == CMYKColorspace)
        sum_squares.direction[i].index+=density_xy[x].direction[i].index*
          density_xy[x].direction[i].index;
      if (image->matte != MagickFalse)
        sum_squares.direction[i].opacity+=density_xy[x].direction[i].opacity*
          density_xy[x].direction[i].opacity;
      /*
        Difference entropy.
      */
      channel_features[RedChannel].difference_entropy[i]-=
        density_xy[x].direction[i].red*
        log10(density_xy[x].direction[i].red+MagickEpsilon);
      channel_features[GreenChannel].difference_entropy[i]-=
        density_xy[x].direction[i].green*
        log10(density_xy[x].direction[i].green+MagickEpsilon);
      channel_features[BlueChannel].difference_entropy[i]-=
        density_xy[x].direction[i].blue*
        log10(density_xy[x].direction[i].blue+MagickEpsilon);
      if (image->colorspace == CMYKColorspace)
        channel_features[IndexChannel].difference_entropy[i]-=
          density_xy[x].direction[i].index*
          log10(density_xy[x].direction[i].index+MagickEpsilon);
      if (image->matte != MagickFalse)
        channel_features[OpacityChannel].difference_entropy[i]-=
          density_xy[x].direction[i].opacity*
          log10(density_xy[x].direction[i].opacity+MagickEpsilon);
      /*
        Information Measures of Correlation.
      */
      entropy_x.direction[i].red-=(density_x[x].direction[i].red*
        log10(density_x[x].direction[i].red+MagickEpsilon));
      entropy_x.direction[i].green-=(density_x[x].direction[i].green*
        log10(density_x[x].direction[i].green+MagickEpsilon));
      entropy_x.direction[i].blue-=(density_x[x].direction[i].blue*
        log10(density_x[x].direction[i].blue+MagickEpsilon));
      if (image->colorspace == CMYKColorspace)
        entropy_x.direction[i].index-=(density_x[x].direction[i].index*
          log10(density_x[x].direction[i].index+MagickEpsilon));
      if (image->matte != MagickFalse)
        entropy_x.direction[i].opacity-=(density_x[x].direction[i].opacity*
          log10(density_x[x].direction[i].opacity+MagickEpsilon));
      entropy_y.direction[i].red-=(density_y[x].direction[i].red*
        log10(density_y[x].direction[i].red+MagickEpsilon));
      entropy_y.direction[i].green-=(density_y[x].direction[i].green*
        log10(density_y[x].direction[i].green+MagickEpsilon));
      entropy_y.direction[i].blue-=(density_y[x].direction[i].blue*
        log10(density_y[x].direction[i].blue+MagickEpsilon));
      if (image->colorspace == CMYKColorspace)
        entropy_y.direction[i].index-=(density_y[x].direction[i].index*
          log10(density_y[x].direction[i].index+MagickEpsilon));
      if (image->matte != MagickFalse)
        entropy_y.direction[i].opacity-=(density_y[x].direction[i].opacity*
          log10(density_y[x].direction[i].opacity+MagickEpsilon));
    }
    /*
      Difference variance.
    */
    channel_features[RedChannel].difference_variance[i]=
      (((double) number_grays*number_grays*sum_squares.direction[i].red)-
      (variance.direction[i].red*variance.direction[i].red))/
      ((double) number_grays*number_grays*number_grays*number_grays);
    channel_features[GreenChannel].difference_variance[i]=
      (((double) number_grays*number_grays*sum_squares.direction[i].green)-
      (variance.direction[i].green*variance.direction[i].green))/
      ((double) number_grays*number_grays*number_grays*number_grays);
    channel_features[BlueChannel].difference_variance[i]=
      (((double) number_grays*number_grays*sum_squares.direction[i].blue)-
      (variance.direction[i].blue*variance.direction[i].blue))/
      ((double) number_grays*number_grays*number_grays*number_grays);
    if (image->matte != MagickFalse)
      channel_features[OpacityChannel].difference_variance[i]=
        (((double) number_grays*number_grays*sum_squares.direction[i].opacity)-
        (variance.direction[i].opacity*variance.direction[i].opacity))/
        ((double) number_grays*number_grays*number_grays*number_grays);
    if (image->colorspace == CMYKColorspace)
      channel_features[IndexChannel].difference_variance[i]=
        (((double) number_grays*number_grays*sum_squares.direction[i].index)-
        (variance.direction[i].index*variance.direction[i].index))/
        ((double) number_grays*number_grays*number_grays*number_grays);
    /*
      Information Measures of Correlation.
    */
    channel_features[RedChannel].measure_of_correlation_1[i]=
      (entropy_xy.direction[i].red-entropy_xy1.direction[i].red)/
      (entropy_x.direction[i].red > entropy_y.direction[i].red ?
       entropy_x.direction[i].red : entropy_y.direction[i].red);
    channel_features[GreenChannel].measure_of_correlation_1[i]=
      (entropy_xy.direction[i].green-entropy_xy1.direction[i].green)/
      (entropy_x.direction[i].green > entropy_y.direction[i].green ?
       entropy_x.direction[i].green : entropy_y.direction[i].green);
    channel_features[BlueChannel].measure_of_correlation_1[i]=
      (entropy_xy.direction[i].blue-entropy_xy1.direction[i].blue)/
      (entropy_x.direction[i].blue > entropy_y.direction[i].blue ?
       entropy_x.direction[i].blue : entropy_y.direction[i].blue);
    if (image->colorspace == CMYKColorspace)
      channel_features[IndexChannel].measure_of_correlation_1[i]=
        (entropy_xy.direction[i].index-entropy_xy1.direction[i].index)/
        (entropy_x.direction[i].index > entropy_y.direction[i].index ?
         entropy_x.direction[i].index : entropy_y.direction[i].index);
    if (image->matte != MagickFalse)
      channel_features[OpacityChannel].measure_of_correlation_1[i]=
        (entropy_xy.direction[i].opacity-entropy_xy1.direction[i].opacity)/
        (entropy_x.direction[i].opacity > entropy_y.direction[i].opacity ?
         entropy_x.direction[i].opacity : entropy_y.direction[i].opacity);
    channel_features[RedChannel].measure_of_correlation_2[i]=
      (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].red-
      entropy_xy.direction[i].red)))));
    channel_features[GreenChannel].measure_of_correlation_2[i]=
      (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].green-
      entropy_xy.direction[i].green)))));
    channel_features[BlueChannel].measure_of_correlation_2[i]=
      (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].blue-
      entropy_xy.direction[i].blue)))));
    if (image->colorspace == CMYKColorspace)
      channel_features[IndexChannel].measure_of_correlation_2[i]=
        (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].index-
        entropy_xy.direction[i].index)))));
    if (image->matte != MagickFalse)
      channel_features[OpacityChannel].measure_of_correlation_2[i]=
        (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].opacity-
        entropy_xy.direction[i].opacity)))));
  }
  /*
    Compute more texture features.
  */
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status)
#endif
  for (i=0; i < 4; i++)
  {
    register ssize_t
      z;

    for (z=0; z < (ssize_t) number_grays; z++)
    {
      register ssize_t
        y;

      ChannelStatistics
        pixel;

      (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
      for (y=0; y < (ssize_t) number_grays; y++)
      {
        register ssize_t
          x;

        for (x=0; x < (ssize_t) number_grays; x++)
        {
          /*
            Contrast:  amount of local variations present in an image.
          */
          if (((y-x) == z) || ((x-y) == z))
            {
              pixel.direction[i].red+=cooccurrence[x][y].direction[i].red;
              pixel.direction[i].green+=cooccurrence[x][y].direction[i].green;
              pixel.direction[i].blue+=cooccurrence[x][y].direction[i].blue;
              if (image->colorspace == CMYKColorspace)
                pixel.direction[i].index+=cooccurrence[x][y].direction[i].index;
              if (image->matte != MagickFalse)
                pixel.direction[i].opacity+=
                  cooccurrence[x][y].direction[i].opacity;
            }
          /*
            Maximum Correlation Coefficient.
          */
          Q[z][y].direction[i].red+=cooccurrence[z][x].direction[i].red*
            cooccurrence[y][x].direction[i].red/density_x[z].direction[i].red/
            density_y[x].direction[i].red;
          Q[z][y].direction[i].green+=cooccurrence[z][x].direction[i].green*
            cooccurrence[y][x].direction[i].green/
            density_x[z].direction[i].green/density_y[x].direction[i].red;
          Q[z][y].direction[i].blue+=cooccurrence[z][x].direction[i].blue*
            cooccurrence[y][x].direction[i].blue/density_x[z].direction[i].blue/
            density_y[x].direction[i].blue;
          if (image->colorspace == CMYKColorspace)
            Q[z][y].direction[i].index+=cooccurrence[z][x].direction[i].index*
              cooccurrence[y][x].direction[i].index/
              density_x[z].direction[i].index/density_y[x].direction[i].index;
          if (image->matte != MagickFalse)
            Q[z][y].direction[i].opacity+=
              cooccurrence[z][x].direction[i].opacity*
              cooccurrence[y][x].direction[i].opacity/
              density_x[z].direction[i].opacity/
              density_y[x].direction[i].opacity;
        }
      }
      channel_features[RedChannel].contrast[i]+=z*z*pixel.direction[i].red;
      channel_features[GreenChannel].contrast[i]+=z*z*pixel.direction[i].green;
      channel_features[BlueChannel].contrast[i]+=z*z*pixel.direction[i].blue;
      if (image->colorspace == CMYKColorspace)
        channel_features[BlackChannel].contrast[i]+=z*z*
          pixel.direction[i].index;
      if (image->matte != MagickFalse)
        channel_features[OpacityChannel].contrast[i]+=z*z*
          pixel.direction[i].opacity;
    }
    /*
      Maximum Correlation Coefficient.
      Future: return second largest eigenvalue of Q.
    */
    channel_features[RedChannel].maximum_correlation_coefficient[i]=
      sqrt((double) -1.0);
    channel_features[GreenChannel].maximum_correlation_coefficient[i]=
      sqrt((double) -1.0);
    channel_features[BlueChannel].maximum_correlation_coefficient[i]=
      sqrt((double) -1.0);
    if (image->colorspace == CMYKColorspace)
      channel_features[IndexChannel].maximum_correlation_coefficient[i]=
        sqrt((double) -1.0);
    if (image->matte != MagickFalse)
      channel_features[OpacityChannel].maximum_correlation_coefficient[i]=
        sqrt((double) -1.0);
  }
  /*
    Relinquish resources.
  */
  sum=(ChannelStatistics *) RelinquishMagickMemory(sum);
  for (i=0; i < (ssize_t) number_grays; i++)
    Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]);
  Q=(ChannelStatistics **) RelinquishMagickMemory(Q);
  density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y);
  density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy);
  density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x);
  for (i=0; i < (ssize_t) number_grays; i++)
    cooccurrence[i]=(ChannelStatistics *)
      RelinquishMagickMemory(cooccurrence[i]);
  cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence);
  return(channel_features);
}
Пример #12
0
bool CxImageICO::Decode(CxFile *hFile)
{
	if (hFile==NULL) return false;

	DWORD off = hFile->Tell(); //<yuandi>
	int	page=info.nFrame;	//internal icon structure indexes

	// read the first part of the header
	ICONHEADER icon_header;
	hFile->Read(&icon_header,sizeof(ICONHEADER),1);

	icon_header.idType = my_ntohs(icon_header.idType);
	icon_header.idCount = my_ntohs(icon_header.idCount);

	// check if it's an icon or a cursor
	if ((icon_header.idReserved == 0) && ((icon_header.idType == 1)||(icon_header.idType == 2))) {

		info.nNumFrames = icon_header.idCount;

		// load the icon descriptions
		ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header.idCount * sizeof(ICONDIRENTRY));
		int c;
		for (c = 0; c < icon_header.idCount; c++) {
			hFile->Read(icon_list + c, sizeof(ICONDIRENTRY), 1);

			icon_list[c].wPlanes = my_ntohs(icon_list[c].wPlanes);
			icon_list[c].wBitCount = my_ntohs(icon_list[c].wBitCount);
			icon_list[c].dwBytesInRes = my_ntohl(icon_list[c].dwBytesInRes);
			icon_list[c].dwImageOffset = my_ntohl(icon_list[c].dwImageOffset);
		}
		
		if ((page>=0)&&(page<icon_header.idCount)){

			if (info.nEscape == -1) {
				// Return output dimensions only
				head.biWidth = icon_list[page].bWidth;
				head.biHeight = icon_list[page].bHeight;
#if CXIMAGE_SUPPORT_PNG
				if (head.biWidth==0 && head.biHeight==0)
				{	// Vista icon support
					hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET);
					CxImage png;
					png.SetEscape(-1);
					if (png.Decode(hFile,CXIMAGE_FORMAT_PNG)){
						Transfer(png);
						info.nNumFrames = icon_header.idCount;
					}
				}
#endif //CXIMAGE_SUPPORT_PNG
				free(icon_list);
				info.dwType = CXIMAGE_FORMAT_ICO;
				return true;
			}

			// get the bit count for the colors in the icon <CoreyRLucier>
			BITMAPINFOHEADER bih;
			hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET);

			if (icon_list[page].bWidth==0 && icon_list[page].bHeight==0)
			{	// Vista icon support
#if CXIMAGE_SUPPORT_PNG
				CxImage png;
				if (png.Decode(hFile,CXIMAGE_FORMAT_PNG)){
					Transfer(png);
					info.nNumFrames = icon_header.idCount;
				}
				SetType(CXIMAGE_FORMAT_ICO);
#endif //CXIMAGE_SUPPORT_PNG
			}
			else
			{	// standard icon
				hFile->Read(&bih,sizeof(BITMAPINFOHEADER),1);

				bihtoh(&bih);

				c = bih.biBitCount;

				// allocate memory for one icon
				Create(icon_list[page].bWidth,icon_list[page].bHeight, c, CXIMAGE_FORMAT_ICO);	//image creation

				// read the palette
				RGBQUAD pal[256];
				if (bih.biClrUsed)
					hFile->Read(pal,bih.biClrUsed*sizeof(RGBQUAD), 1);
				else
					hFile->Read(pal,head.biClrUsed*sizeof(RGBQUAD), 1);

				SetPalette(pal,head.biClrUsed);	//palette assign

				//read the icon
				if (c<=24){
					hFile->Read(info.pImage, head.biSizeImage, 1);
				} else { // 32 bit icon
					BYTE* buf=(BYTE*)malloc(4*head.biHeight*head.biWidth);
					BYTE* src = buf;
					hFile->Read(buf, 4*head.biHeight*head.biWidth, 1);
#if CXIMAGE_SUPPORT_ALPHA
					if (!AlphaIsValid()) AlphaCreate();
#endif //CXIMAGE_SUPPORT_ALPHA
					for (long y = 0; y < head.biHeight; y++) {
						BYTE* dst = GetBits(y);
						for(long x=0;x<head.biWidth;x++){
							*dst++=src[0];
							*dst++=src[1];
							*dst++=src[2];
#if CXIMAGE_SUPPORT_ALPHA
							AlphaSet(x,y,src[3]);
#endif //CXIMAGE_SUPPORT_ALPHA
							src+=4;
						}
					}
					free(buf);
				}
				// apply the AND and XOR masks
				int maskwdt = ((head.biWidth+31) / 32) * 4;	//line width of AND mask (always 1 Bpp)
				int masksize = head.biHeight * maskwdt;				//size of mask
				BYTE *mask = (BYTE *)malloc(masksize);
				if (hFile->Read(mask, masksize, 1)){

					bool bGoodMask=false;
					for (int im=0;im<masksize;im++){
						if (mask[im]!=255){
							bGoodMask=true;
							break;
						}
					}

					if (bGoodMask && c != 32){
#if CXIMAGE_SUPPORT_ALPHA
						bool bNeedAlpha = false;
						if (!AlphaIsValid()){
							AlphaCreate();
						} else { 
							bNeedAlpha=true; //32bit icon
						}
						int x,y;
						for (y = 0; y < head.biHeight; y++) {
							for (x = 0; x < head.biWidth; x++) {
								if (((mask[y*maskwdt+(x>>3)]>>(7-x%8))&0x01)){
									AlphaSet(x,y,0);
									bNeedAlpha=true;
								}
							}
						}
						if (!bNeedAlpha) AlphaDelete();
#endif //CXIMAGE_SUPPORT_ALPHA

						//check if there is only one transparent color
						RGBQUAD cc,ct;
						long* pcc = (long*)&cc;
						long* pct = (long*)&ct;
						int nTransColors=0;
						int nTransIndex=0;
						for (y = 0; y < head.biHeight; y++){
							for (x = 0; x < head.biWidth; x++){
								if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){
									cc = GetPixelColor(x,y,false);
									if (nTransColors==0){
										nTransIndex = GetPixelIndex(x,y);
										nTransColors++;
										ct = cc;
									} else {
										if (*pct!=*pcc){
											nTransColors++;
										}
									}
								}
							}
						}
						if (nTransColors==1){
							SetTransColor(ct);
							SetTransIndex(nTransIndex);
#if CXIMAGE_SUPPORT_ALPHA
							AlphaDelete(); //because we have a unique transparent color in the image
#endif //CXIMAGE_SUPPORT_ALPHA
						}

						// <vho> - Transparency support w/o Alpha support
						if (c <= 8){ // only for icons with less than 256 colors (XP icons need alpha).
							  
							// find a color index, which is not used in the image
							// it is almost sure to find one, bcs. nobody uses all possible colors for an icon

							BYTE colorsUsed[256];
							memset(colorsUsed, 0, sizeof(colorsUsed));

							for (y = 0; y < head.biHeight; y++){
								for (x = 0; x < head.biWidth; x++){
									colorsUsed[BlindGetPixelIndex(x,y)] = 1;
								}
							}

							int iTransIdx = -1;
							for (x = (int)(head.biClrUsed-1); x>=0 ; x--){
								if (colorsUsed[x] == 0){
									iTransIdx = x; // this one is not in use. we may use it as transparent color
									break;
								}
							}

							// Go thru image and set unused color as transparent index if needed
							if (iTransIdx >= 0){
								bool bNeedTrans = false;
								for (y = 0; y < head.biHeight; y++){
									for (x = 0; x < head.biWidth; x++){
										// AND mask (Each Byte represents 8 Pixels)
										if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){
											// AND mask is set (!=0). This is a transparent part
											SetPixelIndex(x, y, (BYTE)iTransIdx);
											bNeedTrans = true;
										}
									}
								}
								// set transparent index if needed
								if (bNeedTrans)	SetTransIndex(iTransIdx);
#if CXIMAGE_SUPPORT_ALPHA
								AlphaDelete(); //because we have a transparent color in the palette
#endif //CXIMAGE_SUPPORT_ALPHA
							}
						}
					} else if(c != 32){
Пример #13
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   G e t W a n d V i e w I t e r a t o r                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  GetWandViewIterator() iterates over the wand view in parallel and calls
%  your get method for each scanline of the view.  The pixel extent is
%  not confined to the image canvas-- that is you can include negative offsets
%  or widths or heights that exceed the image dimension.  Any updates to
%  the pixels in your callback are ignored.
%
%  The callback signature is:
%
%      MagickBooleanType GetImageViewMethod(const WandView *source,
%        const ssize_t y,const int thread_id,void *context)
%
%  Use this pragma if the view is not single threaded:
%
%    #pragma omp critical
%
%  to define a section of code in your callback get method that must be
%  executed by a single thread at a time.
%
%  The format of the GetWandViewIterator method is:
%
%      MagickBooleanType GetWandViewIterator(WandView *source,
%        GetWandViewMethod get,void *context)
%
%  A description of each parameter follows:
%
%    o source: the source wand view.
%
%    o get: the get callback method.
%
%    o context: the user defined context.
%
*/
WandExport MagickBooleanType GetWandViewIterator(WandView *source,
  GetWandViewMethod get,void *context)
{
  Image
    *source_image;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  ssize_t
    y;

  assert(source != (WandView *) NULL);
  assert(source->signature == WandSignature);
  if (get == (GetWandViewMethod) NULL)
    return(MagickFalse);
  source_image=source->wand->images;
  status=MagickTrue;
  progress=0;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
#endif
  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
  {
    const int
      id = GetOpenMPThreadId();

    register const IndexPacket
      *indexes;

    register const PixelPacket
      *pixels;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
      source->extent.width,1,source->exception);
    if (pixels == (const PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewVirtualIndexQueue(source->view);
    for (x=0; x < (ssize_t) source->extent.width; x++)
      PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
    if (source_image->colorspace == CMYKColorspace)
      for (x=0; x < (ssize_t) source->extent.width; x++)
        PixelSetBlackQuantum(source->pixel_wands[id][x],
          GetPixelBlack(indexes+x));
    if (source_image->storage_class == PseudoClass)
      for (x=0; x < (ssize_t) source->extent.width; x++)
        PixelSetIndex(source->pixel_wands[id][x],
          GetPixelIndex(indexes+x));
    if (get(source,y,id,context) == MagickFalse)
      status=MagickFalse;
    if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp critical (MagickWand_GetWandViewIterator)
#endif
        proceed=SetImageProgress(source_image,source->description,progress++,
          source->extent.height);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  return(status);
}
Пример #14
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   D u p l e x T r a n s f e r W a n d V i e w I t e r a t o r               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  DuplexTransferWandViewIterator() iterates over three wand views in
%  parallel and calls your transfer method for each scanline of the view.  The
%  source and duplex pixel extent is not confined to the image canvas-- that is
%  you can include negative offsets or widths or heights that exceed the image
%  dimension.  However, the destination wand view is confined to the image
%  canvas-- that is no negative offsets or widths or heights that exceed the
%  image dimension are permitted.
%
%  The callback signature is:
%
%      MagickBooleanType DuplexTransferImageViewMethod(const WandView *source,
%        const WandView *duplex,WandView *destination,const ssize_t y,
%        const int thread_id,void *context)
%
%  Use this pragma if the view is not single threaded:
%
%    #pragma omp critical
%
%  to define a section of code in your callback transfer method that must be
%  executed by a single thread at a time.
%
%  The format of the DuplexTransferWandViewIterator method is:
%
%      MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
%        WandView *duplex,WandView *destination,
%        DuplexTransferWandViewMethod transfer,void *context)
%
%  A description of each parameter follows:
%
%    o source: the source wand view.
%
%    o duplex: the duplex wand view.
%
%    o destination: the destination wand view.
%
%    o transfer: the transfer callback method.
%
%    o context: the user defined context.
%
*/
WandExport MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
  WandView *duplex,WandView *destination,DuplexTransferWandViewMethod transfer,
  void *context)
{
  ExceptionInfo
    *exception;

  Image
    *destination_image,
    *duplex_image,
    *source_image;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  ssize_t
    y;

  assert(source != (WandView *) NULL);
  assert(source->signature == WandSignature);
  if (transfer == (DuplexTransferWandViewMethod) NULL)
    return(MagickFalse);
  source_image=source->wand->images;
  duplex_image=duplex->wand->images;
  destination_image=destination->wand->images;
  if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
    return(MagickFalse);
  status=MagickTrue;
  progress=0;
  exception=destination->exception;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
#endif
  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
  {
    const int
      id = GetOpenMPThreadId();

    MagickBooleanType
      sync;

    register const IndexPacket
      *restrict duplex_indexes,
      *restrict indexes;

    register const PixelPacket
      *restrict duplex_pixels,
      *restrict pixels;

    register IndexPacket
      *restrict destination_indexes;

    register ssize_t
      x;

    register PixelPacket
      *restrict destination_pixels;

    if (status == MagickFalse)
      continue;
    pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
      source->extent.width,1,source->exception);
    if (pixels == (const PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewVirtualIndexQueue(source->view);
    for (x=0; x < (ssize_t) source->extent.width; x++)
      PixelSetQuantumColor(source->pixel_wands[id][x],pixels+x);
    if (source_image->colorspace == CMYKColorspace)
      for (x=0; x < (ssize_t) source->extent.width; x++)
        PixelSetBlackQuantum(source->pixel_wands[id][x],
          GetPixelBlack(indexes+x));
    if (source_image->storage_class == PseudoClass)
      for (x=0; x < (ssize_t) source->extent.width; x++)
        PixelSetIndex(source->pixel_wands[id][x],
          GetPixelIndex(indexes+x));
    duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
      duplex->extent.width,1,duplex->exception);
    if (duplex_pixels == (const PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    duplex_indexes=GetCacheViewVirtualIndexQueue(duplex->view);
    for (x=0; x < (ssize_t) duplex->extent.width; x++)
      PixelSetQuantumColor(duplex->pixel_wands[id][x],duplex_pixels+x);
    if (duplex_image->colorspace == CMYKColorspace)
      for (x=0; x < (ssize_t) duplex->extent.width; x++)
        PixelSetBlackQuantum(duplex->pixel_wands[id][x],
          GetPixelBlack(duplex_indexes+x));
    if (duplex_image->storage_class == PseudoClass)
      for (x=0; x < (ssize_t) duplex->extent.width; x++)
        PixelSetIndex(duplex->pixel_wands[id][x],
          GetPixelIndex(duplex_indexes+x));
    destination_pixels=GetCacheViewAuthenticPixels(destination->view,
      destination->extent.x,y,destination->extent.width,1,exception);
    if (destination_pixels == (PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
    for (x=0; x < (ssize_t) destination->extent.width; x++)
      PixelSetQuantumColor(destination->pixel_wands[id][x],
        destination_pixels+x);
    if (destination_image->colorspace == CMYKColorspace)
      for (x=0; x < (ssize_t) destination->extent.width; x++)
        PixelSetBlackQuantum(destination->pixel_wands[id][x],
          GetPixelBlack(destination_indexes+x));
    if (destination_image->storage_class == PseudoClass)
      for (x=0; x < (ssize_t) destination->extent.width; x++)
        PixelSetIndex(destination->pixel_wands[id][x],
          GetPixelIndex(destination_indexes+x));
    if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
      status=MagickFalse;
    for (x=0; x < (ssize_t) destination->extent.width; x++)
      PixelGetQuantumColor(destination->pixel_wands[id][x],
        destination_pixels+x);
    if (destination_image->colorspace == CMYKColorspace)
      for (x=0; x < (ssize_t) destination->extent.width; x++)
        SetPixelBlack(destination_indexes+x,PixelGetBlackQuantum(
          destination->pixel_wands[id][x]));
    sync=SyncCacheViewAuthenticPixels(destination->view,exception);
    if (sync == MagickFalse)
      {
        InheritException(destination->exception,GetCacheViewException(
          source->view));
        status=MagickFalse;
      }
    if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp critical (MagickWand_DuplexTransferWandViewIterator)
#endif
        proceed=SetImageProgress(source_image,source->description,progress++,
          source->extent.height);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  return(status);
}
Пример #15
0
MagickExport Image *OilPaintImage(const Image *image,const double radius,
  ExceptionInfo *exception)
{
#define NumberPaintBins  256
#define OilPaintImageTag  "OilPaint/Image"

  CacheView
    *image_view,
    *paint_view;

  Image
    *paint_image;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  size_t
    **restrict histograms,
    width;

  ssize_t
    y;

  /*
    Initialize painted image attributes.
  */
  assert(image != (const Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  width=GetOptimalKernelWidth2D(radius,0.5);
  paint_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
  if (paint_image == (Image *) NULL)
    return((Image *) NULL);
  if (SetImageStorageClass(paint_image,DirectClass) == MagickFalse)
    {
      InheritException(exception,&paint_image->exception);
      paint_image=DestroyImage(paint_image);
      return((Image *) NULL);
    }
  histograms=AcquireHistogramThreadSet(NumberPaintBins);
  if (histograms == (size_t **) NULL)
    {
      paint_image=DestroyImage(paint_image);
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
    }
  /*
    Oil paint image.
  */
  status=MagickTrue;
  progress=0;
  image_view=AcquireVirtualCacheView(image,exception);
  paint_view=AcquireAuthenticCacheView(paint_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(progress,status) \
    IsConcurrentDos(image->columns,image->rows,64)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register const IndexPacket
      *restrict indexes;

    register const PixelPacket
      *restrict p;

    register IndexPacket
      *restrict paint_indexes;

    register ssize_t
      x;

    register PixelPacket
      *restrict q;

    register size_t
      *histogram;

    if (status == MagickFalse)
      continue;
    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t)
      (width/2L),image->columns+width,width,exception);
    q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1,
      exception);
    if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewVirtualIndexQueue(image_view);
    paint_indexes=GetCacheViewAuthenticIndexQueue(paint_view);
    histogram=histograms[GetOpenMPThreadId()];
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      register ssize_t
        i,
        u;

      size_t
        count;

      ssize_t
        j,
        k,
        v;

      /*
        Assign most frequent color.
      */
      i=0;
      j=0;
      count=0;
      (void) ResetMagickMemory(histogram,0,NumberPaintBins*sizeof(*histogram));
      for (v=0; v < (ssize_t) width; v++)
      {
        for (u=0; u < (ssize_t) width; u++)
        {
          k=(ssize_t) ScaleQuantumToChar(PixelIntensityToQuantum(p+u+i));
          histogram[k]++;
          if (histogram[k] > count)
            {
              j=i+u;
              count=histogram[k];
            }
        }
        i+=(ssize_t) (image->columns+width);
      }
      *q=(*(p+j));
      if (image->colorspace == CMYKColorspace)
        SetPixelIndex(paint_indexes+x,GetPixelIndex(
          indexes+x+j));
      p++;
      q++;
    }
    if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse)
      status=MagickFalse;
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

#if defined(MAGICKCORE_OPENMP_SUPPORT)
        #pragma omp critical (MagickCore_OilPaintImage)
#endif
        proceed=SetImageProgress(image,OilPaintImageTag,progress++,image->rows);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  paint_view=DestroyCacheView(paint_view);
  image_view=DestroyCacheView(image_view);
  histograms=DestroyHistogramThreadSet(histograms);
  if (status == MagickFalse)
    paint_image=DestroyImage(paint_image);
  return(paint_image);
}
Пример #16
0
static MagickBooleanType WritePCLImage(const ImageInfo *image_info,Image *image,
  ExceptionInfo *exception)
{
  char
    buffer[MaxTextExtent];

  const char
    *option;

  MagickBooleanType
    status;

  MagickOffsetType
    scene;

  register const Quantum *p;

  register ssize_t i, x;

  register unsigned char *q;

  size_t
    density,
    length,
    one,
    packets;

  ssize_t
    y;

  unsigned char
    bits_per_pixel,
    *compress_pixels,
    *pixels,
    *previous_pixels;

  /*
    Open output image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
  if (status == MagickFalse)
    return(status);
  density=75;
  if (image_info->density != (char *) NULL)
    {
      GeometryInfo
        geometry;

      (void) ParseGeometry(image_info->density,&geometry);
      density=(size_t) geometry.rho;
    }
  scene=0;
  one=1;
  do
  {
    if (IsRGBColorspace(image->colorspace) == MagickFalse)
      (void) TransformImageColorspace(image,RGBColorspace,exception);
    /*
      Initialize the printer.
    */
    (void) WriteBlobString(image,"\033E");  /* printer reset */
    (void) WriteBlobString(image,"\033*r3F");  /* set presentation mode */
    (void) FormatLocaleString(buffer,MaxTextExtent,"\033*r%.20gs%.20gT",
      (double) image->columns,(double) image->rows);
    (void) WriteBlobString(image,buffer);
    (void) FormatLocaleString(buffer,MaxTextExtent,"\033*t%.20gR",(double)
      density);
    (void) WriteBlobString(image,buffer);
    (void) WriteBlobString(image,"\033&l0E");  /* top margin 0 */
    if (IsImageMonochrome(image,exception) != MagickFalse)
      {
        /*
          Monochrome image: use default printer monochrome setup.
        */
        bits_per_pixel=1;
      }
    else
      if (image->storage_class == DirectClass)
        {
          /*
            DirectClass image.
          */
          bits_per_pixel=24;
          (void) WriteBlobString(image,"\033*v6W"); /* set color mode */
          (void) WriteBlobByte(image,0); /* RGB */
          (void) WriteBlobByte(image,3); /* direct by pixel */
          (void) WriteBlobByte(image,0); /* bits per index (ignored) */
          (void) WriteBlobByte(image,8); /* bits per red component */
          (void) WriteBlobByte(image,8); /* bits per green component */
          (void) WriteBlobByte(image,8); /* bits per blue component */
        }
      else
        {
          /*
            Colormapped image.
          */
          bits_per_pixel=8;
          (void) WriteBlobString(image,"\033*v6W"); /* set color mode... */
          (void) WriteBlobByte(image,0); /* RGB */
          (void) WriteBlobByte(image,1); /* indexed by pixel */
          (void) WriteBlobByte(image,bits_per_pixel); /* bits per index */
          (void) WriteBlobByte(image,8); /* bits per red component */
          (void) WriteBlobByte(image,8); /* bits per green component */
          (void) WriteBlobByte(image,8); /* bits per blue component */
          for (i=0; i < (ssize_t) image->colors; i++)
          {
            (void) FormatLocaleString(buffer,MaxTextExtent,
              "\033*v%da%db%dc%.20gI",
              ScaleQuantumToChar(image->colormap[i].red),
              ScaleQuantumToChar(image->colormap[i].green),
              ScaleQuantumToChar(image->colormap[i].blue),(double) i);
            (void) WriteBlobString(image,buffer);
          }
          for (one=1; i < (ssize_t) (one << bits_per_pixel); i++)
          {
            (void) FormatLocaleString(buffer,MaxTextExtent,"\033*v%.20gI",
              (double) i);
            (void) WriteBlobString(image,buffer);
          }
        }
    option=GetImageOption(image_info,"pcl:fit-to-page");
    if ((option != (const char *) NULL) &&
        (IsMagickTrue(option) != MagickFalse))
      (void) WriteBlobString(image,"\033*r3A");
    else
      (void) WriteBlobString(image,"\033*r1A");  /* start raster graphics */
    (void) WriteBlobString(image,"\033*b0Y");  /* set y offset */
    length=(image->columns*bits_per_pixel+7)/8;
    pixels=(unsigned char *) AcquireQuantumMemory(length+1,sizeof(*pixels));
    if (pixels == (unsigned char *) NULL)
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    (void) ResetMagickMemory(pixels,0,(length+1)*sizeof(*pixels));
    compress_pixels=(unsigned char *) NULL;
    previous_pixels=(unsigned char *) NULL;
    switch (image->compression)
    {
      case NoCompression:
      {
        (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b0M");
        (void) WriteBlobString(image,buffer);
        break;
      }
      case RLECompression:
      {
        compress_pixels=(unsigned char *) AcquireQuantumMemory(length+256,
          sizeof(*compress_pixels));
        if (compress_pixels == (unsigned char *) NULL)
          {
            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
          }
        (void) ResetMagickMemory(compress_pixels,0,(length+256)*
          sizeof(*compress_pixels));
        (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b2M");
        (void) WriteBlobString(image,buffer);
        break;
      }
      default:
      {
        compress_pixels=(unsigned char *) AcquireQuantumMemory(3*length+256,
          sizeof(*compress_pixels));
        if (compress_pixels == (unsigned char *) NULL)
          {
            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
          }
        (void) ResetMagickMemory(compress_pixels,0,(3*length+256)*
          sizeof(*compress_pixels));
        previous_pixels=(unsigned char *) AcquireQuantumMemory(length+1,
          sizeof(*previous_pixels));
        if (previous_pixels == (unsigned char *) NULL)
          {
            compress_pixels=(unsigned char *) RelinquishMagickMemory(
              compress_pixels);
            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
          }
        (void) ResetMagickMemory(previous_pixels,0,(length+1)*
          sizeof(*previous_pixels));
        (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b3M");
        (void) WriteBlobString(image,buffer);
        break;
      }
    }
    for (y=0; y < (ssize_t) image->rows; y++)
    {
      p=GetVirtualPixels(image,0,y,image->columns,1,exception);
      if (p == (const Quantum *) NULL)
        break;
      q=pixels;
      switch (bits_per_pixel)
      {
        case 1:
        {
          register unsigned char
            bit,
            byte;

          /*
            Monochrome image.
          */
          bit=0;
          byte=0;
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            byte<<=1;
            if (GetPixelIntensity(image,p) < ((MagickRealType) QuantumRange/2.0))
              byte|=0x01;
            bit++;
            if (bit == 8)
              {
                *q++=byte;
                bit=0;
                byte=0;
              }
            p+=GetPixelChannels(image);
          }
          if (bit != 0)
            *q++=byte << (8-bit);
          break;
        }
        case 8:
        {
          /*
            Colormapped image.
          */
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            *q++=(unsigned char) GetPixelIndex(image,p);
            p+=GetPixelChannels(image);
          }
          break;
        }
        case 24:
        case 32:
        {
          /*
            Truecolor image.
          */
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            *q++=ScaleQuantumToChar(GetPixelRed(image,p));
            *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
            *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
            p+=GetPixelChannels(image);
          }
          break;
        }
      }
      switch (image->compression)
      {
        case NoCompression:
        {
          (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b%.20gW",
            (double) length);
          (void) WriteBlobString(image,buffer);
          (void) WriteBlob(image,length,pixels);
          break;
        }
        case RLECompression:
        {
          packets=PCLPackbitsCompressImage(length,pixels,compress_pixels);
          (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b%.20gW",
            (double) packets);
          (void) WriteBlobString(image,buffer);
          (void) WriteBlob(image,packets,compress_pixels);
          break;
        }
        default:
        {
          if (y == 0)
            for (i=0; i < (ssize_t) length; i++)
              previous_pixels[i]=(~pixels[i]);
          packets=PCLDeltaCompressImage(length,previous_pixels,pixels,
            compress_pixels);
          (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b%.20gW",
            (double) packets);
          (void) WriteBlobString(image,buffer);
          (void) WriteBlob(image,packets,compress_pixels);
          (void) CopyMagickMemory(previous_pixels,pixels,length*
            sizeof(*pixels));
          break;
        }
      }
    }
    (void) WriteBlobString(image,"\033*rB");  /* end graphics */
    switch (image->compression)
    {
      case NoCompression:
        break;
      case RLECompression:
      {
        compress_pixels=(unsigned char *) RelinquishMagickMemory(
          compress_pixels);
        break;
      }
      default:
      {
        previous_pixels=(unsigned char *) RelinquishMagickMemory(
          previous_pixels);
        compress_pixels=(unsigned char *) RelinquishMagickMemory(
          compress_pixels);
        break;
      }
    }
    pixels=(unsigned char *) RelinquishMagickMemory(pixels);
    if (GetNextImageInList(image) == (Image *) NULL)
      break;
    image=SyncNextImageInList(image);
    status=SetImageProgress(image,SaveImagesTag,scene++,
      GetImageListLength(image));
    if (status == MagickFalse)
      break;
  } while (image_info->adjoin != MagickFalse);
  (void) WriteBlobString(image,"\033E");
  (void) CloseBlob(image);
  return(MagickTrue);
}
Пример #17
0
/**
 * HistogramStretch
 * \param method: 0 = luminance (default), 1 = linked channels , 2 = independent channels.
 * \return true if everything is ok
 * \author [dave] and [nipper]
 */
bool CxImage::HistogramStretch(long method)
{
  if (!pDib) return false;

  if ((head.biBitCount==8) && IsGrayScale()){
	// get min/max info
	BYTE minc = 255, maxc = 0;
	BYTE gray;
	long y;

	double dbScaler = 50.0/head.biHeight;

	for (y=0; y<head.biHeight; y++)
	{
		info.nProgress = (long)(y*dbScaler);
		for (long x=0; x<head.biWidth; x++)	{
			gray = GetPixelIndex(x, y);
			if (gray < minc)   minc = gray;
			if (gray > maxc)   maxc = gray; 
		}
	}

	if (minc == 0 && maxc == 255) return true;
	
	// calculate LUT
	BYTE lut[256];
	BYTE range = maxc - minc;
	if (range != 0){
		for (long x = minc; x <= maxc; x++){
			lut[x] = (BYTE)(255 * (x - minc) / range);
		}
	} else lut[minc] = minc;

	for (y=0; y<head.biHeight; y++)	{
		info.nProgress = (long)(50.0+y*dbScaler);
		for (long x=0; x<head.biWidth; x++)
		{
			SetPixelIndex(x, y, lut[GetPixelIndex(x, y)]);
		}
	}
  } else {
	switch(method){
	case 1:
	  { // <nipper>
		// get min/max info
		BYTE minc = 255, maxc = 0;
		RGBQUAD color;
		long y;

		for (y=0; y<head.biHeight; y++)
		{

			for (long x=0; x<head.biWidth; x++)
			{
				color = GetPixelColor(x, y);

				if (color.rgbRed < minc)   minc = color.rgbRed;
				if (color.rgbBlue < minc)  minc = color.rgbBlue;
				if (color.rgbGreen < minc) minc = color.rgbGreen;

				if (color.rgbRed > maxc)   maxc = color.rgbRed; 
				if (color.rgbBlue > maxc)  maxc = color.rgbBlue; 
				if (color.rgbGreen > maxc) maxc = color.rgbGreen; 
			}
		}

		if (minc == 0 && maxc == 255)
			return true;
		
		// calculate LUT
		BYTE lut[256];
		BYTE range = maxc - minc;

		if (range != 0){
			for (long x = minc; x <= maxc; x++){
				lut[x] = (BYTE)(255 * (x - minc) / range);
			}
		} else lut[minc] = minc;

		// normalize image
		double dbScaler = 100.0/head.biHeight;

		for (y=0; y<head.biHeight; y++)	{
			info.nProgress = (long)(y*dbScaler);

			for (long x=0; x<head.biWidth; x++)
			{
				color = GetPixelColor(x, y);

				color.rgbRed = lut[color.rgbRed];
				color.rgbBlue = lut[color.rgbBlue];
				color.rgbGreen = lut[color.rgbGreen];

				SetPixelColor(x, y, color);
			}
		}
	  }
		break;
	case 2:
	  { // <nipper>
		// get min/max info
		BYTE minR = 255, maxR = 0;
		BYTE minG = 255, maxG = 0;
		BYTE minB = 255, maxB = 0;
		RGBQUAD color;
		long y;

		for (y=0; y<head.biHeight; y++)
		{
			for (long x=0; x<head.biWidth; x++)
			{
				color = GetPixelColor(x, y);

				if (color.rgbRed < minR)   minR = color.rgbRed;
				if (color.rgbBlue < minB)  minB = color.rgbBlue;
				if (color.rgbGreen < minG) minG = color.rgbGreen;

				if (color.rgbRed > maxR)   maxR = color.rgbRed; 
				if (color.rgbBlue > maxB)  maxB = color.rgbBlue; 
				if (color.rgbGreen > maxG) maxG = color.rgbGreen; 
			}
		}

		if (minR == 0 && maxR == 255 && minG == 0 && maxG == 255 && minB == 0 && maxB == 255)
			return true;

		// calculate LUT
		BYTE lutR[256];
		BYTE range = maxR - minR;
		if (range != 0)	{
			for (long x = minR; x <= maxR; x++){
				lutR[x] = (BYTE)(255 * (x - minR) / range);
			}
		} else lutR[minR] = minR;

		BYTE lutG[256];
		range = maxG - minG;
		if (range != 0)	{
			for (long x = minG; x <= maxG; x++){
				lutG[x] = (BYTE)(255 * (x - minG) / range);
			}
		} else lutG[minG] = minG;
			
		BYTE lutB[256];
		range = maxB - minB;
		if (range != 0)	{
			for (long x = minB; x <= maxB; x++){
				lutB[x] = (BYTE)(255 * (x - minB) / range);
			}
		} else lutB[minB] = minB;

		// normalize image
		double dbScaler = 100.0/head.biHeight;

		for (y=0; y<head.biHeight; y++)
		{
			info.nProgress = (long)(y*dbScaler);

			for (long x=0; x<head.biWidth; x++)
			{
				color = GetPixelColor(x, y);

				color.rgbRed = lutR[color.rgbRed];
				color.rgbBlue = lutB[color.rgbBlue];
				color.rgbGreen = lutG[color.rgbGreen];

				SetPixelColor(x, y, color);
			}
		}
	  }
		break;
	default:
	  { // <dave>
		// S = ( R - C ) ( B - A / D - C )
		double alimit = 0.0;
		double blimit = 255.0;
		double lowerc = 255.0;
		double upperd = 0.0;
		double tmpGray;

		RGBQUAD color;
		RGBQUAD	yuvClr;
		double  stretcheds;

		if ( head.biClrUsed == 0 ){
			long x, y, xmin, xmax, ymin, ymax;
			xmin = ymin = 0;
			xmax = head.biWidth; 
			ymax = head.biHeight;

			for( y = ymin; y < ymax; y++ ){
				info.nProgress = (long)(50*y/ymax);
				for( x = xmin; x < xmax; x++ ){
					color = GetPixelColor( x, y );
					tmpGray = RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
					if ( tmpGray < lowerc )	lowerc = tmpGray;
					if ( tmpGray > upperd )	upperd = tmpGray;
				}
			}
			if (upperd==lowerc) return false;
			
			for( y = ymin; y < ymax; y++ ){
				info.nProgress = (long)(50+50*y/ymax);
				for( x = xmin; x < xmax; x++ ){

					color = GetPixelColor( x, y );
					yuvClr = RGBtoYUV(color);

					// Stretch Luminance
					tmpGray = (double)yuvClr.rgbRed;
					stretcheds = (double)(tmpGray - lowerc) * ( (blimit - alimit) / (upperd - lowerc) ); // + alimit;
					if ( stretcheds < 0.0 )	stretcheds = 0.0;
					else if ( stretcheds > 255.0 ) stretcheds = 255.0;
					yuvClr.rgbRed = (BYTE)stretcheds;

					color = YUVtoRGB(yuvClr);
					SetPixelColor( x, y, color );
				}
			}
		} else {
			DWORD  j;
			for( j = 0; j < head.biClrUsed; j++ ){
				color = GetPaletteColor( (BYTE)j );
				tmpGray = RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
				if ( tmpGray < lowerc )	lowerc = tmpGray;
				if ( tmpGray > upperd )	upperd = tmpGray;
			}
			if (upperd==lowerc) return false;

			for( j = 0; j < head.biClrUsed; j++ ){

				color = GetPaletteColor( (BYTE)j );
				yuvClr = RGBtoYUV( color );

				// Stretch Luminance
				tmpGray = (double)yuvClr.rgbRed;
				stretcheds = (double)(tmpGray - lowerc) * ( (blimit - alimit) / (upperd - lowerc) ); // + alimit;
				if ( stretcheds < 0.0 )	stretcheds = 0.0;
				else if ( stretcheds > 255.0 ) stretcheds = 255.0;
				yuvClr.rgbRed = (BYTE)stretcheds;

				color = YUVtoRGB(yuvClr);
				SetPaletteColor( (BYTE)j, color );
			}
		}
	  }
	}
  }
  return true;
}
Пример #18
0
MagickExport MagickBooleanType SortColormapByIntensity(Image *image,
  ExceptionInfo *exception)
{
  CacheView
    *image_view;

  MagickBooleanType
    status;

  register ssize_t
    i;

  ssize_t
    y;

  unsigned short
    *pixels;

  assert(image != (Image *) NULL);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  assert(image->signature == MagickCoreSignature);
  if (image->storage_class != PseudoClass)
    return(MagickTrue);
  /*
    Allocate memory for pixel indexes.
  */
  pixels=(unsigned short *) AcquireQuantumMemory((size_t) image->colors,
    sizeof(*pixels));
  if (pixels == (unsigned short *) NULL)
    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
      image->filename);
  /*
    Assign index values to colormap entries.
  */
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status) \
    magick_threads(image,image,1,1)
#endif
  for (i=0; i < (ssize_t) image->colors; i++)
    image->colormap[i].alpha=(double) i;
  /*
    Sort image colormap by decreasing color popularity.
  */
  qsort((void *) image->colormap,(size_t) image->colors,
    sizeof(*image->colormap),IntensityCompare);
  /*
    Update image colormap indexes to sorted colormap order.
  */
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status)
#endif
  for (i=0; i < (ssize_t) image->colors; i++)
    pixels[(ssize_t) image->colormap[i].alpha]=(unsigned short) i;
  status=MagickTrue;
  image_view=AcquireAuthenticCacheView(image,exception);
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    Quantum
      index;

    register ssize_t
      x;

    register Quantum
      *restrict q;

    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if (q == (Quantum *) NULL)
      {
        status=MagickFalse;
        break;
      }
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      index=(Quantum) pixels[(ssize_t) GetPixelIndex(image,q)];
      SetPixelIndex(image,index,q);
      SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
      q+=GetPixelChannels(image);
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
    if (status == MagickFalse)
      break;
  }
  image_view=DestroyCacheView(image_view);
  pixels=(unsigned short *) RelinquishMagickMemory(pixels);
  return(status);
}
Пример #19
0
static MagickBooleanType InverseFourier(FourierInfo *fourier_info,
  const Image *magnitude_image,const Image *phase_image,fftw_complex *fourier,
  ExceptionInfo *exception)
{
  CacheView
    *magnitude_view,
    *phase_view;

  double
    *magnitude,
    *phase,
    *magnitude_source,
    *phase_source;

  MagickBooleanType
    status;

  register const IndexPacket
    *indexes;

  register const PixelPacket
    *p;

  register ssize_t
    i,
    x;

  ssize_t
    y;

  /*
    Inverse fourier - read image and break down into a double array.
  */
  magnitude_source=(double *) AcquireQuantumMemory((size_t)
    fourier_info->height,fourier_info->width*sizeof(*magnitude_source));
  if (magnitude_source == (double *) NULL)
    {
      (void) ThrowMagickException(exception,GetMagickModule(),
        ResourceLimitError,"MemoryAllocationFailed","`%s'",
        magnitude_image->filename);
      return(MagickFalse);
    }
  phase_source=(double *) AcquireQuantumMemory((size_t) fourier_info->height,
    fourier_info->width*sizeof(*phase_source));
  if (phase_source == (double *) NULL)
    {
      (void) ThrowMagickException(exception,GetMagickModule(),
        ResourceLimitError,"MemoryAllocationFailed","`%s'",
        magnitude_image->filename);
      magnitude_source=(double *) RelinquishMagickMemory(magnitude_source);
      return(MagickFalse);
    }
  i=0L;
  magnitude_view=AcquireVirtualCacheView(magnitude_image,exception);
  for (y=0L; y < (ssize_t) fourier_info->height; y++)
  {
    p=GetCacheViewVirtualPixels(magnitude_view,0L,y,fourier_info->width,1UL,
      exception);
    if (p == (const PixelPacket *) NULL)
      break;
    indexes=GetCacheViewAuthenticIndexQueue(magnitude_view);
    for (x=0L; x < (ssize_t) fourier_info->width; x++)
    {
      switch (fourier_info->channel)
      {
        case RedChannel:
        default:
        {
          magnitude_source[i]=QuantumScale*GetPixelRed(p);
          break;
        }
        case GreenChannel:
        {
          magnitude_source[i]=QuantumScale*GetPixelGreen(p);
          break;
        }
        case BlueChannel:
        {
          magnitude_source[i]=QuantumScale*GetPixelBlue(p);
          break;
        }
        case OpacityChannel:
        {
          magnitude_source[i]=QuantumScale*GetPixelOpacity(p);
          break;
        }
        case IndexChannel:
        {
          magnitude_source[i]=QuantumScale*GetPixelIndex(indexes+x);
          break;
        }
        case GrayChannels:
        {
          magnitude_source[i]=QuantumScale*GetPixelGray(p);
          break;
        }
      }
      i++;
      p++;
    }
  }
  i=0L;
  phase_view=AcquireVirtualCacheView(phase_image,exception);
  for (y=0L; y < (ssize_t) fourier_info->height; y++)
  {
    p=GetCacheViewVirtualPixels(phase_view,0,y,fourier_info->width,1,
      exception);
    if (p == (const PixelPacket *) NULL)
      break;
    indexes=GetCacheViewAuthenticIndexQueue(phase_view);
    for (x=0L; x < (ssize_t) fourier_info->width; x++)
    {
      switch (fourier_info->channel)
      {
        case RedChannel:
        default:
        {
          phase_source[i]=QuantumScale*GetPixelRed(p);
          break;
        }
        case GreenChannel:
        {
          phase_source[i]=QuantumScale*GetPixelGreen(p);
          break;
        }
        case BlueChannel:
        {
          phase_source[i]=QuantumScale*GetPixelBlue(p);
          break;
        }
        case OpacityChannel:
        {
          phase_source[i]=QuantumScale*GetPixelOpacity(p);
          break;
        }
        case IndexChannel:
        {
          phase_source[i]=QuantumScale*GetPixelIndex(indexes+x);
          break;
        }
        case GrayChannels:
        {
          phase_source[i]=QuantumScale*GetPixelGray(p);
          break;
        }
      }
      i++;
      p++;
    }
  }
  if (fourier_info->modulus != MagickFalse)
    {
      i=0L;
      for (y=0L; y < (ssize_t) fourier_info->height; y++)
        for (x=0L; x < (ssize_t) fourier_info->width; x++)
        {
          phase_source[i]-=0.5;
          phase_source[i]*=(2.0*MagickPI);
          i++;
        }
    }
  magnitude_view=DestroyCacheView(magnitude_view);
  phase_view=DestroyCacheView(phase_view);
  magnitude=(double *) AcquireQuantumMemory((size_t) fourier_info->height,
    fourier_info->center*sizeof(*magnitude));
  if (magnitude == (double *) NULL)
    {
      (void) ThrowMagickException(exception,GetMagickModule(),
        ResourceLimitError,"MemoryAllocationFailed","`%s'",
        magnitude_image->filename);
      magnitude_source=(double *) RelinquishMagickMemory(magnitude_source);
      phase_source=(double *) RelinquishMagickMemory(phase_source);
      return(MagickFalse);
    }
  status=InverseQuadrantSwap(fourier_info->width,fourier_info->height,
    magnitude_source,magnitude);
  magnitude_source=(double *) RelinquishMagickMemory(magnitude_source);
  phase=(double *) AcquireQuantumMemory((size_t) fourier_info->height,
    fourier_info->width*sizeof(*phase));
  if (phase == (double *) NULL)
    {
      (void) ThrowMagickException(exception,GetMagickModule(),
        ResourceLimitError,"MemoryAllocationFailed","`%s'",
        magnitude_image->filename);
      phase_source=(double *) RelinquishMagickMemory(phase_source);
      return(MagickFalse);
    }
  CorrectPhaseLHS(fourier_info->width,fourier_info->width,phase_source);
  if (status != MagickFalse)
    status=InverseQuadrantSwap(fourier_info->width,fourier_info->height,
      phase_source,phase);
  phase_source=(double *) RelinquishMagickMemory(phase_source);
  /*
    Merge two sets.
  */
  i=0L;
  if (fourier_info->modulus != MagickFalse)
    for (y=0L; y < (ssize_t) fourier_info->height; y++)
       for (x=0L; x < (ssize_t) fourier_info->center; x++)
       {
#if defined(MAGICKCORE_HAVE_COMPLEX_H)
         fourier[i]=magnitude[i]*cos(phase[i])+I*magnitude[i]*sin(phase[i]);
#else
         fourier[i][0]=magnitude[i]*cos(phase[i]);
         fourier[i][1]=magnitude[i]*sin(phase[i]);
#endif
         i++;
      }
  else
    for (y=0L; y < (ssize_t) fourier_info->height; y++)
      for (x=0L; x < (ssize_t) fourier_info->center; x++)
      {
#if defined(MAGICKCORE_HAVE_COMPLEX_H)
        fourier[i]=magnitude[i]+I*phase[i];
#else
        fourier[i][0]=magnitude[i];
        fourier[i][1]=phase[i];
#endif
        i++;
      }
  phase=(double *) RelinquishMagickMemory(phase);
  magnitude=(double *) RelinquishMagickMemory(magnitude);
  return(status);
}
Пример #20
0
static MagickBooleanType WritePS2Image(const ImageInfo *image_info,Image *image)
{
  static const char
    *PostscriptProlog[]=
    {
      "%%%%BeginProlog",
      "%%",
      "%% Display a color image.  The image is displayed in color on",
      "%% Postscript viewers or printers that support color, otherwise",
      "%% it is displayed as grayscale.",
      "%%",
      "/DirectClassImage",
      "{",
      "  %%",
      "  %% Display a DirectClass image.",
      "  %%",
      "  colorspace 0 eq",
      "  {",
      "    /DeviceRGB setcolorspace",
      "    <<",
      "      /ImageType 1",
      "      /Width columns",
      "      /Height rows",
      "      /BitsPerComponent 8",
      "      /Decode [0 1 0 1 0 1]",
      "      /ImageMatrix [columns 0 0 rows neg 0 rows]",
      "      compression 0 gt",
      "      { /DataSource pixel_stream %s }",
      "      { /DataSource pixel_stream %s } ifelse",
      "    >> image",
      "  }",
      "  {",
      "    /DeviceCMYK setcolorspace",
      "    <<",
      "      /ImageType 1",
      "      /Width columns",
      "      /Height rows",
      "      /BitsPerComponent 8",
      "      /Decode [1 0 1 0 1 0 1 0]",
      "      /ImageMatrix [columns 0 0 rows neg 0 rows]",
      "      compression 0 gt",
      "      { /DataSource pixel_stream %s }",
      "      { /DataSource pixel_stream %s } ifelse",
      "    >> image",
      "  } ifelse",
      "} bind def",
      "",
      "/PseudoClassImage",
      "{",
      "  %%",
      "  %% Display a PseudoClass image.",
      "  %%",
      "  %% Parameters:",
      "  %%   colors: number of colors in the colormap.",
      "  %%",
      "  currentfile buffer readline pop",
      "  token pop /colors exch def pop",
      "  colors 0 eq",
      "  {",
      "    %%",
      "    %% Image is grayscale.",
      "    %%",
      "    currentfile buffer readline pop",
      "    token pop /bits exch def pop",
      "    /DeviceGray setcolorspace",
      "    <<",
      "      /ImageType 1",
      "      /Width columns",
      "      /Height rows",
      "      /BitsPerComponent bits",
      "      /Decode [0 1]",
      "      /ImageMatrix [columns 0 0 rows neg 0 rows]",
      "      compression 0 gt",
      "      { /DataSource pixel_stream %s }",
      "      {",
      "        /DataSource pixel_stream %s",
      "        <<",
      "           /K "CCITTParam,
      "           /Columns columns",
      "           /Rows rows",
      "        >> /CCITTFaxDecode filter",
      "      } ifelse",
      "    >> image",
      "  }",
      "  {",
      "    %%",
      "    %% Parameters:",
      "    %%   colormap: red, green, blue color packets.",
      "    %%",
      "    /colormap colors 3 mul string def",
      "    currentfile colormap readhexstring pop pop",
      "    currentfile buffer readline pop",
      "    [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace",
      "    <<",
      "      /ImageType 1",
      "      /Width columns",
      "      /Height rows",
      "      /BitsPerComponent 8",
      "      /Decode [0 255]",
      "      /ImageMatrix [columns 0 0 rows neg 0 rows]",
      "      compression 0 gt",
      "      { /DataSource pixel_stream %s }",
      "      { /DataSource pixel_stream %s } ifelse",
      "    >> image",
      "  } ifelse",
      "} bind def",
      "",
      "/DisplayImage",
      "{",
      "  %%",
      "  %% Display a DirectClass or PseudoClass image.",
      "  %%",
      "  %% Parameters:",
      "  %%   x & y translation.",
      "  %%   x & y scale.",
      "  %%   label pointsize.",
      "  %%   image label.",
      "  %%   image columns & rows.",
      "  %%   class: 0-DirectClass or 1-PseudoClass.",
      "  %%   colorspace: 0-RGB or 1-CMYK.",
      "  %%   compression: 0-RLECompression or 1-NoCompression.",
      "  %%   hex color packets.",
      "  %%",
      "  gsave",
      "  /buffer 512 string def",
      "  /pixel_stream currentfile def",
      "",
      "  currentfile buffer readline pop",
      "  token pop /x exch def",
      "  token pop /y exch def pop",
      "  x y translate",
      "  currentfile buffer readline pop",
      "  token pop /x exch def",
      "  token pop /y exch def pop",
      "  currentfile buffer readline pop",
      "  token pop /pointsize exch def pop",
      "  /Helvetica findfont pointsize scalefont setfont",
      (char *) NULL
    },
    *PostscriptEpilog[]=
    {
      "  x y scale",
      "  currentfile buffer readline pop",
      "  token pop /columns exch def",
      "  token pop /rows exch def pop",
      "  currentfile buffer readline pop",
      "  token pop /class exch def pop",
      "  currentfile buffer readline pop",
      "  token pop /colorspace exch def pop",
      "  currentfile buffer readline pop",
      "  token pop /compression exch def pop",
      "  class 0 gt { PseudoClassImage } { DirectClassImage } ifelse",
      (char *) NULL
    };

  char
    buffer[MaxTextExtent],
    date[MaxTextExtent],
    page_geometry[MaxTextExtent],
    **labels;

  CompressionType
    compression;

  const char
    **q,
    *value;

  double
    pointsize;

  GeometryInfo
    geometry_info;

  MagickOffsetType
    scene,
    start,
    stop;

  MagickBooleanType
    progress,
    status;

  MagickOffsetType
    offset;

  MagickSizeType
    number_pixels;

  MagickStatusType
    flags;

  PointInfo
    delta,
    resolution,
    scale;

  RectangleInfo
    geometry,
    media_info,
    page_info;

  register const IndexPacket
    *indexes;

  register const PixelPacket
    *p;

  register ssize_t
    x;

  register ssize_t
    i;

  SegmentInfo
    bounds;

  size_t
    length,
    page,
    text_size;

  ssize_t
    j,
    y;

  time_t
    timer;

  unsigned char
    *pixels;

  /*
    Open output image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
  if (status == MagickFalse)
    return(status);
  compression=image->compression;
  if (image_info->compression != UndefinedCompression)
    compression=image_info->compression;
  switch (compression)
  {
#if !defined(MAGICKCORE_JPEG_DELEGATE)
    case JPEGCompression:
    {
      compression=RLECompression;
      (void) ThrowMagickException(&image->exception,GetMagickModule(),
        MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)",
        image->filename);
      break;
    }
#endif
    default:
      break;
  }
  (void) ResetMagickMemory(&bounds,0,sizeof(bounds));
  page=1;
  scene=0;
  do
  {
    /*
      Scale relative to dots-per-inch.
    */
    delta.x=DefaultResolution;
    delta.y=DefaultResolution;
    resolution.x=image->x_resolution;
    resolution.y=image->y_resolution;
    if ((resolution.x == 0.0) || (resolution.y == 0.0))
      {
        flags=ParseGeometry(PSDensityGeometry,&geometry_info);
        resolution.x=geometry_info.rho;
        resolution.y=geometry_info.sigma;
        if ((flags & SigmaValue) == 0)
          resolution.y=resolution.x;
      }
    if (image_info->density != (char *) NULL)
      {
        flags=ParseGeometry(image_info->density,&geometry_info);
        resolution.x=geometry_info.rho;
        resolution.y=geometry_info.sigma;
        if ((flags & SigmaValue) == 0)
          resolution.y=resolution.x;
      }
    if (image->units == PixelsPerCentimeterResolution)
      {
        resolution.x=(size_t) (100.0*2.54*resolution.x+0.5)/100.0;
        resolution.y=(size_t) (100.0*2.54*resolution.y+0.5)/100.0;
      }
    SetGeometry(image,&geometry);
    (void) FormatLocaleString(page_geometry,MaxTextExtent,"%.20gx%.20g",
      (double) image->columns,(double) image->rows);
    if (image_info->page != (char *) NULL)
      (void) CopyMagickString(page_geometry,image_info->page,MaxTextExtent);
    else
      if ((image->page.width != 0) && (image->page.height != 0))
        (void) FormatLocaleString(page_geometry,MaxTextExtent,
          "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double)
          image->page.height,(double) image->page.x,(double) image->page.y);
      else
        if ((image->gravity != UndefinedGravity) &&
            (LocaleCompare(image_info->magick,"PS") == 0))
          (void) CopyMagickString(page_geometry,PSPageGeometry,MaxTextExtent);
    (void) ConcatenateMagickString(page_geometry,">",MaxTextExtent);
    (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
      &geometry.width,&geometry.height);
    scale.x=(double) (geometry.width*delta.x)/resolution.x;
    geometry.width=(size_t) floor(scale.x+0.5);
    scale.y=(double) (geometry.height*delta.y)/resolution.y;
    geometry.height=(size_t) floor(scale.y+0.5);
    (void) ParseAbsoluteGeometry(page_geometry,&media_info);
    (void) ParseGravityGeometry(image,page_geometry,&page_info,
      &image->exception);
    if (image->gravity != UndefinedGravity)
      {
        geometry.x=(-page_info.x);
        geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows);
      }
    pointsize=12.0;
    if (image_info->pointsize != 0.0)
      pointsize=image_info->pointsize;
    text_size=0;
    value=GetImageProperty(image,"label");
    if (value != (const char *) NULL)
      text_size=(size_t) (MultilineCensus(value)*pointsize+12);
    if (page == 1)
      {
        /*
          Output Postscript header.
        */
        if (LocaleCompare(image_info->magick,"PS2") == 0)
          (void) CopyMagickString(buffer,"%!PS-Adobe-3.0\n",MaxTextExtent);
        else
          (void) CopyMagickString(buffer,"%!PS-Adobe-3.0 EPSF-3.0\n",
            MaxTextExtent);
        (void) WriteBlobString(image,buffer);
        (void) WriteBlobString(image,"%%Creator: (ImageMagick)\n");
        (void) FormatLocaleString(buffer,MaxTextExtent,"%%%%Title: (%s)\n",
          image->filename);
        (void) WriteBlobString(image,buffer);
        timer=time((time_t *) NULL);
        (void) FormatMagickTime(timer,MaxTextExtent,date);
        (void) FormatLocaleString(buffer,MaxTextExtent,
          "%%%%CreationDate: (%s)\n",date);
        (void) WriteBlobString(image,buffer);
        bounds.x1=(double) geometry.x;
        bounds.y1=(double) geometry.y;
        bounds.x2=(double) geometry.x+geometry.width;
        bounds.y2=(double) geometry.y+geometry.height+text_size;
        if ((image_info->adjoin != MagickFalse) &&
            (GetNextImageInList(image) != (Image *) NULL))
          (void) CopyMagickString(buffer,"%%BoundingBox: (atend)\n",
            MaxTextExtent);
        else
          {
            (void) FormatLocaleString(buffer,MaxTextExtent,
              "%%%%BoundingBox: %.20g %.20g %.20g %.20g\n",ceil(bounds.x1-0.5),
              ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5));
            (void) WriteBlobString(image,buffer);
            (void) FormatLocaleString(buffer,MaxTextExtent,
              "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1,
              bounds.y1,bounds.x2,bounds.y2);
          }
        (void) WriteBlobString(image,buffer);
        value=GetImageProperty(image,"label");
        if (value != (const char *) NULL)
          (void) WriteBlobString(image,
            "%%DocumentNeededResources: font Helvetica\n");
        (void) WriteBlobString(image,"%%LanguageLevel: 2\n");
        if (LocaleCompare(image_info->magick,"PS2") != 0)
          (void) WriteBlobString(image,"%%Pages: 1\n");
        else
          {
            (void) WriteBlobString(image,"%%Orientation: Portrait\n");
            (void) WriteBlobString(image,"%%PageOrder: Ascend\n");
            if (image_info->adjoin == MagickFalse)
              (void) CopyMagickString(buffer,"%%Pages: 1\n",MaxTextExtent);
            else
              (void) FormatLocaleString(buffer,MaxTextExtent,
                "%%%%Pages: %.20g\n",(double) GetImageListLength(image));
            (void) WriteBlobString(image,buffer);
          }
        (void) WriteBlobString(image,"%%EndComments\n");
        (void) WriteBlobString(image,"\n%%BeginDefaults\n");
        (void) WriteBlobString(image,"%%EndDefaults\n\n");
        /*
          Output Postscript commands.
        */
        for (q=PostscriptProlog; *q; q++)
        {
          switch (compression)
          {
            case NoCompression:
            {
              (void) FormatLocaleString(buffer,MaxTextExtent,*q,
                "/ASCII85Decode filter");
              break;
            }
            case JPEGCompression:
            {
              (void) FormatLocaleString(buffer,MaxTextExtent,*q,
                "/DCTDecode filter");
              break;
            }
            case LZWCompression:
            {
              (void) FormatLocaleString(buffer,MaxTextExtent,*q,
                "/LZWDecode filter");
              break;
            }
            case FaxCompression:
            case Group4Compression:
            {
              (void) FormatLocaleString(buffer,MaxTextExtent,*q," ");
              break;
            }
            default:
            {
              (void) FormatLocaleString(buffer,MaxTextExtent,*q,
                "/RunLengthDecode filter");
              break;
            }
          }
          (void) WriteBlobString(image,buffer);
          (void) WriteBlobByte(image,'\n');
        }
        value=GetImageProperty(image,"label");
        if (value != (const char *) NULL)
          for (j=(ssize_t) MultilineCensus(value)-1; j >= 0; j--)
          {
            (void) WriteBlobString(image,"  /label 512 string def\n");
            (void) WriteBlobString(image,"  currentfile label readline pop\n");
            (void) FormatLocaleString(buffer,MaxTextExtent,
              "  0 y %g add moveto label show pop\n",j*pointsize+12);
            (void) WriteBlobString(image,buffer);
          }
        for (q=PostscriptEpilog; *q; q++)
        {
          (void) FormatLocaleString(buffer,MaxTextExtent,"%s\n",*q);
          (void) WriteBlobString(image,buffer);
        }
        if (LocaleCompare(image_info->magick,"PS2") == 0)
          (void) WriteBlobString(image,"  showpage\n");
        (void) WriteBlobString(image,"} bind def\n");
        (void) WriteBlobString(image,"%%EndProlog\n");
      }
    (void) FormatLocaleString(buffer,MaxTextExtent,"%%%%Page:  1 %.20g\n",
      (double) page++);
    (void) WriteBlobString(image,buffer);
    (void) FormatLocaleString(buffer,MaxTextExtent,
      "%%%%PageBoundingBox: %.20g %.20g %.20g %.20g\n",(double) geometry.x,
      (double) geometry.y,geometry.x+(double) geometry.width,geometry.y+(double)
      (geometry.height+text_size));
    (void) WriteBlobString(image,buffer);
    if ((double) geometry.x < bounds.x1)
      bounds.x1=(double) geometry.x;
    if ((double) geometry.y < bounds.y1)
      bounds.y1=(double) geometry.y;
    if ((double) (geometry.x+geometry.width-1) > bounds.x2)
      bounds.x2=(double) geometry.x+geometry.width-1;
    if ((double) (geometry.y+(geometry.height+text_size)-1) > bounds.y2)
      bounds.y2=(double) geometry.y+(geometry.height+text_size)-1;
    value=GetImageProperty(image,"label");
    if (value != (const char *) NULL)
      (void) WriteBlobString(image,"%%PageResources: font Times-Roman\n");
    if (LocaleCompare(image_info->magick,"PS2") != 0)
      (void) WriteBlobString(image,"userdict begin\n");
    start=TellBlob(image);
    (void) FormatLocaleString(buffer,MaxTextExtent,
      "%%%%BeginData:%13ld %s Bytes\n",0L,
      compression == NoCompression ? "ASCII" : "Binary");
    (void) WriteBlobString(image,buffer);
    stop=TellBlob(image);
    (void) WriteBlobString(image,"DisplayImage\n");
    /*
      Output image data.
    */
    (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n%g %g\n%g\n",
      (double) geometry.x,(double) geometry.y,scale.x,scale.y,pointsize);
    (void) WriteBlobString(image,buffer);
    labels=(char **) NULL;
    value=GetImageProperty(image,"label");
    if (value != (const char *) NULL)
      labels=StringToList(value);
    if (labels != (char **) NULL)
      {
        for (i=0; labels[i] != (char *) NULL; i++)
        {
          (void) FormatLocaleString(buffer,MaxTextExtent,"%s \n",
            labels[i]);
          (void) WriteBlobString(image,buffer);
          labels[i]=DestroyString(labels[i]);
        }
        labels=(char **) RelinquishMagickMemory(labels);
      }
    number_pixels=(MagickSizeType) image->columns*image->rows;
    if (number_pixels != (MagickSizeType) ((size_t) number_pixels))
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    if ((compression == FaxCompression) || (compression == Group4Compression) ||
        ((image_info->type != TrueColorType) &&
         (IsGrayImage(image,&image->exception) != MagickFalse)))
      {
        (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n1\n%d\n",
          (double) image->columns,(double) image->rows,(int)
          (image->colorspace == CMYKColorspace));
        (void) WriteBlobString(image,buffer);
        (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n",
          (int) ((compression != FaxCompression) &&
           (compression != Group4Compression)));
        (void) WriteBlobString(image,buffer);
        (void) WriteBlobString(image,"0\n");
        (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n",
           (compression == FaxCompression) ||
           (compression == Group4Compression) ? 1 : 8);
        (void) WriteBlobString(image,buffer);
        switch (compression)
        {
          case FaxCompression:
          case Group4Compression:
          {
            if (LocaleCompare(CCITTParam,"0") == 0)
              {
                (void) HuffmanEncodeImage(image_info,image,image);
                break;
              }
            (void) Huffman2DEncodeImage(image_info,image,image);
            break;
          }
          case JPEGCompression:
          {
            status=InjectImageBlob(image_info,image,image,"jpeg",
              &image->exception);
            if (status == MagickFalse)
              ThrowWriterException(CoderError,image->exception.reason);
            break;
          }
          case RLECompression:
          default:
          {
            register unsigned char
              *q;

            /*
              Allocate pixel array.
            */
            length=(size_t) number_pixels;
            pixels=(unsigned char *) AcquireQuantumMemory(length,
              sizeof(*pixels));
            if (pixels == (unsigned char *) NULL)
              ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
            /*
              Dump Runlength encoded pixels.
            */
            q=pixels;
            for (y=0; y < (ssize_t) image->rows; y++)
            {
              p=GetVirtualPixels(image,0,y,image->columns,1,
                &image->exception);
              if (p == (const PixelPacket *) NULL)
                break;
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p));
                p++;
              }
              progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
                image->rows);
              if (progress == MagickFalse)
                break;
            }
            length=(size_t) (q-pixels);
            if (compression == LZWCompression)
              status=LZWEncodeImage(image,length,pixels);
            else
              status=PackbitsEncodeImage(image,length,pixels);
            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
            if (status == MagickFalse)
              {
                (void) CloseBlob(image);
                return(MagickFalse);
              }
            break;
          }
          case NoCompression:
          {
            /*
              Dump uncompressed PseudoColor packets.
            */
            Ascii85Initialize(image);
            for (y=0; y < (ssize_t) image->rows; y++)
            {
              p=GetVirtualPixels(image,0,y,image->columns,1,
                &image->exception);
              if (p == (const PixelPacket *) NULL)
                break;
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                Ascii85Encode(image,ScaleQuantumToChar(
                  PixelIntensityToQuantum(p)));
                p++;
              }
              progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
                y,image->rows);
              if (progress == MagickFalse)
                break;
            }
            Ascii85Flush(image);
            break;
          }
        }
      }
    else
      if ((image->storage_class == DirectClass) || (image->colors > 256) ||
          (compression == JPEGCompression) || (image->matte != MagickFalse))
        {
          (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n0\n%d\n",
            (double) image->columns,(double) image->rows,(int)
            (image->colorspace == CMYKColorspace));
          (void) WriteBlobString(image,buffer);
          (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n",
            (int) (compression == NoCompression));
          (void) WriteBlobString(image,buffer);
          switch (compression)
          {
            case JPEGCompression:
            {
              status=InjectImageBlob(image_info,image,image,"jpeg",
                &image->exception);
              if (status == MagickFalse)
                ThrowWriterException(CoderError,image->exception.reason);
              break;
            }
            case RLECompression:
            default:
            {
              register unsigned char
                *q;

              /*
                Allocate pixel array.
              */
              length=(size_t) number_pixels;
              pixels=(unsigned char *) AcquireQuantumMemory(length,
                4*sizeof(*pixels));
              if (pixels == (unsigned char *) NULL)
                ThrowWriterException(ResourceLimitError,
                  "MemoryAllocationFailed");
              /*
                Dump Packbit encoded pixels.
              */
              q=pixels;
              for (y=0; y < (ssize_t) image->rows; y++)
              {
                p=GetVirtualPixels(image,0,y,image->columns,1,
                  &image->exception);
                if (p == (const PixelPacket *) NULL)
                  break;
                indexes=GetVirtualIndexQueue(image);
                for (x=0; x < (ssize_t) image->columns; x++)
                {
                  if ((image->matte != MagickFalse) &&
                      (GetPixelOpacity(p) == (Quantum) TransparentOpacity))
                    {
                      *q++=ScaleQuantumToChar((Quantum) QuantumRange);
                      *q++=ScaleQuantumToChar((Quantum) QuantumRange);
                      *q++=ScaleQuantumToChar((Quantum) QuantumRange);
                    }
                  else
                    if (image->colorspace != CMYKColorspace)
                      {
                        *q++=ScaleQuantumToChar(GetPixelRed(p));
                        *q++=ScaleQuantumToChar(GetPixelGreen(p));
                        *q++=ScaleQuantumToChar(GetPixelBlue(p));
                      }
                    else
                      {
                        *q++=ScaleQuantumToChar(GetPixelRed(p));
                        *q++=ScaleQuantumToChar(GetPixelGreen(p));
                        *q++=ScaleQuantumToChar(GetPixelBlue(p));
                        *q++=ScaleQuantumToChar(GetPixelIndex(
                          indexes+x));
                      }
                  p++;
                }
                progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
                  y,image->rows);
                if (progress == MagickFalse)
                  break;
              }
              length=(size_t) (q-pixels);
              if (compression == LZWCompression)
                status=LZWEncodeImage(image,length,pixels);
              else
                status=PackbitsEncodeImage(image,length,pixels);
              if (status == MagickFalse)
                {
                  (void) CloseBlob(image);
                  return(MagickFalse);
                }
              pixels=(unsigned char *) RelinquishMagickMemory(pixels);
              break;
            }
            case NoCompression:
            {
              /*
                Dump uncompressed DirectColor packets.
              */
              Ascii85Initialize(image);
              for (y=0; y < (ssize_t) image->rows; y++)
              {
                p=GetVirtualPixels(image,0,y,image->columns,1,
                  &image->exception);
                if (p == (const PixelPacket *) NULL)
                  break;
                indexes=GetVirtualIndexQueue(image);
                for (x=0; x < (ssize_t) image->columns; x++)
                {
                  if ((image->matte != MagickFalse) &&
                      (GetPixelOpacity(p) == (Quantum) TransparentOpacity))
                    {
                      Ascii85Encode(image,ScaleQuantumToChar((Quantum)
                        QuantumRange));
                      Ascii85Encode(image,ScaleQuantumToChar((Quantum)
                        QuantumRange));
                      Ascii85Encode(image,ScaleQuantumToChar((Quantum)
                        QuantumRange));
                    }
                  else
                    if (image->colorspace != CMYKColorspace)
                      {
                        Ascii85Encode(image,ScaleQuantumToChar(
                          GetPixelRed(p)));
                        Ascii85Encode(image,ScaleQuantumToChar(
                          GetPixelGreen(p)));
                        Ascii85Encode(image,ScaleQuantumToChar(
                          GetPixelBlue(p)));
                      }
                    else
                      {
                        Ascii85Encode(image,ScaleQuantumToChar(
                          GetPixelRed(p)));
                        Ascii85Encode(image,ScaleQuantumToChar(
                          GetPixelGreen(p)));
                        Ascii85Encode(image,ScaleQuantumToChar(
                          GetPixelBlue(p)));
                        Ascii85Encode(image,ScaleQuantumToChar(
                          GetPixelIndex(indexes+x)));
                      }
                  p++;
                }
                progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
                  y,image->rows);
                if (progress == MagickFalse)
                  break;
              }
              Ascii85Flush(image);
              break;
            }
          }
        }
      else
        {
          /*
            Dump number of colors and colormap.
          */
          (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n1\n%d\n",
            (double) image->columns,(double) image->rows,(int)
            (image->colorspace == CMYKColorspace));
          (void) WriteBlobString(image,buffer);
          (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n",
            (int) (compression == NoCompression));
          (void) WriteBlobString(image,buffer);
          (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
            image->colors);
          (void) WriteBlobString(image,buffer);
          for (i=0; i < (ssize_t) image->colors; i++)
          {
            (void) FormatLocaleString(buffer,MaxTextExtent,"%02X%02X%02X\n",
              ScaleQuantumToChar(image->colormap[i].red),
              ScaleQuantumToChar(image->colormap[i].green),
              ScaleQuantumToChar(image->colormap[i].blue));
            (void) WriteBlobString(image,buffer);
          }
          switch (compression)
          {
            case RLECompression:
            default:
            {
              register unsigned char
                *q;

              /*
                Allocate pixel array.
              */
              length=(size_t) number_pixels;
              pixels=(unsigned char *) AcquireQuantumMemory(length,
                sizeof(*pixels));
              if (pixels == (unsigned char *) NULL)
                ThrowWriterException(ResourceLimitError,
                  "MemoryAllocationFailed");
              /*
                Dump Runlength encoded pixels.
              */
              q=pixels;
              for (y=0; y < (ssize_t) image->rows; y++)
              {
                p=GetVirtualPixels(image,0,y,image->columns,1,
                  &image->exception);
                if (p == (const PixelPacket *) NULL)
                  break;
                indexes=GetVirtualIndexQueue(image);
                for (x=0; x < (ssize_t) image->columns; x++)
                  *q++=(unsigned char) GetPixelIndex(indexes+x);
                progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
                  y,image->rows);
                if (progress == MagickFalse)
                  break;
              }
              length=(size_t) (q-pixels);
              if (compression == LZWCompression)
                status=LZWEncodeImage(image,length,pixels);
              else
                status=PackbitsEncodeImage(image,length,pixels);
              pixels=(unsigned char *) RelinquishMagickMemory(pixels);
              if (status == MagickFalse)
                {
                  (void) CloseBlob(image);
                  return(MagickFalse);
                }
              break;
            }
            case NoCompression:
            {
              /*
                Dump uncompressed PseudoColor packets.
              */
              Ascii85Initialize(image);
              for (y=0; y < (ssize_t) image->rows; y++)
              {
                p=GetVirtualPixels(image,0,y,image->columns,1,
                  &image->exception);
                if (p == (const PixelPacket *) NULL)
                  break;
                indexes=GetVirtualIndexQueue(image);
                for (x=0; x < (ssize_t) image->columns; x++)
                  Ascii85Encode(image,(unsigned char) GetPixelIndex(
                    indexes+x));
                progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
                  y,image->rows);
                if (progress == MagickFalse)
                  break;
              }
              Ascii85Flush(image);
              break;
            }
          }
        }
    (void) WriteBlobByte(image,'\n');
    length=(size_t) (TellBlob(image)-stop);
    stop=TellBlob(image);
    offset=SeekBlob(image,start,SEEK_SET);
    if (offset < 0)
      ThrowWriterException(CorruptImageError,"ImproperImageHeader");
    (void) FormatLocaleString(buffer,MaxTextExtent,
      "%%%%BeginData:%13ld %s Bytes\n",(long) length,
      compression == NoCompression ? "ASCII" : "Binary");
    (void) WriteBlobString(image,buffer);
    offset=SeekBlob(image,stop,SEEK_SET);
    (void) WriteBlobString(image,"%%EndData\n");
    if (LocaleCompare(image_info->magick,"PS2") != 0)
      (void) WriteBlobString(image,"end\n");
    (void) WriteBlobString(image,"%%PageTrailer\n");
    if (GetNextImageInList(image) == (Image *) NULL)
      break;
    image=SyncNextImageInList(image);
    status=SetImageProgress(image,SaveImagesTag,scene++,
      GetImageListLength(image));
    if (status == MagickFalse)
      break;
  } while (image_info->adjoin != MagickFalse);
  (void) WriteBlobString(image,"%%Trailer\n");
  if (page > 1)
    {
      (void) FormatLocaleString(buffer,MaxTextExtent,
        "%%%%BoundingBox: %.20g %.20g %.20g %.20g\n",ceil(bounds.x1-0.5),
        ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5));
      (void) WriteBlobString(image,buffer);
      (void) FormatLocaleString(buffer,MaxTextExtent,
        "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1,bounds.y1,
        bounds.x2,bounds.y2);
      (void) WriteBlobString(image,buffer);
    }
  (void) WriteBlobString(image,"%%EOF\n");
  (void) CloseBlob(image);
  return(MagickTrue);
}
Пример #21
0
MagickExport Image *ConnectedComponentsImage(const Image *image,
  const size_t connectivity,CCObjectInfo **objects,ExceptionInfo *exception)
{
#define ConnectedComponentsImageTag  "ConnectedComponents/Image"

  CacheView
    *image_view,
    *component_view;

  CCObjectInfo
    *object;

  char
    *p;

  const char
    *artifact;

  double
    area_threshold;

  Image
    *component_image;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  MatrixInfo
    *equivalences;

  register ssize_t
    i;

  size_t
    size;

  ssize_t
    first,
    last,
    n,
    step,
    y;

  /*
    Initialize connected components image attributes.
  */
  assert(image != (Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  if (objects != (CCObjectInfo **) NULL)
    *objects=(CCObjectInfo *) NULL;
  component_image=CloneImage(image,image->columns,image->rows,MagickTrue,
    exception);
  if (component_image == (Image *) NULL)
    return((Image *) NULL);
  component_image->depth=MAGICKCORE_QUANTUM_DEPTH;
  if (AcquireImageColormap(component_image,MaxColormapSize,exception) == MagickFalse)
    {
      component_image=DestroyImage(component_image);
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
    }
  /*
    Initialize connected components equivalences.
  */
  size=image->columns*image->rows;
  if (image->columns != (size/image->rows))
    {
      component_image=DestroyImage(component_image);
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
    }
  equivalences=AcquireMatrixInfo(size,1,sizeof(ssize_t),exception);
  if (equivalences == (MatrixInfo *) NULL)
    {
      component_image=DestroyImage(component_image);
      return((Image *) NULL);
    }
  for (n=0; n < (ssize_t) (image->columns*image->rows); n++)
    (void) SetMatrixElement(equivalences,n,0,&n);
  object=(CCObjectInfo *) AcquireQuantumMemory(MaxColormapSize,sizeof(*object));
  if (object == (CCObjectInfo *) NULL)
    {
      equivalences=DestroyMatrixInfo(equivalences);
      component_image=DestroyImage(component_image);
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
    }
  (void) ResetMagickMemory(object,0,MaxColormapSize*sizeof(*object));
  for (i=0; i < (ssize_t) MaxColormapSize; i++)
  {
    object[i].id=i;
    object[i].bounding_box.x=(ssize_t) image->columns;
    object[i].bounding_box.y=(ssize_t) image->rows;
    GetPixelInfo(image,&object[i].color);
  }
  /*
    Find connected components.
  */
  status=MagickTrue;
  progress=0;
  image_view=AcquireVirtualCacheView(image,exception);
  for (n=0; n < (ssize_t) (connectivity > 4 ? 4 : 2); n++)
  {
    ssize_t
      connect4[2][2] = { { -1,  0 }, {  0, -1 } },
      connect8[4][2] = { { -1, -1 }, { -1,  0 }, { -1,  1 }, {  0, -1 } },
      dx,
      dy;

    if (status == MagickFalse)
      continue;
    dy=connectivity > 4 ? connect8[n][0] : connect4[n][0];
    dx=connectivity > 4 ? connect8[n][1] : connect4[n][1];
    for (y=0; y < (ssize_t) image->rows; y++)
    {
      register const Quantum
        *magick_restrict p;

      register ssize_t
        x;

      if (status == MagickFalse)
        continue;
      p=GetCacheViewVirtualPixels(image_view,0,y-1,image->columns,3,exception);
      if (p == (const Quantum *) NULL)
        {
          status=MagickFalse;
          continue;
        }
      p+=GetPixelChannels(image)*image->columns;
      for (x=0; x < (ssize_t) image->columns; x++)
      {
        PixelInfo
          pixel,
          target;

        ssize_t
          neighbor_offset,
          object,
          offset,
          ox,
          oy,
          root;

        /*
          Is neighbor an authentic pixel and a different color than the pixel?
        */
        GetPixelInfoPixel(image,p,&pixel);
        neighbor_offset=dy*(GetPixelChannels(image)*image->columns)+dx*
          GetPixelChannels(image);
        GetPixelInfoPixel(image,p+neighbor_offset,&target);
        if (((x+dx) < 0) || ((x+dx) >= (ssize_t) image->columns) ||
            ((y+dy) < 0) || ((y+dy) >= (ssize_t) image->rows) ||
            (IsFuzzyEquivalencePixelInfo(&pixel,&target) == MagickFalse))
          {
            p+=GetPixelChannels(image);
            continue;
          }
        /*
          Resolve this equivalence.
        */
        offset=y*image->columns+x;
        neighbor_offset=dy*image->columns+dx;
        ox=offset;
        status=GetMatrixElement(equivalences,ox,0,&object);
        while (object != ox)
        {
          ox=object;
          status=GetMatrixElement(equivalences,ox,0,&object);
        }
        oy=offset+neighbor_offset;
        status=GetMatrixElement(equivalences,oy,0,&object);
        while (object != oy)
        {
          oy=object;
          status=GetMatrixElement(equivalences,oy,0,&object);
        }
        if (ox < oy)
          {
            status=SetMatrixElement(equivalences,oy,0,&ox);
            root=ox;
          }
        else
          {
            status=SetMatrixElement(equivalences,ox,0,&oy);
            root=oy;
          }
        ox=offset;
        status=GetMatrixElement(equivalences,ox,0,&object);
        while (object != root)
        {
          status=GetMatrixElement(equivalences,ox,0,&object);
          status=SetMatrixElement(equivalences,ox,0,&root);
        }
        oy=offset+neighbor_offset;
        status=GetMatrixElement(equivalences,oy,0,&object);
        while (object != root)
        {
          status=GetMatrixElement(equivalences,oy,0,&object);
          status=SetMatrixElement(equivalences,oy,0,&root);
        }
        status=SetMatrixElement(equivalences,y*image->columns+x,0,&root);
        p+=GetPixelChannels(image);
      }
    }
  }
  image_view=DestroyCacheView(image_view);
  /*
    Label connected components.
  */
  n=0;
  image_view=AcquireVirtualCacheView(image,exception);
  component_view=AcquireAuthenticCacheView(component_image,exception);
  for (y=0; y < (ssize_t) component_image->rows; y++)
  {
    register const Quantum
      *magick_restrict p;

    register Quantum
      *magick_restrict q;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
    q=QueueCacheViewAuthenticPixels(component_view,0,y,component_image->columns,
      1,exception);
    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
      {
        status=MagickFalse;
        continue;
      }
    for (x=0; x < (ssize_t) component_image->columns; x++)
    {
      ssize_t
        id,
        offset;

      offset=y*image->columns+x;
      status=GetMatrixElement(equivalences,offset,0,&id);
      if (id == offset)
        {
          id=n++;
          if (n > (ssize_t) MaxColormapSize)
            break;
          status=SetMatrixElement(equivalences,offset,0,&id);
        }
      else
        {
          status=GetMatrixElement(equivalences,id,0,&id);
          status=SetMatrixElement(equivalences,offset,0,&id);
        }
      if (x < object[id].bounding_box.x)
        object[id].bounding_box.x=x;
      if (x > (ssize_t) object[id].bounding_box.width)
        object[id].bounding_box.width=(size_t) x;
      if (y < object[id].bounding_box.y)
        object[id].bounding_box.y=y;
      if (y > (ssize_t) object[id].bounding_box.height)
        object[id].bounding_box.height=(size_t) y;
      object[id].color.red+=GetPixelRed(image,p);
      object[id].color.green+=GetPixelGreen(image,p);
      object[id].color.blue+=GetPixelBlue(image,p);
      object[id].color.black+=GetPixelBlack(image,p);
      object[id].color.alpha+=GetPixelAlpha(image,p);
      object[id].centroid.x+=x;
      object[id].centroid.y+=y;
      object[id].area++;
      SetPixelIndex(component_image,(Quantum) id,q);
      p+=GetPixelChannels(image);
      q+=GetPixelChannels(component_image);
    }
    if (n > (ssize_t) MaxColormapSize)
      break;
    if (SyncCacheViewAuthenticPixels(component_view,exception) == MagickFalse)
      status=MagickFalse;
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

        proceed=SetImageProgress(image,ConnectedComponentsImageTag,progress++,
          image->rows);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  component_view=DestroyCacheView(component_view);
  image_view=DestroyCacheView(image_view);
  equivalences=DestroyMatrixInfo(equivalences);
  if (n > (ssize_t) MaxColormapSize)
    {
      object=(CCObjectInfo *) RelinquishMagickMemory(object);
      component_image=DestroyImage(component_image);
      ThrowImageException(ResourceLimitError,"TooManyObjects");
    }
  component_image->colors=(size_t) n;
  for (i=0; i < (ssize_t) component_image->colors; i++)
  {
    object[i].bounding_box.width-=(object[i].bounding_box.x-1);
    object[i].bounding_box.height-=(object[i].bounding_box.y-1);
    object[i].color.red=object[i].color.red/object[i].area;
    object[i].color.green=object[i].color.green/object[i].area;
    object[i].color.blue=object[i].color.blue/object[i].area;
    object[i].color.alpha=object[i].color.alpha/object[i].area;
    object[i].color.black=object[i].color.black/object[i].area;
    object[i].centroid.x=object[i].centroid.x/object[i].area;
    object[i].centroid.y=object[i].centroid.y/object[i].area;
  }
  artifact=GetImageArtifact(image,"connected-components:area-threshold");
  area_threshold=0.0;
  if (artifact != (const char *) NULL)
    area_threshold=StringToDouble(artifact,(char **) NULL);
  if (area_threshold > 0.0)
    {
      /*
        Merge object below area threshold.
      */
      component_view=AcquireAuthenticCacheView(component_image,exception);
      for (i=0; i < (ssize_t) component_image->colors; i++)
      {
        double
          census;

        RectangleInfo
          bounding_box;

        register ssize_t
          j;

        size_t
          id;

        if (status == MagickFalse)
          continue;
        if ((double) object[i].area >= area_threshold)
          continue;
        for (j=0; j < (ssize_t) component_image->colors; j++)
          object[j].census=0;
        bounding_box=object[i].bounding_box;
        for (y=0; y < (ssize_t) bounding_box.height+2; y++)
        {
          register const Quantum
            *magick_restrict p;

          register ssize_t
            x;

          if (status == MagickFalse)
            continue;
          p=GetCacheViewVirtualPixels(component_view,bounding_box.x-1,
            bounding_box.y+y-1,bounding_box.width+2,1,exception);
          if (p == (const Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          for (x=0; x < (ssize_t) bounding_box.width+2; x++)
          {
            j=(ssize_t) GetPixelIndex(component_image,p);
            if (j != i)
              object[j].census++;
          }
        }
        census=0;
        id=0;
        for (j=0; j < (ssize_t) component_image->colors; j++)
          if (census < object[j].census)
            {
              census=object[j].census;
              id=(size_t) j;
            }
        object[id].area+=object[i].area;
        for (y=0; y < (ssize_t) bounding_box.height; y++)
        {
          register Quantum
            *magick_restrict q;

          register ssize_t
            x;

          if (status == MagickFalse)
            continue;
          q=GetCacheViewAuthenticPixels(component_view,bounding_box.x,
            bounding_box.y+y,bounding_box.width,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          for (x=0; x < (ssize_t) bounding_box.width; x++)
          {
            if ((ssize_t) GetPixelIndex(component_image,q) == i)
              SetPixelIndex(image,(Quantum) id,q);
            q+=GetPixelChannels(component_image);
          }
          if (SyncCacheViewAuthenticPixels(component_view,exception) == MagickFalse)
            status=MagickFalse;
        }
      }
      (void) SyncImage(component_image,exception);
    }
Пример #22
0
bool CxImagePCX::Encode(CxFile * hFile)
{
	if (EncodeSafeCheck(hFile)) return false;

  try {
	PCXHEADER pcxHeader;
	memset(&pcxHeader,0,sizeof(pcxHeader));
	pcxHeader.Manufacturer = PCX_MAGIC;
	pcxHeader.Version = 5;
	pcxHeader.Encoding = 1;
	pcxHeader.Xmin = 0;
	pcxHeader.Ymin = 0;
	pcxHeader.Xmax = (WORD)head.biWidth-1;
	pcxHeader.Ymax = (WORD)head.biHeight-1;
	pcxHeader.Hres = (WORD)info.xDPI;
	pcxHeader.Vres = (WORD)info.yDPI;
	pcxHeader.Reserved = 0;
	pcxHeader.PaletteType = head.biClrUsed==0;

	switch(head.biBitCount){
	case 24:
	case 8:
		{
			pcxHeader.BitsPerPixel = 8;
			pcxHeader.ColorPlanes = head.biClrUsed==0 ? 3 : 1;
#if CXIMAGE_SUPPORT_ALPHA
			if (AlphaIsValid() && head.biClrUsed==0) pcxHeader.ColorPlanes =4;
#endif //CXIMAGE_SUPPORT_ALPHA
			pcxHeader.BytesPerLine = (WORD)head.biWidth;
			break;
		}
	default: //(4 1)
		pcxHeader.BitsPerPixel = 1;
		pcxHeader.ColorPlanes = head.biClrUsed==16 ? 4 : 1;
		pcxHeader.BytesPerLine = (WORD)((head.biWidth * pcxHeader.BitsPerPixel + 7)>>3);
	}

    if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){
		pcxHeader.ColorMap[0][0] = pcxHeader.ColorMap[0][1] = pcxHeader.ColorMap[0][2] = 0;
		pcxHeader.ColorMap[1][0] = pcxHeader.ColorMap[1][1] = pcxHeader.ColorMap[1][2] = 255;
	}
	if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 4){
		RGBQUAD c;
		for (int i = 0; i < 16; i++){
			c=GetPaletteColor(i);
			pcxHeader.ColorMap[i][0] = c.rgbRed;
			pcxHeader.ColorMap[i][1] = c.rgbGreen;
			pcxHeader.ColorMap[i][2] = c.rgbBlue;
		}
	}

	pcxHeader.BytesPerLine = (pcxHeader.BytesPerLine + 1)&(~1);

	if (hFile->Write(&pcxHeader, sizeof(pcxHeader), 1) == 0 )
	   throw "cannot write PCX header";

	CxMemFile buffer;
	buffer.Open();

	BYTE c,n;
	long x,y;
	if (head.biClrUsed==0){
		for (y = head.biHeight-1; y >=0 ; y--){
			for (int p=0; p<pcxHeader.ColorPlanes; p++){
				c=n=0;
				for (x = 0; x<head.biWidth; x++){
					if (p==0)
						PCX_PackPixels(GetPixelColor(x,y).rgbRed,c,n,buffer);
					else if (p==1)
						PCX_PackPixels(GetPixelColor(x,y).rgbGreen,c,n,buffer);
					else if (p==2)
						PCX_PackPixels(GetPixelColor(x,y).rgbBlue,c,n,buffer);
#if CXIMAGE_SUPPORT_ALPHA
					else if (p==3)
						PCX_PackPixels(AlphaGet(x,y),c,n,buffer);
#endif //CXIMAGE_SUPPORT_ALPHA
				}
				PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer);
			}
		}

		hFile->Write(buffer.GetBuffer(false),buffer.Size(),1);

	} else if (head.biBitCount==8) {

		for (y = head.biHeight-1; y >=0 ; y--){
			c=n=0;
			for (x = 0; x<head.biWidth; x++){
				PCX_PackPixels(GetPixelIndex(x,y),c,n,buffer);
			}
			PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer);
		}

		hFile->Write(buffer.GetBuffer(false),buffer.Size(),1);

		if (head.biBitCount == 8){
			hFile->PutC(0x0C);
			BYTE* pal = (BYTE*)malloc(768);
			RGBQUAD c;
			for (int i=0;i<256;i++){
				c=GetPaletteColor(i);
				pal[3*i+0] = c.rgbRed;
				pal[3*i+1] = c.rgbGreen;
				pal[3*i+2] = c.rgbBlue;
			}
			hFile->Write(pal,768,1);
			free(pal);
		}
	} else { //(head.biBitCount==4) || (head.biBitCount==1)

		RGBQUAD *rgb = GetPalette();
		bool binvert = false;
		if (CompareColors(&rgb[0],&rgb[1])>0) binvert=(head.biBitCount==1);
		
		BYTE* plane = (BYTE*)malloc(pcxHeader.BytesPerLine);
		BYTE* raw = (BYTE*)malloc(head.biWidth);

		for(y = head.biHeight-1; y >=0 ; y--) {

			for( x = 0; x < head.biWidth; x++)	raw[x] = (BYTE)GetPixelIndex(x,y);

			if (binvert) for( x = 0; x < head.biWidth; x++)	raw[x] = 1-raw[x];

			for( x = 0; x < pcxHeader.ColorPlanes; x++ ) {
				PCX_PixelsToPlanes(raw, head.biWidth, plane, x);
				PCX_PackPlanes(plane, pcxHeader.BytesPerLine, buffer);
			}
		}

		free(plane);
		free(raw);

		hFile->Write(buffer.GetBuffer(false),buffer.Size(),1);

	}

  } catch (char *message) {
	strncpy(info.szLastError,message,255);
	return false;
  }
    return true;
}
Пример #23
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   W r i t e P I C O N I m a g e                                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  WritePICONImage() writes an image to a file in the Personal Icon format.
%
%  The format of the WritePICONImage method is:
%
%      MagickBooleanType WritePICONImage(const ImageInfo *image_info,
%        Image *image)
%
%  A description of each parameter follows.
%
%    o image_info: the image info.
%
%    o image:  The image.
%
*/
static MagickBooleanType WritePICONImage(const ImageInfo *image_info,
  Image *image)
{
#define ColormapExtent  155
#define GraymapExtent  95
#define PiconGeometry  "48x48>"

  static unsigned char
    Colormap[]=
    {
      0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x06, 0x00, 0x05, 0x00, 0xf4, 0x05,
      0x00, 0x00, 0x00, 0x00, 0x2f, 0x4f, 0x4f, 0x70, 0x80, 0x90, 0x7e, 0x7e,
      0x7e, 0xdc, 0xdc, 0xdc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00,
      0xff, 0x1e, 0x90, 0xff, 0x87, 0xce, 0xeb, 0xe6, 0xe6, 0xfa, 0x00, 0xff,
      0xff, 0x80, 0x00, 0x80, 0xb2, 0x22, 0x22, 0x2e, 0x8b, 0x57, 0x32, 0xcd,
      0x32, 0x00, 0xff, 0x00, 0x98, 0xfb, 0x98, 0xff, 0x00, 0xff, 0xff, 0x00,
      0x00, 0xff, 0x63, 0x47, 0xff, 0xa5, 0x00, 0xff, 0xd7, 0x00, 0xff, 0xff,
      0x00, 0xee, 0x82, 0xee, 0xa0, 0x52, 0x2d, 0xcd, 0x85, 0x3f, 0xd2, 0xb4,
      0x8c, 0xf5, 0xde, 0xb3, 0xff, 0xfa, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00,
      0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x05, 0x18, 0x20, 0x10, 0x08,
      0x03, 0x51, 0x18, 0x07, 0x92, 0x28, 0x0b, 0xd3, 0x38, 0x0f, 0x14, 0x49,
      0x13, 0x55, 0x59, 0x17, 0x96, 0x69, 0x1b, 0xd7, 0x85, 0x00, 0x3b,
    },
    Graymap[]=
    {
      0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x04, 0x00, 0xf3, 0x0f,
      0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x21, 0x21, 0x21, 0x33, 0x33,
      0x33, 0x45, 0x45, 0x45, 0x54, 0x54, 0x54, 0x66, 0x66, 0x66, 0x78, 0x78,
      0x78, 0x87, 0x87, 0x87, 0x99, 0x99, 0x99, 0xab, 0xab, 0xab, 0xba, 0xba,
      0xba, 0xcc, 0xcc, 0xcc, 0xde, 0xde, 0xde, 0xed, 0xed, 0xed, 0xff, 0xff,
      0xff, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00,
      0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x0c, 0x10, 0x04, 0x31,
      0x48, 0x31, 0x07, 0x25, 0xb5, 0x58, 0x73, 0x4f, 0x04, 0x00, 0x3b,
    };

#define MaxCixels  92

  static const char
    Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk"
                         "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";

  char
    buffer[MaxTextExtent],
    basename[MaxTextExtent],
    name[MaxTextExtent],
    symbol[MaxTextExtent];

  ExceptionInfo
    *exception;

  Image
    *affinity_image,
    *picon;

  ImageInfo
    *blob_info;

  MagickBooleanType
    status,
    transparent;

  MagickPixelPacket
    pixel;

  QuantizeInfo
    *quantize_info;

  RectangleInfo
    geometry;

  register const IndexPacket
    *indexes;

  register const PixelPacket
    *p;

  register ssize_t
    i,
    x;

  register PixelPacket
    *q;

  size_t
    characters_per_pixel,
    colors;

  ssize_t
    j,
    k,
    y;

  /*
    Open output image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
  if (status == MagickFalse)
    return(status);
  (void) TransformImageColorspace(image,sRGBColorspace);
  SetGeometry(image,&geometry);
  (void) ParseMetaGeometry(PiconGeometry,&geometry.x,&geometry.y,
    &geometry.width,&geometry.height);
  picon=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,1.0,
    &image->exception);
  blob_info=CloneImageInfo(image_info);
  (void) AcquireUniqueFilename(blob_info->filename);
  if ((image_info->type != TrueColorType) &&
      (SetImageGray(image,&image->exception) != MagickFalse))
    affinity_image=BlobToImage(blob_info,Graymap,GraymapExtent,
      &image->exception);
  else
    affinity_image=BlobToImage(blob_info,Colormap,ColormapExtent,
      &image->exception);
  (void) RelinquishUniqueFileResource(blob_info->filename);
  blob_info=DestroyImageInfo(blob_info);
  if ((picon == (Image *) NULL) || (affinity_image == (Image *) NULL))
    return(MagickFalse);
  quantize_info=AcquireQuantizeInfo(image_info);
  status=RemapImage(quantize_info,picon,affinity_image);
  quantize_info=DestroyQuantizeInfo(quantize_info);
  affinity_image=DestroyImage(affinity_image);
  transparent=MagickFalse;
  exception=(&image->exception);
  if (picon->storage_class == PseudoClass)
    {
      (void) CompressImageColormap(picon);
      if (picon->matte != MagickFalse)
        transparent=MagickTrue;
    }
  else
    {
      /*
        Convert DirectClass to PseudoClass picon.
      */
      if (picon->matte != MagickFalse)
        {
          /*
            Map all the transparent pixels.
          */
          for (y=0; y < (ssize_t) picon->rows; y++)
          {
            q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception);
            if (q == (PixelPacket *) NULL)
              break;
            for (x=0; x < (ssize_t) picon->columns; x++)
            {
              if (q->opacity == (Quantum) TransparentOpacity)
                transparent=MagickTrue;
              else
                SetPixelOpacity(q,OpaqueOpacity);
              q++;
            }
            if (SyncAuthenticPixels(picon,exception) == MagickFalse)
              break;
          }
        }
      (void) SetImageType(picon,PaletteType);
    }
  colors=picon->colors;
  if (transparent != MagickFalse)
    {
      register IndexPacket
        *indexes;

      colors++;
      picon->colormap=(PixelPacket *) ResizeQuantumMemory((void **)
        picon->colormap,(size_t) colors,sizeof(*picon->colormap));
      if (picon->colormap == (PixelPacket *) NULL)
        ThrowWriterException(ResourceLimitError,"MemoryAllocationError");
      for (y=0; y < (ssize_t) picon->rows; y++)
      {
        q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception);
        if (q == (PixelPacket *) NULL)
          break;
        indexes=GetAuthenticIndexQueue(picon);
        for (x=0; x < (ssize_t) picon->columns; x++)
        {
          if (q->opacity == (Quantum) TransparentOpacity)
            SetPixelIndex(indexes+x,picon->colors);
          q++;
        }
        if (SyncAuthenticPixels(picon,exception) == MagickFalse)
          break;
      }
    }
  /*
    Compute the character per pixel.
  */
  characters_per_pixel=1;
  for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels)
    characters_per_pixel++;
  /*
    XPM header.
  */
  (void) WriteBlobString(image,"/* XPM */\n");
  GetPathComponent(picon->filename,BasePath,basename);
  (void) FormatLocaleString(buffer,MaxTextExtent,
    "static char *%s[] = {\n",basename);
  (void) WriteBlobString(image,buffer);
  (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n");
  (void) FormatLocaleString(buffer,MaxTextExtent,
    "\"%.20g %.20g %.20g %.20g\",\n",(double) picon->columns,(double)
    picon->rows,(double) colors,(double) characters_per_pixel);
  (void) WriteBlobString(image,buffer);
  GetMagickPixelPacket(image,&pixel);
  for (i=0; i < (ssize_t) colors; i++)
  {
    /*
      Define XPM color.
    */
    SetMagickPixelPacket(image,picon->colormap+i,(IndexPacket *) NULL,&pixel);
    pixel.colorspace=sRGBColorspace;
    pixel.depth=8;
    pixel.opacity=(MagickRealType) OpaqueOpacity;
    (void) QueryMagickColorname(image,&pixel,XPMCompliance,name,
      &image->exception);
    if (transparent != MagickFalse)
      {
        if (i == (ssize_t) (colors-1))
          (void) CopyMagickString(name,"grey75",MaxTextExtent);
      }
    /*
      Write XPM color.
    */
    k=i % MaxCixels;
    symbol[0]=Cixel[k];
    for (j=1; j < (ssize_t) characters_per_pixel; j++)
    {
      k=((i-k)/MaxCixels) % MaxCixels;
      symbol[j]=Cixel[k];
    }
    symbol[j]='\0';
    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s c %s\",\n",
       symbol,name);
    (void) WriteBlobString(image,buffer);
  }
  /*
    Define XPM pixels.
  */
  (void) WriteBlobString(image,"/* pixels */\n");
  for (y=0; y < (ssize_t) picon->rows; y++)
  {
    p=GetVirtualPixels(picon,0,y,picon->columns,1,&picon->exception);
    if (p == (const PixelPacket *) NULL)
      break;
    indexes=GetVirtualIndexQueue(picon);
    (void) WriteBlobString(image,"\"");
    for (x=0; x < (ssize_t) picon->columns; x++)
    {
      k=((ssize_t) GetPixelIndex(indexes+x) % MaxCixels);
      symbol[0]=Cixel[k];
      for (j=1; j < (ssize_t) characters_per_pixel; j++)
      {
        k=(((int) GetPixelIndex(indexes+x)-k)/MaxCixels) % MaxCixels;
        symbol[j]=Cixel[k];
      }
      symbol[j]='\0';
      (void) CopyMagickString(buffer,symbol,MaxTextExtent);
      (void) WriteBlobString(image,buffer);
    }
    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s\n",
      y == (ssize_t) (picon->rows-1) ? "" : ",");
    (void) WriteBlobString(image,buffer);
    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
      picon->rows);
    if (status == MagickFalse)
      break;
  }
  picon=DestroyImage(picon);
  (void) WriteBlobString(image,"};\n");
  (void) CloseBlob(image);
  return(MagickTrue);
}
Пример #24
0
bool CxImageJ2K::Encode(CxFile * hFile)
{
	if (EncodeSafeCheck(hFile)) return false;

	if (head.biClrUsed!=0 && !IsGrayScale()){
		strcpy(info.szLastError,"J2K can save only RGB or GrayScale images");
		return false;
	}

    int i,x,y;
    j2k_image_t *img;
    j2k_cp_t *cp;
    j2k_tcp_t *tcp;
    j2k_tccp_t *tccp;

	img = (j2k_image_t *)calloc(sizeof(j2k_image_t),1);
	cp = (j2k_cp_t *)calloc(sizeof(j2k_cp_t),1);

    cp->tx0=0; cp->ty0=0;
    cp->tw=1; cp->th=1;
    cp->tcps=(j2k_tcp_t*)calloc(sizeof(j2k_tcp_t),1);
    tcp=&cp->tcps[0];

	long w=head.biWidth;
	long h=head.biHeight;
 
	tcp->numlayers=1;
	for (i=0;i<tcp->numlayers;i++) tcp->rates[i]=(w*h*GetJpegQuality())/600;


    if (IsGrayScale()) {
        img->x0=0;
		img->y0=0;
		img->x1=w;
		img->y1=h;
        img->numcomps=1;
        img->comps=(j2k_comp_t*)calloc(sizeof(j2k_comp_t),1);
        img->comps[0].data=(int*)calloc(w*h*sizeof(int),1);
        img->comps[0].prec=8;
        img->comps[0].sgnd=0;
        img->comps[0].dx=1;
        img->comps[0].dy=1;
		for (i=0,y=0; y<h; y++) {
			for (x=0; x<w; x++,i++){
				img->comps[0].data[i]=GetPixelIndex(x,h-1-y);
			}
		}
    } else if (!IsIndexed()) {
        img->x0=0;
		img->y0=0;
		img->x1=w;
		img->y1=h;
        img->numcomps=3;
        img->comps=(j2k_comp_t*)calloc(img->numcomps*sizeof(j2k_comp_t),1);
        for (i=0; i<img->numcomps; i++) {
            img->comps[i].data=(int*)calloc(w*h*sizeof(int),1);
            img->comps[i].prec=8;
            img->comps[i].sgnd=0;
            img->comps[i].dx=1;
            img->comps[i].dy=1;
        }
		RGBQUAD c;
        for (i=0,y=0; y<h; y++) {
			for (x=0; x<w; x++,i++){
				c=GetPixelColor(x,h-1-y);
				img->comps[0].data[i]=c.rgbRed;
				img->comps[1].data[i]=c.rgbGreen;
				img->comps[2].data[i]=c.rgbBlue;
			}
		}
    } else {
        return 0;
    }
	
    cp->tdx=img->x1-img->x0;
	cp->tdy=img->y1-img->y0;

    tcp->csty=0;
    tcp->prg=0;
    tcp->mct=img->numcomps==3?1:0;
    tcp->tccps=(j2k_tccp_t*)calloc(img->numcomps*sizeof(j2k_tccp_t),1);

    int ir=0; /* or 1 ???*/

    for (i=0; i<img->numcomps; i++) {
        tccp=&tcp->tccps[i];
        tccp->csty=0;
        tccp->numresolutions=6;
        tccp->cblkw=6;
        tccp->cblkh=6;
        tccp->cblksty=0;
        tccp->qmfbid=ir?0:1;
        tccp->qntsty=ir?J2K_CCP_QNTSTY_SEQNT:J2K_CCP_QNTSTY_NOQNT;
        tccp->numgbits=2;
        tccp->roishift=0;
        j2k_calc_explicit_stepsizes(tccp, img->comps[i].prec);
    }

    BYTE* dest=(BYTE*)calloc(tcp->rates[tcp->numlayers-1]+2,1);
    long len = j2k_encode(img, cp, dest, tcp->rates[tcp->numlayers-1]+2);

    if (len==0) {
		strcpy(info.szLastError,"J2K failed to encode image");
    } else {
		hFile->Write(dest, len, 1);
	}
	
	free(dest);
	j2k_destroy(&img,&cp);

	return (len!=0);
}
Пример #25
0
MagickExport MagickBooleanType SeparateImageChannel(Image *image,
  const ChannelType channel)
{
#define SeparateImageTag  "Separate/Image"

  CacheView
    *image_view;

  ExceptionInfo
    *exception;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  ssize_t
    y;

  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
    return(MagickFalse);
  if (channel == GrayChannels)
    image->matte=MagickTrue;
  /*
    Separate image channels.
  */
  status=MagickTrue;
  progress=0;
  exception=(&image->exception);
  image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(progress,status) \
    magick_threads(image,image,image->rows,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register IndexPacket
      *restrict indexes;

    register PixelPacket
      *restrict q;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if (q == (PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewAuthenticIndexQueue(image_view);
    switch (channel)
    {
      case RedChannel:
      {
        for (x=0; x < (ssize_t) image->columns; x++)
        {
          SetPixelGreen(q,GetPixelRed(q));
          SetPixelBlue(q,GetPixelRed(q));
          q++;
        }
        break;
      }
      case GreenChannel:
      {
        for (x=0; x < (ssize_t) image->columns; x++)
        {
          SetPixelRed(q,GetPixelGreen(q));
          SetPixelBlue(q,GetPixelGreen(q));
          q++;
        }
        break;
      }
      case BlueChannel:
      {
        for (x=0; x < (ssize_t) image->columns; x++)
        {
          SetPixelRed(q,GetPixelBlue(q));
          SetPixelGreen(q,GetPixelBlue(q));
          q++;
        }
        break;
      }
      case OpacityChannel:
      {
        for (x=0; x < (ssize_t) image->columns; x++)
        {
          SetPixelRed(q,GetPixelOpacity(q));
          SetPixelGreen(q,GetPixelOpacity(q));
          SetPixelBlue(q,GetPixelOpacity(q));
          q++;
        }
        break;
      }
      case BlackChannel:
      {
        if ((image->storage_class != PseudoClass) &&
            (image->colorspace != CMYKColorspace))
          break;
        for (x=0; x < (ssize_t) image->columns; x++)
        {
          SetPixelRed(q,GetPixelIndex(indexes+x));
          SetPixelGreen(q,GetPixelIndex(indexes+x));
          SetPixelBlue(q,GetPixelIndex(indexes+x));
          q++;
        }
        break;
      }
      case TrueAlphaChannel:
      {
        for (x=0; x < (ssize_t) image->columns; x++)
        {
          SetPixelRed(q,GetPixelAlpha(q));
          SetPixelGreen(q,GetPixelAlpha(q));
          SetPixelBlue(q,GetPixelAlpha(q));
          q++;
        }
        break;
      }
      case GrayChannels:
      {
        for (x=0; x < (ssize_t) image->columns; x++)
        {
          SetPixelAlpha(q,ClampToQuantum(GetPixelIntensity(image,q)));
          q++;
        }
        break;
      }
      default:
        break;
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

#if defined(MAGICKCORE_OPENMP_SUPPORT)
        #pragma omp critical (MagickCore_SeparateImageChannel)
#endif
        proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  image_view=DestroyCacheView(image_view);
  if (channel != GrayChannels)
    image->matte=MagickFalse;
  (void) SetImageColorspace(image,GRAYColorspace);
  return(status);
}
Пример #26
0
////////////////////////////////////////////////////////////////////////////////
// Draws (stretch) the image with transparency & alpha support
// > hdc: destination device context
// > x,y: (optional) offset
// > cx,cy: (optional) size.
long CxImage::Draw(HDC hdc, long x, long y, long cx, long cy, RECT* pClipRect)
{
	if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0;

	if (cx < 0) cx = head.biWidth;
	if (cy < 0) cy = head.biHeight;
	bool bTransparent = info.nBkgndIndex != -1;
	bool bAlpha = pAlpha != 0;

	RECT mainbox; // (experimental) 
	if (pClipRect){
		GetClipBox(hdc,&mainbox);
		HRGN rgn = CreateRectRgnIndirect(pClipRect);
		ExtSelectClipRgn(hdc,rgn,RGN_AND);
		DeleteObject(rgn);
	}

	if (!(bTransparent || bAlpha || info.bAlphaPaletteEnabled)){
		if (cx==head.biWidth && cy==head.biHeight){ //NORMAL
			SetStretchBltMode(hdc,COLORONCOLOR);	
			SetDIBitsToDevice(hdc, x, y, cx, cy, 0, 0, 0, cy,
						info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS);
		} else { //STRETCH
			RECT clipbox,paintbox;
			GetClipBox(hdc,&clipbox);
			paintbox.left = min(clipbox.right,max(clipbox.left,x));
			paintbox.right = max(clipbox.left,min(clipbox.right,x+cx));
			paintbox.top = min(clipbox.bottom,max(clipbox.top,y));
			paintbox.bottom = max(clipbox.top,min(clipbox.bottom,y+cy));
			long destw = paintbox.right - paintbox.left;
			long desth = paintbox.bottom - paintbox.top;
			//pixel informations
			RGBQUAD c={0,0,0,0};
			//Preparing Bitmap Info
			BITMAPINFO bmInfo;
			memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
			bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
			bmInfo.bmiHeader.biWidth=destw;
			bmInfo.bmiHeader.biHeight=desth;
			bmInfo.bmiHeader.biPlanes=1;
			bmInfo.bmiHeader.biBitCount=24;
			BYTE *pbase;	//points to the final dib
			BYTE *pdst;		//current pixel from pbase
			BYTE *ppix;		//current pixel from image
			//get the background
			HDC TmpDC=CreateCompatibleDC(hdc);
			HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
			HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);

			if (pbase){
				long xx,yy,yoffset;
				long ew = ((((24 * destw) + 31) / 32) * 4);
				long ymax = paintbox.bottom;
				long xmin = paintbox.left;
				float fx=(float)head.biWidth/(float)cx;
				float fy=(float)head.biHeight/(float)cy;
				long sx,sy;
				for(yy=0;yy<desth;yy++){
					sy=max(0L,head.biHeight-(long)ceil(((ymax-yy-y)*fy)));
					yoffset=sy*head.biWidth;
					pdst=pbase+yy*ew;
					for(xx=0;xx<destw;xx++){
						sx=(long)floor(((xx+xmin-x)*fx));
						if (head.biClrUsed){
							c=GetPaletteColor(GetPixelIndex(sx,sy));
						} else {
							ppix=info.pImage+sy*info.dwEffWidth+sx*3;
							c.rgbBlue = *ppix++;
							c.rgbGreen= *ppix++;
							c.rgbRed  = *ppix;
						}
						*pdst++=c.rgbBlue;
						*pdst++=c.rgbGreen;
						*pdst++=c.rgbRed;
					}
				}
			}
			//paint the image & cleanup
			SetDIBitsToDevice(hdc,paintbox.left,paintbox.top,destw,desth,0,0,0,desth,pbase,&bmInfo,0);
			DeleteObject(SelectObject(TmpDC,TmpObj));
			DeleteDC(TmpDC);
		}
	} else {	// draw image with transparent/alpha blending
	//////////////////////////////////////////////////////////////////
		//Alpha blend - Thanks to Florian Egel

		//find the smallest area to paint
		RECT clipbox,paintbox;
		GetClipBox(hdc,&clipbox);
		paintbox.left = min(clipbox.right,max(clipbox.left,x));
		paintbox.right = max(clipbox.left,min(clipbox.right,x+cx));
		paintbox.top = min(clipbox.bottom,max(clipbox.top,y));
		paintbox.bottom = max(clipbox.top,min(clipbox.bottom,y+cy));
		long destw = paintbox.right - paintbox.left;
		long desth = paintbox.bottom - paintbox.top;

		//pixel informations
		RGBQUAD c={0,0,0,0};
		RGBQUAD ct = GetTransColor();
		long* pc = (long*)&c;
		long* pct= (long*)&ct;

		//Preparing Bitmap Info
		BITMAPINFO bmInfo;
		memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
		bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
		bmInfo.bmiHeader.biWidth=destw;
		bmInfo.bmiHeader.biHeight=desth;
		bmInfo.bmiHeader.biPlanes=1;
		bmInfo.bmiHeader.biBitCount=24;

		BYTE *pbase;	//points to the final dib
		BYTE *pdst;		//current pixel from pbase
		BYTE *ppix;		//current pixel from image

		//get the background
		HDC TmpDC=CreateCompatibleDC(hdc);
		HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
		HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
		BitBlt(TmpDC,0,0,destw,desth,hdc,paintbox.left,paintbox.top,SRCCOPY);

		if (pbase){
			long xx,yy,yoffset,ix,iy;
			BYTE a,a1;
			long ew = ((((24 * destw) + 31) / 32) * 4);
			long ymax = paintbox.bottom;
			long xmin = paintbox.left;

			if (cx!=head.biWidth || cy!=head.biHeight){
				//STRETCH
				float fx=(float)head.biWidth/(float)cx;
				float fy=(float)head.biHeight/(float)cy;
				long sx,sy;
				
				for(yy=0;yy<desth;yy++){
					sy=max(0L,head.biHeight-(long)ceil(((ymax-yy-y)*fy)));
					yoffset=sy*head.biWidth;
					pdst=pbase+yy*ew;
					for(xx=0;xx<destw;xx++){
						sx=(long)floor(((xx+xmin-x)*fx));

						if (bAlpha) a=pAlpha[yoffset+sx]; else a=255;
						a =(BYTE)((a*(1+info.nAlphaMax))>>8);

						if (head.biClrUsed){
							c=GetPaletteColor(GetPixelIndex(sx,sy));
							if (info.bAlphaPaletteEnabled){
								a= (BYTE)((a*(1+c.rgbReserved))>>8);
							}
						} else {
							ppix=info.pImage+sy*info.dwEffWidth+sx*3;
							c.rgbBlue = *ppix++;
							c.rgbGreen= *ppix++;
							c.rgbRed  = *ppix;
						}
						if (*pc!=*pct || !bTransparent){
							// DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication
							if (a == 0) {			// Transparent, retain dest 
								pdst+=3; 
							} else if (a == 255) {	// opaque, ignore dest 
								*pdst++= c.rgbBlue; 
								*pdst++= c.rgbGreen; 
								*pdst++= c.rgbRed; 
							} else {				// semi transparent 
								a1=(BYTE)~a;
								*pdst++=(BYTE)((*pdst * a1 + a * c.rgbBlue)>>8); 
								*pdst++=(BYTE)((*pdst * a1 + a * c.rgbGreen)>>8); 
								*pdst++=(BYTE)((*pdst * a1 + a * c.rgbRed)>>8); 
							} 
						} else {
							pdst+=3;
						}
					}