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   if (quantum < 0)
00328     return((QuantumAny) 0);
00329   return((QuantumAny) (((MagickRealType) range*quantum)/QuantumRange+0.5));
00330 }
00331 
00332 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
00333 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00334 {
00335   return((Quantum) value);
00336 }
00337 
00338 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00339 {
00340 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00341   return((Quantum) ((value)/16843009UL));
00342 #else
00343   return((Quantum) (value/16843009.0));
00344 #endif
00345 }
00346 
00347 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00348 {
00349   if (value <= 0.0)
00350     return((Quantum) 0);
00351   if (value >= MaxMap)
00352     return(QuantumRange);
00353 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00354   return((Quantum) (value+0.5));
00355 #else
00356   return((Quantum) value);
00357 #endif
00358 }
00359 
00360 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00361 {
00362 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00363   return((unsigned int) (16843009UL*quantum));
00364 #else
00365   if (quantum <= 0.0)
00366     return(0UL);
00367   if ((16843009.0*quantum) >= 4294967295.0)
00368     return(4294967295UL);
00369   return((unsigned int) (16843009.0*quantum+0.5));
00370 #endif
00371 }
00372 
00373 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00374 {
00375   if (quantum >= (Quantum) MaxMap)
00376     return((unsigned int) MaxMap);
00377 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00378   return((unsigned int) quantum);
00379 #else
00380   if (quantum < 0.0)
00381     return(0UL);
00382   return((unsigned int) (quantum+0.5));
00383 #endif
00384 }
00385 
00386 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00387 {
00388 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00389   return((unsigned short) (257UL*quantum));
00390 #else
00391   if (quantum <= 0.0)
00392     return(0);
00393   if ((257.0*quantum) >= 65535.0)
00394     return(65535);
00395   return((unsigned short) (257.0*quantum+0.5));
00396 #endif
00397 }
00398 
00399 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00400 {
00401 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00402   return((Quantum) ((value+128U)/257U));
00403 #else
00404   return((Quantum) (value/257.0));
00405 #endif
00406 }
00407 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
00408 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00409 {
00410 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00411   return((Quantum) (257U*value));
00412 #else
00413   return((Quantum) (257.0*value));
00414 #endif
00415 }
00416 
00417 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00418 {
00419 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00420   return((Quantum) ((value)/MagickULLConstant(65537)));
00421 #else
00422   return((Quantum) (value/65537.0));
00423 #endif
00424 }
00425 
00426 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00427 {
00428   if (value <= 0.0)
00429     return((Quantum) 0);
00430   if (value >= MaxMap)
00431     return(QuantumRange);
00432 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00433   return((Quantum) (value+0.5));
00434 #else
00435   return((Quantum) value);
00436 #endif
00437 }
00438 
00439 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00440 {
00441 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00442   return((unsigned int) (65537UL*quantum));
00443 #else
00444   if (quantum <= 0.0)
00445     return(0UL);
00446   if ((65537.0*quantum) >= 4294967295.0)
00447     return(4294967295U);
00448   return((unsigned int) (65537.0*quantum+0.5));
00449 #endif
00450 }
00451 
00452 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00453 {
00454   if (quantum >= (Quantum) MaxMap)
00455     return((unsigned int) MaxMap);
00456 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00457   return((unsigned int) quantum);
00458 #else
00459   if (quantum < 0.0)
00460     return(0UL);
00461   return((unsigned int) (quantum+0.5));
00462 #endif
00463 }
00464 
00465 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00466 {
00467 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00468   return((unsigned short) quantum);
00469 #else
00470   if (quantum <= 0.0)
00471     return(0);
00472   if (quantum >= 65535.0)
00473     return(65535);
00474   return((unsigned short) (quantum+0.5));
00475 #endif
00476 }
00477 
00478 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00479 {
00480   return((Quantum) value);
00481 }
00482 #elif (MAGICKCORE_QUANTUM_DEPTH == 32)
00483 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00484 {
00485 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00486   return((Quantum) (16843009UL*value));
00487 #else
00488   return((Quantum) (16843009.0*value));
00489 #endif
00490 }
00491 
00492 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00493 {
00494   return((Quantum) value);
00495 }
00496 
00497 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00498 {
00499   if (value <= 0.0)
00500     return((Quantum) 0);
00501   if (value >= (Quantum) MaxMap)
00502     return(QuantumRange);
00503 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00504   return((Quantum) (65537.0*value+0.5));
00505 #else
00506   return((Quantum) (65537.0*value));
00507 #endif
00508 }
00509 
00510 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00511 {
00512 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00513   return((unsigned int) quantum);
00514 #else
00515   if (quantum <= 0.0)
00516     return(0);
00517   if ((quantum) >= 4294967295.0)
00518     return(4294967295);
00519   return((unsigned int) (quantum+0.5));
00520 #endif
00521 }
00522 
00523 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00524 {
00525   if (quantum < 0.0)
00526     return(0UL);
00527   if ((quantum/65537) >= (Quantum) MaxMap)
00528     return((unsigned int) MaxMap);
00529 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00530   return((unsigned int) ((quantum+MagickULLConstant(32768))/
00531     MagickULLConstant(65537)));
00532 #else
00533   return((unsigned int) (quantum/65537.0+0.5));
00534 #endif
00535 }
00536 
00537 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00538 {
00539 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00540   return((unsigned short) ((quantum+MagickULLConstant(32768))/
00541     MagickULLConstant(65537)));
00542 #else
00543   if (quantum <= 0.0)
00544     return(0);
00545   if ((quantum/65537.0) >= 65535.0)
00546     return(65535);
00547   return((unsigned short) (quantum/65537.0+0.5));
00548 #endif
00549 }
00550 
00551 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00552 {
00553 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00554   return((Quantum) (65537UL*value));
00555 #else
00556   return((Quantum) (65537.0*value));
00557 #endif
00558 }
00559 #elif (MAGICKCORE_QUANTUM_DEPTH == 64)
00560 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00561 {
00562   return((Quantum) (72340172838076673.0*value));
00563 }
00564 
00565 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00566 {
00567   return((Quantum) (4294967297.0*value));
00568 }
00569 
00570 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00571 {
00572   if (value <= 0.0)
00573     return((Quantum) 0);
00574   if (value >= MaxMap)
00575     return(QuantumRange);
00576   return((Quantum) (281479271743489.0*value));
00577 }
00578 
00579 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00580 {
00581   return((unsigned int) (quantum/4294967297.0+0.5));
00582 }
00583 
00584 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00585 {
00586   if (quantum <= 0.0)
00587     return(0UL);
00588   if ((quantum/281479271743489.0) >= MaxMap)
00589     return((unsigned int) MaxMap);
00590   return((unsigned int) (quantum/281479271743489.0+0.5));
00591 }
00592 
00593 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00594 {
00595   if (quantum <= 0.0)
00596     return(0);
00597   if ((quantum/281479271743489.0) >= 65535.0)
00598     return(65535);
00599   return((unsigned short) (quantum/281479271743489.0+0.5));
00600 }
00601 
00602 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00603 {
00604   return((Quantum) (281479271743489.0*value));
00605 }
00606 #endif
00607 
00608 static inline unsigned short SinglePrecisionToHalf(const float value)
00609 {
00610   typedef union _SinglePrecision
00611   {
00612     unsigned int
00613       fixed_point;
00614 
00615     float
00616       single_precision;
00617   } SinglePrecision;
00618 
00619   register int
00620     exponent;
00621 
00622   register unsigned int
00623     significand,
00624     sign_bit;
00625 
00626   SinglePrecision
00627     map;
00628 
00629   unsigned short
00630     half;
00631 
00632   /*
00633     The IEEE 754 standard specifies half precision as having:
00634 
00635       Sign bit: 1 bit
00636       Exponent width: 5 bits
00637       Significand precision: 11 (10 explicitly stored)
00638   */
00639   map.single_precision=value;
00640   sign_bit=(map.fixed_point >> 16) & 0x00008000;
00641   exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
00642   significand=map.fixed_point & 0x007fffff;
00643   if (exponent <= 0)
00644     {
00645       int
00646         shift;
00647 
00648       if (exponent < -10)
00649         return((unsigned short) sign_bit);
00650       significand=significand | 0x00800000;
00651       shift=(int) (14-exponent);
00652       significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
00653         ((significand >> shift) & 0x01)) >> shift);
00654       return((unsigned short) (sign_bit | significand));
00655     }
00656   else
00657     if (exponent == (0xff-ExponentBias))
00658       {
00659         if (significand == 0)
00660           return((unsigned short) (sign_bit | ExponentMask));
00661         else
00662           {
00663             significand>>=SignificandShift;
00664             half=(unsigned short) (sign_bit | significand |
00665               (significand == 0) | ExponentMask);
00666             return(half);
00667           }
00668       }
00669   significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
00670   if ((significand & 0x00800000) != 0)
00671     {
00672       significand=0;
00673       exponent++;
00674     }
00675   if (exponent > 30)
00676     {
00677       float
00678         alpha;
00679 
00680       register int
00681         i;
00682 
00683       /*
00684         Float overflow.
00685       */
00686       alpha=1.0e10;
00687       for (i=0; i < 10; i++)
00688         alpha*=alpha;
00689       return((unsigned short) (sign_bit | ExponentMask));
00690     }
00691   half=(unsigned short) (sign_bit | (exponent << 10) |
00692     (significand >> SignificandShift));
00693   return(half);
00694 }
00695 
00696 #if defined(__cplusplus) || defined(c_plusplus)
00697 }
00698 #endif
00699 
00700 #endif

Generated on 7 Oct 2019 for MagickCore by  doxygen 1.6.1