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-2012 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 "MagickCore/studio.h"
45 #include "MagickCore/blob.h"
46 #include "MagickCore/cache-view.h"
47 #include "MagickCore/cache.h"
48 #include "MagickCore/color.h"
49 #include "MagickCore/color-private.h"
50 #include "MagickCore/colormap.h"
51 #include "MagickCore/client.h"
52 #include "MagickCore/configure.h"
53 #include "MagickCore/exception.h"
54 #include "MagickCore/exception-private.h"
55 #include "MagickCore/gem.h"
56 #include "MagickCore/geometry.h"
57 #include "MagickCore/image-private.h"
58 #include "MagickCore/memory_.h"
59 #include "MagickCore/monitor.h"
60 #include "MagickCore/monitor-private.h"
61 #include "MagickCore/option.h"
62 #include "MagickCore/pixel-accessor.h"
63 #include "MagickCore/quantize.h"
64 #include "MagickCore/quantum.h"
65 #include "MagickCore/semaphore.h"
66 #include "MagickCore/string_.h"
67 #include "MagickCore/token.h"
68 #include "MagickCore/utility.h"
69 #include "MagickCore/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 size_t colors,ExceptionInfo *exception)
92 % A description of each parameter follows:
96 % o colors: the number of colors in the image colormap.
98 % o exception: return any errors or warnings in this structure.
102 static inline size_t MagickMax(const size_t x,
110 MagickExport MagickBooleanType AcquireImageColormap(Image *image,
111 const size_t colors,ExceptionInfo *exception)
120 Allocate image colormap.
122 assert(image != (Image *) NULL);
123 assert(image->signature == MagickSignature);
124 if (image->debug != MagickFalse)
125 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
126 image->colors=colors;
127 length=(size_t) colors;
128 if (image->colormap == (PixelInfo *) NULL)
129 image->colormap=(PixelInfo *) AcquireQuantumMemory(length,
130 sizeof(*image->colormap));
132 image->colormap=(PixelInfo *) ResizeQuantumMemory(image->colormap,length,
133 sizeof(*image->colormap));
134 if (image->colormap == (PixelInfo *) NULL)
135 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
137 for (i=0; i < (ssize_t) image->colors; i++)
142 pixel=(double) (i*(QuantumRange/MagickMax(colors-1,1)));
143 GetPixelInfo(image,image->colormap+i);
144 image->colormap[i].matte=MagickTrue;
145 image->colormap[i].red=pixel;
146 image->colormap[i].green=pixel;
147 image->colormap[i].blue=pixel;
148 image->colormap[i].alpha=OpaqueAlpha;
150 return(SetImageStorageClass(image,PseudoClass,exception));
154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 % C y c l e C o l o r m a p I m a g e %
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 % CycleColormap() displaces an image's colormap by a given number of
165 % positions. If you cycle the colormap a number of times you can produce
166 % a psychodelic effect.
168 % WARNING: this assumes an images colormap is in a well know and defined
169 % order. Currently Imagemagick has no way of setting that order.
171 % The format of the CycleColormapImage method is:
173 % MagickBooleanType CycleColormapImage(Image *image,const ssize_t displace,
174 % ExceptionInfo *exception)
176 % A description of each parameter follows:
178 % o image: the image.
180 % o displace: displace the colormap this amount.
182 % o exception: return any errors or warnings in this structure.
185 MagickExport MagickBooleanType CycleColormapImage(Image *image,
186 const ssize_t displace,ExceptionInfo *exception)
197 assert(image != (Image *) NULL);
198 assert(image->signature == MagickSignature);
199 if (image->debug != MagickFalse)
200 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
201 if (image->storage_class == DirectClass)
202 (void) SetImageType(image,PaletteType,exception);
204 image_view=AcquireCacheView(image);
205 #if defined(MAGICKCORE_OPENMP_SUPPORT)
206 #pragma omp parallel for schedule(static,4) shared(status)
208 for (y=0; y < (ssize_t) image->rows; y++)
219 if (status == MagickFalse)
221 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
222 if (q == (Quantum *) NULL)
227 for (x=0; x < (ssize_t) image->columns; x++)
229 index=(ssize_t) (GetPixelIndex(image,q)+displace) % image->colors;
231 index+=(ssize_t) image->colors;
232 SetPixelIndex(image,(Quantum) index,q);
233 SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
234 q+=GetPixelChannels(image);
236 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
239 image_view=DestroyCacheView(image_view);
244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248 + S o r t C o l o r m a p B y I n t e n s i t y %
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254 % SortColormapByIntensity() sorts the colormap of a PseudoClass image by
255 % decreasing color intensity.
257 % The format of the SortColormapByIntensity method is:
259 % MagickBooleanType SortColormapByIntensity(Image *image,
260 % ExceptionInfo *exception)
262 % A description of each parameter follows:
264 % o image: A pointer to an Image structure.
266 % o exception: return any errors or warnings in this structure.
270 #if defined(__cplusplus) || defined(c_plusplus)
274 static int IntensityCompare(const void *x,const void *y)
283 color_1=(const PixelInfo *) x;
284 color_2=(const PixelInfo *) y;
285 intensity=(int) GetPixelInfoIntensity(color_2)-(int)
286 GetPixelInfoIntensity(color_1);
290 #if defined(__cplusplus) || defined(c_plusplus)
294 MagickExport MagickBooleanType SortColormapByIntensity(Image *image,
295 ExceptionInfo *exception)
312 assert(image != (Image *) NULL);
313 if (image->debug != MagickFalse)
314 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
315 assert(image->signature == MagickSignature);
316 if (image->storage_class != PseudoClass)
319 Allocate memory for pixel indexes.
321 pixels=(unsigned short *) AcquireQuantumMemory((size_t) image->colors,
323 if (pixels == (unsigned short *) NULL)
324 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
327 Assign index values to colormap entries.
329 #if defined(MAGICKCORE_OPENMP_SUPPORT)
330 #pragma omp parallel for schedule(static,4) shared(status)
332 for (i=0; i < (ssize_t) image->colors; i++)
333 image->colormap[i].alpha=(double) i;
335 Sort image colormap by decreasing color popularity.
337 qsort((void *) image->colormap,(size_t) image->colors,
338 sizeof(*image->colormap),IntensityCompare);
340 Update image colormap indexes to sorted colormap order.
342 #if defined(MAGICKCORE_OPENMP_SUPPORT)
343 #pragma omp parallel for schedule(static,4) shared(status)
345 for (i=0; i < (ssize_t) image->colors; i++)
346 pixels[(ssize_t) image->colormap[i].alpha]=(unsigned short) i;
348 image_view=AcquireCacheView(image);
349 for (y=0; y < (ssize_t) image->rows; y++)
360 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
361 if (q == (Quantum *) NULL)
366 for (x=0; x < (ssize_t) image->columns; x++)
368 index=(Quantum) pixels[(ssize_t) GetPixelIndex(image,q)];
369 SetPixelIndex(image,index,q);
370 SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
371 q+=GetPixelChannels(image);
373 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
375 if (status == MagickFalse)
378 image_view=DestroyCacheView(image_view);
379 pixels=(unsigned short *) RelinquishMagickMemory(pixels);