]> granicus.if.org Git - imagemagick/blobdiff - www/architecture.html
(no commit message)
[imagemagick] / www / architecture.html
index 4ccdeadeb54be4586547e68288f9677048da9672..34e7c9e91288f2cc5c3c1d25f4d5b3a9ecb9563a 100644 (file)
@@ -19,7 +19,7 @@
   <meta name="Author" content="ImageMagick Studio LLC"/>
   <meta name="Revisit-after" content="2 DAYS"/>
   <meta name="Resource-type" content="document"/>
-  <meta name="Copyright" content="Copyright (c) 1999-2010 ImageMagick Studio LLC"/>
+  <meta name="Copyright" content="Copyright (c) 1999-2011 ImageMagick Studio LLC"/>
   <meta name="Distribution" content="Global"/>
   <link rel="icon" href="../images/wand.png"  sizes="32x32"/>
   <link rel="shortcut icon" href="../images/wand.ico"  type="images/x-icon"/>
 
 <div class="sponsbox">
 <div  class="sponsor">
-   <a title="Sponsor: Atlas Multimedia" href="http://www.atlas-multimedia.de/">Atlas Multimedia</a><!-- 20101201000025 tanju.temurbas-->
+   <a title="Sponsor: Fernsehdienst Berlin" href="http://www.atlas-multimedia.de">Fernsehdienst Berlin</a><!-- 2011040100025 atlas.multimedia-->
+</div>
+<div  class="sponsor">
+  <a title="Sponsor: Druckerei" href="http://print24.com/de/">Druckerei</a><!-- 201110010720 -->
 </div>
 <div  class="sponsor">
   <a title="Sponsor: Image Converter" href="http://www.batchphoto.com">Image Converter</a><!-- 201103010900 Bits Coffee-->
 <div  class="sponsor">
   <a title="Sponsor: Diamonds are a Girls Best Friend" href="http://www.schmuck.org">Diamonds are a Girls Best Friend</a><!-- 201101010600 Peterssen-->
 </div>
-<div  class="sponsor">
-   <a title="Sponsor: Druckerei Online" href="http://www.allesdruck.de">Druckerei Online</a><!-- 201012011200 allesdruck.de-->
-</div>
 </div>
 </div>
 </div>\r
 <h2><a name="cache"></a>The Pixel Cache</h2>
 <div class="doc-section">
 
-<p>The ImageMagick pixel cache is a repository for image pixels with up to 5 channels.  The first 4 channels are stored contiguously and an optional second area follows with 1 channel.  The channels are at the depth specified when ImageMagick was built.  The channel depths are 8 bits-per-pixel component for the Q8 version of ImageMagick, 16 bits-per-pixel component for the Q16 version, and 32 bits-per-pixel component for the Q32 version.  By default pixel components are unsigned quantities, however, if you use the <a href="../www/high-dynamic-range.html">high dynamic-range</a> version of ImageMagick, the components are 32-bit floating point. The primary 4 channels can hold any value but typically contain red, green, blue, and alpha intensities or cyan, magenta, yellow, and alpha intensities.  The optional fifth channel contains the colormap indexes for colormapped images or the black channel for CMYK images.  The pixel cache storage may be heap memory, anonymous memory mapped memory, disk-backed memory mapped, or on disk.  The pixel cache is reference-counted.  Only the cache properties are copied when the cache is cloned.  The cache pixels are subsequently copied when you signal your intention to update any of the pixels.</p>
+<p>The ImageMagick pixel cache is a repository for image pixels with up to 5 channels.  The first 4 channels are stored contiguously and an optional second area follows with 1 channel.  The channels are at the depth specified when ImageMagick was built.  The channel depths are 8 bits-per-pixel component for the Q8 version of ImageMagick, 16 bits-per-pixel component for the Q16 version, and 32 bits-per-pixel component for the Q32 version.  By default pixel components are unsigned quantities, however, if you use the <a href="../www/high-dynamic-range.html">high dynamic-range</a> version of ImageMagick, the components are 32-bit floating point. The primary 4 channels can hold any value but typically contain red, green, blue, and alpha intensities or cyan, magenta, yellow, and alpha intensities.  The optional fifth channel contains the colormap indexes for colormapped images or the black channel for CMYK images.  The pixel cache storage may be heap memory, anonymous memory mapped memory, disk-backed memory mapped, or on disk.  The pixel cache is reference-counted.  Only the cache properties are copied when the cache is cloned.  The cache pixels are subsequently copied only when you signal your intention to update any of the pixels.</p>
 
 <h3>Create the Pixel Cache</h3>
 <div class="doc-section">
 
 <p>When the pixel cache is initialized, pixels are scaled from whatever bit depth they originated from to that required by the pixel cache.  For example, a 1-channel 1-bit monochrome PBM image is scaled to a 4 channel 8-bit RGBA image, if you are using the Q8 version of ImageMagick, and 16-bit RGBA for the Q16 version.  You can determine which version you have with the <a href="../www/command-line-options.html#version">&#x2011;version</a> option: </p>
 
-<p class='crt'><span class="crtprompt"> $magick&gt; </span><span class='crtin'>identify -version</span><span class='crtout'>Version: ImageMagick 6.6.4-1 2010-19-14 Q16 http://www.imagemagick.org</span></p>
+<p class='crt'><span class="crtprompt"> $magick&gt; </span><span class='crtin'>identify -version</span><span class='crtout'>Version: ImageMagick 6.6.6-3 2010-22-21 Q16 http://www.imagemagick.org</span></p>
 <p>As you can see, the convenience of the pixel cache sometimes comes with a trade-off in storage (e.g. storing a 1-bit monochrome image as 16-bit RGBA is wasteful) and speed (i.e. storing the entire image in memory is generally slower than accessing one scanline of pixels at a time).  In most cases, the benefits of the pixel cache typically outweigh any disadvantages.</p>
 </div>
 
 
 <p>Once the pixel cache is associated with an image, you typically want to get, update, or put pixels into it.  We refer to pixels inside the image region as <em>authentic pixels</em> and outside the region as <em>virtual pixels</em>.  Use these methods to access the pixels in the cache:</p>
 <ul>
-  <li><a href="../www/api/cache.html#GetVirtualPixels">GetVirtualPixels()</a> gets pixels that you do not intend to modify</li>
+  <li><a href="../www/api/cache.html#GetVirtualPixels">GetVirtualPixels()</a> gets pixels that you do not intend to modify or pixels that lie outside the image region (e.g. pixel @ -1,-3)</li>
   <li><a href="../www/api/cache.html#GetAuthenticPixels">GetAuthenticPixels()</a> gets pixels that you intend to modify</li>
   <li><a href="../www/api/cache.html#QueueAuthenticPixels">QueueAuthenticPixels()</a> queue pixels that you intend to modify</li>
   <li><a href="../www/api/cache.html#SyncAuthenticPixels">SyncAuthenticPixels()</a> update the pixel cache with any modified pixels</li>
 
 <div class="viewport">
 <pre class="code">
-  long
-    x,
-    y;
-
   const PixelPacket
     *p;
 
   PixelPacket
     *q;
 
+  ssize_t
+    x,
+    y;
+
   destination=CloneImage(source,source->columns,source->rows,MagickTrue,exception);
   if (destination  == (Image *) NULL)
     { /* an exception was thrown */ }
-  for (y=0; y &lt; (long) source-&gt;rows; y++)
+  for (y=0; y &lt; (ssize_t) source-&gt;rows; y++)
   {
     p=GetVirtualPixels(source,0,y,source-&gt;columns,1,exception);
     q=GetAuthenticPixels(destination,0,y,destination-&gt;columns,1,exception);
     if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)
       break;
-    for (x=0; x &lt; (long) source-&gt;columns; x++)
+    for (x=0; x &lt; (ssize_t) source-&gt;columns; x++)
     {
       q-&gt;red=90*p-&gt;red/100;
       q-&gt;green=90*p-&gt;green/100;
     if (SyncAuthenticPixels(destination,exception) == MagickFalse)
       break;
   }
-  if (y &lt; (long) source-&gt;rows)
+  if (y &lt; (ssize_t) source-&gt;rows)
     { /* an exception was thrown */ }
 </pre>
 </div>
 
-<p>When we first create the destination image by cloning the source image, the pixel cache pixels are not copied.  They are only copied when you signal your intentions to modify the pixel cache by calling <a href="../www/api/cache.html#GetAuthenticPixels">GetAuthenticPixels()</a> or <a href="../www/api/cache.html#QueueAuthenticPixels">QueueAuthenticPixels()</a>. Use <a href="../www/api/cache.html#QueueAuthenticPixels">QueueAuthenticPixels()</a> if you want to set new pixel values rather than update existing ones.  Finally, use <a href="../www/api/cache.html#SyncAuthenticPixels">SyncAuthenticPixels()</a> to ensure any updated pixels are pushed to the pixel cache.</p>
+<p>When we first create the destination image by cloning the source image, the pixel cache pixels are not copied.  They are only copied when you signal your intentions to modify the pixel cache by calling <a href="../www/api/cache.html#GetAuthenticPixels">GetAuthenticPixels()</a> or <a href="../www/api/cache.html#QueueAuthenticPixels">QueueAuthenticPixels()</a>. Use <a href="../www/api/cache.html#QueueAuthenticPixels">QueueAuthenticPixels()</a> if you want to set new pixel values rather than update existing ones.  You could use GetAuthenticPixels() to set pixel values but it is slightly more efficient to use QueueAuthenticPixels() instead. Finally, use <a href="../www/api/cache.html#SyncAuthenticPixels">SyncAuthenticPixels()</a> to ensure any updated pixels are pushed to the pixel cache.</p>
 
 <p>Recall how we mentioned that the indexes of a colormapped image or the black channel of a CMYK image are stored separately.  Use  <a href="../www/api/cache.html#GetVirtualIndexes">GetVirtualIndexes()</a> (to read the indexes) or <a href="../www/api/cache.html#GetAuthenticIndexes">GetAuthenticIndexes()</a> (to update the indexes) to gain access to this channel.  For example, to print the colormap indexes, use:</p>
 
   const IndexPacket
     *indexes;
 
-  for (y=0; y &lt; (long) source-&gt;rows; y++)
+  for (y=0; y &lt; (ssize_t) source-&gt;rows; y++)
   {
     p=GetVirtualPixels(source,0,y,source-&gt;columns,1);
     if (p == (const PixelPacket *) NULL)
       break;
     indexes=GetVirtualIndexes(source);
-    for (x=0; x &lt; (long) source-&gt;columns; x++)
+    for (x=0; x &lt; (ssize_t) source-&gt;columns; x++)
       (void) printf("%d\n",indexes[x];
   }
-  if (y &lt; (long) source-&gt;rows)
+  if (y &lt; (ssize_t) source-&gt;rows)
     /* an exception was thrown */
 </pre>
 
 <p>The pixel cache manager decides whether to give you direct or indirect access to the image pixels.  In some cases the pixels are staged to an intermediate buffer-- and that is why you must call SyncAuthenticPixels() to ensure this buffer is <em>pushed</em> out to the pixel cache to guarantee the corresponding pixels in the cache are updated.  For this reason we recommend that you only read or update a scanline or a few scanlines of pixels at a time.  However, you can get any rectangular region of pixels you want.  GetAuthenticPixels() requires that the region you request is within the bounds of the image area.  For a 640 by 480 image, you can get a scanline of 640 pixels at row 479 but if you ask for a scanline at row 480, an exception is returned (rows are numbered starting at 0).  GetVirtualPixels() does not have this constraint.  For example,</p>
 
 <pre class="code">
-  p=GetVirtualPixels(source,-3,3,source-&gt;columns+7,7,exception);
+  p=GetVirtualPixels(source,-3,-3,source-&gt;columns+3,6,exception);
 </pre>
 
 <p>gives you the pixels you asked for without complaint, even though some are not within the confines of the image region.</p>
   black:                the area surrounding the image is black
   checker-tile:         alternate squares with image and background color
   dither:               non-random 32x32 dithered pattern
-  edge:                 extend the edge pixel toward infinity
+  edge:                 extend the edge pixel toward infinity (default)
   gray:                 the area surrounding the image is gray
   horizontal-tile:      horizontally tile the image, background color above/below
   horizontal-tile-edge: horizontally tile the image and replicate the side edge pixels
   mirror:               mirror tile the image
   random:               choose a random pixel from the image
-  tile:                 tile the image (default)
+  tile:                 tile the image
   transparent:          the area surrounding the image is transparent blackness
   vertical-tile:        vertically tile the image, sides are background color
   vertical-tile-edge:   vertically tile the image and replicate the side edge pixels
 
 <p class='crt'><span class="crtprompt"> $magick&gt; </span><span class='crtin'>identify -list resource</span><span class='crtout'><pre>File         Area       Memory          Map         Disk    Thread         Time
 -------------------------------------------------------------------------------
- 768     12.443GB    8.6917GiB    23.178GiB  18.446744EB         8    unlimited</pre></span></p>
+ 768     1.0386GB    3.8692GiB    7.7384GiB    unlimited         4    unlimited
+</pre
+></span></p>
 <p>You can set these limits either as a <a href="../www/resources.html#configure">policy</a> (see <kbd>policy.xml</kbd>), with an <a href="../www/resources.html#environment">environment variable</a>, with the <a href="../www/command-line-options.html#limit">-limit</a> command line option, or with the <a href="../www/api/resource.html#SetMagickResourceLimit">SetMagickResourceLimit()</a> MagickCore API method. As an example, our online web interface to ImageMagick, <a href="http://www.imagemagick.org/MagickStudio/scripts/MagickStudio.cgi">ImageMagick Studio</a>, has an area limit of 64 megabytes, a memory limit of 128 mebibytes and a map limit of 256 mebibytes and a disk limit of 1 gigabytes.  Since we process multiple simultaneous sessions, we don't want any one session consuming all the available memory.  Instead large images are cached to disk.  If the image is too large and exceeds the pixel cache disk limit, the program exits.  In addition, we place a 60 second time limit to prevent any run-away processing tasks.</p>
 
 <p>Note, the cache limits are global, meaning if you create several images, the combined resource requirements are compared to the limit to determine the pixel cache storage disposition.</p>
 
   view_1=OpenCacheView(source);
   view_2=OpenCacheView(source);
-  for (y=0; y &lt; (long) source-&gt;rows; y++)
+  for (y=0; y &lt; (ssize_t) source-&gt;rows; y++)
   {
     u=GetCacheViewVirtualPixels(view_1,0,y,source-&gt;columns,1,exception);
     v=GetCacheViewVirtualPixels(view_2,0,source-&gt;rows-y-1,source-&gt;columns,1,exception);
     if ((u == (const PixelPacket *) NULL) || (v == (const PixelPacket *) NULL))
       break;
-    for (x=0; x &lt; (long) source-&gt;columns; x++)
+    for (x=0; x &lt; (ssize_t) source-&gt;columns; x++)
     {
       /* do something with u &amp; v here */
     }
   }
   view_1=CloseCacheView(view_1);
   view_2=CloseCacheView(view_2);
-  if (y &lt; (long) source-&gt;rows)
+  if (y &lt; (ssize_t) source-&gt;rows)
     { /* an exception was thrown */ }
 </pre>
 </div>
 <div class="doc-section">
 
 <p>Recall that each image format is decoded by ImageMagick and the pixels are deposited in the pixel cache.  If you write an image, the pixels are read from the pixel cache and encoded as required by the format you are writing (e.g. GIF, PNG, etc.).  The Magick Persistent Cache (MPC) format is designed to eliminate the overhead of decoding and encoding pixels to and from an image format.  MPC writes two files.  One, with the extension <kbd>.mpc</kbd>, retains all the properties associated with the image or image sequence (e.g. width, height, colorspace, etc.) and the second, with the extension <kbd>.cache</kbd>, is the pixel cache in the native raw format.  When reading an MPC image file, ImageMagick reads the image properties and memory maps the pixel cache on disk eliminating the need for decoding the image pixels.  The tradeoff is in disk space.  MPC is generally larger in file size than most other image formats.</p>
+<p>The most efficient use of MPC image files is a write-once, read-many-times pattern.  For example, your workflow requires extracting random blocks of pixels from the source image.  Rather than re-reading and possibly decompressing the source image each time, we use MPC and map the image directly to memory.</p>
 </div>
 
 <h3>Best Practices</h3>
@@ -505,7 +508,7 @@ image=ReadStream(image_info,&amp;StreamHandler,exception);
     (void) printf("Image comment: %s\n",comment);
 </pre>
 
-<p>ImageMagick supports artifacts with the GetImageArtifact() and SetImageArtifact() methods.  Artifacts are stealth properties that are not exported to image formats (e.g. PNG) and they do not display when identifying an image.</p>
+<p>ImageMagick supports artifacts with the GetImageArtifact() and SetImageArtifact() methods.  Artifacts are stealth properties that are not exported to image formats (e.g. PNG).</p>
 
 <p>Image profiles are handled with <a href="../www/api/profile.html#GetImageProfile">GetImageProfile()</a>, <a href="../www/api/profile.html#SetImageProfile">SetImageProfile()</a>, and <a href="../www/api/profile.html#ProfileImage">ProfileImage()</a> methods.  Here we set a profile and fetch it right back:</p>
 
@@ -545,7 +548,7 @@ image=ReadStream(image_info,&amp;StreamHandler,exception);
 <h2><a name="threads"></a>Threads of Execution</h2>
 <div class="doc-section">
 
-<p>Many of ImageMagick's internal algorithms are threaded to take advantage of speed-ups offered by the multicore processor chips. However, you are welcome to use ImageMagick algorithms in your threads of execution with the exception of the MagickCore's GetVirtualPixels(), GetAuthenticPixels(), QueueAuthenticPixels(), or SyncAuthenticPixels() pixel cache methods.  These methods are intended for one thread of execution only. To access the pixel cache with more than one thread of execution, use a cache view.  We do this for the <a href="../www/api/composite.html#CompositeImage">CompositeImage()</a> method, for example.  Suppose we want to composite a single image over a different image in each thread of execution.  If we use GetVirtualPixels(), the results are unpredictable because multiple threads would likely be asking for different areas of the pixel cache simultaneously.  Instead we use GetCacheViewVirtualPixels() which creates a unique view for each thread of execution ensuring our program behaves properly regardless of how many threads are invoked.  The other program interfaces, such as the <a href="../www/magick-wand.html">MagickWand API</a>, are completely thread safe so there are no special precautions for threads of execution.</p>
+<p>Many of ImageMagick's internal algorithms are threaded to take advantage of speed-ups offered by the multicore processor chips. However, you are welcome to use ImageMagick algorithms in your threads of execution with the exception of the MagickCore's GetVirtualPixels(), GetAuthenticPixels(), QueueAuthenticPixels(), or SyncAuthenticPixels() pixel cache methods.  These methods are intended for one thread of execution only with the exception of an OpenMP parallel section.  To access the pixel cache with more than one thread of execution, use a cache view.  We do this for the <a href="../www/api/composite.html#CompositeImage">CompositeImage()</a> method, for example.  Suppose we want to composite a single image over a different image in each thread of execution.  If we use GetVirtualPixels(), the results are unpredictable because multiple threads would likely be asking for different areas of the pixel cache simultaneously.  Instead we use GetCacheViewVirtualPixels() which creates a unique view for each thread of execution ensuring our program behaves properly regardless of how many threads are invoked.  The other program interfaces, such as the <a href="../www/magick-wand.html">MagickWand API</a>, are completely thread safe so there are no special precautions for threads of execution.</p>
 
 <p>Here is an example of how ImageMagick can take advantage of threads of execution with the <a href="http://en.wikipedia.org/wiki/OpenMP">OpenMP</a> programming paradigm:</p>
 
@@ -555,26 +558,26 @@ image=ReadStream(image_info,&amp;StreamHandler,exception);
   CacheView
     *image_view;
 
-  long
-    y;
-
   MagickBooleanType
     status;
 
+  ssize_t
+    y;
+
   status=MagickTrue;
   image_view=AcquireCacheView(image);
   #pragma omp parallel for schedule(dynamic,4) shared(status)
-  for (y=0; y &lt; (long) image-&gt;rows; y++)
+  for (y=0; y &lt; (ssize_t) image-&gt;rows; y++)
   {
     register IndexPacket
       *indexes;
 
-    register long
-      x;
-
     register PixelPacket
       *q;
 
+    register ssize_t
+      x;
+
     if (status == MagickFalse)
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image-&gt;columns,1,exception);
@@ -584,7 +587,7 @@ image=ReadStream(image_info,&amp;StreamHandler,exception);
         continue;
       }
     indexes=GetCacheViewAuthenticIndexQueue(image_view);
-    for (x=0; x &lt; (long) image-&gt;columns; x++)
+    for (x=0; x &lt; (ssize_t) image-&gt;columns; x++)
     {
       q-&gt;red= ...
       q-&gt;green= ...
@@ -607,9 +610,22 @@ image=ReadStream(image_info,&amp;StreamHandler,exception);
 
 <p>If you call the ImageMagick API from your OpenMP-enabled application and you intend to dynamically increase the number of threads available in subsequent parallel regions, be sure to perform the increase <em>before</em> you call the API otherwise ImageMagick may fault.</p>
 
-<p><a href="../www/api/wand-view.html">MagickWand</a> support wand views.  A view iterates over the entire, or portion, of the image in parallel and for each row of pixels, it invokes a callback method you provide.  This limits most of your parallel programming activity to just that one module.  There are similar methods in <a href="../www/api/image-view.html">MagickCore</a>.  For an example, see the same sigmoidal contrast algorithm implemented in both <a href="../www/magick-wand.html#wand-view">MagickWand</a> and <a href="../www/magick-core.html#image-view">MagickCore</a>.</p>
+<p><a href="../www/api/wand-view.html">MagickWand</a> supports wand views.  A view iterates over the entire, or portion, of the image in parallel and for each row of pixels, it invokes a callback method you provide.  This limits most of your parallel programming activity to just that one module.  There are similar methods in <a href="../www/api/image-view.html">MagickCore</a>.  For an example, see the same sigmoidal contrast algorithm implemented in both <a href="../www/magick-wand.html#wand-view">MagickWand</a> and <a href="../www/magick-core.html#image-view">MagickCore</a>.</p>
+
+<p>In most circumstances, the default number of threads is set to the number of processor cores on your system for optimal performance.  However, if your system is hyperthreaded or if you are running on a virtual host and only a subset of the processors are available to your server instance, you might get an increase in performance by setting the thread <a href="../www/resources.html#configure">policy</a> or the <a href="../www/resources.html#environment">MAGICK_THREAD_LIMIT</a> environment variable.  For example, your virtual host has 8 processors but only 2 are assigned to your server instance.  The default of 8 threads can cause severe performance problems.  One solution is to limit the number of threads to the available processors in your <kbd>policy.xml</kbd> configuration file:</p>
+
+<pre class="text">
+  &lt;policy domain="resource" name="thread" value="2"/>
+</pre>
+
+<p>Or suppose your 12 core hyperthreaded computer defaults to 24 threads.  Set the MAGICK_THREAD_LIMIT environment variable and you will likely get improved performance:</p>
+
+<pre class="text">
+  export MAGICK_THREAD_LIMIT=12
+</pre>
 
 <p>The OpenMP committee has not defined the behavior of mixing OpenMP with other threading models such as Posix threads.  However, using modern releases of Linux, OpenMP and Posix threads appear to interoperate without complaint.  If you want to use Posix threads from a program module that calls one of the ImageMagick application programming interfaces (e.g. MagickCore, MagickWand, Magick++, etc.) from Mac OS X or an older Linux release, you may need to disable OpenMP support within ImageMagick.  Add the <kbd>--disable-openmp</kbd> option to the configure script command line and rebuild and reinstall ImageMagick.</p>
+
 </div>
 
 <h2><a name="distributed"></a>Heterogeneous Distributed Processing</h2>
@@ -797,23 +813,21 @@ static Image *ReadMGKImage(const ImageInfo *image_info,
   Image
     *image;
 
-  long
-    y;
-
   MagickBooleanType
     status;
 
-  register long
-    x;
-
   register PixelPacket
     *q;
 
+  register size_t
+    x;
+
   register unsigned char
     *p;
 
   ssize_t
-    count;
+    count,
+    y;
 
   unsigned char
     *pixels;
@@ -870,7 +884,7 @@ static Image *ReadMGKImage(const ImageInfo *image_info,
     pixels=(unsigned char *) AcquireQuantumMemory((size_t) image-&gt;columns,3UL*sizeof(*pixels));
     if (pixels == (unsigned char *) NULL)
       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
-    for (y=0; y &lt; (long) image-&gt;rows; y++)
+    for (y=0; y &lt; (ssize_t) image-&gt;rows; y++)
     {
       count=(ssize_t) ReadBlob(image,(size_t) (3*image-&gt;columns),pixels);
       if (count != (ssize_t) (3*image-&gt;columns))
@@ -879,7 +893,7 @@ static Image *ReadMGKImage(const ImageInfo *image_info,
       q=QueueAuthenticPixels(image,0,y,image-&gt;columns,1,exception);
       if (q == (PixelPacket *) NULL)
         break;
-      for (x=0; x &lt; (long) image-&gt;columns; x++)
+      for (x=0; x &lt; (ssize_t) image-&gt;columns; x++)
       {
         q-&gt;red=ScaleCharToQuantum(*p++);
         q-&gt;green=ScaleCharToQuantum(*p++);
@@ -1020,9 +1034,6 @@ static MagickBooleanType WriteMGKImage(const ImageInfo *image_info,Image *image)
   char
     buffer[MaxTextExtent];
 
-  long
-    y;
-
   MagickBooleanType
     status;
 
@@ -1032,12 +1043,15 @@ static MagickBooleanType WriteMGKImage(const ImageInfo *image_info,Image *image)
   register const PixelPacket
     *p;
 
-  register long
+  register ssize_t
     x;
 
   register unsigned char
     *q;
 
+  ssize_t
+    y;
+
   unsigned char
     *pixels;
 
@@ -1072,13 +1086,13 @@ static MagickBooleanType WriteMGKImage(const ImageInfo *image_info,Image *image)
     (void) FormatMagickString(buffer,MaxTextExtent,"%lu %lu\n",
       image-&gt;columns,image-&gt;rows);
     (void) WriteBlobString(image,buffer);
-    for (y=0; y &lt; (long) image-&gt;rows; y++)
+    for (y=0; y &lt; (ssize_t) image-&gt;rows; y++)
     {
       p=GetVirtualPixels(image,0,y,image-&gt;columns,1,&amp;image-&gt;exception);
       if (p == (const PixelPacket *) NULL)
         break;
       q=pixels;
-      for (x=0; x &lt; (long) image-&gt;columns; x++)
+      for (x=0; x &lt; (ssize_t) image-&gt;columns; x++)
       {
         *q++=ScaleQuantumToChar(p-&gt;red);
         *q++=ScaleQuantumToChar(p-&gt;green);
@@ -1205,12 +1219,12 @@ ModuleExport unsigned long analyzeImage(Image **images,const int argc,
     CacheView
       *image_view;
 
-    long
-      y;
-
     MagickBooleanType
       status;
 
+    ssize_t
+      y;
+
     brightness_sum_x=0.0;
     brightness_sum_x2=0.0;
     brightness_sum_x3=0.0;
@@ -1233,12 +1247,12 @@ ModuleExport unsigned long analyzeImage(Image **images,const int argc,
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
     #pragma omp parallel for schedule(dynamic,4) shared(status)
 #endif
-    for (y=0; y &lt; (long) image-&gt;rows; y++)
+    for (y=0; y &lt; (ssize_t) image-&gt;rows; y++)
     {
       register const PixelPacket
         *p;
 
-      register long
+      register ssize_t
         x;
 
       if (status == MagickFalse)
@@ -1249,7 +1263,7 @@ ModuleExport unsigned long analyzeImage(Image **images,const int argc,
           status=MagickFalse;
           continue;
         }
-      for (x=0; x &lt; (long) image-&gt;columns; x++)
+      for (x=0; x &lt; (ssize_t) image-&gt;columns; x++)
       {
         ConvertRGBToHSB(p-&gt;red,p-&gt;green,p-&gt;blue,&amp;hue,&amp;saturation,&amp;brightness);
         brightness*=QuantumRange;
@@ -1354,7 +1368,7 @@ ModuleExport unsigned long analyzeImage(Image **images,const int argc,
     <span id="linkbar-east">&nbsp;</span>\r
   </div>\r
   <div class="footer">\r
-    <span id="footer-west">&copy; 1999-2010 ImageMagick Studio LLC</span>\r
+    <span id="footer-west">&copy; 1999-2011 ImageMagick Studio LLC</span>\r
     <span id="footer-east"> <a href="http://www.imagemagick.org/script/contact.php">Contact the Wizards</a></span>\r
   </div>\r
   <div style="clear: both; margin: 0; width: 100%; "></div>\r