41#include "magick/studio.h"
42#include "magick/attribute.h"
43#include "magick/blob.h"
44#include "magick/blob-private.h"
45#include "magick/color-private.h"
46#include "magick/exception.h"
47#include "magick/exception-private.h"
48#include "magick/cache.h"
49#include "magick/cache-private.h"
50#include "magick/colorspace.h"
51#include "magick/colorspace-private.h"
52#include "magick/constitute.h"
53#include "magick/delegate.h"
54#include "magick/geometry.h"
55#include "magick/list.h"
56#include "magick/magick.h"
57#include "magick/memory_.h"
58#include "magick/monitor.h"
59#include "magick/option.h"
60#include "magick/pixel.h"
61#include "magick/pixel-private.h"
62#include "magick/property.h"
63#include "magick/quantum.h"
64#include "magick/quantum-private.h"
65#include "magick/resource_.h"
66#include "magick/semaphore.h"
67#include "magick/statistic.h"
68#include "magick/stream.h"
69#include "magick/string_.h"
70#include "magick/string-private.h"
71#include "magick/thread-private.h"
72#include "magick/utility.h"
77#define QuantumSignature 0xab
83 DestroyQuantumPixels(QuantumInfo *);
109MagickExport QuantumInfo *AcquireQuantumInfo(
const ImageInfo *image_info,
118 quantum_info=(QuantumInfo *) AcquireMagickMemory(
sizeof(*quantum_info));
119 if (quantum_info == (QuantumInfo *) NULL)
120 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
121 quantum_info->signature=MagickCoreSignature;
122 GetQuantumInfo(image_info,quantum_info);
123 if (image == (
const Image *) NULL)
124 return(quantum_info);
125 status=SetQuantumDepth(image,quantum_info,image->depth);
126 quantum_info->endian=image->endian;
127 if (status == MagickFalse)
128 quantum_info=DestroyQuantumInfo(quantum_info);
129 return(quantum_info);
157static MagickBooleanType AcquireQuantumPixels(QuantumInfo *quantum_info,
163 assert(quantum_info != (QuantumInfo *) NULL);
164 assert(quantum_info->signature == MagickCoreSignature);
165 quantum_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
166 quantum_info->pixels=(MemoryInfo **) AcquireQuantumMemory(
167 quantum_info->number_threads,
sizeof(*quantum_info->pixels));
168 if (quantum_info->pixels == (MemoryInfo **) NULL)
170 quantum_info->extent=extent;
171 (void) memset(quantum_info->pixels,0,quantum_info->number_threads*
172 sizeof(*quantum_info->pixels));
173 for (i=0; i < (ssize_t) quantum_info->number_threads; i++)
178 quantum_info->pixels[i]=AcquireVirtualMemory(extent+1,
sizeof(*pixels));
179 if (quantum_info->pixels[i] == (MemoryInfo *) NULL)
181 DestroyQuantumPixels(quantum_info);
184 pixels=(
unsigned char *) GetVirtualMemoryBlob(quantum_info->pixels[i]);
185 (void) memset(pixels,0,(extent+1)*
sizeof(*pixels));
186 pixels[extent]=QuantumSignature;
214MagickExport QuantumInfo *DestroyQuantumInfo(QuantumInfo *quantum_info)
216 assert(quantum_info != (QuantumInfo *) NULL);
217 assert(quantum_info->signature == MagickCoreSignature);
218 if (quantum_info->pixels != (MemoryInfo **) NULL)
219 DestroyQuantumPixels(quantum_info);
221 DestroySemaphoreInfo(&quantum_info->semaphore);
222 quantum_info->signature=(~MagickCoreSignature);
223 quantum_info=(QuantumInfo *) RelinquishMagickMemory(quantum_info);
224 return(quantum_info);
249static void DestroyQuantumPixels(QuantumInfo *quantum_info)
257 assert(quantum_info != (QuantumInfo *) NULL);
258 assert(quantum_info->signature == MagickCoreSignature);
259 assert(quantum_info->pixels != (MemoryInfo **) NULL);
260 extent=(ssize_t) quantum_info->extent;
261 for (i=0; i < (ssize_t) quantum_info->number_threads; i++)
262 if (quantum_info->pixels[i] != (MemoryInfo *) NULL)
271 pixels=(
unsigned char *) GetVirtualMemoryBlob(quantum_info->pixels[i]);
272 assert(pixels[extent] == QuantumSignature);
274 quantum_info->pixels[i]=RelinquishVirtualMemory(
275 quantum_info->pixels[i]);
277 quantum_info->pixels=(MemoryInfo **) RelinquishMagickMemory(
278 quantum_info->pixels);
309MagickExport
size_t GetQuantumExtent(
const Image *image,
310 const QuantumInfo *quantum_info,
const QuantumType quantum_type)
315 assert(quantum_info != (QuantumInfo *) NULL);
316 assert(quantum_info->signature == MagickCoreSignature);
318 switch (quantum_type)
320 case GrayAlphaQuantum: channels=2;
break;
321 case IndexAlphaQuantum: channels=2;
break;
322 case RGBQuantum: channels=3;
break;
323 case BGRQuantum: channels=3;
break;
324 case RGBAQuantum: channels=4;
break;
325 case RGBOQuantum: channels=4;
break;
326 case BGRAQuantum: channels=4;
break;
327 case CMYKQuantum: channels=4;
break;
328 case CMYKAQuantum: channels=5;
break;
329 case CbYCrAQuantum: channels=4;
break;
330 case CbYCrQuantum: channels=3;
break;
331 case CbYCrYQuantum: channels=4;
break;
334 if (quantum_info->pack == MagickFalse)
335 return((
size_t) (channels*image->columns*((quantum_info->depth+7)/8))+
336 (quantum_info->pad*image->columns));
337 return((
size_t) ((channels*image->columns*quantum_info->depth+7)/8)+
338 (quantum_info->pad*image->columns));
363MagickExport EndianType GetQuantumEndian(
const QuantumInfo *quantum_info)
365 assert(quantum_info != (QuantumInfo *) NULL);
366 assert(quantum_info->signature == MagickCoreSignature);
367 return(quantum_info->endian);
392MagickExport QuantumFormatType GetQuantumFormat(
const QuantumInfo *quantum_info)
394 assert(quantum_info != (QuantumInfo *) NULL);
395 assert(quantum_info->signature == MagickCoreSignature);
396 return(quantum_info->format);
423MagickExport
void GetQuantumInfo(
const ImageInfo *image_info,
424 QuantumInfo *quantum_info)
429 assert(quantum_info != (QuantumInfo *) NULL);
430 (void) memset(quantum_info,0,
sizeof(*quantum_info));
431 quantum_info->quantum=8;
432 quantum_info->maximum=1.0;
433 quantum_info->scale=QuantumRange;
434 quantum_info->pack=MagickTrue;
435 quantum_info->semaphore=AllocateSemaphoreInfo();
436 quantum_info->signature=MagickCoreSignature;
437 if (image_info == (
const ImageInfo *) NULL)
439 option=GetImageOption(image_info,
"quantum:format");
440 if (option != (
char *) NULL)
441 quantum_info->format=(QuantumFormatType) ParseCommandOption(
442 MagickQuantumFormatOptions,MagickFalse,option);
443 option=GetImageOption(image_info,
"quantum:minimum");
444 if (option != (
char *) NULL)
445 quantum_info->minimum=StringToDouble(option,(
char **) NULL);
446 option=GetImageOption(image_info,
"quantum:maximum");
447 if (option != (
char *) NULL)
448 quantum_info->maximum=StringToDouble(option,(
char **) NULL);
449 if ((quantum_info->minimum == 0.0) && (quantum_info->maximum == 0.0))
450 quantum_info->scale=0.0;
452 if (quantum_info->minimum == quantum_info->maximum)
454 quantum_info->scale=(MagickRealType) QuantumRange/quantum_info->minimum;
455 quantum_info->minimum=0.0;
458 quantum_info->scale=(MagickRealType) QuantumRange/(quantum_info->maximum-
459 quantum_info->minimum);
460 option=GetImageOption(image_info,
"quantum:scale");
461 if (option != (
char *) NULL)
462 quantum_info->scale=StringToDouble(option,(
char **) NULL);
463 option=GetImageOption(image_info,
"quantum:polarity");
464 if (option != (
char *) NULL)
465 quantum_info->min_is_white=LocaleCompare(option,
"min-is-white") == 0 ?
466 MagickTrue : MagickFalse;
467 quantum_info->endian=image_info->endian;
468 ResetQuantumState(quantum_info);
494MagickExport
unsigned char *GetQuantumPixels(
const QuantumInfo *quantum_info)
497 id = GetOpenMPThreadId();
499 assert(quantum_info != (QuantumInfo *) NULL);
500 assert(quantum_info->signature == MagickCoreSignature);
501 return((
unsigned char *) GetVirtualMemoryBlob(quantum_info->pixels[
id]));
526MagickExport QuantumType GetQuantumType(Image *image,ExceptionInfo *exception)
531 assert(image != (Image *) NULL);
532 assert(image->signature == MagickCoreSignature);
533 if (IsEventLogging() != MagickFalse)
534 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
536 quantum_type=RGBQuantum;
537 if (image->matte != MagickFalse)
538 quantum_type=RGBAQuantum;
539 if (image->colorspace == CMYKColorspace)
541 quantum_type=CMYKQuantum;
542 if (image->matte != MagickFalse)
543 quantum_type=CMYKAQuantum;
545 if (IsGrayColorspace(image->colorspace) != MagickFalse)
547 quantum_type=GrayQuantum;
548 if (image->matte != MagickFalse)
549 quantum_type=GrayAlphaQuantum;
551 if (image->storage_class == PseudoClass)
553 quantum_type=IndexQuantum;
554 if (image->matte != MagickFalse)
555 quantum_type=IndexAlphaQuantum;
557 return(quantum_type);
582MagickPrivate
void ResetQuantumState(QuantumInfo *quantum_info)
584 static const unsigned int mask[32] =
586 0x00000000U, 0x00000001U, 0x00000003U, 0x00000007U, 0x0000000fU,
587 0x0000001fU, 0x0000003fU, 0x0000007fU, 0x000000ffU, 0x000001ffU,
588 0x000003ffU, 0x000007ffU, 0x00000fffU, 0x00001fffU, 0x00003fffU,
589 0x00007fffU, 0x0000ffffU, 0x0001ffffU, 0x0003ffffU, 0x0007ffffU,
590 0x000fffffU, 0x001fffffU, 0x003fffffU, 0x007fffffU, 0x00ffffffU,
591 0x01ffffffU, 0x03ffffffU, 0x07ffffffU, 0x0fffffffU, 0x1fffffffU,
592 0x3fffffffU, 0x7fffffffU
595 assert(quantum_info != (QuantumInfo *) NULL);
596 assert(quantum_info->signature == MagickCoreSignature);
597 quantum_info->state.inverse_scale=1.0;
598 if (fabs(quantum_info->scale) >= MagickEpsilon)
599 quantum_info->state.inverse_scale/=quantum_info->scale;
600 quantum_info->state.pixel=0U;
601 quantum_info->state.bits=0U;
602 quantum_info->state.mask=mask;
630MagickExport
void SetQuantumAlphaType(QuantumInfo *quantum_info,
631 const QuantumAlphaType type)
633 assert(quantum_info != (QuantumInfo *) NULL);
634 assert(quantum_info->signature == MagickCoreSignature);
635 quantum_info->alpha_type=type;
665MagickExport MagickBooleanType SetQuantumDepth(
const Image *image,
666 QuantumInfo *quantum_info,
const size_t depth)
671 assert(image != (Image *) NULL);
672 assert(image->signature == MagickCoreSignature);
673 assert(quantum_info != (QuantumInfo *) NULL);
674 assert(quantum_info->signature == MagickCoreSignature);
675 if (IsEventLogging() != MagickFalse)
676 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
677 quantum_info->depth=MagickMin(depth,64);
678 if (quantum_info->format == FloatingPointQuantumFormat)
680 if (quantum_info->depth > 32)
681 quantum_info->depth=64;
683 if (quantum_info->depth > 24)
684 quantum_info->depth=32;
686 if (quantum_info->depth > 16)
687 quantum_info->depth=24;
689 quantum_info->depth=16;
691 return(SetQuantumExtent(image,quantum_info));
721MagickExport MagickBooleanType SetQuantumEndian(
const Image *image,
722 QuantumInfo *quantum_info,
const EndianType endian)
724 assert(image != (Image *) NULL);
725 assert(image->signature == MagickCoreSignature);
726 assert(quantum_info != (QuantumInfo *) NULL);
727 assert(quantum_info->signature == MagickCoreSignature);
728 if (IsEventLogging() != MagickFalse)
729 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
730 quantum_info->endian=endian;
731 return(SetQuantumExtent(image,quantum_info));
759MagickExport MagickBooleanType SetQuantumExtent(
const Image *image,
760 QuantumInfo *quantum_info)
769 assert(image != (Image *) NULL);
770 assert(image->signature == MagickCoreSignature);
771 assert(quantum_info != (QuantumInfo *) NULL);
772 assert(quantum_info->signature == MagickCoreSignature);
773 if (IsEventLogging() != MagickFalse)
774 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
775 quantum=(quantum_info->pad+6)*((quantum_info->depth+7)/8)*
sizeof(double);
776 extent=MagickMax(image->columns,image->rows)*quantum;
777 if ((MagickMax(image->columns,image->rows) != 0) &&
778 (quantum != (extent/MagickMax(image->columns,image->rows))))
780 if (quantum_info->pixels != (MemoryInfo **) NULL)
782 if (extent <= quantum_info->extent)
784 DestroyQuantumPixels(quantum_info);
786 return(AcquireQuantumPixels(quantum_info,extent));
816MagickExport MagickBooleanType SetQuantumFormat(
const Image *image,
817 QuantumInfo *quantum_info,
const QuantumFormatType format)
819 assert(image != (Image *) NULL);
820 assert(image->signature == MagickCoreSignature);
821 assert(quantum_info != (QuantumInfo *) NULL);
822 assert(quantum_info->signature == MagickCoreSignature);
823 if (IsEventLogging() != MagickFalse)
824 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
825 quantum_info->format=format;
826 return(SetQuantumExtent(image,quantum_info));
855MagickExport
void SetQuantumImageType(Image *image,
856 const QuantumType quantum_type)
858 assert(image != (Image *) NULL);
859 assert(image->signature == MagickCoreSignature);
860 if (IsEventLogging() != MagickFalse)
861 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
862 switch (quantum_type)
865 case IndexAlphaQuantum:
867 image->type=PaletteType;
871 case GrayAlphaQuantum:
873 image->type=GrayscaleType;
874 if (image->depth == 1)
875 image->type=BilevelType;
885 image->type=ColorSeparationType;
890 image->type=TrueColorType;
921MagickExport
void SetQuantumPack(QuantumInfo *quantum_info,
922 const MagickBooleanType pack)
924 assert(quantum_info != (QuantumInfo *) NULL);
925 assert(quantum_info->signature == MagickCoreSignature);
926 quantum_info->pack=pack;
956MagickExport MagickBooleanType SetQuantumPad(
const Image *image,
957 QuantumInfo *quantum_info,
const size_t pad)
959 assert(image != (Image *) NULL);
960 assert(image->signature == MagickCoreSignature);
961 assert(quantum_info != (QuantumInfo *) NULL);
962 assert(quantum_info->signature == MagickCoreSignature);
963 if (IsEventLogging() != MagickFalse)
964 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
965 if (pad >= (MAGICK_SSIZE_MAX/5))
967 quantum_info->pad=pad;
968 return(SetQuantumExtent(image,quantum_info));
996MagickExport
void SetQuantumMinIsWhite(QuantumInfo *quantum_info,
997 const MagickBooleanType min_is_white)
999 assert(quantum_info != (QuantumInfo *) NULL);
1000 assert(quantum_info->signature == MagickCoreSignature);
1001 quantum_info->min_is_white=min_is_white;
1028MagickExport
void SetQuantumQuantum(QuantumInfo *quantum_info,
1029 const size_t quantum)
1031 assert(quantum_info != (QuantumInfo *) NULL);
1032 assert(quantum_info->signature == MagickCoreSignature);
1033 quantum_info->quantum=quantum;
1060MagickExport
void SetQuantumScale(QuantumInfo *quantum_info,
const double scale)
1062 assert(quantum_info != (QuantumInfo *) NULL);
1063 assert(quantum_info->signature == MagickCoreSignature);
1064 quantum_info->scale=scale;