bool ScImgDataLoader_GMagick::readCMYK(Image *input, RawImage *output, int width, int height)
{
	/* Mapping:
		red:     cyan
		green:   magenta
		blue:    yellow
		opacity: black
		index:   alpha
	*/
	//Copied from GraphicsMagick header and modified
	#define GetCyanSample(p) (p.red)
	#define GetMagentaSample(p) (p.green)
	#define GetYellowSample(p) (p.blue)
	#define GetCMYKBlackSample(p) (p.opacity)
	#define GetAlphaSample(p) (p)

	bool hasAlpha = input->matte;

	if (!output->create(width, height, hasAlpha ? 5 : 4)) return false;

	ExceptionInfo exception;
	GetExceptionInfo(&exception);
	const PixelPacket *pixels = AcquireImagePixels(input, 0, 0, width, height, &exception);
	if (exception.severity != UndefinedException)
		CatchException(&exception);
	if (!pixels) {
		qCritical() << QObject::tr("Could not get pixel data!");
		return false;
	}

    const IndexPacket *alpha = 0;
    if (hasAlpha) {
        alpha = AccessImmutableIndexes(input);
        if (!alpha) {
            qCritical() << QObject::tr("Could not get alpha channel data!");
            return false;
        }
    }

	unsigned char *buffer = output->bits();
	if (!buffer) {
	   qCritical() << QObject::tr("Could not allocate output buffer!");
	   return false;
    }

	int i;
	for (i = 0; i < width*height; i++) {
		*buffer++ = ScaleQuantumToChar(GetCyanSample(pixels[i]));
		*buffer++ = ScaleQuantumToChar(GetMagentaSample(pixels[i]));
		*buffer++ = ScaleQuantumToChar(GetYellowSample(pixels[i]));
		*buffer++ = ScaleQuantumToChar(GetCMYKBlackSample(pixels[i]));
		if (hasAlpha) {
			*buffer++ = 255 - ScaleQuantumToChar(GetAlphaSample(alpha[i]));
		}
	}
	return true;
}
Exemple #2
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   P i x e l I t e r a t e T r i p l e M o d i f y                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  PixelIterateTripleModify() iterates through pixel regions of three images
%  and invokes a user-provided callback function (of type
%  PixelIteratorTripleModifyCallback) for each row of pixels.  The first two
%  images are read-only, while the third image is read-write for update.
%  Access of the first two images is done lock-step using the same coordinates.
%  This is useful to support operations such as image differencing.
%
%  The format of the PixelIterateTripleModify method is:
%
%      MagickPassFail PixelIterateTripleModify(
%                                PixelIteratorTripleModifyCallback call_back,
%                                const PixelIteratorOptions *options,
%                                const char *description,
%                                void *mutable_data,
%                                const void *immutable_data,
%                                const unsigned long columns,
%                                const unsigned long rows,
%                                const Image *source1_image,
%                                const Image *source2_image,
%                                const long source_x,
%                                const long source_y,
%                                Image *update_image,
%                                const long update_x,
%                                const long update_y,
%                                ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o call_back: A user-provided C callback function which reads from
%      a region of source pixels and updates a region of destination pixels.
%
%    o options: Pixel iterator execution options (may be NULL).
%
%    o description: textual description of operation being performed.
%
%    o mutable_data: User-provided mutable context data.
%
%    o immutable_data: User-provided immutable context data.
%
%    o columns: Width of pixel region
%
%    o rows: Height of pixel region
%
%    o source1_image: The address of the constant source 1 Image.
%
%    o source2_image: The address of the constant source 2 Image.
%
%    o source_x: The horizontal ordinate of the top left corner of the source regions.
%
%    o source_y: The vertical ordinate of the top left corner of the source regions.
%
%    o update_image: The address of the update Image.
%
%    o update_x: The horizontal ordinate of the top left corner of the update region.
%
%    o update_y: The vertical ordinate of the top left corner of the update region.
%
%    o exception: If an error is reported, this argument is updated with the reason.
%
*/
static MagickPassFail
PixelIterateTripleImplementation(PixelIteratorTripleModifyCallback call_back,
                                 const PixelIteratorOptions *options,
                                 const char *description,
                                 void *mutable_data,
                                 const void *immutable_data,
                                 const unsigned long columns,
                                 const unsigned long rows,
                                 const Image *source1_image,
                                 const Image *source2_image,
                                 const long source_x,
                                 const long source_y,
                                 Image *update_image,
                                 const long update_x,
                                 const long update_y,
                                 ExceptionInfo *exception,
                                 MagickBool set)
{
  MagickPassFail
    status = MagickPass;

  register long
    row;

  unsigned long
    row_count=0;

  int
    max_threads;

  max_threads=omp_get_max_threads();
  (void) SetRegionThreads(max_threads,options,columns,rows);

#if defined(HAVE_OPENMP)
#  pragma omp parallel for schedule(static,1) shared(row_count, status)
#endif
  for (row=0; row < (long) rows; row++)
    {
      MagickBool
        thread_status;

      const PixelPacket
        *source1_pixels,
        *source2_pixels;

      const IndexPacket
        *source1_indexes,
        *source2_indexes;

      PixelPacket
        *update_pixels;

      IndexPacket
        *update_indexes;

      long
        source_row,
        update_row;

      thread_status=status;
      if (thread_status == MagickFail)
        continue;

      source_row=source_y+row;
      update_row=update_y+row;

      /*
        First image (read only).
      */
      source1_pixels=AcquireImagePixels(source1_image, source_x, source_row,
                                        columns, 1, exception);
      if (!source1_pixels)
        thread_status=MagickFail;
      source1_indexes=AccessImmutableIndexes(source1_image);

      /*
        Second image (read only).
      */
      source2_pixels=AcquireImagePixels(source2_image, source_x, source_row,
                                        columns, 1, exception);
      if (!source2_pixels)
        thread_status=MagickFail;
      source2_indexes=AccessImmutableIndexes(source2_image);

      /*
        Third image (read/write).
      */
      if (set)
        update_pixels=SetImagePixelsEx(update_image, update_x, update_row,
                                       columns, 1, exception);
      else
        update_pixels=GetImagePixelsEx(update_image, update_x, update_row,
                                       columns, 1, exception);
      if (!update_pixels)
        {
          thread_status=MagickFail;
          CopyException(exception,&update_image->exception);
        }
      update_indexes=AccessMutableIndexes(update_image);

      if (thread_status != MagickFail)
        status=(call_back)(mutable_data,immutable_data,
                           source1_image,source1_pixels,source1_indexes,
                           source2_image,source2_pixels,source2_indexes,
                           update_image,update_pixels,update_indexes,
                           columns,exception);
      
      if (!SyncImagePixelsEx(update_image,exception))
        thread_status=MagickFail;

#if defined(HAVE_OPENMP)
#  pragma omp critical (GM_PixelIterateTripleImplementation)
#endif
      {
        row_count++;
        if (QuantumTick(row_count,rows))
          if (!MagickMonitorFormatted(row_count,rows,exception,description,
                                      source1_image->filename,
                                      source2_image->filename,
                                      update_image->filename))
            thread_status=MagickFail;

        if (thread_status == MagickFail)
          status=MagickFail;
      }
    }

  omp_set_num_threads(max_threads);

  return (status);
}
Exemple #3
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   P i x e l I t e r a t e D u a l R e a d                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  PixelIterateDualRead() iterates through pixel regions of two images and
%  invokes a user-provided callback function (of type
%  PixelIteratorDualReadCallback) for each row of pixels. This is useful to
%  support operations such as image comparison.
%
%  The format of the PixelIterateDualModify method is:
%
%      MagickPassFail PixelIterateDualRead(
%                                PixelIteratorDualReadCallback call_back,
%                                const PixelIteratorOptions *options,
%                                const char *description,
%                                void *mutable_data,
%                                const void *immutable_data,
%                                const unsigned long columns,
%                                const unsigned long rows,
%                                const Image *first_image,
%                                const long first_x,
%                                const long first_y,
%                                const Image *second_image,
%                                const long second_x,
%                                const long second_y,
%                                ExceptionInfo *exception);
%
%  A description of each parameter follows:
%
%    o call_back: A user-provided C callback function which is passed the
%       address of pixels from each image.
%
%    o options: Pixel iterator execution options (may be NULL).
%
%    o description: textual description of operation being performed.
%
%    o mutable_data: User-provided mutable context data.
%
%    o immutable_data: User-provided immutable context data.
%
%    o columns: Width of pixel region
%
%    o rows: Height of pixel region
%
%    o first_image: The address of the first Image.
%
%    o first_x: The horizontal ordinate of the top left corner of the first region.
%
%    o first_y: The vertical ordinate of the top left corner of the first region.
%
%    o second_image: The address of the second Image.
%
%    o second_x: The horizontal ordinate of the top left corner of the second region.
%
%    o second_y: The vertical ordinate of the top left corner of the second region.
%
%    o exception: If an error is reported, this argument is updated with the reason.
%
*/
MagickExport MagickPassFail
PixelIterateDualRead(PixelIteratorDualReadCallback call_back,
                     const PixelIteratorOptions *options,
                     const char *description,
                     void *mutable_data,
                     const void *immutable_data,
                     const unsigned long columns,
                     const unsigned long rows,
                     const Image *first_image,
                     const long first_x,
                     const long first_y,
                     const Image *second_image,
                     const long second_x,
                     const long second_y,
                     ExceptionInfo *exception)
{
  MagickPassFail
    status = MagickPass;

  register long
    row;

  unsigned long
    row_count=0;

  int
    max_threads;

  max_threads=omp_get_max_threads();
  (void) SetRegionThreads(max_threads,options,columns,rows);

#if defined(HAVE_OPENMP)
#  pragma omp parallel for schedule(static,1) shared(row_count, status)
#endif
  for (row=0; row < (long) rows; row++)
    {
      MagickBool
        thread_status;

      long
        first_row,
        second_row;

      const PixelPacket
        *first_pixels,
        *second_pixels;

      const IndexPacket
        *first_indexes,
        *second_indexes;

      thread_status=status;
      if (thread_status == MagickFail)
        continue;

      first_row=first_y+row;
      second_row=second_y+row;

      first_pixels=AcquireImagePixels(first_image, first_x, first_row,
                                      columns, 1, exception);
      if (!first_pixels)
        thread_status=MagickFail;
      first_indexes=AccessImmutableIndexes(first_image);

      second_pixels=AcquireImagePixels(second_image, second_x, second_row,
                                       columns, 1, exception);
      if (!second_pixels)
        thread_status=MagickFail;
      second_indexes=AccessImmutableIndexes(second_image);

      if (thread_status != MagickFail)
        thread_status=(call_back)(mutable_data,immutable_data,
                                  first_image,first_pixels,first_indexes,
                                  second_image,second_pixels,second_indexes,
                                  columns, exception);

#if defined(HAVE_OPENMP)
#  pragma omp critical (GM_PixelIterateDualRead)
#endif
      {
        row_count++;
        if (QuantumTick(row_count,rows))
          if (!MagickMonitorFormatted(row_count,rows,exception,
                                      description,first_image->filename,
                                      second_image->filename))
            thread_status=MagickFail;

        if (thread_status == MagickFail)
          status=MagickFail;
      }
    }

  omp_set_num_threads(max_threads);

  return (status);
}
Exemple #4
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   P i x e l I t e r a t e M o n o R e a d                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% PixelIterateMonoRead() iterates through a region of an image and invokes a
% user-provided callback function (of type PixelRowIteratorMonoReadCallback)
% for a row of pixels. This is useful to support simple operations such as
% statistics computation.
%
%  The format of the PixelIterateMonoRead method is:
%
%      MagickPassFail PixelIterateMonoRead(
%                                 PixelIteratorMonoReadCallback call_back,
%                                 const PixelIteratorOptions *options,
%                                 const char *description,
%                                 void *mutable_data,
%                                 const void *immutable_data,
%                                 const long x,
%                                 const long y,
%                                 const unsigned long columns,
%                                 const unsigned long rows,
%                                 const Image *image,
%                                 ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o call_back: A user-provided C callback function which is passed the
%       address of pixels from each image.
%
%    o options: Pixel iterator execution options (may be NULL).
%
%    o description: textual description of operation being performed.
%
%    o mutable_data: User-provided mutable context data.
%
%    o immutable_data: User-provided immutable context data.
%
%    o x: The horizontal ordinate of the top left corner of the region.
%
%    o y: The vertical ordinate of the top left corner of the region.
%
%    o columns: Width of pixel region
%
%    o rows: Height of pixel region
%
%    o image: The address of the Image.
%
%    o exception: If an error is reported, this argument is updated with the reason.
%
*/
MagickExport MagickPassFail
PixelIterateMonoRead(PixelIteratorMonoReadCallback call_back,
                     const PixelIteratorOptions *options,
                     const char *description,
                     void *mutable_data,
                     const void *immutable_data,
                     const long x,
                     const long y,
                     const unsigned long columns,
                     const unsigned long rows,
                     const Image *image,
                     ExceptionInfo *exception)
{
  MagickPassFail
    status = MagickPass;

  register long
    row;

  unsigned long
    row_count=0;

  int
    max_threads=1;

  max_threads=omp_get_max_threads();
  (void) SetRegionThreads(max_threads,options,columns,rows);

#if defined(HAVE_OPENMP)
#  pragma omp parallel for schedule(static,1) shared(row_count, status)
#endif
  for (row=y; row < (long) (y+rows); row++)
    {
      MagickPassFail
        thread_status;

      const PixelPacket
        *pixels;

      const IndexPacket
        *indexes;

      thread_status=status;
      if (thread_status == MagickFail)
        continue;

      pixels=AcquireImagePixels(image,x, row, columns, 1, exception);
      if (!pixels)
        thread_status=MagickFail;
      indexes=AccessImmutableIndexes(image);

      if (thread_status != MagickFail)
        thread_status=(call_back)(mutable_data,immutable_data,image,pixels,indexes,columns,exception);

#if defined(HAVE_OPENMP)
#  pragma omp critical (GM_PixelIterateMonoRead)
#endif
      {
        row_count++;
        if (QuantumTick(row_count,rows))
          if (!MagickMonitorFormatted(row_count,rows,exception,
                                      description,image->filename))
            thread_status=MagickFail;

        if (thread_status == MagickFail)
          status=MagickFail;
      }
    }

  omp_set_num_threads(max_threads);

  return (status);
}
Exemple #5
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   W r i t e P C L I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method WritePCLImage writes an image in the Page Control Language encoded
%  image format.
%
%  The format of the WritePCLImage method is:
%
%      unsigned int WritePCLImage(const ImageInfo *image_info,Image *image)
%
%  A description of each parameter follows.
%
%    o status: Method WritePCLImage return True if the image is written.
%      False is returned is there is a memory shortage or if the image file
%      fails to write.
%
%    o image_info: Specifies a pointer to a ImageInfo structure.
%
%    o image:  A pointer to an Image structure.
%
%
%
*/
static unsigned int WritePCLImage(const ImageInfo *image_info,Image *image)
{
  char
    buffer[MaxTextExtent];

  long
    sans,
    y;

  register const PixelPacket
    *p;

  register const IndexPacket
    *indexes;

  register long
    i,
    x;

  register unsigned char
    *q;

  unsigned char
    *pixels,
    *last_row_pixels,
    *output_row;

  unsigned int
    status;

  long
    zero_rows;

  unsigned long
    bytes_to_write,
    scene,
    density,
    bytes_per_line;

  unsigned char
    bits_per_pixel;

  ImageCharacteristics
    characteristics;

  PCL_CompressionType
    compression,
    last_row_compression;

  /*
    Open output image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
  if (status == False)
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);

  (void) GetGeometry("75x75",&sans,&sans,&density,&density);
  if (image_info->density != (char *) NULL)
    (void) GetGeometry(image_info->density,&sans,&sans,&density,&density);

  scene = 0;
  output_row = (unsigned char *) NULL;
  last_row_pixels = (unsigned char *) NULL;
  do
    {
      /*
        Ensure that image is in an RGB space.
      */
      (void) TransformColorspace(image,RGBColorspace);

      /*
        Analyze image to be written.
      */
      if (!GetImageCharacteristics(image,&characteristics,
                                   (OptimizeType == image_info->type),
                                   &image->exception))
        {
          CloseBlob(image);
          return MagickFail;
        }

      /*
        Initialize the printer
      */
      (void) WriteBlobString(image,"\033E");  /* printer reset */
      (void) WriteBlobString(image,"\033*r3F");  /* set presentation mode */
      /* define columns and rows in image */
      FormatString(buffer,"\033*r%lus%luT",image->columns,image->rows);
      (void) WriteBlobString(image,buffer);
      FormatString(buffer,"\033*t%luR",density);  /* set resolution */
      (void) WriteBlobString(image,buffer);
      (void) WriteBlobString(image,"\033&l0E");  /* top margin 0 */

      /*
        Determine output type and initialize further accordingly
      */
      if (image->storage_class == DirectClass)
        {
          /*
            Full color
          */
          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
      if (characteristics.monochrome)
        {
          /*
            Use default printer monochrome setup - NB white = 0, black = 1
          */
          bits_per_pixel=1;
        }
      else
        {
          /*
            PseudoClass
          */
          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 (implicit) */
          (void) WriteBlobByte(image,8); /* bits per green component (implicit) */
          (void) WriteBlobByte(image,8); /* bits per blue component (implicit) */

          /*
            Write colormap to file.
          */
          for (i=0; i < (long)(image->colors); i++)
            {
              FormatString(buffer,"\033*v%da%db%dc%ldI",
                           ScaleQuantumToChar(image->colormap[i].red),
                           ScaleQuantumToChar(image->colormap[i].green),
                           ScaleQuantumToChar(image->colormap[i].blue),
                           i);
              WriteBlobString(image,buffer);
            }
          /*
            Initialize rest of palette with empty entries
          */
          for ( ; i < (1L << bits_per_pixel); i++)
            {
              FormatString(buffer,"\033*v%luI",i);
              /* set index to current component values */
              (void) WriteBlobString(image,buffer);
            }
        }

      /*
        Start raster image
      */
      if  ((AccessDefinition(image_info,"pcl","fit-to-page") != NULL) ||
	   (AccessDefinition(image_info,"pcl","fit_to_page") != NULL))
        (void) WriteBlobString(image,"\033*r3A");  /* start raster graphics with scaling */
      else
        (void) WriteBlobString(image,"\033*r1A");  /* start raster graphics */
      (void) WriteBlobString(image,"\033*b0Y");  /* set y offset */

      /*
        Assign row buffer
      */
      bytes_per_line=(image->columns*bits_per_pixel+7)/8;
      pixels=MagickAllocateMemory(unsigned char *,bytes_per_line);
      if (pixels == (unsigned char *) NULL)
        ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);

      /*
        Set up for compression if desired
      */
      last_row_compression = PCL_UndefinedCompression;
      if (image_info->compression != NoCompression)
        {
          MagickFreeMemory(last_row_pixels);
          last_row_pixels=MagickAllocateMemory(unsigned char *,bytes_per_line);
          if (last_row_pixels == (unsigned char *) NULL)
            {
              MagickFreeMemory(pixels);
              ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
            }
          MagickFreeMemory(output_row);
          output_row=MagickAllocateMemory(unsigned char *,bytes_per_line);
          if (output_row == (unsigned char *) NULL)
            {
              MagickFreeMemory(pixels);
              MagickFreeMemory(last_row_pixels);
              ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
            }
            memset(last_row_pixels,0,bytes_per_line);
        }

      /*
        Convert MIFF to PCL raster pixels.
      */
      zero_rows=0;
      for (y=0; y < (long) image->rows; y++)
        {
          p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
          if (p == (const PixelPacket *) NULL)
            break;
          q=pixels;

          if (characteristics.monochrome)
            {
              register unsigned char
                bit,
                byte;
              int
                blk_ind;
              /*
                Monochrome row
              */
              blk_ind = ((image->colormap == NULL) || (image->colormap[0].red == 0)) ? 0 : 1;
              indexes=AccessImmutableIndexes(image);
              bit=0;
              byte=0;
              for (x=0; x < (long) image->columns; x++)
                {
                  byte<<=1;
                  if (indexes[x] == blk_ind) byte |= 1;
                  bit++;
                  if (bit == 8)
                    {
                      *q++=byte;
                      bit=0;
                      byte=0;
                    }
                }
              if (bit != 0)
                *q++=byte << (8-bit);
            }
          else
          if (bits_per_pixel == 8)
            {
              /*
                8 bit PseudoClass row
              */
              indexes=AccessImmutableIndexes(image);
              for (x=0; x < (long) image->columns; x++)
                {
                  *q++=indexes[x];
                }
            }
          else
          if ((bits_per_pixel == 24) || (bits_per_pixel == 32))
            {
              /*
                DirectClass/RGB row
              */
              for (x=0; x < (long) image->columns; x++)
                {
                  *q++=ScaleQuantumToChar(p->red);
                  *q++=ScaleQuantumToChar(p->green);
                  *q++=ScaleQuantumToChar(p->blue);
                  p++;
                }
            }

          if (image_info->compression == NoCompression)
            {
              FormatString(buffer,"\033*b%luW",bytes_per_line);  /* send row */
              (void) WriteBlobString(image,buffer);
              (void) WriteBlob(image,bytes_per_line,pixels);
            }
          else
            {
              compression=PCL_ChooseCompression(bytes_per_line,pixels,last_row_pixels);
              if (compression == PCL_ZeroRowCompression)
                {
                  zero_rows++;
                }
              else
                {
                  /*
                    Skip any omitted zero rows now
                  */
                  if (zero_rows > 0)
                    {
                      i = 32767;
                      do
                        {
                          if (zero_rows < i)
                            i=zero_rows;
                          FormatString(buffer,"\033*b%ldY",i); /* Y Offset */
                          (void) WriteBlobString(image,buffer);
                          zero_rows -= i;
                        } while (zero_rows > 0);
                    }

                  switch (compression)
                    {
                      case PCL_DeltaCompression:
                        {
                          if (compression != last_row_compression)
                            {
                              FormatString(buffer,"\033*b3M");  /* delta compression */
                              (void) WriteBlobString(image,buffer);
                              last_row_compression=compression;
                            }
                          bytes_to_write=PCL_DeltaCompress(bytes_per_line,pixels,
                                                           last_row_pixels,output_row);
                          FormatString(buffer,"\033*b%luW",bytes_to_write);
                          (void) WriteBlobString(image,buffer);
                          WriteBlob(image,bytes_to_write,output_row);
                          break;
                        } 
                      case PCL_TiffRLECompression:
                        {
                          if (compression != last_row_compression)
                            {
                              FormatString(buffer,"\033*b2M");  /* Tiff RLE compression */
                              (void) WriteBlobString(image,buffer);
                              last_row_compression=compression;
                            }
                          bytes_to_write=PCL_TiffRLECompress(bytes_per_line,pixels,output_row);
                          FormatString(buffer,"\033*b%luW",bytes_to_write);
                          (void) WriteBlobString(image,buffer);
                          WriteBlob(image,bytes_to_write,output_row);         
                          break;
                        }
                      case PCL_RLECompression:
                        {
                          if (compression != last_row_compression)
                            {
                              FormatString(buffer,"\033*b1M");  /* RLE compression */
                              (void) WriteBlobString(image,buffer);
                              last_row_compression=compression;
                            }
                          bytes_to_write=PCL_RLECompress(bytes_per_line,pixels,output_row);
                          FormatString(buffer,"\033*b%luW",bytes_to_write);
                          (void) WriteBlobString(image,buffer);
                          WriteBlob(image,bytes_to_write,output_row);         
                          break;
                        }
                      case PCL_RepeatedRowCompression:
                        {
                          compression=PCL_DeltaCompression;
                          if (compression != last_row_compression)
                            {
                              FormatString(buffer,"\033*b3M");  /* delta row compression */
                              (void) WriteBlobString(image,buffer);
                              last_row_compression=compression;
                            }
                          FormatString(buffer,"\033*b0W");  /* no data -> replicate row */
                          (void) WriteBlobString(image,buffer);
                          break;
                        } 
                      case PCL_NoCompression:
                        {
                          if (compression != last_row_compression)
                            {
                              FormatString(buffer,"\033*b0M");  /* no compression */
                              (void) WriteBlobString(image,buffer);
                              last_row_compression=compression;
                            }
                          FormatString(buffer,"\033*b%luW",bytes_per_line);  /* send row */
                          (void) WriteBlobString(image,buffer);
                          (void) WriteBlob(image,bytes_per_line,pixels);
                          break;
                        }
                      case PCL_ZeroRowCompression:
                        {
                          break;
                        }
                      case PCL_UndefinedCompression:
                        {
                          break;
                        }
                    }
                }

            /*
              Swap row with last row
            */
            q=last_row_pixels;
            last_row_pixels=pixels;
            pixels=q;
          }

          if (image->previous == (Image *) NULL)
            if (QuantumTick(y,image->rows))
              if (!MagickMonitorFormatted(y,image->rows,&image->exception,
                                          SaveImageText,image->filename,
                                          image->columns,image->rows))
                break;
        }

      (void) WriteBlobString(image,"\033*rB");  /* end graphics */
      MagickFreeMemory(pixels);
      MagickFreeMemory(last_row_pixels);
      MagickFreeMemory(output_row);
      if (image->next == (Image *) NULL)
        break;
      image=SyncNextImageInList(image);
      if ((status &= MagickMonitorFormatted(scene++,
                                            GetImageListLength(image),
                                            &image->exception,
                                            SaveImagesText,
                                            image->filename)) == MagickFail)
        break;
    } while (image_info->adjoin);
Exemple #6
0
static Image *IntegralRotateImage(const Image *image,unsigned int rotations,
                                  ExceptionInfo *exception)
{
  char
    message[MaxTextExtent];

  Image
    *rotate_image;

  RectangleInfo
    page;

  long
    tile_width_max,
    tile_height_max;

  MagickPassFail
    status=MagickPass;

  /*
    Initialize rotated image attributes.
  */
  assert(image != (Image *) NULL);
  page=image->page;
  rotations%=4;

  {
    /*
      Clone appropriately to create rotate image.
    */
    unsigned long
      clone_columns=0,
      clone_rows=0;
    
    switch (rotations)
      {
      case 0:
	clone_columns=0;
	clone_rows=0;
	break;
      case 2:
	clone_columns=image->columns;
	clone_rows=image->rows;
	break;
      case 1:
      case 3:
	clone_columns=image->rows;
	clone_rows=image->columns;
	break;
      }
    rotate_image=CloneImage(image,clone_columns,clone_rows,True,exception);
    if (rotate_image == (Image *) NULL)
      return((Image *) NULL);
    if (rotations != 0)
      if (ModifyCache(rotate_image,exception) != MagickPass)
	{
	  DestroyImage(rotate_image);
	  return (Image *) NULL;
	}
  }

  tile_height_max=tile_width_max=2048/sizeof(PixelPacket); /* 2k x 2k = 4MB */
  if ((rotations == 1) || (rotations == 3))
    {
      /*
	Allow override of tile geometry for testing.
      */
      const char *
	value;

      if (!GetPixelCacheInCore(image) || !GetPixelCacheInCore(rotate_image))
	tile_height_max=tile_width_max=8192/sizeof(PixelPacket); /* 8k x 8k = 64MB */

      if ((value=getenv("MAGICK_ROTATE_TILE_GEOMETRY")))
	{
	  double
	    width,
	    height;
	  
	  if (GetMagickDimension(value,&width,&height,NULL,NULL) == 2)
	    {
	      tile_height_max=(unsigned long) height;
	      tile_width_max=(unsigned long) width;
	    }
	}
    }

  /*
    Integral rotate the image.
  */
  switch (rotations)
    {
    case 0:
      {
        /*
          Rotate 0 degrees (nothing more to do).
        */
	(void) strlcpy(message,"[%s] Rotate: 0 degrees...",sizeof(message));
	if (!MagickMonitorFormatted(image->rows-1,image->rows,exception,
				    message,image->filename))
	  status=MagickFail;
        break;
      }
    case 1:
      {
        /*
          Rotate 90 degrees.
        */
        magick_int64_t
          tile;

        magick_uint64_t
          total_tiles;

        long
          tile_y;

        (void) strlcpy(message,"[%s] Rotate: 90 degrees...",sizeof(message));
        total_tiles=(((image->rows/tile_height_max)+1)*
                     ((image->columns/tile_width_max)+1));        
        tile=0;

#if defined(IntegralRotateImageUseOpenMP)
#  if defined(HAVE_OPENMP)
#    pragma omp parallel for schedule(static,1) shared(status, tile)
#  endif
#endif
        for (tile_y=0; tile_y < (long) image->rows; tile_y+=tile_height_max)
          {
            long
              tile_x;

            MagickPassFail
              thread_status;

            thread_status=status;
            if (thread_status == MagickFail)
              continue;

            for (tile_x=0; tile_x < (long) image->columns; tile_x+=tile_width_max)
              {
                long
                  dest_tile_x,
                  dest_tile_y;

                long
                  tile_width,
                  tile_height;

                const PixelPacket
                  *tile_pixels;

                long
                  y;

                /*
                  Compute image region corresponding to tile.
                */
                if ((unsigned long) tile_x+tile_width_max > image->columns)
                  tile_width=(tile_width_max-(tile_x+tile_width_max-image->columns));
                else
                  tile_width=tile_width_max;
                if ((unsigned long) tile_y+tile_height_max > image->rows)
                  tile_height=(tile_height_max-(tile_y+tile_height_max-image->rows));
                else
                  tile_height=tile_height_max;
                /*
                  Acquire tile
                */
                tile_pixels=AcquireImagePixels(image,tile_x,tile_y,
                                               tile_width,tile_height,exception);
                if (tile_pixels == (const PixelPacket *) NULL)
                  {
                    thread_status=MagickFail;
                    break;
                  }
                /*
                  Compute destination tile coordinates.
                */
                dest_tile_x=rotate_image->columns-(tile_y+tile_height);
                dest_tile_y=tile_x;
                /*
                  Rotate tile
                */
                for (y=0; y < tile_width; y++)
                  {
                    register const PixelPacket
                      *p;
                    
                    register PixelPacket
                      *q;

                    register const IndexPacket
                      *indexes;
        
                    IndexPacket
                      *rotate_indexes;

                    register long
                      x;

                    q=SetImagePixelsEx(rotate_image,dest_tile_x,dest_tile_y+y,
                                       tile_height,1,exception);
                    if (q == (PixelPacket *) NULL)
                      {
                        thread_status=MagickFail;
                        break;
                      }
                    /*
                      DirectClass pixels
                    */
                    p=tile_pixels+(tile_height-1)*tile_width + y;
                    for (x=tile_height; x != 0; x--) 
                      {
                        *q = *p;
                        q++;
                        p-=tile_width;
                      }
                    /*
                      Indexes
                    */
                    indexes=AccessImmutableIndexes(image);
                    if (indexes != (IndexPacket *) NULL)
                      {
                        rotate_indexes=AccessMutableIndexes(rotate_image);
                        if (rotate_indexes != (IndexPacket *) NULL)
                          {
                            register IndexPacket
                              *iq;
                            
                            register const IndexPacket
                              *ip;

                            iq=rotate_indexes;
                            ip=indexes+(tile_height-1)*tile_width + y;
                            for (x=tile_height; x != 0; x--) 
                              {
                                *iq = *ip;
                                iq++;
                                ip -= tile_width;
                              }
                          }
                      }
                    if (!SyncImagePixelsEx(rotate_image,exception))
                      {
                        thread_status=MagickFail;
                        break;
                      }
                  }

#if defined(IntegralRotateImageUseOpenMP)
#  if defined(HAVE_OPENMP)
#    pragma omp critical (GM_IntegralRotateImage)
#  endif
#endif
                {
                  tile++;
                  if (QuantumTick(tile,total_tiles))
                    if (!MagickMonitorFormatted(tile,total_tiles,exception,
                                                message,image->filename))
                      thread_status=MagickFail;
                  
                  if (thread_status == MagickFail)
                    status=MagickFail;
                }
              }
          }
        Swap(page.width,page.height);
        Swap(page.x,page.y);
        page.x=(long) (page.width-rotate_image->columns-page.x);
        break;
      }
    case 2:
      {
        /*
          Rotate 180 degrees.
        */
        long
          y;

        unsigned long
          row_count=0;

        (void) strlcpy(message,"[%s] Rotate: 180 degrees...",sizeof(message));
#if defined(IntegralRotateImageUseOpenMP)
#  if defined(HAVE_OPENMP)
#    pragma omp parallel for schedule(static,8) shared(row_count, status)
#  endif
#endif
        for (y=0; y < (long) image->rows; y++)
          {
            register const PixelPacket
              *p;

            register PixelPacket
              *q;

            register const IndexPacket
              *indexes;
        
            IndexPacket
              *rotate_indexes;

            register long
              x;

            MagickPassFail
              thread_status;

            thread_status=status;
            if (thread_status == MagickFail)
              continue;

            p=AcquireImagePixels(image,0,y,image->columns,1,exception);
            q=SetImagePixelsEx(rotate_image,0,(long) (image->rows-y-1),
                               image->columns,1,exception);
            if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
              thread_status=MagickFail;
            if (thread_status != MagickFail)
              {
                q+=image->columns;
                indexes=AccessImmutableIndexes(image);
                rotate_indexes=AccessMutableIndexes(rotate_image);
                if ((indexes != (IndexPacket *) NULL) &&
                    (rotate_indexes != (IndexPacket *) NULL))
                  for (x=0; x < (long) image->columns; x++)
                    rotate_indexes[image->columns-x-1]=indexes[x];
                for (x=0; x < (long) image->columns; x++)
                  *--q=(*p++);
                if (!SyncImagePixelsEx(rotate_image,exception))
                  thread_status=MagickFail;
              }
#if defined(IntegralRotateImageUseOpenMP)
#  if defined(HAVE_OPENMP)
#    pragma omp critical (GM_IntegralRotateImage)
#  endif
#endif
            {
              row_count++;
              if (QuantumTick(row_count,image->rows))
                if (!MagickMonitorFormatted(row_count,image->rows,exception,
                                            message,image->filename))
                  thread_status=MagickFail;
                  
              if (thread_status == MagickFail)
                status=MagickFail;
            }
          }
        page.x=(long) (page.width-rotate_image->columns-page.x);
        page.y=(long) (page.height-rotate_image->rows-page.y);
        break;
      }
    case 3:
      {
        /*
          Rotate 270 degrees.
        */

        magick_int64_t
          tile;

        magick_uint64_t
          total_tiles;

        long
          tile_y;

        (void) strlcpy(message,"[%s] Rotate: 270 degrees...",sizeof(message));
        total_tiles=(((image->rows/tile_height_max)+1)*
                     ((image->columns/tile_width_max)+1));
        tile=0;
#if defined(IntegralRotateImageUseOpenMP)
#  if defined(HAVE_OPENMP)
#    pragma omp parallel for schedule(static,1) shared(status, tile)
#  endif
#endif
        for (tile_y=0; tile_y < (long) image->rows; tile_y+=tile_height_max)
          {
            long
              tile_x;

            MagickPassFail
              thread_status;

            thread_status=status;
            if (thread_status == MagickFail)
              continue;

            for (tile_x=0; tile_x < (long) image->columns; tile_x+=tile_width_max)
              {
                long
                  tile_width,
                  tile_height;

                long
                  dest_tile_x,
                  dest_tile_y;

                long
                  y;

                const PixelPacket
                  *tile_pixels;
                    
                /*
                  Compute image region corresponding to tile.
                */
                if ((unsigned long) tile_x+tile_width_max > image->columns)
                  tile_width=(tile_width_max-(tile_x+tile_width_max-image->columns));
                else
                  tile_width=tile_width_max;
                if ((unsigned long) tile_y+tile_height_max > image->rows)
                  tile_height=(tile_height_max-(tile_y+tile_height_max-image->rows));
                else
                  tile_height=tile_height_max;
                /*
                  Acquire tile
                */
                tile_pixels=AcquireImagePixels(image,tile_x,tile_y,
                                               tile_width,tile_height,exception);
                if (tile_pixels == (const PixelPacket *) NULL)
                  {
                    thread_status=MagickFail;
                    break;
                  }
                /*
                  Compute destination tile coordinates.
                */
                dest_tile_x=tile_y;
                dest_tile_y=rotate_image->rows-(tile_x+tile_width);
                /*
                  Rotate tile
                */
                for (y=0; y < tile_width; y++)
                  {
                    register const PixelPacket
                      *p;
                    
                    register PixelPacket
                      *q;

                    register const IndexPacket
                      *indexes;

                    register long
                      x;

                    IndexPacket
                      *rotate_indexes;

                    q=SetImagePixelsEx(rotate_image,dest_tile_x,dest_tile_y+y,
                                       tile_height,1,exception);
                    if (q == (PixelPacket *) NULL)
                      {
                        thread_status=MagickFail;
                        break;
                      }
                    /*
                      DirectClass pixels
                    */
                    p=tile_pixels+(tile_width-1-y);
                    for (x=tile_height; x != 0; x--)
                      {
                        *q = *p;
                        q++;
                        p += tile_width;
                      }
                    /*
                      Indexes
                    */
                    indexes=AccessImmutableIndexes(image);
                    if (indexes != (IndexPacket *) NULL)
                      {
                        rotate_indexes=AccessMutableIndexes(rotate_image);
                        if (rotate_indexes != (IndexPacket *) NULL)
                          {
                            register IndexPacket
                              *iq;
                            
                            register const IndexPacket
                              *ip;

                            iq=rotate_indexes;
                            ip=indexes+(tile_width-1-y);
                            for (x=tile_height; x != 0; x--)
                              {
                                *iq = *ip;
                                iq++;
                                ip += tile_width;
                              }
                          }
                      }
                    if (!SyncImagePixelsEx(rotate_image,exception))
                      {
                        thread_status=MagickFail;
                        break;
                      }
                  }

#if defined(IntegralRotateImageUseOpenMP)
#  if defined(HAVE_OPENMP)
#    pragma omp critical (GM_IntegralRotateImage)
#  endif
#endif
                {
                  tile++;
                  if (QuantumTick(tile,total_tiles))
                    if (!MagickMonitorFormatted(tile,total_tiles,exception,
                                                message,image->filename))
                      thread_status=MagickFail;
                }

                if (thread_status == MagickFail)
                  {
                    status=MagickFail;
                    break;
                  }
              }
          }
        Swap(page.width,page.height);
        Swap(page.x,page.y);
        page.y=(long) (page.height-rotate_image->rows-page.y);
        break;
      }
    }

  rotate_image->page=page;
  rotate_image->is_grayscale=image->is_grayscale;
  rotate_image->is_monochrome=image->is_monochrome;
  return(rotate_image);
}