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