quantum-private.h

Go to the documentation of this file.
00001 /*
00002   Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization
00003   dedicated to making software imaging solutions freely available.
00004 
00005   You may not use this file except in compliance with the License.  You may
00006   obtain a copy of the License at
00007 
00008     https://imagemagick.org/script/license.php
00009 
00010   Unless required by applicable law or agreed to in writing, software
00011   distributed under the License is distributed on an "AS IS" BASIS,
00012   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013   See the License for the specific language governing permissions and
00014   limitations under the License.
00015 
00016   MagickCore quantum inline methods.
00017 */
00018 #ifndef MAGICKCORE_QUANTUM_PRIVATE_H
00019 #define MAGICKCORE_QUANTUM_PRIVATE_H
00020 
00021 #include "magick/memory_.h"
00022 #include "magick/cache.h"
00023 #include "magick/image-private.h"
00024 #include "magick/pixel-accessor.h"
00025 
00026 #if defined(__cplusplus) || defined(c_plusplus)
00027 extern "C" {
00028 #endif
00029 
00030 typedef struct _QuantumState
00031 {
00032   double
00033     inverse_scale;
00034 
00035   unsigned int
00036     pixel;
00037 
00038   size_t
00039     bits;
00040 
00041   const unsigned int
00042     *mask;
00043 } QuantumState;
00044 
00045 struct _QuantumInfo
00046 {
00047   size_t
00048     depth,
00049     quantum;
00050 
00051   QuantumFormatType
00052     format;
00053 
00054   double
00055     minimum,
00056     maximum,
00057     scale;
00058 
00059   size_t
00060     pad;
00061 
00062   MagickBooleanType
00063     min_is_white,
00064     pack;
00065 
00066   QuantumAlphaType
00067     alpha_type;
00068 
00069   size_t
00070     number_threads;
00071 
00072   MemoryInfo
00073     **pixels;
00074 
00075   size_t
00076     extent;
00077 
00078   EndianType
00079     endian;
00080 
00081   QuantumState
00082     state;
00083 
00084   SemaphoreInfo
00085     *semaphore;
00086 
00087   size_t
00088     signature;
00089 };
00090 
00091 extern MagickPrivate void
00092   ResetQuantumState(QuantumInfo *);
00093 
00094 static inline MagickSizeType GetQuantumRange(const size_t depth)
00095 {
00096   MagickSizeType
00097     one;
00098 
00099   size_t
00100     max_depth;
00101 
00102   if (depth == 0)
00103     return(0);
00104   one=1;
00105   max_depth=8*sizeof(MagickSizeType);
00106   return((MagickSizeType) ((one << (MagickMin(depth,max_depth)-1))+
00107     ((one << (MagickMin(depth,max_depth)-1))-1)));
00108 }
00109 
00110 static inline float HalfToSinglePrecision(const unsigned short half)
00111 {
00112 #define ExponentBias  (127-15)
00113 #define ExponentMask  0x7c00
00114 #define ExponentShift  23
00115 #define SignBitShift  31
00116 #define SignificandShift  13
00117 #define SignificandMask  0x00000400
00118 
00119   typedef union _SinglePrecision
00120   {
00121     unsigned int
00122       fixed_point;
00123 
00124     float
00125       single_precision;
00126   } SinglePrecision;
00127 
00128   register unsigned int
00129     exponent,
00130     significand,
00131     sign_bit;
00132 
00133   SinglePrecision
00134     map;
00135 
00136   unsigned int
00137     value;
00138 
00139   /*
00140     The IEEE 754 standard specifies half precision as having:
00141 
00142       Sign bit: 1 bit
00143       Exponent width: 5 bits
00144       Significand precision: 11 (10 explicitly stored)
00145   */
00146   sign_bit=(unsigned int) ((half >> 15) & 0x00000001);
00147   exponent=(unsigned int) ((half >> 10) & 0x0000001f);
00148   significand=(unsigned int) (half & 0x000003ff);
00149   if (exponent == 0)
00150     {
00151       if (significand == 0)
00152         value=sign_bit << SignBitShift;
00153       else
00154         {
00155           while ((significand & SignificandMask) == 0)
00156           {
00157             significand<<=1;
00158             exponent--;
00159           }
00160           exponent++;
00161           significand&=(~SignificandMask);
00162           exponent+=ExponentBias;
00163           value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
00164             (significand << SignificandShift);
00165         }
00166     }
00167   else
00168     if (exponent == SignBitShift)
00169       {
00170         value=(sign_bit << SignBitShift) | 0x7f800000;
00171         if (significand != 0)
00172           value|=(significand << SignificandShift);
00173       }
00174     else
00175       {
00176         exponent+=ExponentBias;
00177         significand<<=SignificandShift;
00178         value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
00179           significand;
00180       }
00181   map.fixed_point=value;
00182   return(map.single_precision);
00183 }
00184 
00185 static inline unsigned char *PopCharPixel(const unsigned char pixel,
00186   unsigned char *pixels)
00187 {
00188   *pixels++=pixel;
00189   return(pixels);
00190 }
00191 
00192 static inline unsigned char *PopLongPixel(const EndianType endian,
00193   const unsigned int pixel,unsigned char *pixels)
00194 {
00195   register unsigned int
00196     quantum;
00197 
00198   quantum=(unsigned int) pixel;
00199   if (endian == LSBEndian)
00200     {
00201       *pixels++=(unsigned char) (quantum);
00202       *pixels++=(unsigned char) (quantum >> 8);
00203       *pixels++=(unsigned char) (quantum >> 16);
00204       *pixels++=(unsigned char) (quantum >> 24);
00205       return(pixels);
00206     }
00207   *pixels++=(unsigned char) (quantum >> 24);
00208   *pixels++=(unsigned char) (quantum >> 16);
00209   *pixels++=(unsigned char) (quantum >> 8);
00210   *pixels++=(unsigned char) (quantum);
00211   return(pixels);
00212 }
00213 
00214 static inline unsigned char *PopShortPixel(const EndianType endian,
00215   const unsigned short pixel,unsigned char *pixels)
00216 {
00217   register unsigned int
00218     quantum;
00219 
00220   quantum=pixel;
00221   if (endian == LSBEndian)
00222     {
00223       *pixels++=(unsigned char) (quantum);
00224       *pixels++=(unsigned char) (quantum >> 8);
00225       return(pixels);
00226     }
00227   *pixels++=(unsigned char) (quantum >> 8);
00228   *pixels++=(unsigned char) (quantum);
00229   return(pixels);
00230 }
00231 
00232 static inline const unsigned char *PushCharPixel(const unsigned char *pixels,
00233   unsigned char *pixel)
00234 {
00235   *pixel=(*pixels++);
00236   return(pixels);
00237 }
00238 
00239 static inline const unsigned char *PushLongPixel(const EndianType endian,
00240   const unsigned char *pixels,unsigned int *pixel)
00241 {
00242   register unsigned int
00243     quantum;
00244 
00245   if (endian == LSBEndian)
00246     {
00247       quantum=((unsigned int) *pixels++);
00248       quantum|=((unsigned int) *pixels++ << 8);
00249       quantum|=((unsigned int) *pixels++ << 16);
00250       quantum|=((unsigned int) *pixels++ << 24);
00251       *pixel=quantum;
00252       return(pixels);
00253     }
00254   quantum=((unsigned int) *pixels++ << 24);
00255   quantum|=((unsigned int) *pixels++ << 16);
00256   quantum|=((unsigned int) *pixels++ << 8);
00257   quantum|=((unsigned int) *pixels++);
00258   *pixel=quantum;
00259   return(pixels);
00260 }
00261 
00262 static inline const unsigned char *PushShortPixel(const EndianType endian,
00263   const unsigned char *pixels,unsigned short *pixel)
00264 {
00265   register unsigned int
00266     quantum;
00267 
00268   if (endian == LSBEndian)
00269     {
00270       quantum=(unsigned int) *pixels++;
00271       quantum|=(unsigned int) (*pixels++ << 8);
00272       *pixel=(unsigned short) (quantum & 0xffff);
00273       return(pixels);
00274     }
00275   quantum=(unsigned int) (*pixels++ << 8);
00276   quantum|=(unsigned int) *pixels++;
00277   *pixel=(unsigned short) (quantum & 0xffff);
00278   return(pixels);
00279 }
00280 
00281 static inline const unsigned char *PushFloatPixel(const EndianType endian,
00282   const unsigned char *pixels,MagickFloatType *pixel)
00283 {
00284   union
00285   {
00286     unsigned int
00287       unsigned_value;
00288 
00289     MagickFloatType
00290       float_value;
00291   } quantum;
00292 
00293   if (endian == LSBEndian)
00294     {
00295       quantum.unsigned_value=((unsigned int) *pixels++);
00296       quantum.unsigned_value|=((unsigned int) *pixels++ << 8);
00297       quantum.unsigned_value|=((unsigned int) *pixels++ << 16);
00298       quantum.unsigned_value|=((unsigned int) *pixels++ << 24);
00299       *pixel=quantum.float_value;
00300       return(pixels);
00301     }
00302   quantum.unsigned_value=((unsigned int) *pixels++ << 24);
00303   quantum.unsigned_value|=((unsigned int) *pixels++ << 16);
00304   quantum.unsigned_value|=((unsigned int) *pixels++ << 8);
00305   quantum.unsigned_value|=((unsigned int) *pixels++);
00306   *pixel=quantum.float_value;
00307   return(pixels);
00308 }
00309 
00310 static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
00311   const QuantumAny range)
00312 {
00313   if (quantum > range)
00314     return(QuantumRange);
00315 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00316   return((Quantum) (((MagickRealType) QuantumRange*quantum)*
00317     PerceptibleReciprocal((double) range)+0.5));
00318 #else
00319   return((Quantum) (((MagickRealType) QuantumRange*quantum)*
00320     PerceptibleReciprocal((double) range)));
00321 #endif
00322 }
00323 
00324 static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
00325   const QuantumAny range)
00326 {
00327   return((QuantumAny) (((MagickRealType) range*quantum)/QuantumRange+0.5));
00328 }
00329 
00330 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
00331 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00332 {
00333   return((Quantum) value);
00334 }
00335 
00336 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00337 {
00338 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00339   return((Quantum) ((value)/16843009UL));
00340 #else
00341   return((Quantum) (value/16843009.0));
00342 #endif
00343 }
00344 
00345 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00346 {
00347   if (value <= 0.0)
00348     return((Quantum) 0);
00349   if (value >= MaxMap)
00350     return(QuantumRange);
00351 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00352   return((Quantum) (value+0.5));
00353 #else
00354   return((Quantum) value);
00355 #endif
00356 }
00357 
00358 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00359 {
00360 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00361   return((unsigned int) (16843009UL*quantum));
00362 #else
00363   if (quantum <= 0.0)
00364     return(0UL);
00365   if ((16843009.0*quantum) >= 4294967295.0)
00366     return(4294967295UL);
00367   return((unsigned int) (16843009.0*quantum+0.5));
00368 #endif
00369 }
00370 
00371 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00372 {
00373   if (quantum >= (Quantum) MaxMap)
00374     return((unsigned int) MaxMap);
00375 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00376   return((unsigned int) quantum);
00377 #else
00378   if (quantum < 0.0)
00379     return(0UL);
00380   return((unsigned int) (quantum+0.5));
00381 #endif
00382 }
00383 
00384 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00385 {
00386 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00387   return((unsigned short) (257UL*quantum));
00388 #else
00389   if (quantum <= 0.0)
00390     return(0);
00391   if ((257.0*quantum) >= 65535.0)
00392     return(65535);
00393   return((unsigned short) (257.0*quantum+0.5));
00394 #endif
00395 }
00396 
00397 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00398 {
00399 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00400   return((Quantum) ((value+128U)/257U));
00401 #else
00402   return((Quantum) (value/257.0));
00403 #endif
00404 }
00405 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
00406 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00407 {
00408 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00409   return((Quantum) (257U*value));
00410 #else
00411   return((Quantum) (257.0*value));
00412 #endif
00413 }
00414 
00415 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00416 {
00417 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00418   return((Quantum) ((value)/MagickULLConstant(65537)));
00419 #else
00420   return((Quantum) (value/65537.0));
00421 #endif
00422 }
00423 
00424 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00425 {
00426   if (value <= 0.0)
00427     return((Quantum) 0);
00428   if (value >= MaxMap)
00429     return(QuantumRange);
00430 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00431   return((Quantum) (value+0.5));
00432 #else
00433   return((Quantum) value);
00434 #endif
00435 }
00436 
00437 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00438 {
00439 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00440   return((unsigned int) (65537UL*quantum));
00441 #else
00442   if (quantum <= 0.0)
00443     return(0UL);
00444   if ((65537.0*quantum) >= 4294967295.0)
00445     return(4294967295U);
00446   return((unsigned int) (65537.0*quantum+0.5));
00447 #endif
00448 }
00449 
00450 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00451 {
00452   if (quantum >= (Quantum) MaxMap)
00453     return((unsigned int) MaxMap);
00454 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00455   return((unsigned int) quantum);
00456 #else
00457   if (quantum < 0.0)
00458     return(0UL);
00459   return((unsigned int) (quantum+0.5));
00460 #endif
00461 }
00462 
00463 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00464 {
00465 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00466   return((unsigned short) quantum);
00467 #else
00468   if (quantum <= 0.0)
00469     return(0);
00470   if (quantum >= 65535.0)
00471     return(65535);
00472   return((unsigned short) (quantum+0.5));
00473 #endif
00474 }
00475 
00476 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00477 {
00478   return((Quantum) value);
00479 }
00480 #elif (MAGICKCORE_QUANTUM_DEPTH == 32)
00481 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00482 {
00483 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00484   return((Quantum) (16843009UL*value));
00485 #else
00486   return((Quantum) (16843009.0*value));
00487 #endif
00488 }
00489 
00490 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00491 {
00492   return((Quantum) value);
00493 }
00494 
00495 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00496 {
00497   if (value <= 0.0)
00498     return((Quantum) 0);
00499   if (value >= (Quantum) MaxMap)
00500     return(QuantumRange);
00501 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00502   return((Quantum) (65537.0*value+0.5));
00503 #else
00504   return((Quantum) (65537.0*value));
00505 #endif
00506 }
00507 
00508 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00509 {
00510 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00511   return((unsigned int) quantum);
00512 #else
00513   if (quantum <= 0.0)
00514     return(0);
00515   if ((quantum) >= 4294967295.0)
00516     return(4294967295);
00517   return((unsigned int) (quantum+0.5));
00518 #endif
00519 }
00520 
00521 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00522 {
00523   if (quantum < 0.0)
00524     return(0UL);
00525   if ((quantum/65537) >= (Quantum) MaxMap)
00526     return((unsigned int) MaxMap);
00527 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00528   return((unsigned int) ((quantum+MagickULLConstant(32768))/
00529     MagickULLConstant(65537)));
00530 #else
00531   return((unsigned int) (quantum/65537.0+0.5));
00532 #endif
00533 }
00534 
00535 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00536 {
00537 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00538   return((unsigned short) ((quantum+MagickULLConstant(32768))/
00539     MagickULLConstant(65537)));
00540 #else
00541   if (quantum <= 0.0)
00542     return(0);
00543   if ((quantum/65537.0) >= 65535.0)
00544     return(65535);
00545   return((unsigned short) (quantum/65537.0+0.5));
00546 #endif
00547 }
00548 
00549 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00550 {
00551 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00552   return((Quantum) (65537UL*value));
00553 #else
00554   return((Quantum) (65537.0*value));
00555 #endif
00556 }
00557 #elif (MAGICKCORE_QUANTUM_DEPTH == 64)
00558 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00559 {
00560   return((Quantum) (72340172838076673.0*value));
00561 }
00562 
00563 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00564 {
00565   return((Quantum) (4294967297.0*value));
00566 }
00567 
00568 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00569 {
00570   if (value <= 0.0)
00571     return((Quantum) 0);
00572   if (value >= MaxMap)
00573     return(QuantumRange);
00574   return((Quantum) (281479271743489.0*value));
00575 }
00576 
00577 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00578 {
00579   return((unsigned int) (quantum/4294967297.0+0.5));
00580 }
00581 
00582 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00583 {
00584   if (quantum <= 0.0)
00585     return(0UL);
00586   if ((quantum/281479271743489.0) >= MaxMap)
00587     return((unsigned int) MaxMap);
00588   return((unsigned int) (quantum/281479271743489.0+0.5));
00589 }
00590 
00591 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00592 {
00593   if (quantum <= 0.0)
00594     return(0);
00595   if ((quantum/281479271743489.0) >= 65535.0)
00596     return(65535);
00597   return((unsigned short) (quantum/281479271743489.0+0.5));
00598 }
00599 
00600 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00601 {
00602   return((Quantum) (281479271743489.0*value));
00603 }
00604 #endif
00605 
00606 static inline unsigned short SinglePrecisionToHalf(const float value)
00607 {
00608   typedef union _SinglePrecision
00609   {
00610     unsigned int
00611       fixed_point;
00612 
00613     float
00614       single_precision;
00615   } SinglePrecision;
00616 
00617   register int
00618     exponent;
00619 
00620   register unsigned int
00621     significand,
00622     sign_bit;
00623 
00624   SinglePrecision
00625     map;
00626 
00627   unsigned short
00628     half;
00629 
00630   /*
00631     The IEEE 754 standard specifies half precision as having:
00632 
00633       Sign bit: 1 bit
00634       Exponent width: 5 bits
00635       Significand precision: 11 (10 explicitly stored)
00636   */
00637   map.single_precision=value;
00638   sign_bit=(map.fixed_point >> 16) & 0x00008000;
00639   exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
00640   significand=map.fixed_point & 0x007fffff;
00641   if (exponent <= 0)
00642     {
00643       int
00644         shift;
00645 
00646       if (exponent < -10)
00647         return((unsigned short) sign_bit);
00648       significand=significand | 0x00800000;
00649       shift=(int) (14-exponent);
00650       significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
00651         ((significand >> shift) & 0x01)) >> shift);
00652       return((unsigned short) (sign_bit | significand));
00653     }
00654   else
00655     if (exponent == (0xff-ExponentBias))
00656       {
00657         if (significand == 0)
00658           return((unsigned short) (sign_bit | ExponentMask));
00659         else
00660           {
00661             significand>>=SignificandShift;
00662             half=(unsigned short) (sign_bit | significand |
00663               (significand == 0) | ExponentMask);
00664             return(half);
00665           }
00666       }
00667   significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
00668   if ((significand & 0x00800000) != 0)
00669     {
00670       significand=0;
00671       exponent++;
00672     }
00673   if (exponent > 30)
00674     {
00675       float
00676         alpha;
00677 
00678       register int
00679         i;
00680 
00681       /*
00682         Float overflow.
00683       */
00684       alpha=1.0e10;
00685       for (i=0; i < 10; i++)
00686         alpha*=alpha;
00687       return((unsigned short) (sign_bit | ExponentMask));
00688     }
00689   half=(unsigned short) (sign_bit | (exponent << 10) |
00690     (significand >> SignificandShift));
00691   return(half);
00692 }
00693 
00694 #if defined(__cplusplus) || defined(c_plusplus)
00695 }
00696 #endif
00697 
00698 #endif

Generated on 23 Sep 2019 for MagickCore by  doxygen 1.6.1