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-2010 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 % A c q u i r e I m a g e C o l o r m a p %
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82 % AcquireImageColormap() allocates an image colormap and initializes
83 % it to a linear gray colorspace. If the image already has a colormap,
84 % it is replaced. AcquireImageColormap() returns MagickTrue if successful,
85 % otherwise MagickFalse if there is not enough memory.
87 % The format of the AcquireImageColormap method is:
89 % MagickBooleanType AcquireImageColormap(Image *image,
90 % const unsigned long colors)
92 % A description of each parameter follows:
96 % o colors: the number of colors in the image colormap.
100 static inline unsigned long MagickMax(const unsigned long x,
101 const unsigned long y)
108 static inline unsigned long MagickMin(const unsigned long x,
109 const unsigned long y)
116 MagickExport MagickBooleanType AcquireImageColormap(Image *image,
117 const unsigned long colors)
126 Allocate image colormap.
128 assert(image != (Image *) NULL);
129 assert(image->signature == MagickSignature);
130 if (image->debug != MagickFalse)
131 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
132 image->colors=colors;
133 length=(size_t) colors;
134 if (image->colormap == (PixelPacket *) NULL)
135 image->colormap=(PixelPacket *) AcquireQuantumMemory(length,
136 sizeof(*image->colormap));
138 image->colormap=(PixelPacket *) ResizeQuantumMemory(image->colormap,length,
139 sizeof(*image->colormap));
140 if (image->colormap == (PixelPacket *) NULL)
141 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
143 for (i=0; i < (long) image->colors; i++)
148 pixel=(unsigned long) (i*(QuantumRange/MagickMax(colors-1,1)));
149 image->colormap[i].red=(Quantum) pixel;
150 image->colormap[i].green=(Quantum) pixel;
151 image->colormap[i].blue=(Quantum) pixel;
152 image->colormap[i].opacity=OpaqueOpacity;
154 return(SetImageStorageClass(image,PseudoClass));
158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
162 % C y c l e C o l o r m a p I m a g e %
166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 % CycleColormap() displaces an image's colormap by a given number of
169 % positions. If you cycle the colormap a number of times you can produce
170 % a psychodelic effect.
172 % The format of the CycleColormapImage method is:
174 % MagickBooleanType CycleColormapImage(Image *image,const long displace)
176 % A description of each parameter follows:
178 % o image: the image.
180 % o displace: displace the colormap this amount.
183 MagickExport MagickBooleanType CycleColormapImage(Image *image,
198 assert(image != (Image *) NULL);
199 assert(image->signature == MagickSignature);
200 if (image->debug != MagickFalse)
201 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
202 if (image->storage_class == DirectClass)
203 (void) SetImageType(image,PaletteType);
205 exception=(&image->exception);
206 image_view=AcquireCacheView(image);
207 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(MAGICKCORE_FUTURE)
208 #pragma omp parallel for schedule(dynamic,4) shared(status)
210 for (y=0; y < (long) image->rows; y++)
224 if (status == MagickFalse)
226 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
227 if (q == (PixelPacket *) NULL)
232 indexes=GetCacheViewAuthenticIndexQueue(image_view);
233 for (x=0; x < (long) image->columns; x++)
235 index=(long) (indexes[x]+displace) % image->colors;
237 index+=image->colors;
238 indexes[x]=(IndexPacket) index;
239 q->red=image->colormap[index].red;
240 q->green=image->colormap[index].green;
241 q->blue=image->colormap[index].blue;
244 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
247 image_view=DestroyCacheView(image_view);
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 + S o r t C o l o r m a p B y I n t e n s i t y %
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262 % SortColormapByIntensity() sorts the colormap of a PseudoClass image by
263 % decreasing color intensity.
265 % The format of the SortColormapByIntensity method is:
267 % MagickBooleanType SortColormapByIntensity(Image *image)
269 % A description of each parameter follows:
271 % o image: A pointer to an Image structure.
275 #if defined(__cplusplus) || defined(c_plusplus)
279 static int IntensityCompare(const void *x,const void *y)
288 color_1=(const PixelPacket *) x;
289 color_2=(const PixelPacket *) y;
290 intensity=(int) PixelIntensityToQuantum(color_2)-
291 (int) PixelIntensityToQuantum(color_1);
295 #if defined(__cplusplus) || defined(c_plusplus)
299 MagickExport MagickBooleanType SortColormapByIntensity(Image *image)
319 assert(image != (Image *) NULL);
320 if (image->debug != MagickFalse)
321 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
322 assert(image->signature == MagickSignature);
323 if (image->storage_class != PseudoClass)
326 Allocate memory for pixel indexes.
328 pixels=(unsigned short *) AcquireQuantumMemory((size_t) image->colors,
330 if (pixels == (unsigned short *) NULL)
331 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
334 Assign index values to colormap entries.
336 #if defined(MAGICKCORE_OPENMP_SUPPORT)
337 #pragma omp parallel for schedule(dynamic,4) shared(status)
339 for (i=0; i < (long) image->colors; i++)
340 image->colormap[i].opacity=(IndexPacket) i;
342 Sort image colormap by decreasing color popularity.
344 qsort((void *) image->colormap,(size_t) image->colors,
345 sizeof(*image->colormap),IntensityCompare);
347 Update image colormap indexes to sorted colormap order.
349 #if defined(MAGICKCORE_OPENMP_SUPPORT)
350 #pragma omp parallel for schedule(dynamic,4) shared(status)
352 for (i=0; i < (long) image->colors; i++)
353 pixels[(long) image->colormap[i].opacity]=(unsigned short) i;
355 exception=(&image->exception);
356 image_view=AcquireCacheView(image);
357 for (y=0; y < (long) image->rows; y++)
371 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
372 if (q == (PixelPacket *) NULL)
377 indexes=GetCacheViewAuthenticIndexQueue(image_view);
378 for (x=0; x < (long) image->columns; x++)
380 index=(IndexPacket) pixels[(long) indexes[x]];
382 *q++=image->colormap[(long) index];
384 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
386 if (status == MagickFalse)
389 image_view=DestroyCacheView(image_view);
390 pixels=(unsigned short *) RelinquishMagickMemory(pixels);