PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/ImageMagick-6.7.1/magick/colormap.c

https://github.com/trevor/ImageMagick
C | 392 lines | 228 code | 30 blank | 134 comment | 49 complexity | 9eb68bad970bd7201d74b0fbaaf70512 MD5 | raw 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. % John Cristy %
  17. % July 1992 %
  18. % %
  19. % %
  20. % Copyright 1999-2011 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. % http://www.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. Include declarations.
  42. */
  43. #include "magick/studio.h"
  44. #include "magick/blob.h"
  45. #include "magick/cache-view.h"
  46. #include "magick/cache.h"
  47. #include "magick/color.h"
  48. #include "magick/color-private.h"
  49. #include "magick/colormap.h"
  50. #include "magick/client.h"
  51. #include "magick/configure.h"
  52. #include "magick/exception.h"
  53. #include "magick/exception-private.h"
  54. #include "magick/gem.h"
  55. #include "magick/geometry.h"
  56. #include "magick/image-private.h"
  57. #include "magick/memory_.h"
  58. #include "magick/monitor.h"
  59. #include "magick/monitor-private.h"
  60. #include "magick/option.h"
  61. #include "magick/pixel-private.h"
  62. #include "magick/quantize.h"
  63. #include "magick/quantum.h"
  64. #include "magick/semaphore.h"
  65. #include "magick/string_.h"
  66. #include "magick/token.h"
  67. #include "magick/utility.h"
  68. #include "magick/xml-tree.h"
  69. /*
  70. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  71. % %
  72. % %
  73. % %
  74. % A c q u i r e I m a g e C o l o r m a p %
  75. % %
  76. % %
  77. % %
  78. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  79. %
  80. % AcquireImageColormap() allocates an image colormap and initializes
  81. % it to a linear gray colorspace. If the image already has a colormap,
  82. % it is replaced. AcquireImageColormap() returns MagickTrue if successful,
  83. % otherwise MagickFalse if there is not enough memory.
  84. %
  85. % The format of the AcquireImageColormap method is:
  86. %
  87. % MagickBooleanType AcquireImageColormap(Image *image,
  88. % const size_t colors)
  89. %
  90. % A description of each parameter follows:
  91. %
  92. % o image: the image.
  93. %
  94. % o colors: the number of colors in the image colormap.
  95. %
  96. */
  97. static inline size_t MagickMax(const size_t x,
  98. const size_t y)
  99. {
  100. if (x > y)
  101. return(x);
  102. return(y);
  103. }
  104. static inline size_t MagickMin(const size_t x,
  105. const size_t y)
  106. {
  107. if (x < y)
  108. return(x);
  109. return(y);
  110. }
  111. MagickExport MagickBooleanType AcquireImageColormap(Image *image,
  112. const size_t colors)
  113. {
  114. register ssize_t
  115. i;
  116. size_t
  117. length;
  118. /*
  119. Allocate image colormap.
  120. */
  121. assert(image != (Image *) NULL);
  122. assert(image->signature == MagickSignature);
  123. if (image->debug != MagickFalse)
  124. (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  125. image->colors=colors;
  126. length=(size_t) colors;
  127. if (image->colormap == (PixelPacket *) NULL)
  128. image->colormap=(PixelPacket *) AcquireQuantumMemory(length,
  129. sizeof(*image->colormap));
  130. else
  131. image->colormap=(PixelPacket *) ResizeQuantumMemory(image->colormap,length,
  132. sizeof(*image->colormap));
  133. if (image->colormap == (PixelPacket *) NULL)
  134. ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
  135. image->filename);
  136. for (i=0; i < (ssize_t) image->colors; i++)
  137. {
  138. size_t
  139. pixel;
  140. pixel=(size_t) (i*(QuantumRange/MagickMax(colors-1,1)));
  141. image->colormap[i].red=(Quantum) pixel;
  142. image->colormap[i].green=(Quantum) pixel;
  143. image->colormap[i].blue=(Quantum) pixel;
  144. image->colormap[i].opacity=OpaqueOpacity;
  145. }
  146. return(SetImageStorageClass(image,PseudoClass));
  147. }
  148. /*
  149. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  150. % %
  151. % %
  152. % %
  153. % C y c l e C o l o r m a p I m a g e %
  154. % %
  155. % %
  156. % %
  157. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  158. %
  159. % CycleColormap() displaces an image's colormap by a given number of
  160. % positions. If you cycle the colormap a number of times you can produce
  161. % a psychodelic effect.
  162. %
  163. % The format of the CycleColormapImage method is:
  164. %
  165. % MagickBooleanType CycleColormapImage(Image *image,const ssize_t displace)
  166. %
  167. % A description of each parameter follows:
  168. %
  169. % o image: the image.
  170. %
  171. % o displace: displace the colormap this amount.
  172. %
  173. */
  174. MagickExport MagickBooleanType CycleColormapImage(Image *image,
  175. const ssize_t displace)
  176. {
  177. CacheView
  178. *image_view;
  179. ExceptionInfo
  180. *exception;
  181. MagickBooleanType
  182. status;
  183. ssize_t
  184. y;
  185. assert(image != (Image *) NULL);
  186. assert(image->signature == MagickSignature);
  187. if (image->debug != MagickFalse)
  188. (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  189. if (image->storage_class == DirectClass)
  190. (void) SetImageType(image,PaletteType);
  191. status=MagickTrue;
  192. exception=(&image->exception);
  193. image_view=AcquireCacheView(image);
  194. #if defined(MAGICKCORE_OPENMP_SUPPORT)
  195. #pragma omp parallel for schedule(dynamic,4) shared(status)
  196. #endif
  197. for (y=0; y < (ssize_t) image->rows; y++)
  198. {
  199. register IndexPacket
  200. *restrict indexes;
  201. register ssize_t
  202. x;
  203. register PixelPacket
  204. *restrict q;
  205. ssize_t
  206. index;
  207. if (status == MagickFalse)
  208. continue;
  209. q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
  210. if (q == (PixelPacket *) NULL)
  211. {
  212. status=MagickFalse;
  213. continue;
  214. }
  215. indexes=GetCacheViewAuthenticIndexQueue(image_view);
  216. for (x=0; x < (ssize_t) image->columns; x++)
  217. {
  218. index=(ssize_t) (GetPixelIndex(indexes+x)+displace) %
  219. image->colors;
  220. if (index < 0)
  221. index+=(ssize_t) image->colors;
  222. SetPixelIndex(indexes+x,index);
  223. SetPixelRGBO(q,image->colormap+(ssize_t) index);
  224. q++;
  225. }
  226. if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
  227. status=MagickFalse;
  228. }
  229. image_view=DestroyCacheView(image_view);
  230. return(status);
  231. }
  232. /*
  233. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  234. % %
  235. % %
  236. % %
  237. + S o r t C o l o r m a p B y I n t e n s i t y %
  238. % %
  239. % %
  240. % %
  241. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  242. %
  243. % SortColormapByIntensity() sorts the colormap of a PseudoClass image by
  244. % decreasing color intensity.
  245. %
  246. % The format of the SortColormapByIntensity method is:
  247. %
  248. % MagickBooleanType SortColormapByIntensity(Image *image)
  249. %
  250. % A description of each parameter follows:
  251. %
  252. % o image: A pointer to an Image structure.
  253. %
  254. */
  255. #if defined(__cplusplus) || defined(c_plusplus)
  256. extern "C" {
  257. #endif
  258. static int IntensityCompare(const void *x,const void *y)
  259. {
  260. const PixelPacket
  261. *color_1,
  262. *color_2;
  263. int
  264. intensity;
  265. color_1=(const PixelPacket *) x;
  266. color_2=(const PixelPacket *) y;
  267. intensity=(int) PixelIntensityToQuantum(color_2)-
  268. (int) PixelIntensityToQuantum(color_1);
  269. return(intensity);
  270. }
  271. #if defined(__cplusplus) || defined(c_plusplus)
  272. }
  273. #endif
  274. MagickExport MagickBooleanType SortColormapByIntensity(Image *image)
  275. {
  276. CacheView
  277. *image_view;
  278. ExceptionInfo
  279. *exception;
  280. MagickBooleanType
  281. status;
  282. register ssize_t
  283. i;
  284. ssize_t
  285. y;
  286. unsigned short
  287. *pixels;
  288. assert(image != (Image *) NULL);
  289. if (image->debug != MagickFalse)
  290. (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  291. assert(image->signature == MagickSignature);
  292. if (image->storage_class != PseudoClass)
  293. return(MagickTrue);
  294. /*
  295. Allocate memory for pixel indexes.
  296. */
  297. pixels=(unsigned short *) AcquireQuantumMemory((size_t) image->colors,
  298. sizeof(*pixels));
  299. if (pixels == (unsigned short *) NULL)
  300. ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
  301. image->filename);
  302. /*
  303. Assign index values to colormap entries.
  304. */
  305. #if defined(MAGICKCORE_OPENMP_SUPPORT)
  306. #pragma omp parallel for schedule(dynamic,4) shared(status)
  307. #endif
  308. for (i=0; i < (ssize_t) image->colors; i++)
  309. image->colormap[i].opacity=(IndexPacket) i;
  310. /*
  311. Sort image colormap by decreasing color popularity.
  312. */
  313. qsort((void *) image->colormap,(size_t) image->colors,
  314. sizeof(*image->colormap),IntensityCompare);
  315. /*
  316. Update image colormap indexes to sorted colormap order.
  317. */
  318. #if defined(MAGICKCORE_OPENMP_SUPPORT)
  319. #pragma omp parallel for schedule(dynamic,4) shared(status)
  320. #endif
  321. for (i=0; i < (ssize_t) image->colors; i++)
  322. pixels[(ssize_t) image->colormap[i].opacity]=(unsigned short) i;
  323. status=MagickTrue;
  324. exception=(&image->exception);
  325. image_view=AcquireCacheView(image);
  326. for (y=0; y < (ssize_t) image->rows; y++)
  327. {
  328. IndexPacket
  329. index;
  330. register ssize_t
  331. x;
  332. register IndexPacket
  333. *restrict indexes;
  334. register PixelPacket
  335. *restrict q;
  336. q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
  337. if (q == (PixelPacket *) NULL)
  338. {
  339. status=MagickFalse;
  340. continue;
  341. }
  342. indexes=GetCacheViewAuthenticIndexQueue(image_view);
  343. for (x=0; x < (ssize_t) image->columns; x++)
  344. {
  345. index=(IndexPacket) pixels[(ssize_t) GetPixelIndex(indexes+x)];
  346. SetPixelIndex(indexes+x,index);
  347. SetPixelRGBO(q,image->colormap+(ssize_t) index);
  348. q++;
  349. }
  350. if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
  351. status=MagickFalse;
  352. if (status == MagickFalse)
  353. break;
  354. }
  355. image_view=DestroyCacheView(image_view);
  356. pixels=(unsigned short *) RelinquishMagickMemory(pixels);
  357. return(status);
  358. }