210 #if !defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
215 #define ErrorQueueLength 16
216 #define MaxNodes 266817
217 #define MaxTreeDepth 8
218 #define NodesInAList 1920
390 if (option != (
const char *) NULL)
395 return(quantize_info);
469 alpha_pixel->
red=(double) pixel->
red;
471 alpha_pixel->
blue=(double) pixel->
blue;
476 alpha_pixel->
red=alpha*pixel->
red;
478 alpha_pixel->
blue=alpha*pixel->
blue;
488 id=(size_t) (((ScaleQuantumToChar(
ClampPixel(pixel->
red)) >> index) & 0x01) |
489 ((ScaleQuantumToChar(
ClampPixel(pixel->
green)) >> index) & 0x01) << 1 |
490 ((ScaleQuantumToChar(
ClampPixel(pixel->
blue)) >> index) & 0x01) << 2);
492 id|=((ScaleQuantumToChar(
ClampPixel(pixel->
alpha)) >> index) & 0x1) << 3;
499 #define AssignImageTag "Assign/Image"
536 #if defined(MAGICKCORE_OPENMP_SUPPORT)
537 #pragma omp parallel for schedule(static) shared(status) \
538 magick_number_threads(image,image,image->rows,1)
540 for (y=0; y < (ssize_t) image->
rows; y++)
564 for (x=0; x < (ssize_t) image->
columns; x+=count)
582 for (count=1; (x+count) < (ssize_t) image->
columns; count++)
593 for (index=
MaxTreeDepth-1; (ssize_t) index > 0; index--)
598 node_info=node_info->
child[id];
608 for (i=0; i < (ssize_t) count; i++)
655 if ((image->
colors > 1) &&
754 #define ClassifyImageTag "Classify/Image"
800 for (y=0; y < (ssize_t) image->
rows; y++)
809 if (p == (
const Quantum *) NULL)
819 for (x=0; x < (ssize_t) image->
columns; x+=(ssize_t) count)
824 for (count=1; (x+(ssize_t) count) < (ssize_t) image->
columns; count++)
837 node_info=cube_info->
root;
845 mid.
red+=(
id & 1) != 0 ? bisect : -bisect;
846 mid.
green+=(
id & 2) != 0 ? bisect : -bisect;
847 mid.
blue+=(
id & 4) != 0 ? bisect : -bisect;
848 mid.
alpha+=(
id & 8) != 0 ? bisect : -bisect;
868 node_info=node_info->
child[id];
907 for (y++; y < (ssize_t) image->
rows; y++)
916 if (p == (
const Quantum *) NULL)
926 for (x=0; x < (ssize_t) image->
columns; x+=(ssize_t) count)
931 for (count=1; (x+(ssize_t) count) < (ssize_t) image->
columns; count++)
944 node_info=cube_info->
root;
945 for (level=1; level <= cube_info->
depth; level++)
952 mid.
red+=(
id & 1) != 0 ? bisect : -bisect;
953 mid.
green+=(
id & 2) != 0 ? bisect : -bisect;
954 mid.
blue+=(
id & 4) != 0 ? bisect : -bisect;
955 mid.
alpha+=(
id & 8) != 0 ? bisect : -bisect;
969 if (level == cube_info->
depth)
975 node_info=node_info->
child[id];
1101 for (i=0; i < (ssize_t) number_children; i++)
1132 pixel=alpha*p->red-beta*q->red;
1133 distance=pixel*pixel;
1134 if (distance <= cube_info->distance)
1136 pixel=alpha*p->green-beta*q->green;
1137 distance+=pixel*pixel;
1138 if (distance <= cube_info->distance)
1140 pixel=alpha*p->blue-beta*q->blue;
1141 distance+=pixel*pixel;
1142 if (distance <= cube_info->distance)
1146 pixel=p->alpha-q->alpha;
1147 distance+=pixel*pixel;
1149 if (distance <= cube_info->distance)
1192 assert(image != (
Image *) NULL);
1248 for (i=0; i < (ssize_t) number_children; i++)
1391 return(quantize_info);
1454 (void) memset(pixels,0,number_threads*
sizeof(*pixels));
1455 for (i=0; i < (ssize_t) number_threads; i++)
1468 #define RedShift(pixel) (((pixel) >> CacheShift) << (0*(8-CacheShift)))
1469 #define GreenShift(pixel) (((pixel) >> CacheShift) << (1*(8-CacheShift)))
1470 #define BlueShift(pixel) (((pixel) >> CacheShift) << (2*(8-CacheShift)))
1471 #define AlphaShift(pixel) (((pixel) >> CacheShift) << (3*(8-CacheShift)))
1487 #define DitherImageTag "Dither/Image"
1516 if (artifact != (
const char *) NULL)
1519 for (y=0; y < (ssize_t) image->
rows; y++)
1552 current=pixels[id]+(y & 0x01)*image->
columns;
1553 previous=pixels[
id]+((y+1) & 0x01)*image->
columns;
1554 v=(ssize_t) ((y & 0x01) != 0 ? -1 : 1);
1555 for (x=0; x < (ssize_t) image->
columns; x++)
1567 u=(y & 0x01) != 0 ? (ssize_t) image->
columns-1-x : x;
1571 pixel.
red+=7.0*amount*current[u-v].
red/16;
1572 pixel.
green+=7.0*amount*current[u-v].
green/16;
1573 pixel.
blue+=7.0*amount*current[u-v].
blue/16;
1575 pixel.
alpha+=7.0*amount*current[u-v].
alpha/16;
1579 if (x < (ssize_t) (image->
columns-1))
1581 pixel.
red+=previous[u+v].
red/16;
1587 pixel.
red+=5.0*amount*previous[u].
red/16;
1588 pixel.
green+=5.0*amount*previous[u].
green/16;
1589 pixel.
blue+=5.0*amount*previous[u].
blue/16;
1591 pixel.
alpha+=5.0*amount*previous[u].
alpha/16;
1594 pixel.
red+=3.0*amount*previous[u-v].
red/16;
1595 pixel.
green+=3.0*amount*previous[u-v].
green/16;
1596 pixel.
blue+=3.0*amount*previous[u-v].
blue/16;
1598 pixel.
alpha+=3.0*amount*previous[u-v].
alpha/16;
1607 if (cube.
cache[i] < 0)
1618 node_info=cube.
root;
1619 for (index=
MaxTreeDepth-1; (ssize_t) index > 0; index--)
1624 node_info=node_info->
child[node_id];
1638 index=(size_t) cube.
cache[i];
1686 const size_t level,
const unsigned int direction,
ExceptionInfo *exception)
1817 #define DitherImageTag "Dither/Image"
1833 if ((p->
x >= 0) && (p->
x < (ssize_t) image->
columns) &&
1834 (p->
y >= 0) && (p->
y < (ssize_t) image->
rows))
1863 if (p->
cache[i] < 0)
1875 for (index=
MaxTreeDepth-1; (ssize_t) index > 0; index--)
1880 node_info=node_info->
child[id];
1894 index=(size_t) p->
cache[i];
1910 (void) memmove(p->
error,p->
error+1,(ErrorQueueLength-1)*
1911 sizeof(p->
error[0]));
1954 sizeof(*cube_info->
error));
1958 for (depth=1; i != 0; depth++)
2007 const size_t depth,
const size_t maximum_colors)
2026 if (cube_info == (
CubeInfo *) NULL)
2028 (void) memset(cube_info,0,
sizeof(*cube_info));
2029 cube_info->
depth=depth;
2032 if (cube_info->
depth < 2)
2056 (void) memset(cube_info->
cache,(-1),
sizeof(*cube_info->
cache)*
2065 weight*=exp(log(((
double)
QuantumRange+1.0))/(ErrorQueueLength-1.0));
2072 weight+=cube_info->
weights[i];
2076 cube_info->
weights[i]/=weight;
2079 cube_info->
weights[0]+=1.0-sum;
2112 const size_t level,
NodeInfo *parent)
2126 if (nodes == (
Nodes *) NULL)
2129 sizeof(*nodes->
nodes));
2140 (void) memset(node_info,0,
sizeof(*node_info));
2141 node_info->
parent=parent;
2143 node_info->
level=level;
2202 mean_error_per_pixel;
2210 assert(image != (
Image *) NULL);
2215 (void) memset(&image->
error,0,
sizeof(image->
error));
2222 mean_error_per_pixel=0.0;
2225 for (y=0; y < (ssize_t) image->
rows; y++)
2234 if (p == (
const Quantum *) NULL)
2236 for (x=0; x < (ssize_t) image->
columns; x++)
2244 distance=fabs((
double) (alpha*
GetPixelRed(image,p)-beta*
2246 mean_error_per_pixel+=distance;
2247 mean_error+=distance*distance;
2248 if (distance > maximum_error)
2249 maximum_error=distance;
2252 mean_error_per_pixel+=distance;
2253 mean_error+=distance*distance;
2254 if (distance > maximum_error)
2255 maximum_error=distance;
2256 distance=fabs((
double) (alpha*
GetPixelBlue(image,p)-beta*
2258 mean_error_per_pixel+=distance;
2259 mean_error+=distance*distance;
2260 if (distance > maximum_error)
2261 maximum_error=distance;
2299 (void) memset(quantize_info,0,
sizeof(*quantize_info));
2345 if ((x-floor(x)) < (ceil(x)-x))
2353 #define PosterizeImageTag "Posterize/Image"
2354 #define PosterizePixel(pixel) (Quantum) (QuantumRange*(MagickRound( \
2355 QuantumScale*pixel*(levels-1)))/MagickMax((ssize_t) levels-1,1))
2375 assert(image != (
Image *) NULL);
2382 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2383 #pragma omp parallel for schedule(static) shared(progress,status) \
2384 magick_number_threads(image,image,image->colors,1)
2386 for (i=0; i < (ssize_t) image->
colors; i++)
2410 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2411 #pragma omp parallel for schedule(static) shared(progress,status) \
2412 magick_number_threads(image,image,image->rows,1)
2414 for (y=0; y < (ssize_t) image->
rows; y++)
2430 for (x=0; x < (ssize_t) image->
columns; x++)
2453 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2513 for (i=0; i < (ssize_t) number_children; i++)
2519 parent=node_info->
parent;
2566 for (i=0; i < (ssize_t) number_children; i++)
2611 for (i=0; i < (ssize_t) number_children; i++)
2663 assert(image != (
Image *) NULL);
2670 if (maximum_colors == 0)
2680 (image->
colors <= maximum_colors))
2697 colors=maximum_colors;
2698 for (depth=1; colors != 0; depth++)
2710 cube_info=
GetCubeInfo(quantize_info,depth,maximum_colors);
2711 if (cube_info == (
CubeInfo *) NULL)
2787 assert(images != (
Image *) NULL);
2803 if (maximum_colors == 0)
2816 colors=maximum_colors;
2817 for (depth=1; colors != 0; depth++)
2825 cube_info=
GetCubeInfo(quantize_info,depth,maximum_colors);
2826 if (cube_info == (
CubeInfo *) NULL)
2834 for (i=0; image != (
Image *) NULL; i++)
2855 for (i=0; image != (
Image *) NULL; i++)
2909 const NodeInfo *node_info,
const ssize_t offset,
double *quantize_error)
2918 if (offset >= (ssize_t) cube_info->
nodes)
2923 for (i=0; i < (ssize_t) number_children ; i++)
2967 for (i=0; i < (ssize_t) number_children; i++)
3045 p=(
double *) error_p;
3046 q=(
double *) error_q;
3056 #define ReduceImageTag "Reduce/Image"
3077 sizeof(*quantize_error));
3078 if (quantize_error != (
double *) NULL)
3082 qsort(quantize_error,cube_info->
nodes,
sizeof(
double),
3146 assert(image != (
Image *) NULL);
3150 assert(remap_image != (
Image *) NULL);
3156 if (cube_info == (
CubeInfo *) NULL)
3214 assert(images != (
Image *) NULL);
3221 if (remap_image == (
Image *) NULL)
3234 if (cube_info == (
CubeInfo *) NULL)
3282 #if defined(__cplusplus) || defined(c_plusplus)
3299 return((
int) intensity);
3302 #if defined(__cplusplus) || defined(c_plusplus)
3326 assert(image != (
Image *) NULL);
3332 sizeof(*colormap_index));
3335 sizeof(*colormap_index));
3336 if (colormap_index == (ssize_t *) NULL)
3342 sizeof(*colormap_index));
3352 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3353 #pragma omp parallel for schedule(static) shared(status) \
3354 magick_number_threads(image,image,image->rows,1)
3356 for (y=0; y < (ssize_t) image->
rows; y++)
3373 for (x=0; x < (ssize_t) image->
columns; x++)
3378 intensity=ScaleQuantumToMap(
GetPixelRed(image,q));
3379 if (colormap_index[intensity] < 0)
3381 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3382 #pragma omp critical (MagickCore_SetGrayscaleImage)
3384 if (colormap_index[intensity] < 0)
3386 colormap_index[intensity]=(ssize_t) image->
colors;
3404 for (i=0; i < (ssize_t) image->
colors; i++)
3417 for (i=0; i < (ssize_t) image->
colors; i++)
3426 image->
colors=(size_t) (j+1);
3431 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3432 #pragma omp parallel for schedule(static) shared(status) \
3433 magick_number_threads(image,image,image->rows,1)
3435 for (y=0; y < (ssize_t) image->
rows; y++)
3451 for (x=0; x < (ssize_t) image->
columns; x++)
MagickExport MagickBooleanType CompressImageColormap(Image *image, ExceptionInfo *exception)
MagickBooleanType associate_alpha
MagickDoubleType MagickRealType
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
MagickExport MemoryInfo * RelinquishVirtualMemory(MemoryInfo *memory_info)
MagickProgressMonitor progress_monitor
static PixelTrait GetPixelBlackTraits(const Image *magick_restrict image)
MagickExport MagickBooleanType SyncImage(Image *image, ExceptionInfo *exception)
static Quantum GetPixelAlpha(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
static PixelTrait GetPixelRedTraits(const Image *magick_restrict image)
MagickExport MagickBooleanType TransformImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
static PixelTrait GetPixelAlphaTraits(const Image *magick_restrict image)
MagickExport MagickBooleanType PosterizeImage(Image *image, const size_t levels, const DitherMethod dither_method, ExceptionInfo *exception)
static Quantum GetPixelRed(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
ColorspaceType colorspace
MagickExport ssize_t ParseCommandOption(const CommandOption option, const MagickBooleanType list, const char *options)
static size_t QuantizeErrorFlatten(const CubeInfo *cube_info, const NodeInfo *node_info, const ssize_t offset, double *quantize_error)
MagickExport MemoryInfo * AcquireVirtualMemory(const size_t count, const size_t quantum)
static void DestroyCubeInfo(CubeInfo *)
static MagickBooleanType DitherImage(Image *, CubeInfo *, ExceptionInfo *)
MagickExport QuantizeInfo * DestroyQuantizeInfo(QuantizeInfo *quantize_info)
MagickExport const char * GetImageArtifact(const Image *image, const char *artifact)
QuantizeInfo * quantize_info
double mean_error_per_pixel
static void * AcquireCriticalMemory(const size_t size)
MagickExport const Quantum * GetCacheViewVirtualPixels(const CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
static void Reduce(CubeInfo *cube_info, const NodeInfo *node_info)
MagickBooleanType verbose
MagickExport const char * GetImageOption(const ImageInfo *image_info, const char *option)
#define PosterizeImageTag
static MagickBooleanType RiemersmaDither(Image *, CacheView *, CubeInfo *, const unsigned int, ExceptionInfo *)
static NodeInfo * GetNodeInfo(CubeInfo *, const size_t, const size_t, NodeInfo *)
#define ThrowBinaryException(severity, tag, context)
static MagickBooleanType IsPixelInfoEquivalent(const PixelInfo *magick_restrict p, const PixelInfo *magick_restrict q)
MagickExport MagickBooleanType SetImageGray(Image *image, ExceptionInfo *exception)
static MagickBooleanType IsPixelEquivalent(const Image *magick_restrict image, const Quantum *magick_restrict p, const PixelInfo *magick_restrict q)
#define MagickCoreSignature
double normalized_mean_error
struct _CubeInfo CubeInfo
MagickExport Quantum * GetCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
static Quantum ClampPixel(const MagickRealType pixel)
#define AlphaShift(pixel)
static void Riemersma(Image *image, CacheView *image_view, CubeInfo *cube_info, const size_t level, const unsigned int direction, ExceptionInfo *exception)
MagickExport MagickBooleanType RemapImages(const QuantizeInfo *quantize_info, Image *images, const Image *remap_image, ExceptionInfo *exception)
static MagickBooleanType FloydSteinbergDither(Image *image, CubeInfo *cube_info, ExceptionInfo *exception)
static double PerceptibleReciprocal(const double x)
double weights[ErrorQueueLength]
DoublePixelPacket total_color
static void PruneChild(CubeInfo *cube_info, const NodeInfo *node_info)
static MagickBooleanType IssRGBCompatibleColorspace(const ColorspaceType colorspace)
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
static size_t DefineImageColormap(Image *, CubeInfo *, NodeInfo *)
MagickExport MagickBooleanType QuantizeImages(const QuantizeInfo *quantize_info, Image *images, ExceptionInfo *exception)
static int GetOpenMPThreadId(void)
static CubeInfo * GetCubeInfo(const QuantizeInfo *, const size_t, const size_t)
static Quantum GetPixelGreen(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
static void GetPixelInfoPixel(const Image *magick_restrict image, const Quantum *magick_restrict pixel, PixelInfo *magick_restrict pixel_info)
MagickExport void GetQuantizeInfo(QuantizeInfo *quantize_info)
static Quantum GetPixelIndex(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
MagickSizeType transparent_pixels
static double MagickRound(double x)
static Quantum GetPixelBlack(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
struct _NodeInfo * child[16]
MagickExport MagickRealType GetPixelInfoIntensity(const Image *magick_restrict image, const PixelInfo *magick_restrict pixel)
MagickExport MagickBooleanType RemapImage(const QuantizeInfo *quantize_info, Image *image, const Image *remap_image, ExceptionInfo *exception)
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
static void AssociateAlphaPixelInfo(const CubeInfo *cube_info, const PixelInfo *pixel, DoublePixelPacket *alpha_pixel)
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
MagickExport MagickBooleanType QuantizeImage(const QuantizeInfo *quantize_info, Image *image, ExceptionInfo *exception)
MagickExport MagickBooleanType GetImageQuantizeError(Image *image, ExceptionInfo *exception)
ssize_t transparent_index
static void PruneLevel(CubeInfo *, const NodeInfo *)
MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
static DoublePixelPacket ** DestroyPixelThreadSet(DoublePixelPacket **pixels)
static DoublePixelPacket ** AcquirePixelThreadSet(const size_t count)
struct _NodeInfo * parent
static PixelTrait GetPixelGreenTraits(const Image *magick_restrict image)
static void SetPixelBlue(const Image *magick_restrict image, const Quantum blue, Quantum *magick_restrict pixel)
MagickExport MagickProgressMonitor SetImageProgressMonitor(Image *image, const MagickProgressMonitor progress_monitor, void *client_data)
MagickSizeType number_unique
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport MagickBooleanType AcquireImageColormap(Image *image, const size_t colors, ExceptionInfo *exception)
MagickExport MagickBooleanType IsPaletteImage(const Image *image)
MagickExport QuantizeInfo * AcquireQuantizeInfo(const ImageInfo *image_info)
static MagickBooleanType AssignImageColors(Image *, CubeInfo *, ExceptionInfo *)
char filename[MagickPathExtent]
#define GetMagickModule()
NodeInfo nodes[NodesInAList]
MagickExport size_t GetNumberColors(const Image *image, FILE *file, ExceptionInfo *exception)
static Quantum ClampToQuantum(const MagickRealType value)
MagickExport CacheView * AcquireVirtualCacheView(const Image *image, ExceptionInfo *exception)
static double StringToDoubleInterval(const char *string, const double interval)
static int IntensityCompare(const void *x, const void *y)
DitherMethod dither_method
double normalized_maximum_error
DoublePixelPacket error[ErrorQueueLength]
static size_t ColorToNodeId(const CubeInfo *cube_info, const DoublePixelPacket *pixel, size_t index)
MagickExport Image * GetNextImageInList(const Image *images)
MagickExport void * AcquireMagickMemory(const size_t size)
MagickExport QuantizeInfo * CloneQuantizeInfo(const QuantizeInfo *quantize_info)
static void SetPixelIndex(const Image *magick_restrict image, const Quantum index, Quantum *magick_restrict pixel)
static MagickBooleanType SetGrayscaleImage(Image *, ExceptionInfo *)
static MagickBooleanType ClassifyImageColors(CubeInfo *, const Image *, ExceptionInfo *)
MagickBooleanType measure_error
static int QuantizeErrorCompare(const void *error_p, const void *error_q)
static void SetPixelAlpha(const Image *magick_restrict image, const Quantum alpha, Quantum *magick_restrict pixel)
MagickExport void * RelinquishMagickMemory(void *memory)
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
static void AssociateAlphaPixel(const Image *image, const CubeInfo *cube_info, const Quantum *pixel, DoublePixelPacket *alpha_pixel)
static void SetPixelRed(const Image *magick_restrict image, const Quantum red, Quantum *magick_restrict pixel)
static ssize_t CacheOffset(CubeInfo *cube_info, const DoublePixelPacket *pixel)
struct _NodeInfo NodeInfo
static void ReduceImageColors(const Image *, CubeInfo *)
static MagickRealType GetPixelInfoLuma(const PixelInfo *magick_restrict pixel)
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
MagickExport MagickBooleanType SetImageMonochrome(Image *image, ExceptionInfo *exception)
static void PruneToCubeDepth(CubeInfo *, const NodeInfo *)
static void SetPixelBlack(const Image *magick_restrict image, const Quantum black, Quantum *magick_restrict pixel)
static Quantum GetPixelBlue(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
MagickExport void * GetVirtualMemoryBlob(const MemoryInfo *memory_info)
#define PosterizePixel(pixel)
MagickExport size_t GetImageListLength(const Image *images)
struct _DoublePixelPacket DoublePixelPacket
static void SetAssociatedAlpha(const Image *image, CubeInfo *cube_info)
ColorspaceType colorspace
MagickExport MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
static void ClosestColor(const Image *, CubeInfo *, const NodeInfo *)
#define GreenShift(pixel)
static void SetPixelGreen(const Image *magick_restrict image, const Quantum green, Quantum *magick_restrict pixel)
static PixelTrait GetPixelBlueTraits(const Image *magick_restrict image)