quantum-private.h

Go to the documentation of this file.
00001 /*
00002   Copyright 1999-2020 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 *magick_restrict 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 *magick_restrict 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 *magick_restrict 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(
00233   const unsigned char *magick_restrict pixels,
00234   unsigned char *magick_restrict pixel)
00235 {
00236   *pixel=(*pixels++);
00237   return(pixels);
00238 }
00239 
00240 static inline const unsigned char *PushLongPixel(const EndianType endian,
00241   const unsigned char *magick_restrict pixels,
00242   unsigned int *magick_restrict pixel)
00243 {
00244   register unsigned int
00245     quantum;
00246 
00247   if (endian == LSBEndian)
00248     {
00249       quantum=((unsigned int) *pixels++);
00250       quantum|=((unsigned int) *pixels++ << 8);
00251       quantum|=((unsigned int) *pixels++ << 16);
00252       quantum|=((unsigned int) *pixels++ << 24);
00253       *pixel=quantum;
00254       return(pixels);
00255     }
00256   quantum=((unsigned int) *pixels++ << 24);
00257   quantum|=((unsigned int) *pixels++ << 16);
00258   quantum|=((unsigned int) *pixels++ << 8);
00259   quantum|=((unsigned int) *pixels++);
00260   *pixel=quantum;
00261   return(pixels);
00262 }
00263 
00264 static inline const unsigned char *PushShortPixel(const EndianType endian,
00265   const unsigned char *magick_restrict pixels,
00266   unsigned short *magick_restrict pixel)
00267 {
00268   register unsigned int
00269     quantum;
00270 
00271   if (endian == LSBEndian)
00272     {
00273       quantum=(unsigned int) *pixels++;
00274       quantum|=(unsigned int) (*pixels++ << 8);
00275       *pixel=(unsigned short) (quantum & 0xffff);
00276       return(pixels);
00277     }
00278   quantum=(unsigned int) (*pixels++ << 8);
00279   quantum|=(unsigned int) *pixels++;
00280   *pixel=(unsigned short) (quantum & 0xffff);
00281   return(pixels);
00282 }
00283 
00284 static inline const unsigned char *PushFloatPixel(const EndianType endian,
00285   const unsigned char *magick_restrict pixels,
00286   MagickFloatType *magick_restrict pixel)
00287 {
00288   union
00289   {
00290     unsigned int
00291       unsigned_value;
00292 
00293     MagickFloatType
00294       float_value;
00295   } quantum;
00296 
00297   if (endian == LSBEndian)
00298     {
00299       quantum.unsigned_value=((unsigned int) *pixels++);
00300       quantum.unsigned_value|=((unsigned int) *pixels++ << 8);
00301       quantum.unsigned_value|=((unsigned int) *pixels++ << 16);
00302       quantum.unsigned_value|=((unsigned int) *pixels++ << 24);
00303       *pixel=quantum.float_value;
00304       return(pixels);
00305     }
00306   quantum.unsigned_value=((unsigned int) *pixels++ << 24);
00307   quantum.unsigned_value|=((unsigned int) *pixels++ << 16);
00308   quantum.unsigned_value|=((unsigned int) *pixels++ << 8);
00309   quantum.unsigned_value|=((unsigned int) *pixels++);
00310   *pixel=quantum.float_value;
00311   return(pixels);
00312 }
00313 
00314 static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
00315   const QuantumAny range)
00316 {
00317   if (quantum > range)
00318     return(QuantumRange);
00319 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00320   return((Quantum) ((double) QuantumRange*(quantum*
00321     PerceptibleReciprocal((double) range))+0.5));
00322 #else
00323   return((Quantum) ((double) QuantumRange*(quantum*
00324     PerceptibleReciprocal((double) range))));
00325 #endif
00326 }
00327 
00328 static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
00329   const QuantumAny range)
00330 {
00331 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00332   return((QuantumAny) ((MagickRealType) range*quantum/QuantumRange));
00333 #else
00334   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00335     return((QuantumAny) 0UL);
00336   if (((MagickRealType) range*quantum/QuantumRange) >= 18446744073709551615.0)
00337     return((QuantumAny) MagickULLConstant(18446744073709551615));
00338   return((QuantumAny) ((MagickRealType) range*quantum/QuantumRange+0.5));
00339 #endif
00340 }
00341 
00342 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
00343 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00344 {
00345   return((Quantum) value);
00346 }
00347 
00348 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00349 {
00350 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00351   return((Quantum) ((value)/16843009UL));
00352 #else
00353   return((Quantum) (value/16843009.0));
00354 #endif
00355 }
00356 
00357 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00358 {
00359   if (value <= 0.0)
00360     return((Quantum) 0);
00361   if (value >= MaxMap)
00362     return(QuantumRange);
00363 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00364   return((Quantum) (value+0.5));
00365 #else
00366   return((Quantum) value);
00367 #endif
00368 }
00369 
00370 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00371 {
00372 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00373   return((unsigned int) (16843009UL*quantum));
00374 #else
00375   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00376     return(0U);
00377   if ((16843009.0*quantum) >= 4294967295.0)
00378     return(4294967295UL);
00379   return((unsigned int) (16843009.0*quantum+0.5));
00380 #endif
00381 }
00382 
00383 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00384 {
00385   if (quantum >= (Quantum) MaxMap)
00386     return((unsigned int) MaxMap);
00387 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00388   return((unsigned int) quantum);
00389 #else
00390   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00391     return(0U);
00392   return((unsigned int) (quantum+0.5));
00393 #endif
00394 }
00395 
00396 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00397 {
00398 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00399   return((unsigned short) (257UL*quantum));
00400 #else
00401   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00402     return(0);
00403   if ((257.0*quantum) >= 65535.0)
00404     return(65535);
00405   return((unsigned short) (257.0*quantum+0.5));
00406 #endif
00407 }
00408 
00409 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00410 {
00411 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00412   return((Quantum) ((value+128U)/257U));
00413 #else
00414   return((Quantum) (value/257.0));
00415 #endif
00416 }
00417 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
00418 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00419 {
00420 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00421   return((Quantum) (257U*value));
00422 #else
00423   return((Quantum) (257.0*value));
00424 #endif
00425 }
00426 
00427 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00428 {
00429 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00430   return((Quantum) ((value)/MagickULLConstant(65537)));
00431 #else
00432   return((Quantum) (value/65537.0));
00433 #endif
00434 }
00435 
00436 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00437 {
00438   if (value <= 0.0)
00439     return((Quantum) 0);
00440   if (value >= MaxMap)
00441     return(QuantumRange);
00442 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00443   return((Quantum) (value+0.5));
00444 #else
00445   return((Quantum) value);
00446 #endif
00447 }
00448 
00449 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00450 {
00451 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00452   return((unsigned int) (65537UL*quantum));
00453 #else
00454   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00455     return(0U);
00456   if ((65537.0*quantum) >= 4294967295.0)
00457     return(4294967295U);
00458   return((unsigned int) (65537.0*quantum+0.5));
00459 #endif
00460 }
00461 
00462 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00463 {
00464   if (quantum >= (Quantum) MaxMap)
00465     return((unsigned int) MaxMap);
00466 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00467   return((unsigned int) quantum);
00468 #else
00469   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00470     return(0U);
00471   return((unsigned int) (quantum+0.5));
00472 #endif
00473 }
00474 
00475 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00476 {
00477 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00478   return((unsigned short) quantum);
00479 #else
00480   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00481     return(0);
00482   if (quantum >= 65535.0)
00483     return(65535);
00484   return((unsigned short) (quantum+0.5));
00485 #endif
00486 }
00487 
00488 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00489 {
00490   return((Quantum) value);
00491 }
00492 #elif (MAGICKCORE_QUANTUM_DEPTH == 32)
00493 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00494 {
00495 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00496   return((Quantum) (16843009UL*value));
00497 #else
00498   return((Quantum) (16843009.0*value));
00499 #endif
00500 }
00501 
00502 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00503 {
00504   return((Quantum) value);
00505 }
00506 
00507 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00508 {
00509   if (value <= 0.0)
00510     return((Quantum) 0);
00511   if (value >= (Quantum) MaxMap)
00512     return(QuantumRange);
00513 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00514   return((Quantum) (65537.0*value+0.5));
00515 #else
00516   return((Quantum) (65537.0*value));
00517 #endif
00518 }
00519 
00520 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00521 {
00522 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00523   return((unsigned int) quantum);
00524 #else
00525   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00526     return(0U);
00527   if ((quantum) >= 4294967295.0)
00528     return(4294967295);
00529   return((unsigned int) (quantum+0.5));
00530 #endif
00531 }
00532 
00533 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00534 {
00535   if ((quantum/65537) >= (Quantum) MaxMap)
00536     return((unsigned int) MaxMap);
00537 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00538   return((unsigned int) ((quantum+MagickULLConstant(32768))/
00539     MagickULLConstant(65537)));
00540 #else
00541   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00542     return(0U);
00543   return((unsigned int) (quantum/65537.0+0.5));
00544 #endif
00545 }
00546 
00547 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00548 {
00549 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00550   return((unsigned short) ((quantum+MagickULLConstant(32768))/
00551     MagickULLConstant(65537)));
00552 #else
00553   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00554     return(0);
00555   if ((quantum/65537.0) >= 65535.0)
00556     return(65535);
00557   return((unsigned short) (quantum/65537.0+0.5));
00558 #endif
00559 }
00560 
00561 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00562 {
00563 #if !defined(MAGICKCORE_HDRI_SUPPORT)
00564   return((Quantum) (65537UL*value));
00565 #else
00566   return((Quantum) (65537.0*value));
00567 #endif
00568 }
00569 #elif (MAGICKCORE_QUANTUM_DEPTH == 64)
00570 static inline Quantum ScaleCharToQuantum(const unsigned char value)
00571 {
00572   return((Quantum) (72340172838076673.0*value));
00573 }
00574 
00575 static inline Quantum ScaleLongToQuantum(const unsigned int value)
00576 {
00577   return((Quantum) (4294967297.0*value));
00578 }
00579 
00580 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
00581 {
00582   if (value <= 0.0)
00583     return((Quantum) 0);
00584   if (value >= MaxMap)
00585     return(QuantumRange);
00586   return((Quantum) (281479271743489.0*value));
00587 }
00588 
00589 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
00590 {
00591   return((unsigned int) (quantum/4294967297.0+0.5));
00592 }
00593 
00594 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
00595 {
00596   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00597     return(0U);
00598   if ((quantum/281479271743489.0) >= MaxMap)
00599     return((unsigned int) MaxMap);
00600   return((unsigned int) (quantum/281479271743489.0+0.5));
00601 }
00602 
00603 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
00604 {
00605   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
00606     return(0);
00607   if ((quantum/281479271743489.0) >= 65535.0)
00608     return(65535);
00609   return((unsigned short) (quantum/281479271743489.0+0.5));
00610 }
00611 
00612 static inline Quantum ScaleShortToQuantum(const unsigned short value)
00613 {
00614   return((Quantum) (281479271743489.0*value));
00615 }
00616 #endif
00617 
00618 static inline unsigned short SinglePrecisionToHalf(const float value)
00619 {
00620   typedef union _SinglePrecision
00621   {
00622     unsigned int
00623       fixed_point;
00624 
00625     float
00626       single_precision;
00627   } SinglePrecision;
00628 
00629   register int
00630     exponent;
00631 
00632   register unsigned int
00633     significand,
00634     sign_bit;
00635 
00636   SinglePrecision
00637     map;
00638 
00639   unsigned short
00640     half;
00641 
00642   /*
00643     The IEEE 754 standard specifies half precision as having:
00644 
00645       Sign bit: 1 bit
00646       Exponent width: 5 bits
00647       Significand precision: 11 (10 explicitly stored)
00648   */
00649   map.single_precision=value;
00650   sign_bit=(map.fixed_point >> 16) & 0x00008000;
00651   exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
00652   significand=map.fixed_point & 0x007fffff;
00653   if (exponent <= 0)
00654     {
00655       int
00656         shift;
00657 
00658       if (exponent < -10)
00659         return((unsigned short) sign_bit);
00660       significand=significand | 0x00800000;
00661       shift=(int) (14-exponent);
00662       significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
00663         ((significand >> shift) & 0x01)) >> shift);
00664       return((unsigned short) (sign_bit | significand));
00665     }
00666   else
00667     if (exponent == (0xff-ExponentBias))
00668       {
00669         if (significand == 0)
00670           return((unsigned short) (sign_bit | ExponentMask));
00671         else
00672           {
00673             significand>>=SignificandShift;
00674             half=(unsigned short) (sign_bit | significand |
00675               (significand == 0) | ExponentMask);
00676             return(half);
00677           }
00678       }
00679   significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
00680   if ((significand & 0x00800000) != 0)
00681     {
00682       significand=0;
00683       exponent++;
00684     }
00685   if (exponent > 30)
00686     {
00687       float
00688         alpha;
00689 
00690       register int
00691         i;
00692 
00693       /*
00694         Float overflow.
00695       */
00696       alpha=1.0e10;
00697       for (i=0; i < 10; i++)
00698         alpha*=alpha;
00699       return((unsigned short) (sign_bit | ExponentMask));
00700     }
00701   half=(unsigned short) (sign_bit | (exponent << 10) |
00702     (significand >> SignificandShift));
00703   return(half);
00704 }
00705 
00706 #if defined(__cplusplus) || defined(c_plusplus)
00707 }
00708 #endif
00709 
00710 #endif

Generated on 7 Sep 2020 for MagickCore by  doxygen 1.6.1