2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % CCCC OOO L OOO RRRR M M AAA PPPP %
7 % C O O L O O R R MM MM A A P P %
8 % C O O L O O RRRR M M M AAAAA PPPP %
9 % C O O L O O R R M M A A P %
10 % CCCC OOO LLLLL OOO R R M M A A P %
13 % MagickCore Colormap Methods %
20 % Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 % We use linked-lists because splay-trees do not currently support duplicate
37 % key / value pairs (.e.g X11 green compliance and SVG green compliance).
44 #include "magick/studio.h"
45 #include "magick/blob.h"
46 #include "magick/cache-view.h"
47 #include "magick/cache.h"
48 #include "magick/color.h"
49 #include "magick/color-private.h"
50 #include "magick/colormap.h"
51 #include "magick/client.h"
52 #include "magick/configure.h"
53 #include "magick/exception.h"
54 #include "magick/exception-private.h"
55 #include "magick/gem.h"
56 #include "magick/geometry.h"
57 #include "magick/image-private.h"
58 #include "magick/memory_.h"
59 #include "magick/monitor.h"
60 #include "magick/monitor-private.h"
61 #include "magick/option.h"
62 #include "magick/pixel-private.h"
63 #include "magick/quantize.h"
64 #include "magick/quantum.h"
65 #include "magick/semaphore.h"
66 #include "magick/string_.h"
67 #include "magick/token.h"
68 #include "magick/utility.h"
69 #include "magick/xml-tree.h"
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 % C y c l e C o l o r m a p I m a g e %
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82 % CycleColormap() displaces an image's colormap by a given number of
83 % positions. If you cycle the colormap a number of times you can produce
84 % a psychodelic effect.
86 % The format of the CycleColormapImage method is:
88 % MagickBooleanType CycleColormapImage(Image *image,const long displace)
90 % A description of each parameter follows:
94 % o displace: displace the colormap this amount.
97 MagickExport MagickBooleanType CycleColormapImage(Image *image,
112 assert(image != (Image *) NULL);
113 assert(image->signature == MagickSignature);
114 if (image->debug != MagickFalse)
115 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
116 if (image->storage_class == DirectClass)
117 (void) SetImageType(image,PaletteType);
119 exception=(&image->exception);
120 image_view=AcquireCacheView(image);
121 #if defined(_OPENMP) && (_OPENMP >= 200203)
122 #pragma omp parallel for schedule(static,1) shared(status)
124 for (y=0; y < (long) image->rows; y++)
138 if (status == MagickFalse)
140 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
141 if (q == (PixelPacket *) NULL)
146 indexes=GetCacheViewAuthenticIndexQueue(image_view);
147 for (x=0; x < (long) image->columns; x++)
149 index=(long) (indexes[x]+displace) % image->colors;
151 index+=image->colors;
152 indexes[x]=(IndexPacket) index;
153 q->red=image->colormap[index].red;
154 q->green=image->colormap[index].green;
155 q->blue=image->colormap[index].blue;
158 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
161 image_view=DestroyCacheView(image_view);
166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 + S o r t C o l o r m a p B y I n t e n s i t y %
174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
176 % SortColormapByIntensity() sorts the colormap of a PseudoClass image by
177 % decreasing color intensity.
179 % The format of the SortColormapByIntensity method is:
181 % MagickBooleanType SortColormapByIntensity(Image *image)
183 % A description of each parameter follows:
185 % o image: A pointer to an Image structure.
189 #if defined(__cplusplus) || defined(c_plusplus)
193 static int IntensityCompare(const void *x,const void *y)
202 color_1=(const PixelPacket *) x;
203 color_2=(const PixelPacket *) y;
204 intensity=(int) PixelIntensityToQuantum(color_2)-
205 (int) PixelIntensityToQuantum(color_1);
209 #if defined(__cplusplus) || defined(c_plusplus)
213 MagickExport MagickBooleanType SortColormapByIntensity(Image *image)
233 assert(image != (Image *) NULL);
234 if (image->debug != MagickFalse)
235 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
236 assert(image->signature == MagickSignature);
237 if (image->storage_class != PseudoClass)
240 Allocate memory for pixel indexes.
242 pixels=(unsigned short *) AcquireQuantumMemory((size_t) image->colors,
244 if (pixels == (unsigned short *) NULL)
245 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
248 Assign index values to colormap entries.
250 #if defined(_OPENMP) && (_OPENMP >= 200203)
251 #pragma omp parallel for schedule(static,1) shared(status)
253 for (i=0; i < (long) image->colors; i++)
254 image->colormap[i].opacity=(IndexPacket) i;
256 Sort image colormap by decreasing color popularity.
258 qsort((void *) image->colormap,(size_t) image->colors,
259 sizeof(*image->colormap),IntensityCompare);
261 Update image colormap indexes to sorted colormap order.
263 #if defined(_OPENMP) && (_OPENMP >= 200203)
264 #pragma omp parallel for schedule(static,1) shared(status)
266 for (i=0; i < (long) image->colors; i++)
267 pixels[(long) image->colormap[i].opacity]=(unsigned short) i;
269 exception=(&image->exception);
270 image_view=AcquireCacheView(image);
271 for (y=0; y < (long) image->rows; y++)
285 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
286 if (q == (PixelPacket *) NULL)
291 indexes=GetCacheViewAuthenticIndexQueue(image_view);
292 for (x=0; x < (long) image->columns; x++)
294 index=(IndexPacket) pixels[(long) indexes[x]];
296 *q++=image->colormap[(long) index];
298 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
300 if (status == MagickFalse)
303 image_view=DestroyCacheView(image_view);
304 pixels=(unsigned short *) RelinquishMagickMemory(pixels);