MagickCore  7.0.10
colormap.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
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 %
11 % %
12 % %
13 % MagickCore Colormap Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2020 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
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. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
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).
38 %
39 */
40 
41 /*
42  Include declarations.
43 */
44 #include "MagickCore/studio.h"
45 #include "MagickCore/attribute.h"
46 #include "MagickCore/blob.h"
47 #include "MagickCore/cache-view.h"
48 #include "MagickCore/cache.h"
49 #include "MagickCore/color.h"
51 #include "MagickCore/colormap.h"
52 #include "MagickCore/client.h"
53 #include "MagickCore/configure.h"
54 #include "MagickCore/exception.h"
56 #include "MagickCore/gem.h"
57 #include "MagickCore/geometry.h"
59 #include "MagickCore/memory_.h"
60 #include "MagickCore/monitor.h"
62 #include "MagickCore/option.h"
64 #include "MagickCore/quantize.h"
65 #include "MagickCore/quantum.h"
66 #include "MagickCore/resource_.h"
67 #include "MagickCore/semaphore.h"
68 #include "MagickCore/string_.h"
70 #include "MagickCore/token.h"
71 #include "MagickCore/utility.h"
72 #include "MagickCore/xml-tree.h"
73 
74 /*
75 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 % %
77 % %
78 % %
79 % A c q u i r e I m a g e C o l o r m a p %
80 % %
81 % %
82 % %
83 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84 %
85 % AcquireImageColormap() allocates an image colormap and initializes
86 % it to a linear gray colorspace. If the image already has a colormap,
87 % it is replaced. AcquireImageColormap() returns MagickTrue if successful,
88 % otherwise MagickFalse if there is not enough memory.
89 %
90 % The format of the AcquireImageColormap method is:
91 %
92 % MagickBooleanType AcquireImageColormap(Image *image,const size_t colors,
93 % ExceptionInfo *exception)
94 %
95 % A description of each parameter follows:
96 %
97 % o image: the image.
98 %
99 % o colors: the number of colors in the image colormap.
100 %
101 % o exception: return any errors or warnings in this structure.
102 %
103 */
105  const size_t colors,ExceptionInfo *exception)
106 {
107  register ssize_t
108  i;
109 
110  /*
111  Allocate image colormap.
112  */
113  assert(image != (Image *) NULL);
114  assert(image->signature == MagickCoreSignature);
115  if (image->debug != MagickFalse)
116  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
117  if (colors > MaxColormapSize)
118  {
119  image->colors=0;
120  image->storage_class=DirectClass;
121  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
122  image->filename);
123  }
124  image->colors=MagickMax(colors,1);
125  if (image->colormap == (PixelInfo *) NULL)
126  image->colormap=(PixelInfo *) AcquireQuantumMemory(image->colors+1,
127  sizeof(*image->colormap));
128  else
130  image->colors+1,sizeof(*image->colormap));
131  if (image->colormap == (PixelInfo *) NULL)
132  {
133  image->colors=0;
134  image->storage_class=DirectClass;
135  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
136  image->filename);
137  }
138  for (i=0; i < (ssize_t) image->colors; i++)
139  {
140  double
141  pixel;
142 
143  GetPixelInfo(image,image->colormap+i);
144  pixel=(double) (i*(QuantumRange/MagickMax(colors-1,1)));
145  image->colormap[i].red=pixel;
146  image->colormap[i].green=pixel;
147  image->colormap[i].blue=pixel;
150  }
151  return(SetImageStorageClass(image,PseudoClass,exception));
152 }
153 
154 /*
155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156 % %
157 % %
158 % %
159 % C y c l e C o l o r m a p I m a g e %
160 % %
161 % %
162 % %
163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 %
165 % CycleColormap() displaces an image's colormap by a given number of
166 % positions. If you cycle the colormap a number of times you can produce
167 % a psychodelic effect.
168 %
169 % WARNING: this assumes an images colormap is in a well know and defined
170 % order. Currently Imagemagick has no way of setting that order.
171 %
172 % The format of the CycleColormapImage method is:
173 %
174 % MagickBooleanType CycleColormapImage(Image *image,const ssize_t displace,
175 % ExceptionInfo *exception)
176 %
177 % A description of each parameter follows:
178 %
179 % o image: the image.
180 %
181 % o displace: displace the colormap this amount.
182 %
183 % o exception: return any errors or warnings in this structure.
184 %
185 */
187  const ssize_t displace,ExceptionInfo *exception)
188 {
189  CacheView
190  *image_view;
191 
193  status;
194 
195  ssize_t
196  y;
197 
198  assert(image != (Image *) NULL);
199  assert(image->signature == MagickCoreSignature);
200  if (image->debug != MagickFalse)
201  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
202  if (image->storage_class == DirectClass)
203  (void) SetImageType(image,PaletteType,exception);
204  status=MagickTrue;
205  image_view=AcquireAuthenticCacheView(image,exception);
206 #if defined(MAGICKCORE_OPENMP_SUPPORT)
207  #pragma omp parallel for schedule(static) \
208  magick_number_threads(image,image,image->rows,1)
209 #endif
210  for (y=0; y < (ssize_t) image->rows; y++)
211  {
212  register ssize_t
213  x;
214 
215  register Quantum
216  *magick_restrict q;
217 
218  ssize_t
219  index;
220 
221  if (status == MagickFalse)
222  continue;
223  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
224  if (q == (Quantum *) NULL)
225  {
226  status=MagickFalse;
227  continue;
228  }
229  for (x=0; x < (ssize_t) image->columns; x++)
230  {
231  index=(ssize_t) (GetPixelIndex(image,q)+displace) % image->colors;
232  if (index < 0)
233  index+=(ssize_t) image->colors;
234  SetPixelIndex(image,(Quantum) index,q);
235  SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
236  q+=GetPixelChannels(image);
237  }
238  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
239  status=MagickFalse;
240  }
241  image_view=DestroyCacheView(image_view);
242  return(status);
243 }
244 
245 /*
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 % %
248 % %
249 % %
250 + S o r t C o l o r m a p B y I n t e n s i t y %
251 % %
252 % %
253 % %
254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
255 %
256 % SortColormapByIntensity() sorts the colormap of a PseudoClass image by
257 % decreasing color intensity.
258 %
259 % The format of the SortColormapByIntensity method is:
260 %
261 % MagickBooleanType SortColormapByIntensity(Image *image,
262 % ExceptionInfo *exception)
263 %
264 % A description of each parameter follows:
265 %
266 % o image: A pointer to an Image structure.
267 %
268 % o exception: return any errors or warnings in this structure.
269 %
270 */
271 
272 #if defined(__cplusplus) || defined(c_plusplus)
273 extern "C" {
274 #endif
275 
276 static int IntensityCompare(const void *x,const void *y)
277 {
278  const PixelInfo
279  *color_1,
280  *color_2;
281 
282  int
283  intensity;
284 
285  color_1=(const PixelInfo *) x;
286  color_2=(const PixelInfo *) y;
287  intensity=(int) GetPixelInfoIntensity((const Image *) NULL,color_2)-(int)
288  GetPixelInfoIntensity((const Image *) NULL,color_1);
289  return(intensity);
290 }
291 
292 #if defined(__cplusplus) || defined(c_plusplus)
293 }
294 #endif
295 
297  ExceptionInfo *exception)
298 {
299  CacheView
300  *image_view;
301 
303  status;
304 
305  register ssize_t
306  i;
307 
308  ssize_t
309  y;
310 
311  unsigned short
312  *pixels;
313 
314  assert(image != (Image *) NULL);
315  if (image->debug != MagickFalse)
316  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
317  assert(image->signature == MagickCoreSignature);
318  if (image->storage_class != PseudoClass)
319  return(MagickTrue);
320  /*
321  Allocate memory for pixel indexes.
322  */
323  pixels=(unsigned short *) AcquireQuantumMemory((size_t) image->colors,
324  sizeof(*pixels));
325  if (pixels == (unsigned short *) NULL)
326  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
327  image->filename);
328  /*
329  Assign index values to colormap entries.
330  */
331  for (i=0; i < (ssize_t) image->colors; i++)
332  image->colormap[i].alpha=(double) i;
333  /*
334  Sort image colormap by decreasing color popularity.
335  */
336  qsort((void *) image->colormap,(size_t) image->colors,
337  sizeof(*image->colormap),IntensityCompare);
338  /*
339  Update image colormap indexes to sorted colormap order.
340  */
341  for (i=0; i < (ssize_t) image->colors; i++)
342  pixels[(ssize_t) image->colormap[i].alpha]=(unsigned short) i;
343  status=MagickTrue;
344  image_view=AcquireAuthenticCacheView(image,exception);
345  for (y=0; y < (ssize_t) image->rows; y++)
346  {
347  Quantum
348  index;
349 
350  register ssize_t
351  x;
352 
353  register Quantum
354  *magick_restrict q;
355 
356  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
357  if (q == (Quantum *) NULL)
358  {
359  status=MagickFalse;
360  break;
361  }
362  for (x=0; x < (ssize_t) image->columns; x++)
363  {
364  index=(Quantum) pixels[(ssize_t) GetPixelIndex(image,q)];
365  SetPixelIndex(image,index,q);
366  SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
367  q+=GetPixelChannels(image);
368  }
369  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
370  status=MagickFalse;
371  if (status == MagickFalse)
372  break;
373  }
374  image_view=DestroyCacheView(image_view);
375  pixels=(unsigned short *) RelinquishMagickMemory(pixels);
376  return(status);
377 }
size_t rows
Definition: image.h:172
#define magick_restrict
Definition: MagickCore.h:41
MagickDoubleType MagickRealType
Definition: magick-type.h:124
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
Definition: cache-view.c:252
MagickExport MagickBooleanType SortColormapByIntensity(Image *image, ExceptionInfo *exception)
Definition: colormap.c:296
PixelInfo * colormap
Definition: image.h:179
MagickExport MagickBooleanType CycleColormapImage(Image *image, const ssize_t displace, ExceptionInfo *exception)
Definition: colormap.c:186
PixelTrait alpha_trait
Definition: pixel.h:181
#define OpaqueAlpha
Definition: image.h:25
MagickRealType red
Definition: pixel.h:193
#define MaxColormapSize
Definition: magick-type.h:78
static void SetPixelViaPixelInfo(const Image *magick_restrict image, const PixelInfo *magick_restrict pixel_info, Quantum *magick_restrict pixel)
MagickRealType alpha
Definition: pixel.h:193
MagickExport void * ResizeQuantumMemory(void *memory, const size_t count, const size_t quantum)
Definition: memory.c:1408
ClassType storage_class
Definition: image.h:154
#define ThrowBinaryException(severity, tag, context)
Definition: log.h:52
MagickExport void GetPixelInfo(const Image *image, PixelInfo *pixel)
Definition: pixel.c:2170
Definition: image.h:151
#define MagickCoreSignature
MagickExport MagickBooleanType SetImageType(Image *image, const ImageType type, ExceptionInfo *exception)
Definition: attribute.c:2090
MagickExport Quantum * GetCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:299
MagickBooleanType
Definition: magick-type.h:169
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:634
static int IntensityCompare(const void *x, const void *y)
Definition: colormap.c:276
MagickRealType blue
Definition: pixel.h:193
static Quantum GetPixelIndex(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
MagickExport MagickRealType GetPixelInfoIntensity(const Image *magick_restrict image, const PixelInfo *magick_restrict pixel)
Definition: pixel.c:2224
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1660
size_t signature
Definition: image.h:354
size_t columns
Definition: image.h:172
MagickExport MagickBooleanType SetImageStorageClass(Image *image, const ClassType storage_class, ExceptionInfo *exception)
Definition: image.c:2595
#define MagickMax(x, y)
Definition: image-private.h:36
size_t colors
Definition: image.h:172
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport MagickBooleanType AcquireImageColormap(Image *image, const size_t colors, ExceptionInfo *exception)
Definition: colormap.c:104
char filename[MagickPathExtent]
Definition: image.h:319
#define GetMagickModule()
Definition: log.h:28
unsigned short Quantum
Definition: magick-type.h:86
static void SetPixelIndex(const Image *magick_restrict image, const Quantum index, Quantum *magick_restrict pixel)
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1123
MagickRealType green
Definition: pixel.h:193
#define MagickExport
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
Definition: cache-view.c:1100
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:112
#define QuantumRange
Definition: magick-type.h:87
MagickBooleanType debug
Definition: image.h:334