|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % CCCC OOO L OOO RRRR M M AAA PPPP % 00007 % C O O L O O R R MM MM A A P P % 00008 % C O O L O O RRRR M M M AAAAA PPPP % 00009 % C O O L O O R R M M A A P % 00010 % CCCC OOO LLLLL OOO R R M M A A P % 00011 % % 00012 % % 00013 % MagickCore Colormap Methods % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % July 1992 % 00018 % % 00019 % % 00020 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.imagemagick.org/script/license.php % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % We use linked-lists because splay-trees do not currently support duplicate 00037 % key / value pairs (.e.g X11 green compliance and SVG green compliance). 00038 % 00039 */ 00040 00041 /* 00042 Include declarations. 00043 */ 00044 #include "MagickCore/studio.h" 00045 #include "MagickCore/blob.h" 00046 #include "MagickCore/cache-view.h" 00047 #include "MagickCore/cache.h" 00048 #include "MagickCore/color.h" 00049 #include "MagickCore/color-private.h" 00050 #include "MagickCore/colormap.h" 00051 #include "MagickCore/client.h" 00052 #include "MagickCore/configure.h" 00053 #include "MagickCore/exception.h" 00054 #include "MagickCore/exception-private.h" 00055 #include "MagickCore/gem.h" 00056 #include "MagickCore/geometry.h" 00057 #include "MagickCore/image-private.h" 00058 #include "MagickCore/memory_.h" 00059 #include "MagickCore/monitor.h" 00060 #include "MagickCore/monitor-private.h" 00061 #include "MagickCore/option.h" 00062 #include "MagickCore/pixel-accessor.h" 00063 #include "MagickCore/quantize.h" 00064 #include "MagickCore/quantum.h" 00065 #include "MagickCore/semaphore.h" 00066 #include "MagickCore/string_.h" 00067 #include "MagickCore/token.h" 00068 #include "MagickCore/utility.h" 00069 #include "MagickCore/xml-tree.h" 00070 00071 /* 00072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00073 % % 00074 % % 00075 % % 00076 % A c q u i r e I m a g e C o l o r m a p % 00077 % % 00078 % % 00079 % % 00080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00081 % 00082 % AcquireImageColormap() allocates an image colormap and initializes 00083 % it to a linear gray colorspace. If the image already has a colormap, 00084 % it is replaced. AcquireImageColormap() returns MagickTrue if successful, 00085 % otherwise MagickFalse if there is not enough memory. 00086 % 00087 % The format of the AcquireImageColormap method is: 00088 % 00089 % MagickBooleanType AcquireImageColormap(Image *image, 00090 % const size_t colors,ExceptionInfo *exception) 00091 % 00092 % A description of each parameter follows: 00093 % 00094 % o image: the image. 00095 % 00096 % o colors: the number of colors in the image colormap. 00097 % 00098 % o exception: return any errors or warnings in this structure. 00099 % 00100 */ 00101 00102 static inline size_t MagickMax(const size_t x, 00103 const size_t y) 00104 { 00105 if (x > y) 00106 return(x); 00107 return(y); 00108 } 00109 00110 MagickExport MagickBooleanType AcquireImageColormap(Image *image, 00111 const size_t colors,ExceptionInfo *exception) 00112 { 00113 register ssize_t 00114 i; 00115 00116 size_t 00117 length; 00118 00119 /* 00120 Allocate image colormap. 00121 */ 00122 assert(image != (Image *) NULL); 00123 assert(image->signature == MagickSignature); 00124 if (image->debug != MagickFalse) 00125 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00126 image->colors=colors; 00127 length=(size_t) colors; 00128 if (image->colormap == (PixelInfo *) NULL) 00129 image->colormap=(PixelInfo *) AcquireQuantumMemory(length, 00130 sizeof(*image->colormap)); 00131 else 00132 image->colormap=(PixelInfo *) ResizeQuantumMemory(image->colormap,length, 00133 sizeof(*image->colormap)); 00134 if (image->colormap == (PixelInfo *) NULL) 00135 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00136 image->filename); 00137 for (i=0; i < (ssize_t) image->colors; i++) 00138 { 00139 size_t 00140 pixel; 00141 00142 pixel=(size_t) (i*(QuantumRange/MagickMax(colors-1,1))); 00143 image->colormap[i].red=(Quantum) pixel; 00144 image->colormap[i].green=(Quantum) pixel; 00145 image->colormap[i].blue=(Quantum) pixel; 00146 image->colormap[i].alpha=OpaqueAlpha; 00147 } 00148 return(SetImageStorageClass(image,PseudoClass,exception)); 00149 } 00150 00151 /* 00152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00153 % % 00154 % % 00155 % % 00156 % C y c l e C o l o r m a p I m a g e % 00157 % % 00158 % % 00159 % % 00160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00161 % 00162 % CycleColormap() displaces an image's colormap by a given number of 00163 % positions. If you cycle the colormap a number of times you can produce 00164 % a psychodelic effect. 00165 % 00166 % WARNING: this assumes an images colormap is in a well know and defined 00167 % order. Currently Imagemagick has no way of setting that order. 00168 % 00169 % The format of the CycleColormapImage method is: 00170 % 00171 % MagickBooleanType CycleColormapImage(Image *image,const ssize_t displace, 00172 % ExceptionInfo *exception) 00173 % 00174 % A description of each parameter follows: 00175 % 00176 % o image: the image. 00177 % 00178 % o displace: displace the colormap this amount. 00179 % 00180 % o exception: return any errors or warnings in this structure. 00181 % 00182 */ 00183 MagickExport MagickBooleanType CycleColormapImage(Image *image, 00184 const ssize_t displace,ExceptionInfo *exception) 00185 { 00186 CacheView 00187 *image_view; 00188 00189 MagickBooleanType 00190 status; 00191 00192 ssize_t 00193 y; 00194 00195 assert(image != (Image *) NULL); 00196 assert(image->signature == MagickSignature); 00197 if (image->debug != MagickFalse) 00198 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00199 if (image->storage_class == DirectClass) 00200 (void) SetImageType(image,PaletteType,exception); 00201 status=MagickTrue; 00202 image_view=AcquireCacheView(image); 00203 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00204 #pragma omp parallel for schedule(static,4) shared(status) 00205 #endif 00206 for (y=0; y < (ssize_t) image->rows; y++) 00207 { 00208 register ssize_t 00209 x; 00210 00211 register Quantum 00212 *restrict q; 00213 00214 ssize_t 00215 index; 00216 00217 if (status == MagickFalse) 00218 continue; 00219 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 00220 if (q == (Quantum *) NULL) 00221 { 00222 status=MagickFalse; 00223 continue; 00224 } 00225 for (x=0; x < (ssize_t) image->columns; x++) 00226 { 00227 index=(ssize_t) (GetPixelIndex(image,q)+displace) % image->colors; 00228 if (index < 0) 00229 index+=(ssize_t) image->colors; 00230 SetPixelIndex(image,(Quantum) index,q); 00231 SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q); 00232 q+=GetPixelChannels(image); 00233 } 00234 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 00235 status=MagickFalse; 00236 } 00237 image_view=DestroyCacheView(image_view); 00238 return(status); 00239 } 00240 00241 /* 00242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00243 % % 00244 % % 00245 % % 00246 + S o r t C o l o r m a p B y I n t e n s i t y % 00247 % % 00248 % % 00249 % % 00250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00251 % 00252 % SortColormapByIntensity() sorts the colormap of a PseudoClass image by 00253 % decreasing color intensity. 00254 % 00255 % The format of the SortColormapByIntensity method is: 00256 % 00257 % MagickBooleanType SortColormapByIntensity(Image *image, 00258 % ExceptionInfo *exception) 00259 % 00260 % A description of each parameter follows: 00261 % 00262 % o image: A pointer to an Image structure. 00263 % 00264 % o exception: return any errors or warnings in this structure. 00265 % 00266 */ 00267 00268 #if defined(__cplusplus) || defined(c_plusplus) 00269 extern "C" { 00270 #endif 00271 00272 static int IntensityCompare(const void *x,const void *y) 00273 { 00274 const PixelInfo 00275 *color_1, 00276 *color_2; 00277 00278 int 00279 intensity; 00280 00281 color_1=(const PixelInfo *) x; 00282 color_2=(const PixelInfo *) y; 00283 intensity=(int) GetPixelInfoIntensity(color_2)-(int) 00284 GetPixelInfoIntensity(color_1); 00285 return(intensity); 00286 } 00287 00288 #if defined(__cplusplus) || defined(c_plusplus) 00289 } 00290 #endif 00291 00292 MagickExport MagickBooleanType SortColormapByIntensity(Image *image, 00293 ExceptionInfo *exception) 00294 { 00295 CacheView 00296 *image_view; 00297 00298 MagickBooleanType 00299 status; 00300 00301 register ssize_t 00302 i; 00303 00304 ssize_t 00305 y; 00306 00307 unsigned short 00308 *pixels; 00309 00310 assert(image != (Image *) NULL); 00311 if (image->debug != MagickFalse) 00312 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00313 assert(image->signature == MagickSignature); 00314 if (image->storage_class != PseudoClass) 00315 return(MagickTrue); 00316 /* 00317 Allocate memory for pixel indexes. 00318 */ 00319 pixels=(unsigned short *) AcquireQuantumMemory((size_t) image->colors, 00320 sizeof(*pixels)); 00321 if (pixels == (unsigned short *) NULL) 00322 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00323 image->filename); 00324 /* 00325 Assign index values to colormap entries. 00326 */ 00327 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00328 #pragma omp parallel for schedule(static,4) shared(status) 00329 #endif 00330 for (i=0; i < (ssize_t) image->colors; i++) 00331 image->colormap[i].alpha=(Quantum) i; 00332 /* 00333 Sort image colormap by decreasing color popularity. 00334 */ 00335 qsort((void *) image->colormap,(size_t) image->colors, 00336 sizeof(*image->colormap),IntensityCompare); 00337 /* 00338 Update image colormap indexes to sorted colormap order. 00339 */ 00340 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00341 #pragma omp parallel for schedule(static,4) shared(status) 00342 #endif 00343 for (i=0; i < (ssize_t) image->colors; i++) 00344 pixels[(ssize_t) image->colormap[i].alpha]=(unsigned short) i; 00345 status=MagickTrue; 00346 image_view=AcquireCacheView(image); 00347 for (y=0; y < (ssize_t) image->rows; y++) 00348 { 00349 Quantum 00350 index; 00351 00352 register ssize_t 00353 x; 00354 00355 register Quantum 00356 *restrict q; 00357 00358 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 00359 if (q == (Quantum *) NULL) 00360 { 00361 status=MagickFalse; 00362 break; 00363 } 00364 for (x=0; x < (ssize_t) image->columns; x++) 00365 { 00366 index=(Quantum) pixels[(ssize_t) GetPixelIndex(image,q)]; 00367 SetPixelIndex(image,index,q); 00368 SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q); 00369 q+=GetPixelChannels(image); 00370 } 00371 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 00372 status=MagickFalse; 00373 if (status == MagickFalse) 00374 break; 00375 } 00376 image_view=DestroyCacheView(image_view); 00377 pixels=(unsigned short *) RelinquishMagickMemory(pixels); 00378 return(status); 00379 }