|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % CCCC OOO L OOO RRRR SSSSS PPPP AAA CCCC EEEEE % 00007 % C O O L O O R R SS P P A A C E % 00008 % C O O L O O RRRR SSS PPPP AAAAA C EEE % 00009 % C O O L O O R R SS P A A C E % 00010 % CCCC OOO LLLLL OOO R R SSSSS P A A CCCC EEEEE % 00011 % % 00012 % % 00013 % MagickCore Image Colorspace 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 % 00037 */ 00038 00039 /* 00040 Include declarations. 00041 */ 00042 #include "MagickCore/studio.h" 00043 #include "MagickCore/property.h" 00044 #include "MagickCore/cache.h" 00045 #include "MagickCore/cache-private.h" 00046 #include "MagickCore/cache-view.h" 00047 #include "MagickCore/color.h" 00048 #include "MagickCore/color-private.h" 00049 #include "MagickCore/colorspace.h" 00050 #include "MagickCore/colorspace-private.h" 00051 #include "MagickCore/exception.h" 00052 #include "MagickCore/exception-private.h" 00053 #include "MagickCore/image.h" 00054 #include "MagickCore/image-private.h" 00055 #include "MagickCore/gem.h" 00056 #include "MagickCore/gem-private.h" 00057 #include "MagickCore/memory_.h" 00058 #include "MagickCore/monitor.h" 00059 #include "MagickCore/monitor-private.h" 00060 #include "MagickCore/pixel-accessor.h" 00061 #include "MagickCore/quantize.h" 00062 #include "MagickCore/quantum.h" 00063 #include "MagickCore/quantum-private.h" 00064 #include "MagickCore/string_.h" 00065 #include "MagickCore/string-private.h" 00066 #include "MagickCore/utility.h" 00067 00068 /* 00069 Typedef declarations. 00070 */ 00071 typedef struct _TransformPacket 00072 { 00073 MagickRealType 00074 x, 00075 y, 00076 z; 00077 } TransformPacket; 00078 00079 /* 00080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00081 % % 00082 % % 00083 % % 00084 + R G B T r a n s f o r m I m a g e % 00085 % % 00086 % % 00087 % % 00088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00089 % 00090 % RGBTransformImage() converts the reference image from RGB to an alternate 00091 % colorspace. The transformation matrices are not the standard ones: the 00092 % weights are rescaled to normalized the range of the transformed values to 00093 % be [0..QuantumRange]. 00094 % 00095 % The format of the RGBTransformImage method is: 00096 % 00097 % MagickBooleanType RGBTransformImage(Image *image, 00098 % const ColorspaceType colorspace,EsceptionInfo *exception) 00099 % 00100 % A description of each parameter follows: 00101 % 00102 % o image: the image. 00103 % 00104 % o colorspace: the colorspace to transform the image to. 00105 % 00106 % o exception: return any errors or warnings in this structure. 00107 % 00108 */ 00109 00110 static inline void ConvertRGBToXYZ(const Quantum red,const Quantum green, 00111 const Quantum blue,double *X,double *Y,double *Z) 00112 { 00113 double 00114 b, 00115 g, 00116 r; 00117 00118 assert(X != (double *) NULL); 00119 assert(Y != (double *) NULL); 00120 assert(Z != (double *) NULL); 00121 r=QuantumScale*red; 00122 if (r > 0.04045) 00123 r=pow((r+0.055)/1.055,2.4); 00124 else 00125 r/=12.92; 00126 g=QuantumScale*green; 00127 if (g > 0.04045) 00128 g=pow((g+0.055)/1.055,2.4); 00129 else 00130 g/=12.92; 00131 b=QuantumScale*blue; 00132 if (b > 0.04045) 00133 b=pow((b+0.055)/1.055,2.4); 00134 else 00135 b/=12.92; 00136 *X=0.4124240*r+0.3575790*g+0.1804640*b; 00137 *Y=0.2126560*r+0.7151580*g+0.0721856*b; 00138 *Z=0.0193324*r+0.1191930*g+0.9504440*b; 00139 } 00140 00141 static double LabF1(double alpha) 00142 { 00143 00144 if (alpha <= ((24.0/116.0)*(24.0/116.0)*(24.0/116.0))) 00145 return((841.0/108.0)*alpha+(16.0/116.0)); 00146 return(pow(alpha,1.0/3.0)); 00147 } 00148 00149 static inline void ConvertXYZToLab(const double X,const double Y,const double Z, 00150 double *L,double *a,double *b) 00151 { 00152 #define D50X (0.9642) 00153 #define D50Y (1.0) 00154 #define D50Z (0.8249) 00155 00156 double 00157 fx, 00158 fy, 00159 fz; 00160 00161 assert(L != (double *) NULL); 00162 assert(a != (double *) NULL); 00163 assert(b != (double *) NULL); 00164 *L=0.0; 00165 *a=0.5; 00166 *b=0.5; 00167 if ((fabs(X) < MagickEpsilon) && (fabs(Y) < MagickEpsilon) && 00168 (fabs(Z) < MagickEpsilon)) 00169 return; 00170 fx=LabF1(X/D50X); 00171 fy=LabF1(Y/D50Y); 00172 fz=LabF1(Z/D50Z); 00173 *L=(116.0*fy-16.0)/100.0; 00174 *a=(500.0*(fx-fy))/255.0; 00175 if (*a < 0.0) 00176 *a+=1.0; 00177 *b=(200.0*(fy-fz))/255.0; 00178 if (*b < 0.0) 00179 *b+=1.0; 00180 } 00181 00182 MagickExport MagickBooleanType RGBTransformImage(Image *image, 00183 const ColorspaceType colorspace,ExceptionInfo *exception) 00184 { 00185 #define RGBTransformImageTag "RGBTransform/Image" 00186 00187 CacheView 00188 *image_view; 00189 00190 MagickBooleanType 00191 status; 00192 00193 MagickOffsetType 00194 progress; 00195 00196 PrimaryInfo 00197 primary_info; 00198 00199 register ssize_t 00200 i; 00201 00202 ssize_t 00203 y; 00204 00205 TransformPacket 00206 *x_map, 00207 *y_map, 00208 *z_map; 00209 00210 assert(image != (Image *) NULL); 00211 assert(image->signature == MagickSignature); 00212 if (image->debug != MagickFalse) 00213 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00214 assert(colorspace != RGBColorspace); 00215 assert(colorspace != TransparentColorspace); 00216 assert(colorspace != UndefinedColorspace); 00217 if (SetImageColorspace(image,colorspace,exception) == MagickFalse) 00218 return(MagickFalse); 00219 status=MagickTrue; 00220 progress=0; 00221 switch (colorspace) 00222 { 00223 case CMYColorspace: 00224 { 00225 /* 00226 Convert RGB to CMY colorspace. 00227 */ 00228 if (image->storage_class == PseudoClass) 00229 { 00230 if (SyncImage(image,exception) == MagickFalse) 00231 return(MagickFalse); 00232 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 00233 return(MagickFalse); 00234 } 00235 image_view=AcquireCacheView(image); 00236 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00237 #pragma omp parallel for schedule(static,4) shared(status) 00238 #endif 00239 for (y=0; y < (ssize_t) image->rows; y++) 00240 { 00241 MagickBooleanType 00242 sync; 00243 00244 register ssize_t 00245 x; 00246 00247 register Quantum 00248 *restrict q; 00249 00250 if (status == MagickFalse) 00251 continue; 00252 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 00253 exception); 00254 if (q == (Quantum *) NULL) 00255 { 00256 status=MagickFalse; 00257 continue; 00258 } 00259 for (x=0; x < (ssize_t) image->columns; x++) 00260 { 00261 SetPixelRed(image,ClampToQuantum((MagickRealType) (QuantumRange- 00262 GetPixelRed(image,q))),q); 00263 SetPixelGreen(image,ClampToQuantum((MagickRealType) (QuantumRange- 00264 GetPixelGreen(image,q))),q); 00265 SetPixelBlue(image,ClampToQuantum((MagickRealType) (QuantumRange- 00266 GetPixelBlue(image,q))),q); 00267 q+=GetPixelChannels(image); 00268 } 00269 sync=SyncCacheViewAuthenticPixels(image_view,exception); 00270 if (sync == MagickFalse) 00271 status=MagickFalse; 00272 } 00273 image_view=DestroyCacheView(image_view); 00274 image->type=image->matte == MagickFalse ? ColorSeparationType : 00275 ColorSeparationMatteType; 00276 return(status); 00277 } 00278 case CMYKColorspace: 00279 { 00280 PixelInfo 00281 zero; 00282 00283 /* 00284 Convert RGB to CMYK colorspace. 00285 */ 00286 if (image->storage_class == PseudoClass) 00287 { 00288 if (SyncImage(image,exception) == MagickFalse) 00289 return(MagickFalse); 00290 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 00291 return(MagickFalse); 00292 } 00293 GetPixelInfo(image,&zero); 00294 image_view=AcquireCacheView(image); 00295 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00296 #pragma omp parallel for schedule(static,4) shared(status) 00297 #endif 00298 for (y=0; y < (ssize_t) image->rows; y++) 00299 { 00300 MagickBooleanType 00301 sync; 00302 00303 PixelInfo 00304 pixel; 00305 00306 register ssize_t 00307 x; 00308 00309 register Quantum 00310 *restrict q; 00311 00312 if (status == MagickFalse) 00313 continue; 00314 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 00315 exception); 00316 if (q == (Quantum *) NULL) 00317 { 00318 status=MagickFalse; 00319 continue; 00320 } 00321 pixel=zero; 00322 for (x=0; x < (ssize_t) image->columns; x++) 00323 { 00324 GetPixelInfoPixel(image,q,&pixel); 00325 ConvertRGBToCMYK(&pixel); 00326 SetPixelInfoPixel(image,&pixel,q); 00327 q+=GetPixelChannels(image); 00328 } 00329 sync=SyncCacheViewAuthenticPixels(image_view,exception); 00330 if (sync == MagickFalse) 00331 status=MagickFalse; 00332 } 00333 image_view=DestroyCacheView(image_view); 00334 image->type=image->matte == MagickFalse ? ColorSeparationType : 00335 ColorSeparationMatteType; 00336 return(status); 00337 } 00338 case HSBColorspace: 00339 { 00340 /* 00341 Transform image from RGB to HSB. 00342 */ 00343 if (image->storage_class == PseudoClass) 00344 { 00345 if (SyncImage(image,exception) == MagickFalse) 00346 return(MagickFalse); 00347 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 00348 return(MagickFalse); 00349 } 00350 image_view=AcquireCacheView(image); 00351 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00352 #pragma omp parallel for schedule(static,4) shared(status) 00353 #endif 00354 for (y=0; y < (ssize_t) image->rows; y++) 00355 { 00356 double 00357 brightness, 00358 hue, 00359 saturation; 00360 00361 MagickBooleanType 00362 sync; 00363 00364 register ssize_t 00365 x; 00366 00367 register Quantum 00368 *restrict q; 00369 00370 if (status == MagickFalse) 00371 continue; 00372 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 00373 exception); 00374 if (q == (Quantum *) NULL) 00375 { 00376 status=MagickFalse; 00377 continue; 00378 } 00379 hue=0.0; 00380 saturation=0.0; 00381 brightness=0.0; 00382 for (x=0; x < (ssize_t) image->columns; x++) 00383 { 00384 ConvertRGBToHSB((double) GetPixelRed(image,q), 00385 (double) GetPixelGreen(image,q),(double) GetPixelBlue(image,q), 00386 &hue,&saturation,&brightness); 00387 SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange* 00388 hue),q); 00389 SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange* 00390 saturation),q); 00391 SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange* 00392 brightness),q); 00393 q+=GetPixelChannels(image); 00394 } 00395 sync=SyncCacheViewAuthenticPixels(image_view,exception); 00396 if (sync == MagickFalse) 00397 status=MagickFalse; 00398 } 00399 image_view=DestroyCacheView(image_view); 00400 return(status); 00401 } 00402 case HSLColorspace: 00403 { 00404 /* 00405 Transform image from RGB to HSL. 00406 */ 00407 if (image->storage_class == PseudoClass) 00408 { 00409 if (SyncImage(image,exception) == MagickFalse) 00410 return(MagickFalse); 00411 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 00412 return(MagickFalse); 00413 } 00414 image_view=AcquireCacheView(image); 00415 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00416 #pragma omp parallel for schedule(static,4) shared(status) 00417 #endif 00418 for (y=0; y < (ssize_t) image->rows; y++) 00419 { 00420 double 00421 hue, 00422 lightness, 00423 saturation; 00424 00425 MagickBooleanType 00426 sync; 00427 00428 register ssize_t 00429 x; 00430 00431 register Quantum 00432 *restrict q; 00433 00434 if (status == MagickFalse) 00435 continue; 00436 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 00437 exception); 00438 if (q == (Quantum *) NULL) 00439 { 00440 status=MagickFalse; 00441 continue; 00442 } 00443 hue=0.0; 00444 saturation=0.0; 00445 lightness=0.0; 00446 for (x=0; x < (ssize_t) image->columns; x++) 00447 { 00448 ConvertRGBToHSL((double) GetPixelRed(image,q),(double) 00449 GetPixelGreen(image,q),(double) GetPixelBlue(image,q), 00450 &hue,&saturation,&lightness); 00451 SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange* 00452 hue),q); 00453 SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange* 00454 saturation),q); 00455 SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange* 00456 lightness),q); 00457 q+=GetPixelChannels(image); 00458 } 00459 sync=SyncCacheViewAuthenticPixels(image_view,exception); 00460 if (sync == MagickFalse) 00461 status=MagickFalse; 00462 } 00463 image_view=DestroyCacheView(image_view); 00464 return(status); 00465 } 00466 case HWBColorspace: 00467 { 00468 /* 00469 Transform image from RGB to HWB. 00470 */ 00471 if (image->storage_class == PseudoClass) 00472 { 00473 if (SyncImage(image,exception) == MagickFalse) 00474 return(MagickFalse); 00475 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 00476 return(MagickFalse); 00477 } 00478 image_view=AcquireCacheView(image); 00479 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00480 #pragma omp parallel for schedule(static,4) shared(status) 00481 #endif 00482 for (y=0; y < (ssize_t) image->rows; y++) 00483 { 00484 double 00485 blackness, 00486 hue, 00487 whiteness; 00488 00489 MagickBooleanType 00490 sync; 00491 00492 register ssize_t 00493 x; 00494 00495 register Quantum 00496 *restrict q; 00497 00498 if (status == MagickFalse) 00499 continue; 00500 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 00501 exception); 00502 if (q == (Quantum *) NULL) 00503 { 00504 status=MagickFalse; 00505 continue; 00506 } 00507 hue=0.0; 00508 whiteness=0.0; 00509 blackness=0.0; 00510 for (x=0; x < (ssize_t) image->columns; x++) 00511 { 00512 ConvertRGBToHWB((double) GetPixelRed(image,q),(double) 00513 GetPixelGreen(image,q),(double) GetPixelBlue(image,q), 00514 &hue,&whiteness,&blackness); 00515 SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange* 00516 hue),q); 00517 SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange* 00518 whiteness),q); 00519 SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange* 00520 blackness),q); 00521 q+=GetPixelChannels(image); 00522 } 00523 sync=SyncCacheViewAuthenticPixels(image_view,exception); 00524 if (sync == MagickFalse) 00525 status=MagickFalse; 00526 } 00527 image_view=DestroyCacheView(image_view); 00528 return(status); 00529 } 00530 case LabColorspace: 00531 { 00532 /* 00533 Transform image from RGB to Lab. 00534 */ 00535 if (image->storage_class == PseudoClass) 00536 { 00537 if (SyncImage(image,exception) == MagickFalse) 00538 return(MagickFalse); 00539 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 00540 return(MagickFalse); 00541 } 00542 image_view=AcquireCacheView(image); 00543 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00544 #pragma omp parallel for schedule(static,4) shared(status) 00545 #endif 00546 for (y=0; y < (ssize_t) image->rows; y++) 00547 { 00548 double 00549 a, 00550 b, 00551 L, 00552 X, 00553 Y, 00554 Z; 00555 00556 MagickBooleanType 00557 sync; 00558 00559 register ssize_t 00560 x; 00561 00562 register Quantum 00563 *restrict q; 00564 00565 if (status == MagickFalse) 00566 continue; 00567 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 00568 exception); 00569 if (q == (Quantum *) NULL) 00570 { 00571 status=MagickFalse; 00572 continue; 00573 } 00574 L=0.0; 00575 a=0.0; 00576 b=0.0; 00577 X=0.0; 00578 Y=0.0; 00579 Z=0.0; 00580 for (x=0; x < (ssize_t) image->columns; x++) 00581 { 00582 ConvertRGBToXYZ(GetPixelRed(image,q),GetPixelGreen(image,q), 00583 GetPixelBlue(image,q),&X,&Y,&Z); 00584 ConvertXYZToLab(X,Y,Z,&L,&a,&b); 00585 SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange* 00586 L),q); 00587 SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange* 00588 a),q); 00589 SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange* 00590 b),q); 00591 q+=GetPixelChannels(image); 00592 } 00593 sync=SyncCacheViewAuthenticPixels(image_view,exception); 00594 if (sync == MagickFalse) 00595 status=MagickFalse; 00596 } 00597 image_view=DestroyCacheView(image_view); 00598 return(status); 00599 } 00600 case LogColorspace: 00601 { 00602 #define DisplayGamma (1.0/1.7) 00603 #define FilmGamma 0.6 00604 #define ReferenceBlack 95.0 00605 #define ReferenceWhite 685.0 00606 00607 const char 00608 *value; 00609 00610 double 00611 black, 00612 density, 00613 film_gamma, 00614 gamma, 00615 reference_black, 00616 reference_white; 00617 00618 Quantum 00619 *logmap; 00620 00621 /* 00622 Transform RGB to Log colorspace. 00623 */ 00624 density=DisplayGamma; 00625 gamma=DisplayGamma; 00626 value=GetImageProperty(image,"gamma",exception); 00627 if (value != (const char *) NULL) 00628 gamma=1.0/fabs(StringToDouble(value,(char **) NULL)) >= MagickEpsilon ? 00629 StringToDouble(value,(char **) NULL) : 1.0; 00630 film_gamma=FilmGamma; 00631 value=GetImageProperty(image,"film-gamma",exception); 00632 if (value != (const char *) NULL) 00633 film_gamma=StringToDouble(value,(char **) NULL); 00634 reference_black=ReferenceBlack; 00635 value=GetImageProperty(image,"reference-black",exception); 00636 if (value != (const char *) NULL) 00637 reference_black=StringToDouble(value,(char **) NULL); 00638 reference_white=ReferenceWhite; 00639 value=GetImageProperty(image,"reference-white",exception); 00640 if (value != (const char *) NULL) 00641 reference_white=StringToDouble(value,(char **) NULL); 00642 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL, 00643 sizeof(*logmap)); 00644 if (logmap == (Quantum *) NULL) 00645 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00646 image->filename); 00647 black=pow(10.0,(reference_black-reference_white)*(gamma/density)* 00648 0.002/film_gamma); 00649 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00650 #pragma omp parallel for schedule(static) 00651 #endif 00652 for (i=0; i <= (ssize_t) MaxMap; i++) 00653 logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+ 00654 log10(black+((MagickRealType) i/MaxMap)*(1.0-black))/((gamma/density)* 00655 0.002/film_gamma))/1024.0)); 00656 image_view=AcquireCacheView(image); 00657 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00658 #pragma omp parallel for schedule(static,4) shared(status) 00659 #endif 00660 for (y=0; y < (ssize_t) image->rows; y++) 00661 { 00662 MagickBooleanType 00663 sync; 00664 00665 register ssize_t 00666 x; 00667 00668 register Quantum 00669 *restrict q; 00670 00671 if (status == MagickFalse) 00672 continue; 00673 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 00674 exception); 00675 if (q == (Quantum *) NULL) 00676 { 00677 status=MagickFalse; 00678 continue; 00679 } 00680 for (x=(ssize_t) image->columns; x != 0; x--) 00681 { 00682 SetPixelRed(image,logmap[ScaleQuantumToMap( 00683 GetPixelRed(image,q))],q); 00684 SetPixelGreen(image,logmap[ScaleQuantumToMap( 00685 GetPixelGreen(image,q))],q); 00686 SetPixelBlue(image,logmap[ScaleQuantumToMap( 00687 GetPixelBlue(image,q))],q); 00688 q+=GetPixelChannels(image); 00689 } 00690 sync=SyncCacheViewAuthenticPixels(image_view,exception); 00691 if (sync == MagickFalse) 00692 status=MagickFalse; 00693 } 00694 image_view=DestroyCacheView(image_view); 00695 logmap=(Quantum *) RelinquishMagickMemory(logmap); 00696 return(status); 00697 } 00698 default: 00699 break; 00700 } 00701 /* 00702 Allocate the tables. 00703 */ 00704 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL, 00705 sizeof(*x_map)); 00706 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL, 00707 sizeof(*y_map)); 00708 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL, 00709 sizeof(*z_map)); 00710 if ((x_map == (TransformPacket *) NULL) || 00711 (y_map == (TransformPacket *) NULL) || 00712 (z_map == (TransformPacket *) NULL)) 00713 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 00714 image->filename); 00715 (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info)); 00716 switch (colorspace) 00717 { 00718 case OHTAColorspace: 00719 { 00720 /* 00721 Initialize OHTA tables: 00722 00723 I1 = 0.33333*R+0.33334*G+0.33333*B 00724 I2 = 0.50000*R+0.00000*G-0.50000*B 00725 I3 =-0.25000*R+0.50000*G-0.25000*B 00726 00727 I and Q, normally -0.5 through 0.5, are normalized to the range 0 00728 through QuantumRange. 00729 */ 00730 primary_info.y=(double) (MaxMap+1.0)/2.0; 00731 primary_info.z=(double) (MaxMap+1.0)/2.0; 00732 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00733 #pragma omp parallel for schedule(static) 00734 #endif 00735 for (i=0; i <= (ssize_t) MaxMap; i++) 00736 { 00737 x_map[i].x=0.33333f*(MagickRealType) i; 00738 y_map[i].x=0.33334f*(MagickRealType) i; 00739 z_map[i].x=0.33333f*(MagickRealType) i; 00740 x_map[i].y=0.50000f*(MagickRealType) i; 00741 y_map[i].y=0.00000f*(MagickRealType) i; 00742 z_map[i].y=(-0.50000f)*(MagickRealType) i; 00743 x_map[i].z=(-0.25000f)*(MagickRealType) i; 00744 y_map[i].z=0.50000f*(MagickRealType) i; 00745 z_map[i].z=(-0.25000f)*(MagickRealType) i; 00746 } 00747 break; 00748 } 00749 case Rec601LumaColorspace: 00750 case GRAYColorspace: 00751 { 00752 /* 00753 Initialize Rec601 luma tables: 00754 00755 G = 0.29900*R+0.58700*G+0.11400*B 00756 */ 00757 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00758 #pragma omp parallel for schedule(static) 00759 #endif 00760 for (i=0; i <= (ssize_t) MaxMap; i++) 00761 { 00762 x_map[i].x=0.29900f*(MagickRealType) i; 00763 y_map[i].x=0.58700f*(MagickRealType) i; 00764 z_map[i].x=0.11400f*(MagickRealType) i; 00765 x_map[i].y=0.29900f*(MagickRealType) i; 00766 y_map[i].y=0.58700f*(MagickRealType) i; 00767 z_map[i].y=0.11400f*(MagickRealType) i; 00768 x_map[i].z=0.29900f*(MagickRealType) i; 00769 y_map[i].z=0.58700f*(MagickRealType) i; 00770 z_map[i].z=0.11400f*(MagickRealType) i; 00771 } 00772 image->type=GrayscaleType; 00773 break; 00774 } 00775 case Rec601YCbCrColorspace: 00776 case YCbCrColorspace: 00777 { 00778 /* 00779 Initialize YCbCr tables (ITU-R BT.601): 00780 00781 Y = 0.299000*R+0.587000*G+0.114000*B 00782 Cb= -0.168736*R-0.331264*G+0.500000*B 00783 Cr= 0.500000*R-0.418688*G-0.081312*B 00784 00785 Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0 00786 through QuantumRange. 00787 */ 00788 primary_info.y=(double) (MaxMap+1.0)/2.0; 00789 primary_info.z=(double) (MaxMap+1.0)/2.0; 00790 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00791 #pragma omp parallel for schedule(static) 00792 #endif 00793 for (i=0; i <= (ssize_t) MaxMap; i++) 00794 { 00795 x_map[i].x=0.299000f*(MagickRealType) i; 00796 y_map[i].x=0.587000f*(MagickRealType) i; 00797 z_map[i].x=0.114000f*(MagickRealType) i; 00798 x_map[i].y=(-0.168730f)*(MagickRealType) i; 00799 y_map[i].y=(-0.331264f)*(MagickRealType) i; 00800 z_map[i].y=0.500000f*(MagickRealType) i; 00801 x_map[i].z=0.500000f*(MagickRealType) i; 00802 y_map[i].z=(-0.418688f)*(MagickRealType) i; 00803 z_map[i].z=(-0.081312f)*(MagickRealType) i; 00804 } 00805 break; 00806 } 00807 case Rec709LumaColorspace: 00808 { 00809 /* 00810 Initialize Rec709 luma tables: 00811 00812 G = 0.21260*R+0.71520*G+0.07220*B 00813 */ 00814 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00815 #pragma omp parallel for schedule(static) 00816 #endif 00817 for (i=0; i <= (ssize_t) MaxMap; i++) 00818 { 00819 x_map[i].x=0.21260f*(MagickRealType) i; 00820 y_map[i].x=0.71520f*(MagickRealType) i; 00821 z_map[i].x=0.07220f*(MagickRealType) i; 00822 x_map[i].y=0.21260f*(MagickRealType) i; 00823 y_map[i].y=0.71520f*(MagickRealType) i; 00824 z_map[i].y=0.07220f*(MagickRealType) i; 00825 x_map[i].z=0.21260f*(MagickRealType) i; 00826 y_map[i].z=0.71520f*(MagickRealType) i; 00827 z_map[i].z=0.07220f*(MagickRealType) i; 00828 } 00829 break; 00830 } 00831 case Rec709YCbCrColorspace: 00832 { 00833 /* 00834 Initialize YCbCr tables (ITU-R BT.709): 00835 00836 Y = 0.212600*R+0.715200*G+0.072200*B 00837 Cb= -0.114572*R-0.385428*G+0.500000*B 00838 Cr= 0.500000*R-0.454153*G-0.045847*B 00839 00840 Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0 00841 through QuantumRange. 00842 */ 00843 primary_info.y=(double) (MaxMap+1.0)/2.0; 00844 primary_info.z=(double) (MaxMap+1.0)/2.0; 00845 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00846 #pragma omp parallel for schedule(static) 00847 #endif 00848 for (i=0; i <= (ssize_t) MaxMap; i++) 00849 { 00850 x_map[i].x=0.212600f*(MagickRealType) i; 00851 y_map[i].x=0.715200f*(MagickRealType) i; 00852 z_map[i].x=0.072200f*(MagickRealType) i; 00853 x_map[i].y=(-0.114572f)*(MagickRealType) i; 00854 y_map[i].y=(-0.385428f)*(MagickRealType) i; 00855 z_map[i].y=0.500000f*(MagickRealType) i; 00856 x_map[i].z=0.500000f*(MagickRealType) i; 00857 y_map[i].z=(-0.454153f)*(MagickRealType) i; 00858 z_map[i].z=(-0.045847f)*(MagickRealType) i; 00859 } 00860 break; 00861 } 00862 case sRGBColorspace: 00863 { 00864 /* 00865 Nonlinear sRGB to linear RGB (http://www.w3.org/Graphics/Color/sRGB): 00866 00867 R = 1.0*R+0.0*G+0.0*B 00868 G = 0.0*R+1.0*G+0.0*B 00869 B = 0.0*R+0.0*G+1.0*B 00870 */ 00871 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00872 #pragma omp parallel for schedule(static) 00873 #endif 00874 for (i=0; i <= (ssize_t) MaxMap; i++) 00875 { 00876 MagickRealType 00877 v; 00878 00879 v=(MagickRealType) i/(MagickRealType) MaxMap; 00880 if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.0031308) 00881 v*=12.92f; 00882 else 00883 v=(MagickRealType) (1.055*pow((double) i/MaxMap,1.0/2.4)-0.055); 00884 x_map[i].x=1.0f*MaxMap*v; 00885 y_map[i].x=0.0f*MaxMap*v; 00886 z_map[i].x=0.0f*MaxMap*v; 00887 x_map[i].y=0.0f*MaxMap*v; 00888 y_map[i].y=1.0f*MaxMap*v; 00889 z_map[i].y=0.0f*MaxMap*v; 00890 x_map[i].z=0.0f*MaxMap*v; 00891 y_map[i].z=0.0f*MaxMap*v; 00892 z_map[i].z=1.0f*MaxMap*v; 00893 } 00894 break; 00895 } 00896 case XYZColorspace: 00897 { 00898 /* 00899 Initialize CIE XYZ tables (ITU-R 709 RGB): 00900 00901 X = 0.4124564*R+0.3575761*G+0.1804375*B 00902 Y = 0.2126729*R+0.7151522*G+0.0721750*B 00903 Z = 0.0193339*R+0.1191920*G+0.9503041*B 00904 */ 00905 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00906 #pragma omp parallel for schedule(static) 00907 #endif 00908 for (i=0; i <= (ssize_t) MaxMap; i++) 00909 { 00910 x_map[i].x=0.4124564f*(MagickRealType) i; 00911 y_map[i].x=0.3575761f*(MagickRealType) i; 00912 z_map[i].x=0.1804375f*(MagickRealType) i; 00913 x_map[i].y=0.2126729f*(MagickRealType) i; 00914 y_map[i].y=0.7151522f*(MagickRealType) i; 00915 z_map[i].y=0.0721750f*(MagickRealType) i; 00916 x_map[i].z=0.0193339f*(MagickRealType) i; 00917 y_map[i].z=0.1191920f*(MagickRealType) i; 00918 z_map[i].z=0.9503041f*(MagickRealType) i; 00919 } 00920 break; 00921 } 00922 case YCCColorspace: 00923 { 00924 /* 00925 Initialize YCC tables: 00926 00927 Y = 0.29900*R+0.58700*G+0.11400*B 00928 C1= -0.29900*R-0.58700*G+0.88600*B 00929 C2= 0.70100*R-0.58700*G-0.11400*B 00930 00931 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137. 00932 */ 00933 primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156)); 00934 primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137)); 00935 for (i=0; i <= (ssize_t) (0.018*MaxMap); i++) 00936 { 00937 x_map[i].x=0.003962014134275617f*(MagickRealType) i; 00938 y_map[i].x=0.007778268551236748f*(MagickRealType) i; 00939 z_map[i].x=0.001510600706713781f*(MagickRealType) i; 00940 x_map[i].y=(-0.002426619775463276f)*(MagickRealType) i; 00941 y_map[i].y=(-0.004763965913702149f)*(MagickRealType) i; 00942 z_map[i].y=0.007190585689165425f*(MagickRealType) i; 00943 x_map[i].z=0.006927257754597858f*(MagickRealType) i; 00944 y_map[i].z=(-0.005800713697502058f)*(MagickRealType) i; 00945 z_map[i].z=(-0.0011265440570958f)*(MagickRealType) i; 00946 } 00947 for ( ; i <= (ssize_t) MaxMap; i++) 00948 { 00949 x_map[i].x=0.2201118963486454*(1.099f*(MagickRealType) i-0.099f); 00950 y_map[i].x=0.4321260306242638*(1.099f*(MagickRealType) i-0.099f); 00951 z_map[i].x=0.08392226148409894*(1.099f*(MagickRealType) i-0.099f); 00952 x_map[i].y=(-0.1348122097479598)*(1.099f*(MagickRealType) i-0.099f); 00953 y_map[i].y=(-0.2646647729834528)*(1.099f*(MagickRealType) i-0.099f); 00954 z_map[i].y=0.3994769827314126*(1.099f*(MagickRealType) i-0.099f); 00955 x_map[i].z=0.3848476530332144*(1.099f*(MagickRealType) i-0.099f); 00956 y_map[i].z=(-0.3222618720834477)*(1.099f*(MagickRealType) i-0.099f); 00957 z_map[i].z=(-0.06258578094976668)*(1.099f*(MagickRealType) i-0.099f); 00958 } 00959 break; 00960 } 00961 case YIQColorspace: 00962 { 00963 /* 00964 Initialize YIQ tables: 00965 00966 Y = 0.29900*R+0.58700*G+0.11400*B 00967 I = 0.59600*R-0.27400*G-0.32200*B 00968 Q = 0.21100*R-0.52300*G+0.31200*B 00969 00970 I and Q, normally -0.5 through 0.5, are normalized to the range 0 00971 through QuantumRange. 00972 */ 00973 primary_info.y=(double) (MaxMap+1.0)/2.0; 00974 primary_info.z=(double) (MaxMap+1.0)/2.0; 00975 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00976 #pragma omp parallel for schedule(static) 00977 #endif 00978 for (i=0; i <= (ssize_t) MaxMap; i++) 00979 { 00980 x_map[i].x=0.29900f*(MagickRealType) i; 00981 y_map[i].x=0.58700f*(MagickRealType) i; 00982 z_map[i].x=0.11400f*(MagickRealType) i; 00983 x_map[i].y=0.59600f*(MagickRealType) i; 00984 y_map[i].y=(-0.27400f)*(MagickRealType) i; 00985 z_map[i].y=(-0.32200f)*(MagickRealType) i; 00986 x_map[i].z=0.21100f*(MagickRealType) i; 00987 y_map[i].z=(-0.52300f)*(MagickRealType) i; 00988 z_map[i].z=0.31200f*(MagickRealType) i; 00989 } 00990 break; 00991 } 00992 case YPbPrColorspace: 00993 { 00994 /* 00995 Initialize YPbPr tables (ITU-R BT.601): 00996 00997 Y = 0.299000*R+0.587000*G+0.114000*B 00998 Pb= -0.168736*R-0.331264*G+0.500000*B 00999 Pr= 0.500000*R-0.418688*G-0.081312*B 01000 01001 Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0 01002 through QuantumRange. 01003 */ 01004 primary_info.y=(double) (MaxMap+1.0)/2.0; 01005 primary_info.z=(double) (MaxMap+1.0)/2.0; 01006 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01007 #pragma omp parallel for schedule(static) 01008 #endif 01009 for (i=0; i <= (ssize_t) MaxMap; i++) 01010 { 01011 x_map[i].x=0.299000f*(MagickRealType) i; 01012 y_map[i].x=0.587000f*(MagickRealType) i; 01013 z_map[i].x=0.114000f*(MagickRealType) i; 01014 x_map[i].y=(-0.168736f)*(MagickRealType) i; 01015 y_map[i].y=(-0.331264f)*(MagickRealType) i; 01016 z_map[i].y=0.500000f*(MagickRealType) i; 01017 x_map[i].z=0.500000f*(MagickRealType) i; 01018 y_map[i].z=(-0.418688f)*(MagickRealType) i; 01019 z_map[i].z=(-0.081312f)*(MagickRealType) i; 01020 } 01021 break; 01022 } 01023 case YUVColorspace: 01024 default: 01025 { 01026 /* 01027 Initialize YUV tables: 01028 01029 Y = 0.29900*R+0.58700*G+0.11400*B 01030 U = -0.14740*R-0.28950*G+0.43690*B 01031 V = 0.61500*R-0.51500*G-0.10000*B 01032 01033 U and V, normally -0.5 through 0.5, are normalized to the range 0 01034 through QuantumRange. Note that U = 0.493*(B-Y), V = 0.877*(R-Y). 01035 */ 01036 primary_info.y=(double) (MaxMap+1.0)/2.0; 01037 primary_info.z=(double) (MaxMap+1.0)/2.0; 01038 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01039 #pragma omp parallel for schedule(static) 01040 #endif 01041 for (i=0; i <= (ssize_t) MaxMap; i++) 01042 { 01043 x_map[i].x=0.29900f*(MagickRealType) i; 01044 y_map[i].x=0.58700f*(MagickRealType) i; 01045 z_map[i].x=0.11400f*(MagickRealType) i; 01046 x_map[i].y=(-0.14740f)*(MagickRealType) i; 01047 y_map[i].y=(-0.28950f)*(MagickRealType) i; 01048 z_map[i].y=0.43690f*(MagickRealType) i; 01049 x_map[i].z=0.61500f*(MagickRealType) i; 01050 y_map[i].z=(-0.51500f)*(MagickRealType) i; 01051 z_map[i].z=(-0.10000f)*(MagickRealType) i; 01052 } 01053 break; 01054 } 01055 } 01056 /* 01057 Convert from RGB. 01058 */ 01059 switch (image->storage_class) 01060 { 01061 case DirectClass: 01062 default: 01063 { 01064 /* 01065 Convert DirectClass image. 01066 */ 01067 image_view=AcquireCacheView(image); 01068 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01069 #pragma omp parallel for schedule(static,4) shared(status) 01070 #endif 01071 for (y=0; y < (ssize_t) image->rows; y++) 01072 { 01073 MagickBooleanType 01074 sync; 01075 01076 PixelInfo 01077 pixel; 01078 01079 register Quantum 01080 *restrict q; 01081 01082 register ssize_t 01083 x; 01084 01085 register unsigned int 01086 blue, 01087 green, 01088 red; 01089 01090 if (status == MagickFalse) 01091 continue; 01092 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 01093 exception); 01094 if (q == (Quantum *) NULL) 01095 { 01096 status=MagickFalse; 01097 continue; 01098 } 01099 for (x=0; x < (ssize_t) image->columns; x++) 01100 { 01101 red=ScaleQuantumToMap(GetPixelRed(image,q)); 01102 green=ScaleQuantumToMap(GetPixelGreen(image,q)); 01103 blue=ScaleQuantumToMap(GetPixelBlue(image,q)); 01104 pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+ 01105 (MagickRealType) primary_info.x; 01106 pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+ 01107 (MagickRealType) primary_info.y; 01108 pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+ 01109 (MagickRealType) primary_info.z; 01110 SetPixelRed(image,ScaleMapToQuantum(pixel.red),q); 01111 SetPixelGreen(image,ScaleMapToQuantum(pixel.green),q); 01112 SetPixelBlue(image,ScaleMapToQuantum(pixel.blue),q); 01113 q+=GetPixelChannels(image); 01114 } 01115 sync=SyncCacheViewAuthenticPixels(image_view,exception); 01116 if (sync == MagickFalse) 01117 status=MagickFalse; 01118 if (image->progress_monitor != (MagickProgressMonitor) NULL) 01119 { 01120 MagickBooleanType 01121 proceed; 01122 01123 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01124 #pragma omp critical (MagickCore_RGBTransformImage) 01125 #endif 01126 proceed=SetImageProgress(image,RGBTransformImageTag,progress++, 01127 image->rows); 01128 if (proceed == MagickFalse) 01129 status=MagickFalse; 01130 } 01131 } 01132 image_view=DestroyCacheView(image_view); 01133 break; 01134 } 01135 case PseudoClass: 01136 { 01137 register unsigned int 01138 blue, 01139 green, 01140 red; 01141 01142 /* 01143 Convert PseudoClass image. 01144 */ 01145 for (i=0; i < (ssize_t) image->colors; i++) 01146 { 01147 PixelInfo 01148 pixel; 01149 01150 red=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red)); 01151 green=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green)); 01152 blue=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue)); 01153 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x; 01154 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y; 01155 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z; 01156 image->colormap[i].red=(double) ScaleMapToQuantum(pixel.red); 01157 image->colormap[i].green=(double) ScaleMapToQuantum(pixel.green); 01158 image->colormap[i].blue=(double) ScaleMapToQuantum(pixel.blue); 01159 } 01160 (void) SyncImage(image,exception); 01161 break; 01162 } 01163 } 01164 /* 01165 Relinquish resources. 01166 */ 01167 z_map=(TransformPacket *) RelinquishMagickMemory(z_map); 01168 y_map=(TransformPacket *) RelinquishMagickMemory(y_map); 01169 x_map=(TransformPacket *) RelinquishMagickMemory(x_map); 01170 if (SetImageColorspace(image,colorspace,exception) == MagickFalse) 01171 return(MagickFalse); 01172 return(status); 01173 } 01174 01175 /* 01176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01177 % % 01178 % % 01179 % % 01180 % S e t I m a g e C o l o r s p a c e % 01181 % % 01182 % % 01183 % % 01184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01185 % 01186 % SetImageColorspace() sets the colorspace member of the Image structure. 01187 % 01188 % The format of the SetImageColorspace method is: 01189 % 01190 % MagickBooleanType SetImageColorspace(Image *image, 01191 % const ColorspaceType colorspace,ExceptiionInfo *exception) 01192 % 01193 % A description of each parameter follows: 01194 % 01195 % o image: the image. 01196 % 01197 % o colorspace: the colorspace. 01198 % 01199 % o exception: return any errors or warnings in this structure. 01200 % 01201 */ 01202 MagickExport MagickBooleanType SetImageColorspace(Image *image, 01203 const ColorspaceType colorspace,ExceptionInfo *exception) 01204 { 01205 image->colorspace=colorspace; 01206 return(SyncImagePixelCache(image,exception)); 01207 } 01208 01209 /* 01210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01211 % % 01212 % % 01213 % % 01214 % T r a n s f o r m I m a g e C o l o r s p a c e % 01215 % % 01216 % % 01217 % % 01218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01219 % 01220 % TransformImageColorspace() transforms an image colorspace. 01221 % 01222 % The format of the TransformImageColorspace method is: 01223 % 01224 % MagickBooleanType TransformImageColorspace(Image *image, 01225 % const ColorspaceType colorspace,ExceptionInfo *exception) 01226 % 01227 % A description of each parameter follows: 01228 % 01229 % o image: the image. 01230 % 01231 % o colorspace: the colorspace. 01232 % 01233 % o exception: return any errors or warnings in this structure. 01234 % 01235 */ 01236 MagickExport MagickBooleanType TransformImageColorspace(Image *image, 01237 const ColorspaceType colorspace,ExceptionInfo *exception) 01238 { 01239 MagickBooleanType 01240 status; 01241 01242 assert(image != (Image *) NULL); 01243 assert(image->signature == MagickSignature); 01244 if (image->debug != MagickFalse) 01245 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01246 if (colorspace == UndefinedColorspace) 01247 return(SetImageColorspace(image,colorspace,exception)); 01248 if (image->colorspace == colorspace) 01249 return(MagickTrue); /* same colorspace: no op */ 01250 /* 01251 Convert the reference image from an alternate colorspace to RGB. 01252 */ 01253 if ((colorspace == RGBColorspace) || (colorspace == TransparentColorspace)) 01254 return(TransformRGBImage(image,colorspace,exception)); 01255 status=MagickTrue; 01256 if (IsRGBColorspace(image->colorspace) == MagickFalse) 01257 status=TransformRGBImage(image,image->colorspace,exception); 01258 /* 01259 Convert the reference image from RGB to an alternate colorspace. 01260 */ 01261 if (RGBTransformImage(image,colorspace,exception) == MagickFalse) 01262 status=MagickFalse; 01263 return(status); 01264 } 01265 01266 /* 01267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01268 % % 01269 % % 01270 % % 01271 + T r a n s f o r m R G B I m a g e % 01272 % % 01273 % % 01274 % % 01275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01276 % 01277 % TransformRGBImage() converts the reference image from an alternate 01278 % colorspace to RGB. The transformation matrices are not the standard ones: 01279 % the weights are rescaled to normalize the range of the transformed values to 01280 % be [0..QuantumRange]. 01281 % 01282 % The format of the TransformRGBImage method is: 01283 % 01284 % MagickBooleanType TransformRGBImage(Image *image, 01285 % const ColorspaceType colorspace,ExceptionInfo *exception) 01286 % 01287 % A description of each parameter follows: 01288 % 01289 % o image: the image. 01290 % 01291 % o colorspace: the colorspace to transform the image to. 01292 % 01293 % o exception: return any errors or warnings in this structure. 01294 % 01295 */ 01296 01297 static double LabF2(double alpha) 01298 { 01299 double 01300 beta; 01301 01302 if (alpha > (24.0/116.0)) 01303 return(alpha*alpha*alpha); 01304 beta=(108.0/841.0)*(alpha-(16.0/116.0)); 01305 if (beta > 0.0) 01306 return(beta); 01307 return(0.0); 01308 } 01309 01310 static inline void ConvertLabToXYZ(const double L,const double a,const double b, 01311 double *X,double *Y,double *Z) 01312 { 01313 01314 double 01315 x, 01316 y, 01317 z; 01318 01319 assert(X != (double *) NULL); 01320 assert(Y != (double *) NULL); 01321 assert(Z != (double *) NULL); 01322 *X=0.0; 01323 *Y=0.0; 01324 *Z=0.0; 01325 if (L <= 0.0) 01326 return; 01327 y=(100.0*L+16.0)/116.0; 01328 x=y+255.0*0.002*(a > 0.5 ? a-1.0 : a); 01329 z=y-255.0*0.005*(b > 0.5 ? b-1.0 : b); 01330 *X=D50X*LabF2(x); 01331 *Y=D50Y*LabF2(y); 01332 *Z=D50Z*LabF2(z); 01333 } 01334 01335 static inline ssize_t RoundToYCC(const MagickRealType value) 01336 { 01337 if (value <= 0.0) 01338 return(0); 01339 if (value >= 1388.0) 01340 return(1388); 01341 return((ssize_t) (value+0.5)); 01342 } 01343 01344 static inline void ConvertXYZToRGB(const double x,const double y,const double z, 01345 Quantum *red,Quantum *green,Quantum *blue) 01346 { 01347 double 01348 b, 01349 g, 01350 r; 01351 01352 /* 01353 Convert XYZ to RGB colorspace. 01354 */ 01355 assert(red != (Quantum *) NULL); 01356 assert(green != (Quantum *) NULL); 01357 assert(blue != (Quantum *) NULL); 01358 r=3.2404542*x-1.5371385*y-0.4985314*z; 01359 g=(-0.9692660*x+1.8760108*y+0.0415560*z); 01360 b=0.0556434*x-0.2040259*y+1.0572252*z; 01361 if (r > 0.0031308) 01362 r=1.055*pow(r,1.0/2.4)-0.055; 01363 else 01364 r*=12.92; 01365 if (g > 0.0031308) 01366 g=1.055*pow(g,1.0/2.4)-0.055; 01367 else 01368 g*=12.92; 01369 if (b > 0.0031308) 01370 b=1.055*pow(b,1.0/2.4)-0.055; 01371 else 01372 b*=12.92; 01373 *red=RoundToQuantum((MagickRealType) QuantumRange*r); 01374 *green=RoundToQuantum((MagickRealType) QuantumRange*g); 01375 *blue=RoundToQuantum((MagickRealType) QuantumRange*b); 01376 } 01377 01378 static inline void ConvertCMYKToRGB(PixelInfo *pixel) 01379 { 01380 pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red* 01381 (QuantumRange-pixel->black)+pixel->black); 01382 pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green* 01383 (QuantumRange-pixel->black)+pixel->black); 01384 pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue* 01385 (QuantumRange-pixel->black)+pixel->black); 01386 } 01387 01388 MagickExport MagickBooleanType TransformRGBImage(Image *image, 01389 const ColorspaceType colorspace,ExceptionInfo *exception) 01390 { 01391 #define D50X (0.9642) 01392 #define D50Y (1.0) 01393 #define D50Z (0.8249) 01394 #define TransformRGBImageTag "Transform/Image" 01395 01396 #if !defined(MAGICKCORE_HDRI_SUPPORT) 01397 static const float 01398 YCCMap[1389] = 01399 { 01400 0.000000f, 0.000720f, 0.001441f, 0.002161f, 0.002882f, 0.003602f, 01401 0.004323f, 0.005043f, 0.005764f, 0.006484f, 0.007205f, 0.007925f, 01402 0.008646f, 0.009366f, 0.010086f, 0.010807f, 0.011527f, 0.012248f, 01403 0.012968f, 0.013689f, 0.014409f, 0.015130f, 0.015850f, 0.016571f, 01404 0.017291f, 0.018012f, 0.018732f, 0.019452f, 0.020173f, 0.020893f, 01405 0.021614f, 0.022334f, 0.023055f, 0.023775f, 0.024496f, 0.025216f, 01406 0.025937f, 0.026657f, 0.027378f, 0.028098f, 0.028818f, 0.029539f, 01407 0.030259f, 0.030980f, 0.031700f, 0.032421f, 0.033141f, 0.033862f, 01408 0.034582f, 0.035303f, 0.036023f, 0.036744f, 0.037464f, 0.038184f, 01409 0.038905f, 0.039625f, 0.040346f, 0.041066f, 0.041787f, 0.042507f, 01410 0.043228f, 0.043948f, 0.044669f, 0.045389f, 0.046110f, 0.046830f, 01411 0.047550f, 0.048271f, 0.048991f, 0.049712f, 0.050432f, 0.051153f, 01412 0.051873f, 0.052594f, 0.053314f, 0.054035f, 0.054755f, 0.055476f, 01413 0.056196f, 0.056916f, 0.057637f, 0.058357f, 0.059078f, 0.059798f, 01414 0.060519f, 0.061239f, 0.061960f, 0.062680f, 0.063401f, 0.064121f, 01415 0.064842f, 0.065562f, 0.066282f, 0.067003f, 0.067723f, 0.068444f, 01416 0.069164f, 0.069885f, 0.070605f, 0.071326f, 0.072046f, 0.072767f, 01417 0.073487f, 0.074207f, 0.074928f, 0.075648f, 0.076369f, 0.077089f, 01418 0.077810f, 0.078530f, 0.079251f, 0.079971f, 0.080692f, 0.081412f, 01419 0.082133f, 0.082853f, 0.083573f, 0.084294f, 0.085014f, 0.085735f, 01420 0.086455f, 0.087176f, 0.087896f, 0.088617f, 0.089337f, 0.090058f, 01421 0.090778f, 0.091499f, 0.092219f, 0.092939f, 0.093660f, 0.094380f, 01422 0.095101f, 0.095821f, 0.096542f, 0.097262f, 0.097983f, 0.098703f, 01423 0.099424f, 0.100144f, 0.100865f, 0.101585f, 0.102305f, 0.103026f, 01424 0.103746f, 0.104467f, 0.105187f, 0.105908f, 0.106628f, 0.107349f, 01425 0.108069f, 0.108790f, 0.109510f, 0.110231f, 0.110951f, 0.111671f, 01426 0.112392f, 0.113112f, 0.113833f, 0.114553f, 0.115274f, 0.115994f, 01427 0.116715f, 0.117435f, 0.118156f, 0.118876f, 0.119597f, 0.120317f, 01428 0.121037f, 0.121758f, 0.122478f, 0.123199f, 0.123919f, 0.124640f, 01429 0.125360f, 0.126081f, 0.126801f, 0.127522f, 0.128242f, 0.128963f, 01430 0.129683f, 0.130403f, 0.131124f, 0.131844f, 0.132565f, 0.133285f, 01431 0.134006f, 0.134726f, 0.135447f, 0.136167f, 0.136888f, 0.137608f, 01432 0.138329f, 0.139049f, 0.139769f, 0.140490f, 0.141210f, 0.141931f, 01433 0.142651f, 0.143372f, 0.144092f, 0.144813f, 0.145533f, 0.146254f, 01434 0.146974f, 0.147695f, 0.148415f, 0.149135f, 0.149856f, 0.150576f, 01435 0.151297f, 0.152017f, 0.152738f, 0.153458f, 0.154179f, 0.154899f, 01436 0.155620f, 0.156340f, 0.157061f, 0.157781f, 0.158501f, 0.159222f, 01437 0.159942f, 0.160663f, 0.161383f, 0.162104f, 0.162824f, 0.163545f, 01438 0.164265f, 0.164986f, 0.165706f, 0.166427f, 0.167147f, 0.167867f, 01439 0.168588f, 0.169308f, 0.170029f, 0.170749f, 0.171470f, 0.172190f, 01440 0.172911f, 0.173631f, 0.174352f, 0.175072f, 0.175793f, 0.176513f, 01441 0.177233f, 0.177954f, 0.178674f, 0.179395f, 0.180115f, 0.180836f, 01442 0.181556f, 0.182277f, 0.182997f, 0.183718f, 0.184438f, 0.185159f, 01443 0.185879f, 0.186599f, 0.187320f, 0.188040f, 0.188761f, 0.189481f, 01444 0.190202f, 0.190922f, 0.191643f, 0.192363f, 0.193084f, 0.193804f, 01445 0.194524f, 0.195245f, 0.195965f, 0.196686f, 0.197406f, 0.198127f, 01446 0.198847f, 0.199568f, 0.200288f, 0.201009f, 0.201729f, 0.202450f, 01447 0.203170f, 0.203890f, 0.204611f, 0.205331f, 0.206052f, 0.206772f, 01448 0.207493f, 0.208213f, 0.208934f, 0.209654f, 0.210375f, 0.211095f, 01449 0.211816f, 0.212536f, 0.213256f, 0.213977f, 0.214697f, 0.215418f, 01450 0.216138f, 0.216859f, 0.217579f, 0.218300f, 0.219020f, 0.219741f, 01451 0.220461f, 0.221182f, 0.221902f, 0.222622f, 0.223343f, 0.224063f, 01452 0.224784f, 0.225504f, 0.226225f, 0.226945f, 0.227666f, 0.228386f, 01453 0.229107f, 0.229827f, 0.230548f, 0.231268f, 0.231988f, 0.232709f, 01454 0.233429f, 0.234150f, 0.234870f, 0.235591f, 0.236311f, 0.237032f, 01455 0.237752f, 0.238473f, 0.239193f, 0.239914f, 0.240634f, 0.241354f, 01456 0.242075f, 0.242795f, 0.243516f, 0.244236f, 0.244957f, 0.245677f, 01457 0.246398f, 0.247118f, 0.247839f, 0.248559f, 0.249280f, 0.250000f, 01458 0.250720f, 0.251441f, 0.252161f, 0.252882f, 0.253602f, 0.254323f, 01459 0.255043f, 0.255764f, 0.256484f, 0.257205f, 0.257925f, 0.258646f, 01460 0.259366f, 0.260086f, 0.260807f, 0.261527f, 0.262248f, 0.262968f, 01461 0.263689f, 0.264409f, 0.265130f, 0.265850f, 0.266571f, 0.267291f, 01462 0.268012f, 0.268732f, 0.269452f, 0.270173f, 0.270893f, 0.271614f, 01463 0.272334f, 0.273055f, 0.273775f, 0.274496f, 0.275216f, 0.275937f, 01464 0.276657f, 0.277378f, 0.278098f, 0.278818f, 0.279539f, 0.280259f, 01465 0.280980f, 0.281700f, 0.282421f, 0.283141f, 0.283862f, 0.284582f, 01466 0.285303f, 0.286023f, 0.286744f, 0.287464f, 0.288184f, 0.288905f, 01467 0.289625f, 0.290346f, 0.291066f, 0.291787f, 0.292507f, 0.293228f, 01468 0.293948f, 0.294669f, 0.295389f, 0.296109f, 0.296830f, 0.297550f, 01469 0.298271f, 0.298991f, 0.299712f, 0.300432f, 0.301153f, 0.301873f, 01470 0.302594f, 0.303314f, 0.304035f, 0.304755f, 0.305476f, 0.306196f, 01471 0.306916f, 0.307637f, 0.308357f, 0.309078f, 0.309798f, 0.310519f, 01472 0.311239f, 0.311960f, 0.312680f, 0.313401f, 0.314121f, 0.314842f, 01473 0.315562f, 0.316282f, 0.317003f, 0.317723f, 0.318444f, 0.319164f, 01474 0.319885f, 0.320605f, 0.321326f, 0.322046f, 0.322767f, 0.323487f, 01475 0.324207f, 0.324928f, 0.325648f, 0.326369f, 0.327089f, 0.327810f, 01476 0.328530f, 0.329251f, 0.329971f, 0.330692f, 0.331412f, 0.332133f, 01477 0.332853f, 0.333573f, 0.334294f, 0.335014f, 0.335735f, 0.336455f, 01478 0.337176f, 0.337896f, 0.338617f, 0.339337f, 0.340058f, 0.340778f, 01479 0.341499f, 0.342219f, 0.342939f, 0.343660f, 0.344380f, 0.345101f, 01480 0.345821f, 0.346542f, 0.347262f, 0.347983f, 0.348703f, 0.349424f, 01481 0.350144f, 0.350865f, 0.351585f, 0.352305f, 0.353026f, 0.353746f, 01482 0.354467f, 0.355187f, 0.355908f, 0.356628f, 0.357349f, 0.358069f, 01483 0.358790f, 0.359510f, 0.360231f, 0.360951f, 0.361671f, 0.362392f, 01484 0.363112f, 0.363833f, 0.364553f, 0.365274f, 0.365994f, 0.366715f, 01485 0.367435f, 0.368156f, 0.368876f, 0.369597f, 0.370317f, 0.371037f, 01486 0.371758f, 0.372478f, 0.373199f, 0.373919f, 0.374640f, 0.375360f, 01487 0.376081f, 0.376801f, 0.377522f, 0.378242f, 0.378963f, 0.379683f, 01488 0.380403f, 0.381124f, 0.381844f, 0.382565f, 0.383285f, 0.384006f, 01489 0.384726f, 0.385447f, 0.386167f, 0.386888f, 0.387608f, 0.388329f, 01490 0.389049f, 0.389769f, 0.390490f, 0.391210f, 0.391931f, 0.392651f, 01491 0.393372f, 0.394092f, 0.394813f, 0.395533f, 0.396254f, 0.396974f, 01492 0.397695f, 0.398415f, 0.399135f, 0.399856f, 0.400576f, 0.401297f, 01493 0.402017f, 0.402738f, 0.403458f, 0.404179f, 0.404899f, 0.405620f, 01494 0.406340f, 0.407061f, 0.407781f, 0.408501f, 0.409222f, 0.409942f, 01495 0.410663f, 0.411383f, 0.412104f, 0.412824f, 0.413545f, 0.414265f, 01496 0.414986f, 0.415706f, 0.416427f, 0.417147f, 0.417867f, 0.418588f, 01497 0.419308f, 0.420029f, 0.420749f, 0.421470f, 0.422190f, 0.422911f, 01498 0.423631f, 0.424352f, 0.425072f, 0.425793f, 0.426513f, 0.427233f, 01499 0.427954f, 0.428674f, 0.429395f, 0.430115f, 0.430836f, 0.431556f, 01500 0.432277f, 0.432997f, 0.433718f, 0.434438f, 0.435158f, 0.435879f, 01501 0.436599f, 0.437320f, 0.438040f, 0.438761f, 0.439481f, 0.440202f, 01502 0.440922f, 0.441643f, 0.442363f, 0.443084f, 0.443804f, 0.444524f, 01503 0.445245f, 0.445965f, 0.446686f, 0.447406f, 0.448127f, 0.448847f, 01504 0.449568f, 0.450288f, 0.451009f, 0.451729f, 0.452450f, 0.453170f, 01505 0.453891f, 0.454611f, 0.455331f, 0.456052f, 0.456772f, 0.457493f, 01506 0.458213f, 0.458934f, 0.459654f, 0.460375f, 0.461095f, 0.461816f, 01507 0.462536f, 0.463256f, 0.463977f, 0.464697f, 0.465418f, 0.466138f, 01508 0.466859f, 0.467579f, 0.468300f, 0.469020f, 0.469741f, 0.470461f, 01509 0.471182f, 0.471902f, 0.472622f, 0.473343f, 0.474063f, 0.474784f, 01510 0.475504f, 0.476225f, 0.476945f, 0.477666f, 0.478386f, 0.479107f, 01511 0.479827f, 0.480548f, 0.481268f, 0.481988f, 0.482709f, 0.483429f, 01512 0.484150f, 0.484870f, 0.485591f, 0.486311f, 0.487032f, 0.487752f, 01513 0.488473f, 0.489193f, 0.489914f, 0.490634f, 0.491354f, 0.492075f, 01514 0.492795f, 0.493516f, 0.494236f, 0.494957f, 0.495677f, 0.496398f, 01515 0.497118f, 0.497839f, 0.498559f, 0.499280f, 0.500000f, 0.500720f, 01516 0.501441f, 0.502161f, 0.502882f, 0.503602f, 0.504323f, 0.505043f, 01517 0.505764f, 0.506484f, 0.507205f, 0.507925f, 0.508646f, 0.509366f, 01518 0.510086f, 0.510807f, 0.511527f, 0.512248f, 0.512968f, 0.513689f, 01519 0.514409f, 0.515130f, 0.515850f, 0.516571f, 0.517291f, 0.518012f, 01520 0.518732f, 0.519452f, 0.520173f, 0.520893f, 0.521614f, 0.522334f, 01521 0.523055f, 0.523775f, 0.524496f, 0.525216f, 0.525937f, 0.526657f, 01522 0.527378f, 0.528098f, 0.528818f, 0.529539f, 0.530259f, 0.530980f, 01523 0.531700f, 0.532421f, 0.533141f, 0.533862f, 0.534582f, 0.535303f, 01524 0.536023f, 0.536744f, 0.537464f, 0.538184f, 0.538905f, 0.539625f, 01525 0.540346f, 0.541066f, 0.541787f, 0.542507f, 0.543228f, 0.543948f, 01526 0.544669f, 0.545389f, 0.546109f, 0.546830f, 0.547550f, 0.548271f, 01527 0.548991f, 0.549712f, 0.550432f, 0.551153f, 0.551873f, 0.552594f, 01528 0.553314f, 0.554035f, 0.554755f, 0.555476f, 0.556196f, 0.556916f, 01529 0.557637f, 0.558357f, 0.559078f, 0.559798f, 0.560519f, 0.561239f, 01530 0.561960f, 0.562680f, 0.563401f, 0.564121f, 0.564842f, 0.565562f, 01531 0.566282f, 0.567003f, 0.567723f, 0.568444f, 0.569164f, 0.569885f, 01532 0.570605f, 0.571326f, 0.572046f, 0.572767f, 0.573487f, 0.574207f, 01533 0.574928f, 0.575648f, 0.576369f, 0.577089f, 0.577810f, 0.578530f, 01534 0.579251f, 0.579971f, 0.580692f, 0.581412f, 0.582133f, 0.582853f, 01535 0.583573f, 0.584294f, 0.585014f, 0.585735f, 0.586455f, 0.587176f, 01536 0.587896f, 0.588617f, 0.589337f, 0.590058f, 0.590778f, 0.591499f, 01537 0.592219f, 0.592939f, 0.593660f, 0.594380f, 0.595101f, 0.595821f, 01538 0.596542f, 0.597262f, 0.597983f, 0.598703f, 0.599424f, 0.600144f, 01539 0.600865f, 0.601585f, 0.602305f, 0.603026f, 0.603746f, 0.604467f, 01540 0.605187f, 0.605908f, 0.606628f, 0.607349f, 0.608069f, 0.608790f, 01541 0.609510f, 0.610231f, 0.610951f, 0.611671f, 0.612392f, 0.613112f, 01542 0.613833f, 0.614553f, 0.615274f, 0.615994f, 0.616715f, 0.617435f, 01543 0.618156f, 0.618876f, 0.619597f, 0.620317f, 0.621037f, 0.621758f, 01544 0.622478f, 0.623199f, 0.623919f, 0.624640f, 0.625360f, 0.626081f, 01545 0.626801f, 0.627522f, 0.628242f, 0.628963f, 0.629683f, 0.630403f, 01546 0.631124f, 0.631844f, 0.632565f, 0.633285f, 0.634006f, 0.634726f, 01547 0.635447f, 0.636167f, 0.636888f, 0.637608f, 0.638329f, 0.639049f, 01548 0.639769f, 0.640490f, 0.641210f, 0.641931f, 0.642651f, 0.643372f, 01549 0.644092f, 0.644813f, 0.645533f, 0.646254f, 0.646974f, 0.647695f, 01550 0.648415f, 0.649135f, 0.649856f, 0.650576f, 0.651297f, 0.652017f, 01551 0.652738f, 0.653458f, 0.654179f, 0.654899f, 0.655620f, 0.656340f, 01552 0.657061f, 0.657781f, 0.658501f, 0.659222f, 0.659942f, 0.660663f, 01553 0.661383f, 0.662104f, 0.662824f, 0.663545f, 0.664265f, 0.664986f, 01554 0.665706f, 0.666427f, 0.667147f, 0.667867f, 0.668588f, 0.669308f, 01555 0.670029f, 0.670749f, 0.671470f, 0.672190f, 0.672911f, 0.673631f, 01556 0.674352f, 0.675072f, 0.675793f, 0.676513f, 0.677233f, 0.677954f, 01557 0.678674f, 0.679395f, 0.680115f, 0.680836f, 0.681556f, 0.682277f, 01558 0.682997f, 0.683718f, 0.684438f, 0.685158f, 0.685879f, 0.686599f, 01559 0.687320f, 0.688040f, 0.688761f, 0.689481f, 0.690202f, 0.690922f, 01560 0.691643f, 0.692363f, 0.693084f, 0.693804f, 0.694524f, 0.695245f, 01561 0.695965f, 0.696686f, 0.697406f, 0.698127f, 0.698847f, 0.699568f, 01562 0.700288f, 0.701009f, 0.701729f, 0.702450f, 0.703170f, 0.703891f, 01563 0.704611f, 0.705331f, 0.706052f, 0.706772f, 0.707493f, 0.708213f, 01564 0.708934f, 0.709654f, 0.710375f, 0.711095f, 0.711816f, 0.712536f, 01565 0.713256f, 0.713977f, 0.714697f, 0.715418f, 0.716138f, 0.716859f, 01566 0.717579f, 0.718300f, 0.719020f, 0.719741f, 0.720461f, 0.721182f, 01567 0.721902f, 0.722622f, 0.723343f, 0.724063f, 0.724784f, 0.725504f, 01568 0.726225f, 0.726945f, 0.727666f, 0.728386f, 0.729107f, 0.729827f, 01569 0.730548f, 0.731268f, 0.731988f, 0.732709f, 0.733429f, 0.734150f, 01570 0.734870f, 0.735591f, 0.736311f, 0.737032f, 0.737752f, 0.738473f, 01571 0.739193f, 0.739914f, 0.740634f, 0.741354f, 0.742075f, 0.742795f, 01572 0.743516f, 0.744236f, 0.744957f, 0.745677f, 0.746398f, 0.747118f, 01573 0.747839f, 0.748559f, 0.749280f, 0.750000f, 0.750720f, 0.751441f, 01574 0.752161f, 0.752882f, 0.753602f, 0.754323f, 0.755043f, 0.755764f, 01575 0.756484f, 0.757205f, 0.757925f, 0.758646f, 0.759366f, 0.760086f, 01576 0.760807f, 0.761527f, 0.762248f, 0.762968f, 0.763689f, 0.764409f, 01577 0.765130f, 0.765850f, 0.766571f, 0.767291f, 0.768012f, 0.768732f, 01578 0.769452f, 0.770173f, 0.770893f, 0.771614f, 0.772334f, 0.773055f, 01579 0.773775f, 0.774496f, 0.775216f, 0.775937f, 0.776657f, 0.777378f, 01580 0.778098f, 0.778818f, 0.779539f, 0.780259f, 0.780980f, 0.781700f, 01581 0.782421f, 0.783141f, 0.783862f, 0.784582f, 0.785303f, 0.786023f, 01582 0.786744f, 0.787464f, 0.788184f, 0.788905f, 0.789625f, 0.790346f, 01583 0.791066f, 0.791787f, 0.792507f, 0.793228f, 0.793948f, 0.794669f, 01584 0.795389f, 0.796109f, 0.796830f, 0.797550f, 0.798271f, 0.798991f, 01585 0.799712f, 0.800432f, 0.801153f, 0.801873f, 0.802594f, 0.803314f, 01586 0.804035f, 0.804755f, 0.805476f, 0.806196f, 0.806916f, 0.807637f, 01587 0.808357f, 0.809078f, 0.809798f, 0.810519f, 0.811239f, 0.811960f, 01588 0.812680f, 0.813401f, 0.814121f, 0.814842f, 0.815562f, 0.816282f, 01589 0.817003f, 0.817723f, 0.818444f, 0.819164f, 0.819885f, 0.820605f, 01590 0.821326f, 0.822046f, 0.822767f, 0.823487f, 0.824207f, 0.824928f, 01591 0.825648f, 0.826369f, 0.827089f, 0.827810f, 0.828530f, 0.829251f, 01592 0.829971f, 0.830692f, 0.831412f, 0.832133f, 0.832853f, 0.833573f, 01593 0.834294f, 0.835014f, 0.835735f, 0.836455f, 0.837176f, 0.837896f, 01594 0.838617f, 0.839337f, 0.840058f, 0.840778f, 0.841499f, 0.842219f, 01595 0.842939f, 0.843660f, 0.844380f, 0.845101f, 0.845821f, 0.846542f, 01596 0.847262f, 0.847983f, 0.848703f, 0.849424f, 0.850144f, 0.850865f, 01597 0.851585f, 0.852305f, 0.853026f, 0.853746f, 0.854467f, 0.855187f, 01598 0.855908f, 0.856628f, 0.857349f, 0.858069f, 0.858790f, 0.859510f, 01599 0.860231f, 0.860951f, 0.861671f, 0.862392f, 0.863112f, 0.863833f, 01600 0.864553f, 0.865274f, 0.865994f, 0.866715f, 0.867435f, 0.868156f, 01601 0.868876f, 0.869597f, 0.870317f, 0.871037f, 0.871758f, 0.872478f, 01602 0.873199f, 0.873919f, 0.874640f, 0.875360f, 0.876081f, 0.876801f, 01603 0.877522f, 0.878242f, 0.878963f, 0.879683f, 0.880403f, 0.881124f, 01604 0.881844f, 0.882565f, 0.883285f, 0.884006f, 0.884726f, 0.885447f, 01605 0.886167f, 0.886888f, 0.887608f, 0.888329f, 0.889049f, 0.889769f, 01606 0.890490f, 0.891210f, 0.891931f, 0.892651f, 0.893372f, 0.894092f, 01607 0.894813f, 0.895533f, 0.896254f, 0.896974f, 0.897695f, 0.898415f, 01608 0.899135f, 0.899856f, 0.900576f, 0.901297f, 0.902017f, 0.902738f, 01609 0.903458f, 0.904179f, 0.904899f, 0.905620f, 0.906340f, 0.907061f, 01610 0.907781f, 0.908501f, 0.909222f, 0.909942f, 0.910663f, 0.911383f, 01611 0.912104f, 0.912824f, 0.913545f, 0.914265f, 0.914986f, 0.915706f, 01612 0.916427f, 0.917147f, 0.917867f, 0.918588f, 0.919308f, 0.920029f, 01613 0.920749f, 0.921470f, 0.922190f, 0.922911f, 0.923631f, 0.924352f, 01614 0.925072f, 0.925793f, 0.926513f, 0.927233f, 0.927954f, 0.928674f, 01615 0.929395f, 0.930115f, 0.930836f, 0.931556f, 0.932277f, 0.932997f, 01616 0.933718f, 0.934438f, 0.935158f, 0.935879f, 0.936599f, 0.937320f, 01617 0.938040f, 0.938761f, 0.939481f, 0.940202f, 0.940922f, 0.941643f, 01618 0.942363f, 0.943084f, 0.943804f, 0.944524f, 0.945245f, 0.945965f, 01619 0.946686f, 0.947406f, 0.948127f, 0.948847f, 0.949568f, 0.950288f, 01620 0.951009f, 0.951729f, 0.952450f, 0.953170f, 0.953891f, 0.954611f, 01621 0.955331f, 0.956052f, 0.956772f, 0.957493f, 0.958213f, 0.958934f, 01622 0.959654f, 0.960375f, 0.961095f, 0.961816f, 0.962536f, 0.963256f, 01623 0.963977f, 0.964697f, 0.965418f, 0.966138f, 0.966859f, 0.967579f, 01624 0.968300f, 0.969020f, 0.969741f, 0.970461f, 0.971182f, 0.971902f, 01625 0.972622f, 0.973343f, 0.974063f, 0.974784f, 0.975504f, 0.976225f, 01626 0.976945f, 0.977666f, 0.978386f, 0.979107f, 0.979827f, 0.980548f, 01627 0.981268f, 0.981988f, 0.982709f, 0.983429f, 0.984150f, 0.984870f, 01628 0.985591f, 0.986311f, 0.987032f, 0.987752f, 0.988473f, 0.989193f, 01629 0.989914f, 0.990634f, 0.991354f, 0.992075f, 0.992795f, 0.993516f, 01630 0.994236f, 0.994957f, 0.995677f, 0.996398f, 0.997118f, 0.997839f, 01631 0.998559f, 0.999280f, 1.000000f 01632 }; 01633 #endif 01634 01635 CacheView 01636 *image_view; 01637 01638 MagickBooleanType 01639 status; 01640 01641 MagickOffsetType 01642 progress; 01643 01644 register ssize_t 01645 i; 01646 01647 ssize_t 01648 y; 01649 01650 TransformPacket 01651 *y_map, 01652 *x_map, 01653 *z_map; 01654 01655 assert(image != (Image *) NULL); 01656 assert(image->signature == MagickSignature); 01657 if (image->debug != MagickFalse) 01658 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01659 status=MagickTrue; 01660 progress=0; 01661 switch (image->colorspace) 01662 { 01663 case CMYColorspace: 01664 { 01665 /* 01666 Transform image from CMY to RGB. 01667 */ 01668 if (image->storage_class == PseudoClass) 01669 { 01670 if (SyncImage(image,exception) == MagickFalse) 01671 return(MagickFalse); 01672 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 01673 return(MagickFalse); 01674 } 01675 image_view=AcquireCacheView(image); 01676 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01677 #pragma omp parallel for schedule(static,4) shared(status) 01678 #endif 01679 for (y=0; y < (ssize_t) image->rows; y++) 01680 { 01681 MagickBooleanType 01682 sync; 01683 01684 register ssize_t 01685 x; 01686 01687 register Quantum 01688 *restrict q; 01689 01690 if (status == MagickFalse) 01691 continue; 01692 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 01693 exception); 01694 if (q == (Quantum *) NULL) 01695 { 01696 status=MagickFalse; 01697 continue; 01698 } 01699 for (x=0; x < (ssize_t) image->columns; x++) 01700 { 01701 SetPixelRed(image,ClampToQuantum((MagickRealType) (QuantumRange- 01702 GetPixelRed(image,q))),q); 01703 SetPixelGreen(image,ClampToQuantum((MagickRealType) (QuantumRange- 01704 GetPixelGreen(image,q))),q); 01705 SetPixelBlue(image,ClampToQuantum((MagickRealType) (QuantumRange- 01706 GetPixelBlue(image,q))),q); 01707 q+=GetPixelChannels(image); 01708 } 01709 sync=SyncCacheViewAuthenticPixels(image_view,exception); 01710 if (sync == MagickFalse) 01711 status=MagickFalse; 01712 } 01713 image_view=DestroyCacheView(image_view); 01714 if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse) 01715 return(MagickFalse); 01716 return(status); 01717 } 01718 case CMYKColorspace: 01719 { 01720 PixelInfo 01721 zero; 01722 01723 /* 01724 Transform image from CMYK to RGB. 01725 */ 01726 if (image->storage_class == PseudoClass) 01727 { 01728 if (SyncImage(image,exception) == MagickFalse) 01729 return(MagickFalse); 01730 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 01731 return(MagickFalse); 01732 } 01733 GetPixelInfo(image,&zero); 01734 image_view=AcquireCacheView(image); 01735 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01736 #pragma omp parallel for schedule(static,4) shared(status) 01737 #endif 01738 for (y=0; y < (ssize_t) image->rows; y++) 01739 { 01740 MagickBooleanType 01741 sync; 01742 01743 PixelInfo 01744 pixel; 01745 01746 register ssize_t 01747 x; 01748 01749 register Quantum 01750 *restrict q; 01751 01752 if (status == MagickFalse) 01753 continue; 01754 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 01755 exception); 01756 if (q == (Quantum *) NULL) 01757 { 01758 status=MagickFalse; 01759 continue; 01760 } 01761 pixel=zero; 01762 for (x=0; x < (ssize_t) image->columns; x++) 01763 { 01764 GetPixelInfoPixel(image,q,&pixel); 01765 ConvertCMYKToRGB(&pixel); 01766 SetPixelInfoPixel(image,&pixel,q); 01767 q+=GetPixelChannels(image); 01768 } 01769 sync=SyncCacheViewAuthenticPixels(image_view,exception); 01770 if (sync == MagickFalse) 01771 status=MagickFalse; 01772 } 01773 image_view=DestroyCacheView(image_view); 01774 if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse) 01775 return(MagickFalse); 01776 return(status); 01777 } 01778 case HSBColorspace: 01779 { 01780 /* 01781 Transform image from HSB to RGB. 01782 */ 01783 if (image->storage_class == PseudoClass) 01784 { 01785 if (SyncImage(image,exception) == MagickFalse) 01786 return(MagickFalse); 01787 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 01788 return(MagickFalse); 01789 } 01790 image_view=AcquireCacheView(image); 01791 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01792 #pragma omp parallel for schedule(static,4) shared(status) 01793 #endif 01794 for (y=0; y < (ssize_t) image->rows; y++) 01795 { 01796 double 01797 brightness, 01798 hue, 01799 saturation; 01800 01801 MagickBooleanType 01802 sync; 01803 01804 register ssize_t 01805 x; 01806 01807 register Quantum 01808 *restrict q; 01809 01810 if (status == MagickFalse) 01811 continue; 01812 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 01813 exception); 01814 if (q == (Quantum *) NULL) 01815 { 01816 status=MagickFalse; 01817 continue; 01818 } 01819 for (x=0; x < (ssize_t) image->columns; x++) 01820 { 01821 double 01822 blue, 01823 green, 01824 red; 01825 01826 hue=(double) (QuantumScale*GetPixelRed(image,q)); 01827 saturation=(double) (QuantumScale*GetPixelGreen(image,q)); 01828 brightness=(double) (QuantumScale*GetPixelBlue(image,q)); 01829 ConvertHSBToRGB(hue,saturation,brightness,&red,&green,&blue); 01830 SetPixelRed(image,ClampToQuantum(red),q); 01831 SetPixelGreen(image,ClampToQuantum(green),q); 01832 SetPixelBlue(image,ClampToQuantum(blue),q); 01833 q+=GetPixelChannels(image); 01834 } 01835 sync=SyncCacheViewAuthenticPixels(image_view,exception); 01836 if (sync == MagickFalse) 01837 status=MagickFalse; 01838 } 01839 image_view=DestroyCacheView(image_view); 01840 if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse) 01841 return(MagickFalse); 01842 return(status); 01843 } 01844 case HSLColorspace: 01845 { 01846 /* 01847 Transform image from HSL to RGB. 01848 */ 01849 if (image->storage_class == PseudoClass) 01850 { 01851 if (SyncImage(image,exception) == MagickFalse) 01852 return(MagickFalse); 01853 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 01854 return(MagickFalse); 01855 } 01856 image_view=AcquireCacheView(image); 01857 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01858 #pragma omp parallel for schedule(static,4) shared(status) 01859 #endif 01860 for (y=0; y < (ssize_t) image->rows; y++) 01861 { 01862 double 01863 hue, 01864 lightness, 01865 saturation; 01866 01867 MagickBooleanType 01868 sync; 01869 01870 register ssize_t 01871 x; 01872 01873 register Quantum 01874 *restrict q; 01875 01876 if (status == MagickFalse) 01877 continue; 01878 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 01879 exception); 01880 if (q == (Quantum *) NULL) 01881 { 01882 status=MagickFalse; 01883 continue; 01884 } 01885 for (x=0; x < (ssize_t) image->columns; x++) 01886 { 01887 double 01888 blue, 01889 green, 01890 red; 01891 01892 hue=(double) (QuantumScale*GetPixelRed(image,q)); 01893 saturation=(double) (QuantumScale*GetPixelGreen(image,q)); 01894 lightness=(double) (QuantumScale*GetPixelBlue(image,q)); 01895 ConvertHSLToRGB(hue,saturation,lightness,&red,&green,&blue); 01896 SetPixelRed(image,ClampToQuantum(red),q); 01897 SetPixelGreen(image,ClampToQuantum(green),q); 01898 SetPixelBlue(image,ClampToQuantum(blue),q); 01899 q+=GetPixelChannels(image); 01900 } 01901 sync=SyncCacheViewAuthenticPixels(image_view,exception); 01902 if (sync == MagickFalse) 01903 status=MagickFalse; 01904 } 01905 image_view=DestroyCacheView(image_view); 01906 if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse) 01907 return(MagickFalse); 01908 return(status); 01909 } 01910 case HWBColorspace: 01911 { 01912 /* 01913 Transform image from HWB to RGB. 01914 */ 01915 if (image->storage_class == PseudoClass) 01916 { 01917 if (SyncImage(image,exception) == MagickFalse) 01918 return(MagickFalse); 01919 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 01920 return(MagickFalse); 01921 } 01922 image_view=AcquireCacheView(image); 01923 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01924 #pragma omp parallel for schedule(static,4) shared(status) 01925 #endif 01926 for (y=0; y < (ssize_t) image->rows; y++) 01927 { 01928 double 01929 blackness, 01930 hue, 01931 whiteness; 01932 01933 MagickBooleanType 01934 sync; 01935 01936 register ssize_t 01937 x; 01938 01939 register Quantum 01940 *restrict q; 01941 01942 if (status == MagickFalse) 01943 continue; 01944 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 01945 exception); 01946 if (q == (Quantum *) NULL) 01947 { 01948 status=MagickFalse; 01949 continue; 01950 } 01951 for (x=0; x < (ssize_t) image->columns; x++) 01952 { 01953 double 01954 blue, 01955 green, 01956 red; 01957 01958 hue=(double) (QuantumScale*GetPixelRed(image,q)); 01959 whiteness=(double) (QuantumScale*GetPixelGreen(image,q)); 01960 blackness=(double) (QuantumScale*GetPixelBlue(image,q)); 01961 ConvertHWBToRGB(hue,whiteness,blackness,&red,&green,&blue); 01962 SetPixelRed(image,ClampToQuantum(red),q); 01963 SetPixelGreen(image,ClampToQuantum(green),q); 01964 SetPixelBlue(image,ClampToQuantum(blue),q); 01965 q+=GetPixelChannels(image); 01966 } 01967 sync=SyncCacheViewAuthenticPixels(image_view,exception); 01968 if (sync == MagickFalse) 01969 status=MagickFalse; 01970 } 01971 image_view=DestroyCacheView(image_view); 01972 if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse) 01973 return(MagickFalse); 01974 return(status); 01975 } 01976 case LabColorspace: 01977 { 01978 /* 01979 Transform image from Lab to RGB. 01980 */ 01981 if (image->storage_class == PseudoClass) 01982 { 01983 if (SyncImage(image,exception) == MagickFalse) 01984 return(MagickFalse); 01985 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 01986 return(MagickFalse); 01987 } 01988 image_view=AcquireCacheView(image); 01989 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01990 #pragma omp parallel for schedule(static,4) shared(status) 01991 #endif 01992 for (y=0; y < (ssize_t) image->rows; y++) 01993 { 01994 double 01995 a, 01996 b, 01997 L, 01998 X, 01999 Y, 02000 Z; 02001 02002 MagickBooleanType 02003 sync; 02004 02005 register ssize_t 02006 x; 02007 02008 register Quantum 02009 *restrict q; 02010 02011 if (status == MagickFalse) 02012 continue; 02013 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 02014 exception); 02015 if (q == (Quantum *) NULL) 02016 { 02017 status=MagickFalse; 02018 continue; 02019 } 02020 X=0.0; 02021 Y=0.0; 02022 Z=0.0; 02023 for (x=0; x < (ssize_t) image->columns; x++) 02024 { 02025 Quantum 02026 blue, 02027 green, 02028 red; 02029 02030 L=QuantumScale*GetPixelRed(image,q); 02031 a=QuantumScale*GetPixelGreen(image,q); 02032 b=QuantumScale*GetPixelBlue(image,q); 02033 ConvertLabToXYZ(L,a,b,&X,&Y,&Z); 02034 ConvertXYZToRGB(X,Y,Z,&red,&green,&blue); 02035 SetPixelRed(image,red,q); 02036 SetPixelGreen(image,green,q); 02037 SetPixelBlue(image,blue,q); 02038 q+=GetPixelChannels(image); 02039 } 02040 sync=SyncCacheViewAuthenticPixels(image_view,exception); 02041 if (sync == MagickFalse) 02042 status=MagickFalse; 02043 } 02044 image_view=DestroyCacheView(image_view); 02045 if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse) 02046 return(MagickFalse); 02047 return(status); 02048 } 02049 case LogColorspace: 02050 { 02051 const char 02052 *value; 02053 02054 double 02055 black, 02056 density, 02057 film_gamma, 02058 gamma, 02059 reference_black, 02060 reference_white; 02061 02062 Quantum 02063 *logmap; 02064 02065 /* 02066 Transform Log to RGB colorspace. 02067 */ 02068 density=DisplayGamma; 02069 gamma=DisplayGamma; 02070 value=GetImageProperty(image,"gamma",exception); 02071 if (value != (const char *) NULL) 02072 gamma=1.0/fabs(StringToDouble(value,(char **) NULL)) >= 02073 MagickEpsilon ? StringToDouble(value,(char **) NULL) : 1.0; 02074 film_gamma=FilmGamma; 02075 value=GetImageProperty(image,"film-gamma",exception); 02076 if (value != (const char *) NULL) 02077 film_gamma=StringToDouble(value,(char **) NULL); 02078 reference_black=ReferenceBlack; 02079 value=GetImageProperty(image,"reference-black",exception); 02080 if (value != (const char *) NULL) 02081 reference_black=StringToDouble(value,(char **) NULL); 02082 reference_white=ReferenceWhite; 02083 value=GetImageProperty(image,"reference-white",exception); 02084 if (value != (const char *) NULL) 02085 reference_white=StringToDouble(value,(char **) NULL); 02086 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL, 02087 sizeof(*logmap)); 02088 if (logmap == (Quantum *) NULL) 02089 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 02090 image->filename); 02091 black=pow(10.0,(reference_black-reference_white)*(gamma/density)* 02092 0.002/film_gamma); 02093 for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++) 02094 logmap[i]=(Quantum) 0; 02095 for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0); i++) 02096 logmap[i]=ClampToQuantum((MagickRealType) QuantumRange/(1.0-black)* 02097 (pow(10.0,(1024.0*i/MaxMap-reference_white)* 02098 (gamma/density)*0.002/film_gamma)-black)); 02099 for ( ; i <= (ssize_t) MaxMap; i++) 02100 logmap[i]=(Quantum) QuantumRange; 02101 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 02102 return(MagickFalse); 02103 image_view=AcquireCacheView(image); 02104 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02105 #pragma omp parallel for schedule(static,4) shared(status) 02106 #endif 02107 for (y=0; y < (ssize_t) image->rows; y++) 02108 { 02109 MagickBooleanType 02110 sync; 02111 02112 register ssize_t 02113 x; 02114 02115 register Quantum 02116 *restrict q; 02117 02118 if (status == MagickFalse) 02119 continue; 02120 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 02121 exception); 02122 if (q == (Quantum *) NULL) 02123 { 02124 status=MagickFalse; 02125 continue; 02126 } 02127 for (x=(ssize_t) image->columns; x != 0; x--) 02128 { 02129 SetPixelRed(image,logmap[ScaleQuantumToMap( 02130 GetPixelRed(image,q))],q); 02131 SetPixelGreen(image,logmap[ScaleQuantumToMap( 02132 GetPixelGreen(image,q))],q); 02133 SetPixelBlue(image,logmap[ScaleQuantumToMap( 02134 GetPixelBlue(image,q))],q); 02135 q+=GetPixelChannels(image); 02136 } 02137 sync=SyncCacheViewAuthenticPixels(image_view,exception); 02138 if (sync == MagickFalse) 02139 status=MagickFalse; 02140 } 02141 image_view=DestroyCacheView(image_view); 02142 logmap=(Quantum *) RelinquishMagickMemory(logmap); 02143 if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse) 02144 return(MagickFalse); 02145 return(status); 02146 } 02147 default: 02148 break; 02149 } 02150 /* 02151 Allocate the tables. 02152 */ 02153 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL, 02154 sizeof(*x_map)); 02155 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL, 02156 sizeof(*y_map)); 02157 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL, 02158 sizeof(*z_map)); 02159 if ((x_map == (TransformPacket *) NULL) || 02160 (y_map == (TransformPacket *) NULL) || 02161 (z_map == (TransformPacket *) NULL)) 02162 { 02163 if (z_map != (TransformPacket *) NULL) 02164 z_map=(TransformPacket *) RelinquishMagickMemory(z_map); 02165 if (y_map != (TransformPacket *) NULL) 02166 y_map=(TransformPacket *) RelinquishMagickMemory(y_map); 02167 if (x_map != (TransformPacket *) NULL) 02168 x_map=(TransformPacket *) RelinquishMagickMemory(x_map); 02169 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 02170 image->filename); 02171 } 02172 switch (image->colorspace) 02173 { 02174 case OHTAColorspace: 02175 { 02176 /* 02177 Initialize OHTA tables: 02178 02179 R = I1+1.00000*I2-0.66668*I3 02180 G = I1+0.00000*I2+1.33333*I3 02181 B = I1-1.00000*I2-0.66668*I3 02182 02183 I and Q, normally -0.5 through 0.5, must be normalized to the range 0 02184 through QuantumRange. 02185 */ 02186 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02187 #pragma omp parallel for schedule(static) 02188 #endif 02189 for (i=0; i <= (ssize_t) MaxMap; i++) 02190 { 02191 x_map[i].x=(MagickRealType) i; 02192 y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType) 02193 MaxMap); 02194 z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType) 02195 MaxMap); 02196 x_map[i].y=(MagickRealType) i; 02197 y_map[i].y=0.000000f; 02198 z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType) 02199 MaxMap); 02200 x_map[i].z=(MagickRealType) i; 02201 y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType) 02202 MaxMap); 02203 z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType) 02204 MaxMap); 02205 } 02206 break; 02207 } 02208 case Rec601YCbCrColorspace: 02209 case YCbCrColorspace: 02210 { 02211 /* 02212 Initialize YCbCr tables: 02213 02214 R = Y +1.402000*Cr 02215 G = Y-0.344136*Cb-0.714136*Cr 02216 B = Y+1.772000*Cb 02217 02218 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0 02219 through QuantumRange. 02220 */ 02221 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02222 #pragma omp parallel for schedule(static) 02223 #endif 02224 for (i=0; i <= (ssize_t) MaxMap; i++) 02225 { 02226 x_map[i].x=(MagickRealType) i; 02227 y_map[i].x=0.000000f; 02228 z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i- 02229 (MagickRealType) MaxMap); 02230 x_map[i].y=(MagickRealType) i; 02231 y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i- 02232 (MagickRealType) MaxMap); 02233 z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i- 02234 (MagickRealType) MaxMap); 02235 x_map[i].z=(MagickRealType) i; 02236 y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i- 02237 (MagickRealType) MaxMap); 02238 z_map[i].z=0.000000f; 02239 } 02240 break; 02241 } 02242 case Rec709YCbCrColorspace: 02243 { 02244 /* 02245 Initialize YCbCr tables: 02246 02247 R = Y +1.574800*Cr 02248 G = Y-0.187324*Cb-0.468124*Cr 02249 B = Y+1.855600*Cb 02250 02251 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0 02252 through QuantumRange. 02253 */ 02254 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02255 #pragma omp parallel for schedule(static) 02256 #endif 02257 for (i=0; i <= (ssize_t) MaxMap; i++) 02258 { 02259 x_map[i].x=(MagickRealType) i; 02260 y_map[i].x=0.000000f; 02261 z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i- 02262 (MagickRealType) MaxMap); 02263 x_map[i].y=(MagickRealType) i; 02264 y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i- 02265 (MagickRealType) MaxMap); 02266 z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i- 02267 (MagickRealType) MaxMap); 02268 x_map[i].z=(MagickRealType) i; 02269 y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i- 02270 (MagickRealType) MaxMap); 02271 z_map[i].z=0.00000f; 02272 } 02273 break; 02274 } 02275 case sRGBColorspace: 02276 { 02277 /* 02278 Nonlinear sRGB to linear RGB. 02279 02280 R = 1.0*R+0.0*G+0.0*B 02281 G = 0.0*R+1.0*G+0.0*B 02282 B = 0.0*R+0.0*G+1.0*B 02283 */ 02284 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02285 #pragma omp parallel for schedule(static) 02286 #endif 02287 for (i=0; i <= (ssize_t) MaxMap; i++) 02288 { 02289 MagickRealType 02290 v; 02291 02292 v=(MagickRealType) i/(MagickRealType) MaxMap; 02293 if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.04045f) 02294 v/=12.92f; 02295 else 02296 v=(MagickRealType) pow((((double) i/MaxMap)+0.055)/1.055,2.4); 02297 x_map[i].x=1.0f*MaxMap*v; 02298 y_map[i].x=0.0f*MaxMap*v; 02299 z_map[i].x=0.0f*MaxMap*v; 02300 x_map[i].y=0.0f*MaxMap*v; 02301 y_map[i].y=1.0f*MaxMap*v; 02302 z_map[i].y=0.0f*MaxMap*v; 02303 x_map[i].z=0.0f*MaxMap*v; 02304 y_map[i].z=0.0f*MaxMap*v; 02305 z_map[i].z=1.0f*MaxMap*v; 02306 } 02307 break; 02308 } 02309 case XYZColorspace: 02310 { 02311 /* 02312 Initialize CIE XYZ tables (ITU R-709 RGB): 02313 02314 R = 3.2404542*X-1.5371385*Y-0.4985314*Z 02315 G = -0.9692660*X+1.8760108*Y+0.0415560*Z 02316 B = 0.0556434*X-0.2040259*Y+1.057225*Z 02317 */ 02318 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02319 #pragma omp parallel for schedule(static) 02320 #endif 02321 for (i=0; i <= (ssize_t) MaxMap; i++) 02322 { 02323 x_map[i].x=3.2404542f*(MagickRealType) i; 02324 x_map[i].y=(-0.9692660f)*(MagickRealType) i; 02325 x_map[i].z=0.0556434f*(MagickRealType) i; 02326 y_map[i].x=(-1.5371385f)*(MagickRealType) i; 02327 y_map[i].y=1.8760108f*(MagickRealType) i; 02328 y_map[i].z=(-0.2040259f)*(MagickRealType) i; 02329 z_map[i].x=(-0.4985314f)*(MagickRealType) i; 02330 z_map[i].y=0.0415560f*(MagickRealType) i; 02331 z_map[i].z=1.0572252f*(MagickRealType) i; 02332 } 02333 break; 02334 } 02335 case YCCColorspace: 02336 { 02337 /* 02338 Initialize YCC tables: 02339 02340 R = Y +1.340762*C2 02341 G = Y-0.317038*C1-0.682243*C2 02342 B = Y+1.632639*C1 02343 02344 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137. 02345 */ 02346 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02347 #pragma omp parallel for schedule(static) 02348 #endif 02349 for (i=0; i <= (ssize_t) MaxMap; i++) 02350 { 02351 x_map[i].x=1.3584000f*(MagickRealType) i; 02352 y_map[i].x=0.0000000f; 02353 z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType) 02354 ScaleQuantumToMap(ScaleCharToQuantum(137))); 02355 x_map[i].y=1.3584000f*(MagickRealType) i; 02356 y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType) 02357 ScaleQuantumToMap(ScaleCharToQuantum(156))); 02358 z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType) 02359 ScaleQuantumToMap(ScaleCharToQuantum(137))); 02360 x_map[i].z=1.3584000f*(MagickRealType) i; 02361 y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType) 02362 ScaleQuantumToMap(ScaleCharToQuantum(156))); 02363 z_map[i].z=0.0000000f; 02364 } 02365 break; 02366 } 02367 case YIQColorspace: 02368 { 02369 /* 02370 Initialize YIQ tables: 02371 02372 R = Y+0.95620*I+0.62140*Q 02373 G = Y-0.27270*I-0.64680*Q 02374 B = Y-1.10370*I+1.70060*Q 02375 02376 I and Q, normally -0.5 through 0.5, must be normalized to the range 0 02377 through QuantumRange. 02378 */ 02379 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02380 #pragma omp parallel for schedule(static) 02381 #endif 02382 for (i=0; i <= (ssize_t) MaxMap; i++) 02383 { 02384 x_map[i].x=(MagickRealType) i; 02385 y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType) 02386 MaxMap); 02387 z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType) 02388 MaxMap); 02389 x_map[i].y=(MagickRealType) i; 02390 y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType) 02391 MaxMap); 02392 z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType) 02393 MaxMap); 02394 x_map[i].z=(MagickRealType) i; 02395 y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType) 02396 MaxMap); 02397 z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType) 02398 MaxMap); 02399 } 02400 break; 02401 } 02402 case YPbPrColorspace: 02403 { 02404 /* 02405 Initialize YPbPr tables: 02406 02407 R = Y +1.402000*C2 02408 G = Y-0.344136*C1+0.714136*C2 02409 B = Y+1.772000*C1 02410 02411 Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0 02412 through QuantumRange. 02413 */ 02414 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02415 #pragma omp parallel for schedule(static) 02416 #endif 02417 for (i=0; i <= (ssize_t) MaxMap; i++) 02418 { 02419 x_map[i].x=(MagickRealType) i; 02420 y_map[i].x=0.000000f; 02421 z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType) 02422 MaxMap); 02423 x_map[i].y=(MagickRealType) i; 02424 y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType) 02425 MaxMap); 02426 z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType) 02427 MaxMap); 02428 x_map[i].z=(MagickRealType) i; 02429 y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType) 02430 MaxMap); 02431 z_map[i].z=0.00000f; 02432 } 02433 break; 02434 } 02435 case YUVColorspace: 02436 { 02437 /* 02438 Initialize YUV tables: 02439 02440 R = Y +1.13980*V 02441 G = Y-0.39380*U-0.58050*V 02442 B = Y+2.02790*U 02443 02444 U and V, normally -0.5 through 0.5, must be normalized to the range 0 02445 through QuantumRange. 02446 */ 02447 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02448 #pragma omp parallel for schedule(static) 02449 #endif 02450 for (i=0; i <= (ssize_t) MaxMap; i++) 02451 { 02452 x_map[i].x=(MagickRealType) i; 02453 y_map[i].x=0.00000f; 02454 z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType) 02455 MaxMap); 02456 x_map[i].y=(MagickRealType) i; 02457 y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType) 02458 MaxMap); 02459 z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType) 02460 MaxMap); 02461 x_map[i].z=(MagickRealType) i; 02462 y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType) 02463 MaxMap); 02464 z_map[i].z=0.00000f; 02465 } 02466 break; 02467 } 02468 default: 02469 { 02470 /* 02471 Linear conversion tables. 02472 */ 02473 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02474 #pragma omp parallel for schedule(static) 02475 #endif 02476 for (i=0; i <= (ssize_t) MaxMap; i++) 02477 { 02478 x_map[i].x=(MagickRealType) i; 02479 y_map[i].x=0.0f; 02480 z_map[i].x=0.0f; 02481 x_map[i].y=0.0f; 02482 y_map[i].y=(MagickRealType) i; 02483 z_map[i].y=0.0f; 02484 x_map[i].z=0.0f; 02485 y_map[i].z=0.0f; 02486 z_map[i].z=(MagickRealType) i; 02487 } 02488 break; 02489 } 02490 } 02491 /* 02492 Convert to RGB. 02493 */ 02494 switch (image->storage_class) 02495 { 02496 case DirectClass: 02497 default: 02498 { 02499 /* 02500 Convert DirectClass image. 02501 */ 02502 image_view=AcquireCacheView(image); 02503 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02504 #pragma omp parallel for schedule(static,4) shared(status) 02505 #endif 02506 for (y=0; y < (ssize_t) image->rows; y++) 02507 { 02508 MagickBooleanType 02509 sync; 02510 02511 PixelInfo 02512 pixel; 02513 02514 register ssize_t 02515 x; 02516 02517 register Quantum 02518 *restrict q; 02519 02520 if (status == MagickFalse) 02521 continue; 02522 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 02523 exception); 02524 if (q == (Quantum *) NULL) 02525 { 02526 status=MagickFalse; 02527 continue; 02528 } 02529 for (x=0; x < (ssize_t) image->columns; x++) 02530 { 02531 register size_t 02532 blue, 02533 green, 02534 red; 02535 02536 red=ScaleQuantumToMap(GetPixelRed(image,q)); 02537 green=ScaleQuantumToMap(GetPixelGreen(image,q)); 02538 blue=ScaleQuantumToMap(GetPixelBlue(image,q)); 02539 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x; 02540 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y; 02541 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z; 02542 switch (colorspace) 02543 { 02544 case YCCColorspace: 02545 { 02546 #if !defined(MAGICKCORE_HDRI_SUPPORT) 02547 pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale* 02548 pixel.red)]; 02549 pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale* 02550 pixel.green)]; 02551 pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale* 02552 pixel.blue)]; 02553 #endif 02554 break; 02555 } 02556 case sRGBColorspace: 02557 { 02558 if ((QuantumScale*pixel.red) <= 0.0031308) 02559 pixel.red*=12.92f; 02560 else 02561 pixel.red=(MagickRealType) QuantumRange*(1.055* 02562 pow(QuantumScale*pixel.red,(1.0/2.4))-0.055); 02563 if ((QuantumScale*pixel.green) <= 0.0031308) 02564 pixel.green*=12.92f; 02565 else 02566 pixel.green=(MagickRealType) QuantumRange*(1.055* 02567 pow(QuantumScale*pixel.green,(1.0/2.4))-0.055); 02568 if ((QuantumScale*pixel.blue) <= 0.0031308) 02569 pixel.blue*=12.92f; 02570 else 02571 pixel.blue=(MagickRealType) QuantumRange*(1.055* 02572 pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055); 02573 break; 02574 } 02575 default: 02576 break; 02577 } 02578 SetPixelRed(image,ScaleMapToQuantum((MagickRealType) MaxMap* 02579 QuantumScale*pixel.red),q); 02580 SetPixelGreen(image,ScaleMapToQuantum((MagickRealType) MaxMap* 02581 QuantumScale*pixel.green),q); 02582 SetPixelBlue(image,ScaleMapToQuantum((MagickRealType) MaxMap* 02583 QuantumScale*pixel.blue),q); 02584 q+=GetPixelChannels(image); 02585 } 02586 sync=SyncCacheViewAuthenticPixels(image_view,exception); 02587 if (sync == MagickFalse) 02588 status=MagickFalse; 02589 if (image->progress_monitor != (MagickProgressMonitor) NULL) 02590 { 02591 MagickBooleanType 02592 proceed; 02593 02594 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02595 #pragma omp critical (MagickCore_TransformRGBImage) 02596 #endif 02597 proceed=SetImageProgress(image,TransformRGBImageTag,progress++, 02598 image->rows); 02599 if (proceed == MagickFalse) 02600 status=MagickFalse; 02601 } 02602 } 02603 image_view=DestroyCacheView(image_view); 02604 break; 02605 } 02606 case PseudoClass: 02607 { 02608 /* 02609 Convert PseudoClass image. 02610 */ 02611 image_view=AcquireCacheView(image); 02612 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02613 #pragma omp parallel for schedule(static,4) shared(status) 02614 #endif 02615 for (i=0; i < (ssize_t) image->colors; i++) 02616 { 02617 PixelInfo 02618 pixel; 02619 02620 register size_t 02621 blue, 02622 green, 02623 red; 02624 02625 red=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red)); 02626 green=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green)); 02627 blue=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue)); 02628 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x; 02629 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y; 02630 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z; 02631 switch (colorspace) 02632 { 02633 case YCCColorspace: 02634 { 02635 #if !defined(MAGICKCORE_HDRI_SUPPORT) 02636 image->colormap[i].red=(double) (QuantumRange*YCCMap[ 02637 RoundToYCC(1024.0*QuantumScale*pixel.red)]); 02638 image->colormap[i].green=(double) (QuantumRange*YCCMap[ 02639 RoundToYCC(1024.0*QuantumScale*pixel.green)]); 02640 image->colormap[i].blue=(double) (QuantumRange*YCCMap[ 02641 RoundToYCC(1024.0*QuantumScale*pixel.blue)]); 02642 #endif 02643 break; 02644 } 02645 case sRGBColorspace: 02646 { 02647 if ((QuantumScale*pixel.red) <= 0.0031308) 02648 pixel.red*=12.92f; 02649 else 02650 pixel.red=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale* 02651 pixel.red,(1.0/2.4))-0.055); 02652 if ((QuantumScale*pixel.green) <= 0.0031308) 02653 pixel.green*=12.92f; 02654 else 02655 pixel.green=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale* 02656 pixel.green,(1.0/2.4))-0.055); 02657 if ((QuantumScale*pixel.blue) <= 0.0031308) 02658 pixel.blue*=12.92f; 02659 else 02660 pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale* 02661 pixel.blue,(1.0/2.4))-0.055); 02662 } 02663 default: 02664 { 02665 image->colormap[i].red=(double) ScaleMapToQuantum((MagickRealType) 02666 MaxMap*QuantumScale*pixel.red); 02667 image->colormap[i].green=(double) ScaleMapToQuantum((MagickRealType) 02668 MaxMap*QuantumScale*pixel.green); 02669 image->colormap[i].blue=(double) ScaleMapToQuantum((MagickRealType) 02670 MaxMap*QuantumScale*pixel.blue); 02671 break; 02672 } 02673 } 02674 } 02675 image_view=DestroyCacheView(image_view); 02676 (void) SyncImage(image,exception); 02677 break; 02678 } 02679 } 02680 /* 02681 Relinquish resources. 02682 */ 02683 z_map=(TransformPacket *) RelinquishMagickMemory(z_map); 02684 y_map=(TransformPacket *) RelinquishMagickMemory(y_map); 02685 x_map=(TransformPacket *) RelinquishMagickMemory(x_map); 02686 if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse) 02687 return(MagickFalse); 02688 return(MagickTrue); 02689 }