00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "magick/studio.h"
00043 #include "magick/property.h"
00044 #include "magick/cache.h"
00045 #include "magick/cache-private.h"
00046 #include "magick/cache-view.h"
00047 #include "magick/color.h"
00048 #include "magick/color-private.h"
00049 #include "magick/colorspace.h"
00050 #include "magick/colorspace-private.h"
00051 #include "magick/exception.h"
00052 #include "magick/exception-private.h"
00053 #include "magick/image.h"
00054 #include "magick/image-private.h"
00055 #include "magick/gem.h"
00056 #include "magick/memory_.h"
00057 #include "magick/monitor.h"
00058 #include "magick/monitor-private.h"
00059 #include "magick/pixel-private.h"
00060 #include "magick/quantize.h"
00061 #include "magick/quantum.h"
00062 #include "magick/string_.h"
00063 #include "magick/utility.h"
00064
00065
00066
00067
00068 typedef struct _TransformPacket
00069 {
00070 MagickRealType
00071 x,
00072 y,
00073 z;
00074 } TransformPacket;
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 static inline void ConvertRGBToXYZ(const Quantum red,const Quantum green,
00106 const Quantum blue,double *X,double *Y,double *Z)
00107 {
00108 double
00109 b,
00110 g,
00111 r;
00112
00113 assert(X != (double *) NULL);
00114 assert(Y != (double *) NULL);
00115 assert(Z != (double *) NULL);
00116 r=QuantumScale*red;
00117 g=QuantumScale*green;
00118 b=QuantumScale*blue;
00119 *X=0.4124240*r+0.3575790*g+0.1804640*b;
00120 *Y=0.2126560*r+0.7151580*g+0.0721856*b;
00121 *Z=0.0193324*r+0.1191930*g+0.9504440*b;
00122 }
00123
00124 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
00125 double *L,double *a,double *b)
00126 {
00127 double
00128 x,
00129 y,
00130 z;
00131
00132 assert(L != (double *) NULL);
00133 assert(a != (double *) NULL);
00134 assert(b != (double *) NULL);
00135 x=X/0.9504559271;
00136 if (x > (216/24389.0))
00137 x=pow(x,1.0/3.0);
00138 else
00139 x=(7.787*x)+(16.0/116.0);
00140 y=Y/1.00000;
00141 if (y > (216/24389.0))
00142 y=pow(y,1.0/3.0);
00143 else
00144 y=(7.787*y)+(16.0/116.0);
00145 z=Z/1.0890577508;
00146 if (z > (216/24389.0))
00147 z=pow(z,1.0/3.0);
00148 else
00149 z=(7.787*z)+(16.0/116.0);
00150 *L=0.5*((1.160*y)-0.160+1.0);
00151 *a=0.5*(5.000*(x-y)+1.0);
00152 *b=0.5*(2.000*(y-z)+1.0);
00153 }
00154
00155 MagickExport MagickBooleanType RGBTransformImage(Image *image,
00156 const ColorspaceType colorspace)
00157 {
00158 #define RGBTransformImageTag "RGBTransform/Image"
00159
00160 ExceptionInfo
00161 *exception;
00162
00163 long
00164 progress,
00165 y;
00166
00167 MagickBooleanType
00168 status,
00169 sync;
00170
00171 PrimaryInfo
00172 primary_info;
00173
00174 register long
00175 i;
00176
00177 TransformPacket
00178 *x_map,
00179 *y_map,
00180 *z_map;
00181
00182 CacheView
00183 *image_view;
00184
00185 assert(image != (Image *) NULL);
00186 assert(image->signature == MagickSignature);
00187 if (image->debug != MagickFalse)
00188 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00189 assert(colorspace != RGBColorspace);
00190 assert(colorspace != TransparentColorspace);
00191 assert(colorspace != UndefinedColorspace);
00192 switch (image->colorspace)
00193 {
00194 case GRAYColorspace:
00195 case Rec601LumaColorspace:
00196 case Rec709LumaColorspace:
00197 case RGBColorspace:
00198 case TransparentColorspace:
00199 break;
00200 default:
00201 {
00202 (void) TransformImageColorspace(image,image->colorspace);
00203 break;
00204 }
00205 }
00206 if (SetImageColorspace(image,colorspace) == MagickFalse)
00207 return(MagickFalse);
00208 status=MagickTrue;
00209 progress=0;
00210 exception=(&image->exception);
00211 switch (colorspace)
00212 {
00213 case CMYColorspace:
00214 {
00215
00216
00217
00218 if (image->storage_class == PseudoClass)
00219 {
00220 if (SyncImage(image) == MagickFalse)
00221 return(MagickFalse);
00222 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00223 return(MagickFalse);
00224 }
00225 image_view=AcquireCacheView(image);
00226 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00227 #pragma omp parallel for schedule(dynamic,4) shared(status)
00228 #endif
00229 for (y=0; y < (long) image->rows; y++)
00230 {
00231 register long
00232 x;
00233
00234 register PixelPacket
00235 *__restrict q;
00236
00237 if (status == MagickFalse)
00238 continue;
00239 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00240 exception);
00241 if (q == (PixelPacket *) NULL)
00242 {
00243 status=MagickFalse;
00244 continue;
00245 }
00246 for (x=0; x < (long) image->columns; x++)
00247 {
00248 q->red=RoundToQuantum((MagickRealType) (QuantumRange-q->red));
00249 q->green=RoundToQuantum((MagickRealType) (QuantumRange-q->green));
00250 q->blue=RoundToQuantum((MagickRealType) (QuantumRange-q->blue));
00251 q++;
00252 }
00253 sync=SyncCacheViewAuthenticPixels(image_view,exception);
00254 if (sync == MagickFalse)
00255 status=MagickFalse;
00256 }
00257 image_view=DestroyCacheView(image_view);
00258 image->type=image->matte == MagickFalse ? ColorSeparationType :
00259 ColorSeparationMatteType;
00260 return(status);
00261 }
00262 case CMYKColorspace:
00263 {
00264 MagickPixelPacket
00265 zero;
00266
00267
00268
00269
00270 if (image->storage_class == PseudoClass)
00271 {
00272 if (SyncImage(image) == MagickFalse)
00273 return(MagickFalse);
00274 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00275 return(MagickFalse);
00276 }
00277 GetMagickPixelPacket(image,&zero);
00278 image_view=AcquireCacheView(image);
00279 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00280 #pragma omp parallel for schedule(dynamic,4) shared(status)
00281 #endif
00282 for (y=0; y < (long) image->rows; y++)
00283 {
00284 MagickPixelPacket
00285 pixel;
00286
00287 register IndexPacket
00288 *__restrict indexes;
00289
00290 register long
00291 x;
00292
00293 register PixelPacket
00294 *__restrict q;
00295
00296 if (status == MagickFalse)
00297 continue;
00298 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00299 exception);
00300 if (q == (PixelPacket *) NULL)
00301 {
00302 status=MagickFalse;
00303 continue;
00304 }
00305 indexes=GetCacheViewAuthenticIndexQueue(image_view);
00306 pixel=zero;
00307 for (x=0; x < (long) image->columns; x++)
00308 {
00309 SetMagickPixelPacket(image,q,indexes+x,&pixel);
00310 ConvertRGBToCMYK(&pixel);
00311 SetPixelPacket(image,&pixel,q,indexes+x);
00312 q++;
00313 }
00314 sync=SyncCacheViewAuthenticPixels(image_view,exception);
00315 if (sync == MagickFalse)
00316 status=MagickFalse;
00317 }
00318 image_view=DestroyCacheView(image_view);
00319 image->type=image->matte == MagickFalse ? ColorSeparationType :
00320 ColorSeparationMatteType;
00321 return(status);
00322 }
00323 case HSBColorspace:
00324 {
00325
00326
00327
00328 if (image->storage_class == PseudoClass)
00329 {
00330 if (SyncImage(image) == MagickFalse)
00331 return(MagickFalse);
00332 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00333 return(MagickFalse);
00334 }
00335 image_view=AcquireCacheView(image);
00336 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00337 #pragma omp parallel for schedule(dynamic,4) shared(status)
00338 #endif
00339 for (y=0; y < (long) image->rows; y++)
00340 {
00341 double
00342 brightness,
00343 hue,
00344 saturation;
00345
00346 register long
00347 x;
00348
00349 register PixelPacket
00350 *__restrict q;
00351
00352 if (status == MagickFalse)
00353 continue;
00354 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00355 exception);
00356 if (q == (PixelPacket *) NULL)
00357 {
00358 status=MagickFalse;
00359 continue;
00360 }
00361 hue=0.0;
00362 saturation=0.0;
00363 brightness=0.0;
00364 for (x=0; x < (long) image->columns; x++)
00365 {
00366 ConvertRGBToHSB(q->red,q->green,q->blue,&hue,&saturation,&brightness);
00367 q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
00368 q->green=RoundToQuantum((MagickRealType) QuantumRange*saturation);
00369 q->blue=RoundToQuantum((MagickRealType) QuantumRange*brightness);
00370 q++;
00371 }
00372 sync=SyncCacheViewAuthenticPixels(image_view,exception);
00373 if (sync == MagickFalse)
00374 status=MagickFalse;
00375 }
00376 image_view=DestroyCacheView(image_view);
00377 return(status);
00378 }
00379 case HSLColorspace:
00380 {
00381
00382
00383
00384 if (image->storage_class == PseudoClass)
00385 {
00386 if (SyncImage(image) == MagickFalse)
00387 return(MagickFalse);
00388 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00389 return(MagickFalse);
00390 }
00391 image_view=AcquireCacheView(image);
00392 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00393 #pragma omp parallel for schedule(dynamic,4) shared(status)
00394 #endif
00395 for (y=0; y < (long) image->rows; y++)
00396 {
00397 double
00398 hue,
00399 lightness,
00400 saturation;
00401
00402 register long
00403 x;
00404
00405 register PixelPacket
00406 *__restrict q;
00407
00408 if (status == MagickFalse)
00409 continue;
00410 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00411 exception);
00412 if (q == (PixelPacket *) NULL)
00413 {
00414 status=MagickFalse;
00415 continue;
00416 }
00417 hue=0.0;
00418 saturation=0.0;
00419 lightness=0.0;
00420 for (x=0; x < (long) image->columns; x++)
00421 {
00422 ConvertRGBToHSL(q->red,q->green,q->blue,&hue,&saturation,&lightness);
00423 q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
00424 q->green=RoundToQuantum((MagickRealType) QuantumRange*saturation);
00425 q->blue=RoundToQuantum((MagickRealType) QuantumRange*lightness);
00426 q++;
00427 }
00428 sync=SyncCacheViewAuthenticPixels(image_view,exception);
00429 if (sync == MagickFalse)
00430 status=MagickFalse;
00431 }
00432 image_view=DestroyCacheView(image_view);
00433 return(status);
00434 }
00435 case HWBColorspace:
00436 {
00437
00438
00439
00440 if (image->storage_class == PseudoClass)
00441 {
00442 if (SyncImage(image) == MagickFalse)
00443 return(MagickFalse);
00444 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00445 return(MagickFalse);
00446 }
00447 image_view=AcquireCacheView(image);
00448 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00449 #pragma omp parallel for schedule(dynamic,4) shared(status)
00450 #endif
00451 for (y=0; y < (long) image->rows; y++)
00452 {
00453 double
00454 blackness,
00455 hue,
00456 whiteness;
00457
00458 register long
00459 x;
00460
00461 register PixelPacket
00462 *__restrict q;
00463
00464 if (status == MagickFalse)
00465 continue;
00466 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00467 exception);
00468 if (q == (PixelPacket *) NULL)
00469 {
00470 status=MagickFalse;
00471 continue;
00472 }
00473 hue=0.0;
00474 whiteness=0.0;
00475 blackness=0.0;
00476 for (x=0; x < (long) image->columns; x++)
00477 {
00478 ConvertRGBToHWB(q->red,q->green,q->blue,&hue,&whiteness,&blackness);
00479 q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
00480 q->green=RoundToQuantum((MagickRealType) QuantumRange*whiteness);
00481 q->blue=RoundToQuantum((MagickRealType) QuantumRange*blackness);
00482 q++;
00483 }
00484 sync=SyncCacheViewAuthenticPixels(image_view,exception);
00485 if (sync == MagickFalse)
00486 status=MagickFalse;
00487 }
00488 image_view=DestroyCacheView(image_view);
00489 return(status);
00490 }
00491 case LabColorspace:
00492 {
00493
00494
00495
00496 if (image->storage_class == PseudoClass)
00497 {
00498 if (SyncImage(image) == MagickFalse)
00499 return(MagickFalse);
00500 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00501 return(MagickFalse);
00502 }
00503 image_view=AcquireCacheView(image);
00504 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00505 #pragma omp parallel for schedule(dynamic,4) shared(status)
00506 #endif
00507 for (y=0; y < (long) image->rows; y++)
00508 {
00509 double
00510 a,
00511 b,
00512 L,
00513 X,
00514 Y,
00515 Z;
00516
00517 register long
00518 x;
00519
00520 register PixelPacket
00521 *__restrict q;
00522
00523 if (status == MagickFalse)
00524 continue;
00525 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00526 exception);
00527 if (q == (PixelPacket *) NULL)
00528 {
00529 status=MagickFalse;
00530 continue;
00531 }
00532 L=0.0;
00533 a=0.0;
00534 b=0.0;
00535 X=0.0;
00536 Y=0.0;
00537 Z=0.0;
00538 for (x=0; x < (long) image->columns; x++)
00539 {
00540 ConvertRGBToXYZ(q->red,q->green,q->blue,&X,&Y,&Z);
00541 ConvertXYZToLab(X,Y,Z,&L,&a,&b);
00542 q->red=RoundToQuantum((MagickRealType) QuantumRange*L);
00543 q->green=RoundToQuantum((MagickRealType) QuantumRange*a);
00544 q->blue=RoundToQuantum((MagickRealType) QuantumRange*b);
00545 q++;
00546 }
00547 sync=SyncCacheViewAuthenticPixels(image_view,exception);
00548 if (sync == MagickFalse)
00549 status=MagickFalse;
00550 }
00551 image_view=DestroyCacheView(image_view);
00552 return(status);
00553 }
00554 case LogColorspace:
00555 {
00556 #define ReferenceBlack 95.0
00557 #define ReferenceWhite 685.0
00558 #define DisplayGamma (1.0/1.7)
00559
00560 const char
00561 *value;
00562
00563 double
00564 black,
00565 density,
00566 gamma,
00567 reference_black,
00568 reference_white;
00569
00570 Quantum
00571 *logmap;
00572
00573
00574
00575
00576 density=2.03728;
00577 gamma=DisplayGamma;
00578 value=GetImageProperty(image,"gamma");
00579 if (value != (const char *) NULL)
00580 gamma=1.0/atof(value) != 0.0 ? atof(value) : 1.0;
00581 reference_black=ReferenceBlack;
00582 value=GetImageProperty(image,"reference-black");
00583 if (value != (const char *) NULL)
00584 reference_black=atof(value);
00585 reference_white=ReferenceWhite;
00586 value=GetImageProperty(image,"reference-white");
00587 if (value != (const char *) NULL)
00588 reference_white=atof(value);
00589 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00590 sizeof(*logmap));
00591 if (logmap == (Quantum *) NULL)
00592 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00593 image->filename);
00594 black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
00595 0.002/0.6);
00596 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00597 #pragma omp parallel for schedule(dynamic,4)
00598 #endif
00599 for (i=0; i <= (long) MaxMap; i++)
00600 logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+
00601 log10(black+((MagickRealType) i/MaxMap)*(1.0-black))/((gamma/density)*
00602 0.002/0.6))/1024.0+0.5));
00603 image_view=AcquireCacheView(image);
00604 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00605 #pragma omp parallel for schedule(dynamic,4) shared(status)
00606 #endif
00607 for (y=0; y < (long) image->rows; y++)
00608 {
00609 register long
00610 x;
00611
00612 register PixelPacket
00613 *__restrict q;
00614
00615 if (status == MagickFalse)
00616 continue;
00617 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00618 exception);
00619 if (q == (PixelPacket *) NULL)
00620 {
00621 status=MagickFalse;
00622 continue;
00623 }
00624 for (x=(long) image->columns; x != 0; x--)
00625 {
00626 q->red=logmap[ScaleQuantumToMap(q->red)];
00627 q->green=logmap[ScaleQuantumToMap(q->green)];
00628 q->blue=logmap[ScaleQuantumToMap(q->blue)];
00629 q++;
00630 }
00631 sync=SyncCacheViewAuthenticPixels(image_view,exception);
00632 if (sync == MagickFalse)
00633 status=MagickFalse;
00634 }
00635 image_view=DestroyCacheView(image_view);
00636 logmap=(Quantum *) RelinquishMagickMemory(logmap);
00637 return(status);
00638 }
00639 default:
00640 break;
00641 }
00642
00643
00644
00645 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00646 sizeof(*x_map));
00647 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00648 sizeof(*y_map));
00649 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00650 sizeof(*z_map));
00651 if ((x_map == (TransformPacket *) NULL) ||
00652 (y_map == (TransformPacket *) NULL) ||
00653 (z_map == (TransformPacket *) NULL))
00654 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00655 image->filename);
00656 (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
00657 switch (colorspace)
00658 {
00659 case OHTAColorspace:
00660 {
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 primary_info.y=(double) (MaxMap+1.0)/2.0;
00672 primary_info.z=(double) (MaxMap+1.0)/2.0;
00673 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00674 #pragma omp parallel for schedule(dynamic,4)
00675 #endif
00676 for (i=0; i <= (long) MaxMap; i++)
00677 {
00678 x_map[i].x=0.33333f*(MagickRealType) i;
00679 y_map[i].x=0.33334f*(MagickRealType) i;
00680 z_map[i].x=0.33333f*(MagickRealType) i;
00681 x_map[i].y=0.50000f*(MagickRealType) i;
00682 y_map[i].y=0.00000f*(MagickRealType) i;
00683 z_map[i].y=(-0.50000f)*(MagickRealType) i;
00684 x_map[i].z=(-0.25000f)*(MagickRealType) i;
00685 y_map[i].z=0.50000f*(MagickRealType) i;
00686 z_map[i].z=(-0.25000f)*(MagickRealType) i;
00687 }
00688 break;
00689 }
00690 case Rec601LumaColorspace:
00691 case GRAYColorspace:
00692 {
00693
00694
00695
00696
00697
00698 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00699 #pragma omp parallel for schedule(dynamic,4)
00700 #endif
00701 for (i=0; i <= (long) MaxMap; i++)
00702 {
00703 x_map[i].x=0.29900f*(MagickRealType) i;
00704 y_map[i].x=0.58700f*(MagickRealType) i;
00705 z_map[i].x=0.11400f*(MagickRealType) i;
00706 x_map[i].y=0.29900f*(MagickRealType) i;
00707 y_map[i].y=0.58700f*(MagickRealType) i;
00708 z_map[i].y=0.11400f*(MagickRealType) i;
00709 x_map[i].z=0.29900f*(MagickRealType) i;
00710 y_map[i].z=0.58700f*(MagickRealType) i;
00711 z_map[i].z=0.11400f*(MagickRealType) i;
00712 }
00713 image->type=GrayscaleType;
00714 break;
00715 }
00716 case Rec601YCbCrColorspace:
00717 case YCbCrColorspace:
00718 {
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729 primary_info.y=(double) (MaxMap+1.0)/2.0;
00730 primary_info.z=(double) (MaxMap+1.0)/2.0;
00731 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00732 #pragma omp parallel for schedule(dynamic,4)
00733 #endif
00734 for (i=0; i <= (long) MaxMap; i++)
00735 {
00736 x_map[i].x=0.299000f*(MagickRealType) i;
00737 y_map[i].x=0.587000f*(MagickRealType) i;
00738 z_map[i].x=0.114000f*(MagickRealType) i;
00739 x_map[i].y=(-0.168730f)*(MagickRealType) i;
00740 y_map[i].y=(-0.331264f)*(MagickRealType) i;
00741 z_map[i].y=0.500000f*(MagickRealType) i;
00742 x_map[i].z=0.500000f*(MagickRealType) i;
00743 y_map[i].z=(-0.418688f)*(MagickRealType) i;
00744 z_map[i].z=(-0.081312f)*(MagickRealType) i;
00745 }
00746 break;
00747 }
00748 case Rec709LumaColorspace:
00749 {
00750
00751
00752
00753
00754
00755 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00756 #pragma omp parallel for schedule(dynamic,4)
00757 #endif
00758 for (i=0; i <= (long) MaxMap; i++)
00759 {
00760 x_map[i].x=0.21260f*(MagickRealType) i;
00761 y_map[i].x=0.71520f*(MagickRealType) i;
00762 z_map[i].x=0.07220f*(MagickRealType) i;
00763 x_map[i].y=0.21260f*(MagickRealType) i;
00764 y_map[i].y=0.71520f*(MagickRealType) i;
00765 z_map[i].y=0.07220f*(MagickRealType) i;
00766 x_map[i].z=0.21260f*(MagickRealType) i;
00767 y_map[i].z=0.71520f*(MagickRealType) i;
00768 z_map[i].z=0.07220f*(MagickRealType) i;
00769 }
00770 break;
00771 }
00772 case Rec709YCbCrColorspace:
00773 {
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784 primary_info.y=(double) (MaxMap+1.0)/2.0;
00785 primary_info.z=(double) (MaxMap+1.0)/2.0;
00786 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00787 #pragma omp parallel for schedule(dynamic,4)
00788 #endif
00789 for (i=0; i <= (long) MaxMap; i++)
00790 {
00791 x_map[i].x=0.212600f*(MagickRealType) i;
00792 y_map[i].x=0.715200f*(MagickRealType) i;
00793 z_map[i].x=0.072200f*(MagickRealType) i;
00794 x_map[i].y=(-0.114572f)*(MagickRealType) i;
00795 y_map[i].y=(-0.385428f)*(MagickRealType) i;
00796 z_map[i].y=0.500000f*(MagickRealType) i;
00797 x_map[i].z=0.500000f*(MagickRealType) i;
00798 y_map[i].z=(-0.454153f)*(MagickRealType) i;
00799 z_map[i].z=(-0.045847f)*(MagickRealType) i;
00800 }
00801 break;
00802 }
00803 case sRGBColorspace:
00804 {
00805
00806
00807
00808
00809
00810
00811
00812 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00813 #pragma omp parallel for schedule(dynamic,4)
00814 #endif
00815 for (i=0; i <= (long) MaxMap; i++)
00816 {
00817 MagickRealType
00818 v;
00819
00820 v=(MagickRealType) i/(MagickRealType) MaxMap;
00821 if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.03928f)
00822 v/=12.92f;
00823 else
00824 v=(MagickRealType) MaxMap*pow((((double) i/MaxMap)+0.055)/1.055,2.4);
00825 x_map[i].x=1.0f*v;
00826 y_map[i].x=0.0f*v;
00827 z_map[i].x=0.0f*v;
00828 x_map[i].y=0.0f*v;
00829 y_map[i].y=1.0f*v;
00830 z_map[i].y=0.0f*v;
00831 x_map[i].z=0.0f*v;
00832 y_map[i].z=0.0f*v;
00833 z_map[i].z=1.0f*v;
00834 }
00835 break;
00836 }
00837 case XYZColorspace:
00838 {
00839
00840
00841
00842
00843
00844
00845
00846 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00847 #pragma omp parallel for schedule(dynamic,4)
00848 #endif
00849 for (i=0; i <= (long) MaxMap; i++)
00850 {
00851 x_map[i].x=0.4124564f*(MagickRealType) i;
00852 y_map[i].x=0.3575761f*(MagickRealType) i;
00853 z_map[i].x=0.1804375f*(MagickRealType) i;
00854 x_map[i].y=0.2126729f*(MagickRealType) i;
00855 y_map[i].y=0.7151522f*(MagickRealType) i;
00856 z_map[i].y=0.0721750f*(MagickRealType) i;
00857 x_map[i].z=0.0193339f*(MagickRealType) i;
00858 y_map[i].z=0.1191920f*(MagickRealType) i;
00859 z_map[i].z=0.9503041f*(MagickRealType) i;
00860 }
00861 break;
00862 }
00863 case YCCColorspace:
00864 {
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874 primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
00875 primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
00876 for (i=0; i <= (long) (0.018*MaxMap); i++)
00877 {
00878 x_map[i].x=0.003962014134275617f*(MagickRealType) i;
00879 y_map[i].x=0.007778268551236748f*(MagickRealType) i;
00880 z_map[i].x=0.001510600706713781f*(MagickRealType) i;
00881 x_map[i].y=(-0.002426619775463276f)*(MagickRealType) i;
00882 y_map[i].y=(-0.004763965913702149f)*(MagickRealType) i;
00883 z_map[i].y=0.007190585689165425f*(MagickRealType) i;
00884 x_map[i].z=0.006927257754597858f*(MagickRealType) i;
00885 y_map[i].z=(-0.005800713697502058f)*(MagickRealType) i;
00886 z_map[i].z=(-0.0011265440570958f)*(MagickRealType) i;
00887 }
00888 for ( ; i <= (long) MaxMap; i++)
00889 {
00890 x_map[i].x=0.2201118963486454*(1.099f*(MagickRealType) i-0.099f);
00891 y_map[i].x=0.4321260306242638*(1.099f*(MagickRealType) i-0.099f);
00892 z_map[i].x=0.08392226148409894*(1.099f*(MagickRealType) i-0.099f);
00893 x_map[i].y=(-0.1348122097479598)*(1.099f*(MagickRealType) i-0.099f);
00894 y_map[i].y=(-0.2646647729834528)*(1.099f*(MagickRealType) i-0.099f);
00895 z_map[i].y=0.3994769827314126*(1.099f*(MagickRealType) i-0.099f);
00896 x_map[i].z=0.3848476530332144*(1.099f*(MagickRealType) i-0.099f);
00897 y_map[i].z=(-0.3222618720834477)*(1.099f*(MagickRealType) i-0.099f);
00898 z_map[i].z=(-0.06258578094976668)*(1.099f*(MagickRealType) i-0.099f);
00899 }
00900 break;
00901 }
00902 case YIQColorspace:
00903 {
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914 primary_info.y=(double) (MaxMap+1.0)/2.0;
00915 primary_info.z=(double) (MaxMap+1.0)/2.0;
00916 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00917 #pragma omp parallel for schedule(dynamic,4)
00918 #endif
00919 for (i=0; i <= (long) MaxMap; i++)
00920 {
00921 x_map[i].x=0.29900f*(MagickRealType) i;
00922 y_map[i].x=0.58700f*(MagickRealType) i;
00923 z_map[i].x=0.11400f*(MagickRealType) i;
00924 x_map[i].y=0.59600f*(MagickRealType) i;
00925 y_map[i].y=(-0.27400f)*(MagickRealType) i;
00926 z_map[i].y=(-0.32200f)*(MagickRealType) i;
00927 x_map[i].z=0.21100f*(MagickRealType) i;
00928 y_map[i].z=(-0.52300f)*(MagickRealType) i;
00929 z_map[i].z=0.31200f*(MagickRealType) i;
00930 }
00931 break;
00932 }
00933 case YPbPrColorspace:
00934 {
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 primary_info.y=(double) (MaxMap+1.0)/2.0;
00946 primary_info.z=(double) (MaxMap+1.0)/2.0;
00947 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00948 #pragma omp parallel for schedule(dynamic,4)
00949 #endif
00950 for (i=0; i <= (long) MaxMap; i++)
00951 {
00952 x_map[i].x=0.299000f*(MagickRealType) i;
00953 y_map[i].x=0.587000f*(MagickRealType) i;
00954 z_map[i].x=0.114000f*(MagickRealType) i;
00955 x_map[i].y=(-0.168736f)*(MagickRealType) i;
00956 y_map[i].y=(-0.331264f)*(MagickRealType) i;
00957 z_map[i].y=0.500000f*(MagickRealType) i;
00958 x_map[i].z=0.500000f*(MagickRealType) i;
00959 y_map[i].z=(-0.418688f)*(MagickRealType) i;
00960 z_map[i].z=(-0.081312f)*(MagickRealType) i;
00961 }
00962 break;
00963 }
00964 case YUVColorspace:
00965 default:
00966 {
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977 primary_info.y=(double) (MaxMap+1.0)/2.0;
00978 primary_info.z=(double) (MaxMap+1.0)/2.0;
00979 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00980 #pragma omp parallel for schedule(dynamic,4)
00981 #endif
00982 for (i=0; i <= (long) MaxMap; i++)
00983 {
00984 x_map[i].x=0.29900f*(MagickRealType) i;
00985 y_map[i].x=0.58700f*(MagickRealType) i;
00986 z_map[i].x=0.11400f*(MagickRealType) i;
00987 x_map[i].y=(-0.14740f)*(MagickRealType) i;
00988 y_map[i].y=(-0.28950f)*(MagickRealType) i;
00989 z_map[i].y=0.43690f*(MagickRealType) i;
00990 x_map[i].z=0.61500f*(MagickRealType) i;
00991 y_map[i].z=(-0.51500f)*(MagickRealType) i;
00992 z_map[i].z=(-0.10000f)*(MagickRealType) i;
00993 }
00994 break;
00995 }
00996 }
00997
00998
00999
01000 switch (image->storage_class)
01001 {
01002 case DirectClass:
01003 default:
01004 {
01005
01006
01007
01008 image_view=AcquireCacheView(image);
01009 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01010 #pragma omp parallel for schedule(dynamic,4) shared(status)
01011 #endif
01012 for (y=0; y < (long) image->rows; y++)
01013 {
01014 MagickPixelPacket
01015 pixel;
01016
01017 register long
01018 x;
01019
01020 register PixelPacket
01021 *__restrict q;
01022
01023 register unsigned long
01024 blue,
01025 green,
01026 red;
01027
01028 if (status == MagickFalse)
01029 continue;
01030 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01031 exception);
01032 if (q == (PixelPacket *) NULL)
01033 {
01034 status=MagickFalse;
01035 continue;
01036 }
01037 for (x=0; x < (long) image->columns; x++)
01038 {
01039 red=ScaleQuantumToMap(q->red);
01040 green=ScaleQuantumToMap(q->green);
01041 blue=ScaleQuantumToMap(q->blue);
01042 pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
01043 (MagickRealType) primary_info.x;
01044 pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
01045 (MagickRealType) primary_info.y;
01046 pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
01047 (MagickRealType) primary_info.z;
01048 q->red=ScaleMapToQuantum(pixel.red);
01049 q->green=ScaleMapToQuantum(pixel.green);
01050 q->blue=ScaleMapToQuantum(pixel.blue);
01051 q++;
01052 }
01053 sync=SyncCacheViewAuthenticPixels(image_view,exception);
01054 if (sync == MagickFalse)
01055 status=MagickFalse;
01056 if (image->progress_monitor != (MagickProgressMonitor) NULL)
01057 {
01058 MagickBooleanType
01059 proceed;
01060
01061 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01062 #pragma omp critical (MagickCore_RGBTransformImage)
01063 #endif
01064 proceed=SetImageProgress(image,RGBTransformImageTag,progress++,
01065 image->rows);
01066 if (proceed == MagickFalse)
01067 status=MagickFalse;
01068 }
01069 }
01070 image_view=DestroyCacheView(image_view);
01071 break;
01072 }
01073 case PseudoClass:
01074 {
01075 register unsigned long
01076 blue,
01077 green,
01078 red;
01079
01080
01081
01082
01083 image_view=AcquireCacheView(image);
01084 for (i=0; i < (long) image->colors; i++)
01085 {
01086 MagickPixelPacket
01087 pixel;
01088
01089 red=ScaleQuantumToMap(image->colormap[i].red);
01090 green=ScaleQuantumToMap(image->colormap[i].green);
01091 blue=ScaleQuantumToMap(image->colormap[i].blue);
01092 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
01093 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
01094 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
01095 image->colormap[i].red=ScaleMapToQuantum(pixel.red);
01096 image->colormap[i].green=ScaleMapToQuantum(pixel.green);
01097 image->colormap[i].blue=ScaleMapToQuantum(pixel.blue);
01098 }
01099 image_view=DestroyCacheView(image_view);
01100 (void) SyncImage(image);
01101 break;
01102 }
01103 }
01104
01105
01106
01107 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
01108 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
01109 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
01110 if (SetImageColorspace(image,colorspace) == MagickFalse)
01111 return(MagickFalse);
01112 return(status);
01113 }
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 MagickExport MagickBooleanType SetImageColorspace(Image *image,
01141 const ColorspaceType colorspace)
01142 {
01143 Cache
01144 cache;
01145
01146 if (image->colorspace == colorspace)
01147 return(MagickTrue);
01148 image->colorspace=colorspace;
01149 cache=GetImagePixelCache(image,MagickTrue,&image->exception);
01150 image->colorspace=colorspace;
01151 return(cache == (Cache) NULL ? MagickFalse: MagickTrue);
01152 }
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
01180 const ColorspaceType colorspace)
01181 {
01182 MagickBooleanType
01183 status;
01184
01185 assert(image != (Image *) NULL);
01186 assert(image->signature == MagickSignature);
01187 if (image->debug != MagickFalse)
01188 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01189 if (colorspace == UndefinedColorspace)
01190 {
01191 if (SetImageColorspace(image,colorspace) == MagickFalse)
01192 return(MagickFalse);
01193 return(MagickTrue);
01194 }
01195 if (image->colorspace == colorspace)
01196 return(MagickTrue);
01197 if ((colorspace == RGBColorspace) || (colorspace == TransparentColorspace))
01198 return(TransformRGBImage(image,image->colorspace));
01199 status=MagickTrue;
01200 if ((image->colorspace != RGBColorspace) &&
01201 (image->colorspace != TransparentColorspace) &&
01202 (image->colorspace != GRAYColorspace))
01203 status=TransformRGBImage(image,image->colorspace);
01204 if (RGBTransformImage(image,colorspace) == MagickFalse)
01205 status=MagickFalse;
01206 return(status);
01207 }
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
01239 double *X,double *Y,double *Z)
01240 {
01241 double
01242 cube,
01243 x,
01244 y,
01245 z;
01246
01247 assert(X != (double *) NULL);
01248 assert(Y != (double *) NULL);
01249 assert(Z != (double *) NULL);
01250 y=(100.0*L+16.0)/116.0;
01251 x=255.0*(a > 0.5 ? a-1.0 : a)/500.0+y;
01252 z=y-255.0*(b > 0.5 ? b-1.0 : b)/200.0;
01253 cube=y*y*y;
01254 if (cube > 0.008856)
01255 y=cube;
01256 else
01257 y=(y-16.0/116.0)/7.787;
01258 cube=x*x*x;
01259 if (cube > 0.008856)
01260 x=cube;
01261 else
01262 x=(x-16.0/116.0)/7.787;
01263 cube=z*z*z;
01264 if (cube > 0.008856)
01265 z=cube;
01266 else
01267 z=(z-16.0/116.0)/7.787;
01268 *X=0.9504559271*x;
01269 *Y=1.0000000000*y;
01270 *Z=1.0890577508*z;
01271 }
01272
01273 static inline unsigned short RoundToYCC(const MagickRealType value)
01274 {
01275 if (value <= 0.0)
01276 return(0UL);
01277 if (value >= 350.0)
01278 return(350);
01279 return((unsigned short) (value+0.5));
01280 }
01281
01282 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
01283 Quantum *red,Quantum *green,Quantum *blue)
01284 {
01285 double
01286 b,
01287 g,
01288 r;
01289
01290
01291
01292
01293 assert(red != (Quantum *) NULL);
01294 assert(green != (Quantum *) NULL);
01295 assert(blue != (Quantum *) NULL);
01296 r=3.2404542*x-1.5371385*y-0.4985314*z;
01297 g=(-0.9692660*x+1.8760108*y+0.0415560*z);
01298 b=0.0556434*x-0.2040259*y+1.0572252*z;
01299 if (r > 0.0031308)
01300 r=1.055*pow(r,1.0/2.4)-0.055;
01301 else
01302 r*=12.92;
01303 if (g > 0.0031308)
01304 g=1.055*pow(g,1.0/2.4)-0.055;
01305 else
01306 g*=12.92;
01307 if (b > 0.0031308)
01308 b=1.055*pow(b,1.0/2.4)-0.055;
01309 else
01310 b*=12.92;
01311 *red=RoundToQuantum((MagickRealType) QuantumRange*r);
01312 *green=RoundToQuantum((MagickRealType) QuantumRange*g);
01313 *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
01314 }
01315
01316 static inline void ConvertCMYKToRGB(MagickPixelPacket *pixel)
01317 {
01318 pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red*
01319 (QuantumRange-pixel->index)+pixel->index);
01320 pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green*
01321 (QuantumRange-pixel->index)+pixel->index);
01322 pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue*
01323 (QuantumRange-pixel->index)+pixel->index);
01324 }
01325
01326 MagickExport MagickBooleanType TransformRGBImage(Image *image,
01327 const ColorspaceType colorspace)
01328 {
01329 #define D50X (0.9642)
01330 #define D50Y (1.0)
01331 #define D50Z (0.8249)
01332 #define TransformRGBImageTag "Transform/Image"
01333
01334 #if !defined(MAGICKCORE_HDRI_SUPPORT)
01335 static const unsigned char
01336 YCCMap[351] =
01337 {
01338 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
01339 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
01340 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
01341 43, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 58,
01342 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 71, 72, 73,
01343 74, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89,
01344 90, 91, 92, 93, 94, 95, 97, 98, 99, 100, 101, 102, 103, 104,
01345 105, 106, 107, 108, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
01346 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134,
01347 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
01348 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
01349 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
01350 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
01351 190, 191, 192, 193, 193, 194, 195, 196, 197, 198, 199, 200, 201, 201,
01352 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 211, 212, 213,
01353 214, 215, 215, 216, 217, 218, 218, 219, 220, 221, 221, 222, 223, 224,
01354 224, 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232, 233,
01355 234, 234, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240, 241, 241,
01356 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 247,
01357 248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 251, 251, 251,
01358 251, 251, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253,
01359 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254,
01360 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255,
01361 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
01362 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
01363 255
01364 };
01365 #endif
01366
01367 ExceptionInfo
01368 *exception;
01369
01370 long
01371 progress,
01372 y;
01373
01374 MagickBooleanType
01375 status;
01376
01377 register long
01378 i;
01379
01380 TransformPacket
01381 *y_map,
01382 *x_map,
01383 *z_map;
01384
01385 CacheView
01386 *image_view;
01387
01388 assert(image != (Image *) NULL);
01389 assert(image->signature == MagickSignature);
01390 if (image->debug != MagickFalse)
01391 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01392 switch (colorspace)
01393 {
01394 case GRAYColorspace:
01395 case Rec601LumaColorspace:
01396 case Rec709LumaColorspace:
01397 case RGBColorspace:
01398 case TransparentColorspace:
01399 case UndefinedColorspace:
01400 return(MagickTrue);
01401 default:
01402 break;
01403 }
01404 status=MagickTrue;
01405 progress=0;
01406 exception=(&image->exception);
01407 switch (colorspace)
01408 {
01409 case CMYColorspace:
01410 {
01411
01412
01413
01414 if (image->storage_class == PseudoClass)
01415 {
01416 if (SyncImage(image) == MagickFalse)
01417 return(MagickFalse);
01418 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
01419 return(MagickFalse);
01420 }
01421 image_view=AcquireCacheView(image);
01422 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01423 #pragma omp parallel for schedule(dynamic,4) shared(status)
01424 #endif
01425 for (y=0; y < (long) image->rows; y++)
01426 {
01427 MagickBooleanType
01428 sync;
01429
01430 register long
01431 x;
01432
01433 register PixelPacket
01434 *__restrict q;
01435
01436 if (status == MagickFalse)
01437 continue;
01438 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01439 exception);
01440 if (q == (PixelPacket *) NULL)
01441 {
01442 status=MagickFalse;
01443 continue;
01444 }
01445 for (x=0; x < (long) image->columns; x++)
01446 {
01447 q->red=RoundToQuantum((MagickRealType) (QuantumRange-q->red));
01448 q->green=RoundToQuantum((MagickRealType) (QuantumRange-q->green));
01449 q->blue=RoundToQuantum((MagickRealType) (QuantumRange-q->blue));
01450 q++;
01451 }
01452 sync=SyncCacheViewAuthenticPixels(image_view,exception);
01453 if (sync == MagickFalse)
01454 status=MagickFalse;
01455 }
01456 image_view=DestroyCacheView(image_view);
01457 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
01458 return(MagickFalse);
01459 return(status);
01460 }
01461 case CMYKColorspace:
01462 {
01463 MagickPixelPacket
01464 zero;
01465
01466
01467
01468
01469 if (image->storage_class == PseudoClass)
01470 {
01471 if (SyncImage(image) == MagickFalse)
01472 return(MagickFalse);
01473 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
01474 return(MagickFalse);
01475 }
01476 GetMagickPixelPacket(image,&zero);
01477 image_view=AcquireCacheView(image);
01478 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01479 #pragma omp parallel for schedule(dynamic,4) shared(status)
01480 #endif
01481 for (y=0; y < (long) image->rows; y++)
01482 {
01483 MagickBooleanType
01484 sync;
01485
01486 MagickPixelPacket
01487 pixel;
01488
01489 register IndexPacket
01490 *__restrict indexes;
01491
01492 register long
01493 x;
01494
01495 register PixelPacket
01496 *__restrict q;
01497
01498 if (status == MagickFalse)
01499 continue;
01500 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01501 exception);
01502 if (q == (PixelPacket *) NULL)
01503 {
01504 status=MagickFalse;
01505 continue;
01506 }
01507 indexes=GetCacheViewAuthenticIndexQueue(image_view);
01508 pixel=zero;
01509 for (x=0; x < (long) image->columns; x++)
01510 {
01511 SetMagickPixelPacket(image,q,indexes+x,&pixel);
01512 ConvertCMYKToRGB(&pixel);
01513 SetPixelPacket(image,&pixel,q,indexes+x);
01514 q++;
01515 }
01516 sync=SyncCacheViewAuthenticPixels(image_view,exception);
01517 if (sync == MagickFalse)
01518 status=MagickFalse;
01519 }
01520 image_view=DestroyCacheView(image_view);
01521 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
01522 return(MagickFalse);
01523 return(status);
01524 }
01525 case HSBColorspace:
01526 {
01527
01528
01529
01530 if (image->storage_class == PseudoClass)
01531 {
01532 if (SyncImage(image) == MagickFalse)
01533 return(MagickFalse);
01534 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
01535 return(MagickFalse);
01536 }
01537 image_view=AcquireCacheView(image);
01538 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01539 #pragma omp parallel for schedule(dynamic,4) shared(status)
01540 #endif
01541 for (y=0; y < (long) image->rows; y++)
01542 {
01543 double
01544 brightness,
01545 hue,
01546 saturation;
01547
01548 MagickBooleanType
01549 sync;
01550
01551 register long
01552 x;
01553
01554 register PixelPacket
01555 *__restrict q;
01556
01557 if (status == MagickFalse)
01558 continue;
01559 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01560 exception);
01561 if (q == (PixelPacket *) NULL)
01562 {
01563 status=MagickFalse;
01564 continue;
01565 }
01566 for (x=0; x < (long) image->columns; x++)
01567 {
01568 hue=(double) (QuantumScale*q->red);
01569 saturation=(double) (QuantumScale*q->green);
01570 brightness=(double) (QuantumScale*q->blue);
01571 ConvertHSBToRGB(hue,saturation,brightness,&q->red,&q->green,&q->blue);
01572 q++;
01573 }
01574 sync=SyncCacheViewAuthenticPixels(image_view,exception);
01575 if (sync == MagickFalse)
01576 status=MagickFalse;
01577 }
01578 image_view=DestroyCacheView(image_view);
01579 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
01580 return(MagickFalse);
01581 return(status);
01582 }
01583 case HSLColorspace:
01584 {
01585
01586
01587
01588 if (image->storage_class == PseudoClass)
01589 {
01590 if (SyncImage(image) == MagickFalse)
01591 return(MagickFalse);
01592 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
01593 return(MagickFalse);
01594 }
01595 image_view=AcquireCacheView(image);
01596 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01597 #pragma omp parallel for schedule(dynamic,4) shared(status)
01598 #endif
01599 for (y=0; y < (long) image->rows; y++)
01600 {
01601 double
01602 hue,
01603 lightness,
01604 saturation;
01605
01606 MagickBooleanType
01607 sync;
01608
01609 register long
01610 x;
01611
01612 register PixelPacket
01613 *__restrict q;
01614
01615 if (status == MagickFalse)
01616 continue;
01617 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01618 exception);
01619 if (q == (PixelPacket *) NULL)
01620 {
01621 status=MagickFalse;
01622 continue;
01623 }
01624 for (x=0; x < (long) image->columns; x++)
01625 {
01626 hue=(double) (QuantumScale*q->red);
01627 saturation=(double) (QuantumScale*q->green);
01628 lightness=(double) (QuantumScale*q->blue);
01629 ConvertHSLToRGB(hue,saturation,lightness,&q->red,&q->green,&q->blue);
01630 q++;
01631 }
01632 sync=SyncCacheViewAuthenticPixels(image_view,exception);
01633 if (sync == MagickFalse)
01634 status=MagickFalse;
01635 }
01636 image_view=DestroyCacheView(image_view);
01637 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
01638 return(MagickFalse);
01639 return(status);
01640 }
01641 case HWBColorspace:
01642 {
01643
01644
01645
01646 if (image->storage_class == PseudoClass)
01647 {
01648 if (SyncImage(image) == MagickFalse)
01649 return(MagickFalse);
01650 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
01651 return(MagickFalse);
01652 }
01653 image_view=AcquireCacheView(image);
01654 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01655 #pragma omp parallel for schedule(dynamic,4) shared(status)
01656 #endif
01657 for (y=0; y < (long) image->rows; y++)
01658 {
01659 double
01660 blackness,
01661 hue,
01662 whiteness;
01663
01664 MagickBooleanType
01665 sync;
01666
01667 register long
01668 x;
01669
01670 register PixelPacket
01671 *__restrict q;
01672
01673 if (status == MagickFalse)
01674 continue;
01675 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01676 exception);
01677 if (q == (PixelPacket *) NULL)
01678 {
01679 status=MagickFalse;
01680 continue;
01681 }
01682 for (x=0; x < (long) image->columns; x++)
01683 {
01684 hue=(double) (QuantumScale*q->red);
01685 whiteness=(double) (QuantumScale*q->green);
01686 blackness=(double) (QuantumScale*q->blue);
01687 ConvertHWBToRGB(hue,whiteness,blackness,&q->red,&q->green,&q->blue);
01688 q++;
01689 }
01690 sync=SyncCacheViewAuthenticPixels(image_view,exception);
01691 if (sync == MagickFalse)
01692 status=MagickFalse;
01693 }
01694 image_view=DestroyCacheView(image_view);
01695 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
01696 return(MagickFalse);
01697 return(status);
01698 }
01699 case LabColorspace:
01700 {
01701
01702
01703
01704 if (image->storage_class == PseudoClass)
01705 {
01706 if (SyncImage(image) == MagickFalse)
01707 return(MagickFalse);
01708 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
01709 return(MagickFalse);
01710 }
01711 image_view=AcquireCacheView(image);
01712 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01713 #pragma omp parallel for schedule(dynamic,4) shared(status)
01714 #endif
01715 for (y=0; y < (long) image->rows; y++)
01716 {
01717 double
01718 a,
01719 b,
01720 L,
01721 X,
01722 Y,
01723 Z;
01724
01725 MagickBooleanType
01726 sync;
01727
01728 register long
01729 x;
01730
01731 register PixelPacket
01732 *__restrict q;
01733
01734 if (status == MagickFalse)
01735 continue;
01736 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01737 exception);
01738 if (q == (PixelPacket *) NULL)
01739 {
01740 status=MagickFalse;
01741 continue;
01742 }
01743 X=0.0;
01744 Y=0.0;
01745 Z=0.0;
01746 for (x=0; x < (long) image->columns; x++)
01747 {
01748 L=QuantumScale*q->red;
01749 a=QuantumScale*q->green;
01750 b=QuantumScale*q->blue;
01751 ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
01752 ConvertXYZToRGB(X,Y,Z,&q->red,&q->green,&q->blue);
01753 q++;
01754 }
01755 sync=SyncCacheViewAuthenticPixels(image_view,exception);
01756 if (sync == MagickFalse)
01757 status=MagickFalse;
01758 }
01759 image_view=DestroyCacheView(image_view);
01760 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
01761 return(MagickFalse);
01762 return(status);
01763 }
01764 case LogColorspace:
01765 {
01766 const char
01767 *value;
01768
01769 double
01770 black,
01771 density,
01772 gamma,
01773 reference_black,
01774 reference_white;
01775
01776 Quantum
01777 *logmap;
01778
01779
01780
01781
01782 density=2.03728;
01783 gamma=DisplayGamma;
01784 value=GetImageProperty(image,"gamma");
01785 if (value != (const char *) NULL)
01786 gamma=1.0/atof(value) != 0.0 ? atof(value) : 1.0;
01787 reference_black=ReferenceBlack;
01788 value=GetImageProperty(image,"reference-black");
01789 if (value != (const char *) NULL)
01790 reference_black=atof(value);
01791 reference_white=ReferenceWhite;
01792 value=GetImageProperty(image,"reference-white");
01793 if (value != (const char *) NULL)
01794 reference_white=atof(value);
01795 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
01796 sizeof(*logmap));
01797 if (logmap == (Quantum *) NULL)
01798 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
01799 image->filename);
01800 black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
01801 0.002/0.6);
01802 for (i=0; i <= (long) (reference_black*MaxMap/1024.0); i++)
01803 logmap[i]=(Quantum) 0;
01804 for ( ; i < (long) (reference_white*MaxMap/1024.0); i++)
01805 logmap[i]=RoundToQuantum((MagickRealType) QuantumRange/(1.0-black)*
01806 (pow(10.0,(1024.0*i/MaxMap-reference_white)*
01807 (gamma/density)*0.002/0.6)-black));
01808 for ( ; i <= (long) MaxMap; i++)
01809 logmap[i]=(Quantum) QuantumRange;
01810 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
01811 return(MagickFalse);
01812 image_view=AcquireCacheView(image);
01813 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01814 #pragma omp parallel for schedule(dynamic,4) shared(status)
01815 #endif
01816 for (y=0; y < (long) image->rows; y++)
01817 {
01818 MagickBooleanType
01819 sync;
01820
01821 register long
01822 x;
01823
01824 register PixelPacket
01825 *__restrict q;
01826
01827 if (status == MagickFalse)
01828 continue;
01829 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01830 exception);
01831 if (q == (PixelPacket *) NULL)
01832 {
01833 status=MagickFalse;
01834 continue;
01835 }
01836 for (x=(long) image->columns; x != 0; x--)
01837 {
01838 q->red=logmap[ScaleQuantumToMap(q->red)];
01839 q->green=logmap[ScaleQuantumToMap(q->green)];
01840 q->blue=logmap[ScaleQuantumToMap(q->blue)];
01841 q++;
01842 }
01843 sync=SyncCacheViewAuthenticPixels(image_view,exception);
01844 if (sync == MagickFalse)
01845 status=MagickFalse;
01846 }
01847 image_view=DestroyCacheView(image_view);
01848 logmap=(Quantum *) RelinquishMagickMemory(logmap);
01849 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
01850 return(MagickFalse);
01851 return(status);
01852 }
01853 default:
01854 break;
01855 }
01856
01857
01858
01859 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
01860 sizeof(*x_map));
01861 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
01862 sizeof(*y_map));
01863 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
01864 sizeof(*z_map));
01865 if ((x_map == (TransformPacket *) NULL) ||
01866 (y_map == (TransformPacket *) NULL) ||
01867 (z_map == (TransformPacket *) NULL))
01868 {
01869 if (z_map != (TransformPacket *) NULL)
01870 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
01871 if (y_map != (TransformPacket *) NULL)
01872 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
01873 if (x_map != (TransformPacket *) NULL)
01874 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
01875 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
01876 image->filename);
01877 }
01878 switch (colorspace)
01879 {
01880 case OHTAColorspace:
01881 {
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01893 #pragma omp parallel for schedule(dynamic,4)
01894 #endif
01895 for (i=0; i <= (long) MaxMap; i++)
01896 {
01897 x_map[i].x=(MagickRealType) i;
01898 y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType)
01899 MaxMap);
01900 z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
01901 MaxMap);
01902 x_map[i].y=(MagickRealType) i;
01903 y_map[i].y=0.000000f;
01904 z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType)
01905 MaxMap);
01906 x_map[i].z=(MagickRealType) i;
01907 y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType)
01908 MaxMap);
01909 z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
01910 MaxMap);
01911 }
01912 break;
01913 }
01914 case Rec601YCbCrColorspace:
01915 case YCbCrColorspace:
01916 {
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01928 #pragma omp parallel for schedule(dynamic,4)
01929 #endif
01930 for (i=0; i <= (long) MaxMap; i++)
01931 {
01932 x_map[i].x=(MagickRealType) i;
01933 y_map[i].x=0.000000f;
01934 z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i-
01935 (MagickRealType) MaxMap);
01936 x_map[i].y=(MagickRealType) i;
01937 y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i-
01938 (MagickRealType) MaxMap);
01939 z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i-
01940 (MagickRealType) MaxMap);
01941 x_map[i].z=(MagickRealType) i;
01942 y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i-
01943 (MagickRealType) MaxMap);
01944 z_map[i].z=0.000000f;
01945 }
01946 break;
01947 }
01948 case Rec709YCbCrColorspace:
01949 {
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01961 #pragma omp parallel for schedule(dynamic,4)
01962 #endif
01963 for (i=0; i <= (long) MaxMap; i++)
01964 {
01965 x_map[i].x=(MagickRealType) i;
01966 y_map[i].x=0.000000f;
01967 z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i-
01968 (MagickRealType) MaxMap);
01969 x_map[i].y=(MagickRealType) i;
01970 y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i-
01971 (MagickRealType) MaxMap);
01972 z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i-
01973 (MagickRealType) MaxMap);
01974 x_map[i].z=(MagickRealType) i;
01975 y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i-
01976 (MagickRealType) MaxMap);
01977 z_map[i].z=0.00000f;
01978 }
01979 break;
01980 }
01981 case sRGBColorspace:
01982 {
01983
01984
01985
01986
01987
01988
01989
01990 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01991 #pragma omp parallel for schedule(dynamic,4)
01992 #endif
01993 for (i=0; i <= (long) MaxMap; i++)
01994 {
01995 x_map[i].x=1.0f*(MagickRealType) i;
01996 y_map[i].x=0.0f*(MagickRealType) i;
01997 z_map[i].x=0.0f*(MagickRealType) i;
01998 x_map[i].y=0.0f*(MagickRealType) i;
01999 y_map[i].y=1.0f*(MagickRealType) i;
02000 z_map[i].y=0.0f*(MagickRealType) i;
02001 x_map[i].z=0.0f*(MagickRealType) i;
02002 y_map[i].z=0.0f*(MagickRealType) i;
02003 z_map[i].z=1.0f*(MagickRealType) i;
02004 }
02005 break;
02006 }
02007 case XYZColorspace:
02008 {
02009
02010
02011
02012
02013
02014
02015
02016 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02017 #pragma omp parallel for schedule(dynamic,4)
02018 #endif
02019 for (i=0; i <= (long) MaxMap; i++)
02020 {
02021 x_map[i].x=3.2404542f*(MagickRealType) i;
02022 x_map[i].y=(-0.9692660f)*(MagickRealType) i;
02023 x_map[i].z=0.0556434f*(MagickRealType) i;
02024 y_map[i].x=(-1.5371385f)*(MagickRealType) i;
02025 y_map[i].y=1.8760108f*(MagickRealType) i;
02026 y_map[i].z=(-0.2040259f)*(MagickRealType) i;
02027 z_map[i].x=(-0.4985314f)*(MagickRealType) i;
02028 z_map[i].y=0.0415560f*(MagickRealType) i;
02029 z_map[i].z=1.0572252f*(MagickRealType) i;
02030 }
02031 break;
02032 }
02033 case YCCColorspace:
02034 {
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02045 #pragma omp parallel for schedule(dynamic,4)
02046 #endif
02047 for (i=0; i <= (long) MaxMap; i++)
02048 {
02049 x_map[i].x=1.3584000f*(MagickRealType) i;
02050 y_map[i].x=0.0000000f;
02051 z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType)
02052 ScaleQuantumToMap(ScaleCharToQuantum(137)));
02053 x_map[i].y=1.3584000f*(MagickRealType) i;
02054 y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType)
02055 ScaleQuantumToMap(ScaleCharToQuantum(156)));
02056 z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType)
02057 ScaleQuantumToMap(ScaleCharToQuantum(137)));
02058 x_map[i].z=1.3584000f*(MagickRealType) i;
02059 y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType)
02060 ScaleQuantumToMap(ScaleCharToQuantum(156)));
02061 z_map[i].z=0.0000000f;
02062 }
02063 break;
02064 }
02065 case YIQColorspace:
02066 {
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02078 #pragma omp parallel for schedule(dynamic,4)
02079 #endif
02080 for (i=0; i <= (long) MaxMap; i++)
02081 {
02082 x_map[i].x=(MagickRealType) i;
02083 y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType)
02084 MaxMap);
02085 z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType)
02086 MaxMap);
02087 x_map[i].y=(MagickRealType) i;
02088 y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02089 MaxMap);
02090 z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02091 MaxMap);
02092 x_map[i].z=(MagickRealType) i;
02093 y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02094 MaxMap);
02095 z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType)
02096 MaxMap);
02097 }
02098 break;
02099 }
02100 case YPbPrColorspace:
02101 {
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02113 #pragma omp parallel for schedule(dynamic,4)
02114 #endif
02115 for (i=0; i <= (long) MaxMap; i++)
02116 {
02117 x_map[i].x=(MagickRealType) i;
02118 y_map[i].x=0.000000f;
02119 z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType)
02120 MaxMap);
02121 x_map[i].y=(MagickRealType) i;
02122 y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02123 MaxMap);
02124 z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType)
02125 MaxMap);
02126 x_map[i].z=(MagickRealType) i;
02127 y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType)
02128 MaxMap);
02129 z_map[i].z=0.00000f;
02130 }
02131 break;
02132 }
02133 case YUVColorspace:
02134 default:
02135 {
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02147 #pragma omp parallel for schedule(dynamic,4)
02148 #endif
02149 for (i=0; i <= (long) MaxMap; i++)
02150 {
02151 x_map[i].x=(MagickRealType) i;
02152 y_map[i].x=0.00000f;
02153 z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType)
02154 MaxMap);
02155 x_map[i].y=(MagickRealType) i;
02156 y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02157 MaxMap);
02158 z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02159 MaxMap);
02160 x_map[i].z=(MagickRealType) i;
02161 y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType)
02162 MaxMap);
02163 z_map[i].z=0.00000f;
02164 }
02165 break;
02166 }
02167 }
02168
02169
02170
02171 switch (image->storage_class)
02172 {
02173 case DirectClass:
02174 default:
02175 {
02176
02177
02178
02179 image_view=AcquireCacheView(image);
02180 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02181 #pragma omp parallel for schedule(dynamic,4) shared(status)
02182 #endif
02183 for (y=0; y < (long) image->rows; y++)
02184 {
02185 MagickBooleanType
02186 sync;
02187
02188 MagickPixelPacket
02189 pixel;
02190
02191 register long
02192 x;
02193
02194 register PixelPacket
02195 *__restrict q;
02196
02197 if (status == MagickFalse)
02198 continue;
02199 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
02200 exception);
02201 if (q == (PixelPacket *) NULL)
02202 {
02203 status=MagickFalse;
02204 continue;
02205 }
02206 for (x=0; x < (long) image->columns; x++)
02207 {
02208 register unsigned long
02209 blue,
02210 green,
02211 red;
02212
02213 red=ScaleQuantumToMap(q->red);
02214 green=ScaleQuantumToMap(q->green);
02215 blue=ScaleQuantumToMap(q->blue);
02216 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
02217 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
02218 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
02219 switch (colorspace)
02220 {
02221 case YCCColorspace:
02222 {
02223 #if !defined(MAGICKCORE_HDRI_SUPPORT)
02224 pixel.red=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
02225 255.0*QuantumScale*pixel.red)]);
02226 pixel.green=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
02227 255.0*QuantumScale*pixel.green)]);
02228 pixel.blue=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
02229 255.0*QuantumScale*pixel.blue)]);
02230 #endif
02231 break;
02232 }
02233 case sRGBColorspace:
02234 {
02235 if ((QuantumScale*pixel.red) <= 0.0031308)
02236 pixel.red*=12.92f;
02237 else
02238 pixel.red=(MagickRealType) QuantumRange*(1.055*
02239 pow(QuantumScale*pixel.red,(1.0/2.4))-0.055);
02240 if ((QuantumScale*pixel.green) <= 0.0031308)
02241 pixel.green*=12.92f;
02242 else
02243 pixel.green=(MagickRealType) QuantumRange*(1.055*
02244 pow(QuantumScale*pixel.green,(1.0/2.4))-0.055);
02245 if ((QuantumScale*pixel.blue) <= 0.0031308)
02246 pixel.blue*=12.92f;
02247 else
02248 pixel.blue=(MagickRealType) QuantumRange*(1.055*
02249 pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055);
02250 break;
02251 }
02252 default:
02253 break;
02254 }
02255 q->red=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
02256 pixel.red);
02257 q->green=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
02258 pixel.green);
02259 q->blue=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
02260 pixel.blue);
02261 q++;
02262 }
02263 sync=SyncCacheViewAuthenticPixels(image_view,exception);
02264 if (sync == MagickFalse)
02265 status=MagickFalse;
02266 if (image->progress_monitor != (MagickProgressMonitor) NULL)
02267 {
02268 MagickBooleanType
02269 proceed;
02270
02271 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02272 #pragma omp critical (MagickCore_TransformRGBImage)
02273 #endif
02274 proceed=SetImageProgress(image,TransformRGBImageTag,progress++,
02275 image->rows);
02276 if (proceed == MagickFalse)
02277 status=MagickFalse;
02278 }
02279 }
02280 image_view=DestroyCacheView(image_view);
02281 break;
02282 }
02283 case PseudoClass:
02284 {
02285
02286
02287
02288 image_view=AcquireCacheView(image);
02289 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02290 #pragma omp parallel for schedule(dynamic,4) shared(status)
02291 #endif
02292 for (i=0; i < (long) image->colors; i++)
02293 {
02294 MagickPixelPacket
02295 pixel;
02296
02297 register unsigned long
02298 blue,
02299 green,
02300 red;
02301
02302 red=ScaleQuantumToMap(image->colormap[i].red);
02303 green=ScaleQuantumToMap(image->colormap[i].green);
02304 blue=ScaleQuantumToMap(image->colormap[i].blue);
02305 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
02306 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
02307 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
02308 switch (colorspace)
02309 {
02310 case YCCColorspace:
02311 {
02312 #if !defined(MAGICKCORE_HDRI_SUPPORT)
02313 image->colormap[i].red=ScaleCharToQuantum(YCCMap[RoundToYCC(
02314 255.0*QuantumScale*pixel.red)]);
02315 image->colormap[i].green=ScaleCharToQuantum(YCCMap[RoundToYCC(
02316 255.0*QuantumScale*pixel.green)]);
02317 image->colormap[i].blue=ScaleCharToQuantum(YCCMap[RoundToYCC(
02318 255.0*QuantumScale*pixel.blue)]);
02319 #endif
02320 break;
02321 }
02322 case sRGBColorspace:
02323 {
02324 if ((QuantumScale*pixel.red) <= 0.0031308)
02325 pixel.red*=12.92f;
02326 else
02327 pixel.red=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
02328 pixel.red,(1.0/2.4))-0.055);
02329 if ((QuantumScale*pixel.green) <= 0.0031308)
02330 pixel.green*=12.92f;
02331 else
02332 pixel.green=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
02333 pixel.green,(1.0/2.4))-0.055);
02334 if ((QuantumScale*pixel.blue) <= 0.0031308)
02335 pixel.blue*=12.92f;
02336 else
02337 pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
02338 pixel.blue,(1.0/2.4))-0.055);
02339 }
02340 default:
02341 {
02342 image->colormap[i].red=ScaleMapToQuantum((MagickRealType) MaxMap*
02343 QuantumScale*pixel.red);
02344 image->colormap[i].green=ScaleMapToQuantum((MagickRealType) MaxMap*
02345 QuantumScale*pixel.green);
02346 image->colormap[i].blue=ScaleMapToQuantum((MagickRealType) MaxMap*
02347 QuantumScale*pixel.blue);
02348 break;
02349 }
02350 }
02351 }
02352 image_view=DestroyCacheView(image_view);
02353 (void) SyncImage(image);
02354 break;
02355 }
02356 }
02357
02358
02359
02360 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
02361 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
02362 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
02363 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
02364 return(MagickFalse);
02365 return(MagickTrue);
02366 }