Shinya Kitaoka 810553
#pragma once
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef T_PIXELUTILS_INCLUDED
Toshihiro Shimizu 890ddd
#define T_PIXELUTILS_INCLUDED
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tpixel.h"
Toshihiro Shimizu 890ddd
#include "tpixelgr.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#undef DVAPI
Toshihiro Shimizu 890ddd
#undef DVVAR
Toshihiro Shimizu 890ddd
#ifdef TCOLOR_EXPORTS
Toshihiro Shimizu 890ddd
#define DVAPI DV_EXPORT_API
Toshihiro Shimizu 890ddd
#define DVVAR DV_EXPORT_VAR
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
#define DVAPI DV_IMPORT_API
Toshihiro Shimizu 890ddd
#define DVVAR DV_IMPORT_VAR
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
/*! this template function computes a linear interpolation between
Toshihiro Shimizu 890ddd
    the color \b a and \b b according to the parameter \b t.
Toshihiro Shimizu 890ddd
    If \b t = 0, it returns \b a;
Toshihiro Shimizu 890ddd
    if \b t = 1, it returns \b b;
Toshihiro Shimizu 890ddd
    No check is performed.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
inline T blend(const T &a, const T &b, double t) {
Shinya Kitaoka 120a6e
  return T(troundp((1 - t) * a.r + t * b.r), troundp((1 - t) * a.g + t * b.g),
Shinya Kitaoka 120a6e
           troundp((1 - t) * a.b + t * b.b), troundp((1 - t) * a.m + t * b.m));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
/*! this template function computes a linear interpolation between
Toshihiro Shimizu 890ddd
    the color \b a and \b b according to the ratio between \b num and \b den.
Toshihiro Shimizu 890ddd
    If \b num / \b den = 0, it returns \b a;
Toshihiro Shimizu 890ddd
    if \b num / \b den = 1, it returns \b b;
Shinya Kitaoka 120a6e
    No check is performed.
Toshihiro Shimizu 890ddd
    \warning \b b MUST be not zero.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
inline T blend(const T &a, const T &b, int num, int den) {
Shinya Kitaoka 120a6e
  return T((int)(((den - num) * a.r + num * b.r) / den),
Shinya Kitaoka 120a6e
           (int)(((den - num) * a.g + num * b.g) / den),
Shinya Kitaoka 120a6e
           (int)(((den - num) * a.b + num * b.b) / den),
Shinya Kitaoka 120a6e
           (int)(((den - num) * a.m + num * b.m) / den));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
inline T antialias(const T &a, int num) {
Shinya Kitaoka 120a6e
  return T((int)((num * a.r) / 255), (int)((num * a.g) / 255),
Shinya Kitaoka 120a6e
           (int)((num * a.b) / 255), (int)((num * a.m) / 255));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! this function combines two pixels according to their alpha channel.
Toshihiro Shimizu 890ddd
    If the \b top pixel is completely opaque the function returns it.
Toshihiro Shimizu 890ddd
    If the \b top pixel is completely transparent the function returns \b bot.
Toshihiro Shimizu 890ddd
    In the other cases a blend is performed.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class class="" q="" t,=""></class>
Shinya Kitaoka 120a6e
DVAPI inline T overPixT(const T &bot, const T &top) {
Shinya Kitaoka 120a6e
  UINT max = T::maxChannelValue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (top.m == max) return top;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (top.m == 0) return bot;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUINT32 r = top.r + bot.r * (max - top.m) / max;
Shinya Kitaoka 120a6e
  TUINT32 g = top.g + bot.g * (max - top.m) / max;
Shinya Kitaoka 120a6e
  TUINT32 b = top.b + bot.b * (max - top.m) / max;
Shinya Kitaoka 120a6e
  return T((r < max) ? (Q)r : (Q)max, (g < max) ? (Q)g : (Q)max,
Shinya Kitaoka 120a6e
           (b < max) ? (Q)b : (Q)max,
Shinya Kitaoka 120a6e
           (bot.m == max) ? max : max - (max - bot.m) * (max - top.m) / max);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
template <class class="" q="" s,="" t,=""></class>
Shinya Kitaoka 120a6e
DVAPI inline T overPixGRT(const T &bot, const S &top) {
Shinya Kitaoka 120a6e
  UINT max = T::maxChannelValue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (top.value == max) return T(top.value, top.value, top.value, top.value);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (top.value == 0) return bot;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double aux = (max - top.value) / max;
Shinya Kitaoka 120a6e
  TUINT32 r  = (TUINT32)(top.value + bot.r * aux);
Shinya Kitaoka 120a6e
  TUINT32 g  = (TUINT32)(top.value + bot.g * aux);
Shinya Kitaoka 120a6e
  TUINT32 b  = (TUINT32)(top.value + bot.b * aux);
Shinya Kitaoka 120a6e
  return T((r < max) ? (Q)r : (Q)max, (g < max) ? (Q)g : (Q)max,
Shinya Kitaoka 120a6e
           (b < max) ? (Q)b : (Q)max,
Shinya Kitaoka 120a6e
           (bot.m == max) ? max : (TUINT32)(max - (max - bot.m) * aux));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
// as the other, but without if's. it's quicker if you know for sure that top.m
Shinya Kitaoka 120a6e
// is not 0 or 255.
Toshihiro Shimizu 890ddd
template <class class="" q="" t,=""></class>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline T quickOverPixT(const T &bot, const T &top) {
Shinya Kitaoka 120a6e
  UINT max = T::maxChannelValue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUINT32 r = top.r + bot.r * (max - top.m) / max;
Shinya Kitaoka 120a6e
  TUINT32 g = top.g + bot.g * (max - top.m) / max;
Shinya Kitaoka 120a6e
  TUINT32 b = top.b + bot.b * (max - top.m) / max;
Shinya Kitaoka 120a6e
  return T((r < max) ? (Q)r : (Q)max, (g < max) ? (Q)g : (Q)max,
Shinya Kitaoka 120a6e
           (b < max) ? (Q)b : (Q)max,
Shinya Kitaoka 120a6e
           (bot.m == max) ? max : max - (max - bot.m) * (max - top.m) / max);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class class="" q="" t,=""></class>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline T quickOverPixPremultT(const T &bot, const T &top) {
Shinya Kitaoka 120a6e
  UINT max = T::maxChannelValue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUINT32 r = (top.r * top.m + bot.r * (max - top.m)) / max;
Shinya Kitaoka 120a6e
  TUINT32 g = (top.g * top.m + bot.g * (max - top.m)) / max;
Shinya Kitaoka 120a6e
  TUINT32 b = (top.b * top.m + bot.b * (max - top.m)) / max;
Shinya Kitaoka 120a6e
  return T((r < max) ? (Q)r : (Q)max, (g < max) ? (Q)g : (Q)max,
Shinya Kitaoka 120a6e
           (b < max) ? (Q)b : (Q)max,
Shinya Kitaoka 120a6e
           (bot.m == max) ? max : max - (max - bot.m) * (max - top.m) / max);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------------
shun_iwasawa 21a6b6
/*-- Show raster images darken-blended on the viewer --*/
Toshihiro Shimizu 890ddd
template <class class="" q="" t,=""></class>
Shinya Kitaoka 120a6e
DVAPI inline T quickOverPixDarkenBlendedT(const T &bot, const T &top) {
shun_iwasawa 21a6b6
  UINT max = T::maxChannelValue;
shun_iwasawa 21a6b6
  if (bot.m == 0) return top;
Shinya Kitaoka 120a6e
  TUINT32 r = (top.r < bot.r) ? top.r : bot.r;
Shinya Kitaoka 120a6e
  TUINT32 g = (top.g < bot.g) ? top.g : bot.g;
Shinya Kitaoka 120a6e
  TUINT32 b = (top.b < bot.b) ? top.b : bot.b;
Shinya Kitaoka 120a6e
  return T((Q)r, (Q)g, (Q)b, max);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
template <class class="" q="" s,="" t,=""></class>
Shinya Kitaoka 120a6e
DVAPI inline T quickOverPixGRT(const T &bot, const S &top) {
Shinya Kitaoka 120a6e
  UINT max = T::maxChannelValue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double aux = (max - top.value) / max;
Shinya Kitaoka 120a6e
  TUINT32 r  = (TUINT32)(top.value + bot.r * aux);
Shinya Kitaoka 120a6e
  TUINT32 g  = (TUINT32)(top.value + bot.g * aux);
Shinya Kitaoka 120a6e
  TUINT32 b  = (TUINT32)(top.value + bot.b * aux);
Shinya Kitaoka 120a6e
  return T((r < max) ? (Q)r : (Q)max, (g < max) ? (Q)g : (Q)max,
Shinya Kitaoka 120a6e
           (b < max) ? (Q)b : (Q)max,
Shinya Kitaoka 120a6e
           (bot.m == max) ? max : (TUINT32)(max - (max - bot.m) * aux));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel32 overPix(const TPixel32 &bot, const TPixelGR8 &top) {
Shinya Kitaoka 120a6e
  return overPixGRT<tpixel32, tpixelgr8,="" uchar="">(bot, top);</tpixel32,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel64 overPix(const TPixel64 &bot, const TPixelGR16 &top) {
Shinya Kitaoka 120a6e
  return overPixGRT<tpixel64, tpixelgr16,="" ushort="">(bot, top);</tpixel64,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel32 overPix(const TPixel32 &bot, const TPixel32 &top) {
Shinya Kitaoka 120a6e
  return overPixT<tpixel32, uchar="">(bot, top);</tpixel32,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel64 overPix(const TPixel64 &bot, const TPixel64 &top) {
Shinya Kitaoka 120a6e
  return overPixT<tpixel64, ushort="">(bot, top);</tpixel64,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel32 quickOverPix(const TPixel32 &bot, const TPixelGR8 &top) {
Shinya Kitaoka 120a6e
  return quickOverPixGRT<tpixel32, tpixelgr8,="" uchar="">(bot, top);</tpixel32,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel64 quickOverPix(const TPixel64 &bot, const TPixelGR16 &top) {
Shinya Kitaoka 120a6e
  return quickOverPixGRT<tpixel64, tpixelgr16,="" ushort="">(bot, top);</tpixel64,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel32 quickOverPix(const TPixel32 &bot, const TPixel32 &top) {
Shinya Kitaoka 120a6e
  return quickOverPixT<tpixel32, uchar="">(bot, top);</tpixel32,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel32 quickOverPixPremult(const TPixel32 &bot,
Shinya Kitaoka 120a6e
                                          const TPixel32 &top) {
Shinya Kitaoka 120a6e
  return quickOverPixPremultT<tpixel32, uchar="">(bot, top);</tpixel32,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel64 quickOverPix(const TPixel64 &bot, const TPixel64 &top) {
Shinya Kitaoka 120a6e
  return quickOverPixT<tpixel64, ushort="">(bot, top);</tpixel64,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel32 quickOverPixDarkenBlended(const TPixel32 &bot,
Shinya Kitaoka 120a6e
                                                const TPixel32 &top) {
Shinya Kitaoka 120a6e
  return quickOverPixDarkenBlendedT<tpixel32, uchar="">(bot, top);</tpixel32,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class class="" q="" t,=""></class>
Shinya Kitaoka 120a6e
DVAPI inline void overPix(T &outPix, const T &bot, const T &top) {
Shinya Kitaoka 120a6e
  UINT max = T::maxChannelValue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (top.m == max)
Shinya Kitaoka 120a6e
    outPix = top;
Shinya Kitaoka 120a6e
  else if (top.m == 0)
Shinya Kitaoka 120a6e
    outPix = bot;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    TUINT32 r = top.r + bot.r * (max - top.m) / max;
Shinya Kitaoka 120a6e
    TUINT32 g = top.g + bot.g * (max - top.m) / max;
Shinya Kitaoka 120a6e
    TUINT32 b = top.b + bot.b * (max - top.m) / max;
Shinya Kitaoka 120a6e
    outPix.r = (r < max) ? (Q)r : (Q)max, outPix.g = (g < max) ? (Q)g : (Q)max,
Shinya Kitaoka 120a6e
    outPix.b = (b < max) ? (Q)b : (Q)max,
Shinya Kitaoka 120a6e
    outPix.m = (bot.m == max) ? max : max - (max - bot.m) * (max - top.m) / max;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel32 overPixOnWhite(const TPixel32 &top) {
Shinya Kitaoka 120a6e
  UINT max = TPixel32::maxChannelValue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (top.m == max)
Shinya Kitaoka 120a6e
    return top;
Shinya Kitaoka 120a6e
  else if (top.m == 0)
Shinya Kitaoka 120a6e
    return TPixel32::White;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return TPixel32(top.r + max - top.m, top.g + max - top.m,
Shinya Kitaoka 120a6e
                    top.b + max - top.m, max);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel32 overPixOnBlack(const TPixel32 &top) {
Shinya Kitaoka 120a6e
  UINT max = TPixel32::maxChannelValue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (top.m == max) return top;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (top.m == 0) return TPixel32::Black;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return TPixel32(top.r, top.g, top.b, max);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! this function combines two GR8 pixels returning the darker.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixelGR8 over(const TPixelGR8 &bot, const TPixelGR8 &top) {
Shinya Kitaoka 120a6e
  return TPixelGR8(std::min(bot.value, top.value));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! this function premultiply a not-premultiplied pixel.
Shinya Kitaoka 120a6e
    \note
Shinya Kitaoka 120a6e
     Premultiplied alpha is a term used to describe a source color,
Shinya Kitaoka 120a6e
     the components of which have already been multiplied by an alpha value.
Shinya Kitaoka 120a6e
     Premultiplied alpha is just a different way of representing alphified
Shinya Kitaoka 120a6e
   pixels.
Shinya Kitaoka 120a6e
     If the separate alpha pixel is (r, g, b, a), then the premultiplied alpha
Shinya Kitaoka 120a6e
   pixel is
Toshihiro Shimizu 890ddd
     (ar, ag, ab, a).
Shinya Kitaoka 120a6e
     Premultiplying speeds up the rendering of the image by eliminating an extra
Shinya Kitaoka 120a6e
     multiplication operation per color component.
Shinya Kitaoka 120a6e
     For example, in an RGB color space, rendering the image with premultiplied
Shinya Kitaoka 120a6e
   alpha
Shinya Kitaoka 120a6e
     eliminates three multiplication operations (red times alpha, green times
Shinya Kitaoka 120a6e
   alpha,
Toshihiro Shimizu 890ddd
     and blue times alpha) for each pixel in the image.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
     (Without premultiplication, the calculation to composite an image w/alpha
Shinya Kitaoka 120a6e
   into a comp is:
Shinya Kitaoka 120a6e
         dest = pix1 * alpha1 + (1 - alpha1) * pix2 * alpha2
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
     If both images' alphas are premultiplied, this gets reduced to:
Shinya Kitaoka 120a6e
         dest = pix1 + (1 - alpha1) * pix2
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline void premult(TPixel32 &pix) {
Shinya Kitaoka 120a6e
  const int MAGICFAC = (257U * 256U + 1U);
Shinya Kitaoka 120a6e
  UINT fac           = MAGICFAC * pix.m;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  pix.r = (UINT)(pix.r * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
  pix.g = (UINT)(pix.g * fac + (1U << 23)) >> 24;
Shinya Kitaoka 120a6e
  pix.b = (UINT)(pix.b * fac + (1U << 23)) >> 24;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline void premult(TPixel64 &pix) {
Shinya Kitaoka 120a6e
  pix.r = pix.r * pix.m / 65535.0;
Shinya Kitaoka 120a6e
  pix.g = pix.g * pix.m / 65535.0;
Shinya Kitaoka 120a6e
  pix.b = pix.b * pix.m / 65535.0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline void depremult(TPixel32 &pix) {
Shinya Kitaoka 120a6e
  float fac = 255.0f / pix.m;
Shinya Kitaoka 120a6e
  pix.r     = std::min(pix.r * fac, 255.0f);
Shinya Kitaoka 120a6e
  pix.g     = std::min(pix.g * fac, 255.0f);
Shinya Kitaoka 120a6e
  pix.b     = std::min(pix.b * fac, 255.0f);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline void depremult(TPixel64 &pix) {
Shinya Kitaoka 120a6e
  double fac = 65535.0 / pix.m;
Shinya Kitaoka 120a6e
  pix.r      = std::min(pix.r * fac, 65535.0);
Shinya Kitaoka 120a6e
  pix.g      = std::min(pix.g * fac, 65535.0);
Shinya Kitaoka 120a6e
  pix.b      = std::min(pix.b * fac, 65535.0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename chan=""></typename>
Toshihiro Shimizu 890ddd
const double *premultiplyTable();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename chan=""></typename>
Toshihiro Shimizu 890ddd
const double *depremultiplyTable();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel32 premultiply(const TPixel32 &pix) {
Shinya Kitaoka 120a6e
  const int MAGICFAC = (257U * 256U + 1U);
Shinya Kitaoka 120a6e
  UINT fac           = MAGICFAC * pix.m;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return TPixel32(((UINT)(pix.r * fac + (1U << 23)) >> 24),
Shinya Kitaoka 120a6e
                  ((UINT)(pix.g * fac + (1U << 23)) >> 24),
Shinya Kitaoka 120a6e
                  ((UINT)(pix.b * fac + (1U << 23)) >> 24), pix.m);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel64 premultiply(const TPixel64 &pix) {
Shinya Kitaoka 120a6e
  return TPixel64(pix.r * pix.m / 65535.0, pix.g * pix.m / 65535.0,
Shinya Kitaoka 120a6e
                  pix.b * pix.m / 65535.0, pix.m);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel32 depremultiply(const TPixel32 &pix) {
Shinya Kitaoka 120a6e
  return TPixel32(pix.r * 255.0 / pix.m, pix.g * 255.0 / pix.m,
Shinya Kitaoka 120a6e
                  pix.b * 255.0 / pix.m, pix.m);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI inline TPixel64 depremultiply(const TPixel64 &pix) {
Shinya Kitaoka 120a6e
  return TPixel64(pix.r * 65535.0 / pix.m, pix.g * 65535.0 / pix.m,
Shinya Kitaoka 120a6e
                  pix.b * 65535.0 / pix.m, pix.m);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! onversion between RGB and HSV colorspace
Toshihiro Shimizu 890ddd
DVAPI void hsv2rgb(TPixel32 &dstRgb, int srcHsv[3], int maxHsv = 255);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  IN : h in [0..360], s and v in [0..1]
Toshihiro Shimizu 890ddd
  OUT: r,g,b in [0..1]
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
DVAPI void HSV2RGB(double hue, double sat, double value, double *red,
Shinya Kitaoka 120a6e
                   double *green, double *blue);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DVAPI void rgb2hsv(int dstHsv[3], const TPixel32 &srcRgb, int maxHsv = 255);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI void RGB2HSV(double r, double g, double b, double *h, double *s,
Shinya Kitaoka 120a6e
                   double *v);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  IN : h in [0..360], l and s in [0..1]
Toshihiro Shimizu 890ddd
  OUT: r,g,b in [0..1]
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI void HLS2RGB(double h, double l, double s, double *r, double *g,
Shinya Kitaoka 120a6e
                   double *b);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  IN : r,g,b in [0..1]
Toshihiro Shimizu 890ddd
  OUT: h in [0..360], l and s in [0..1]
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DVAPI void rgb2hls(double r, double g, double b, double *h, double *l,
Shinya Kitaoka 120a6e
                   double *s);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DVAPI TPixel32 toPixel32(const TPixel64 &);
Toshihiro Shimizu 890ddd
DVAPI TPixel32 toPixel32(const TPixelD &);
Toshihiro Shimizu 890ddd
DVAPI TPixel32 toPixel32(const TPixelGR8 &);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DVAPI TPixel64 toPixel64(const TPixel32 &);
Toshihiro Shimizu 890ddd
DVAPI TPixel64 toPixel64(const TPixelD &);
Toshihiro Shimizu 890ddd
DVAPI TPixel64 toPixel64(const TPixelGR8 &);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DVAPI TPixelD toPixelD(const TPixel32 &);
Toshihiro Shimizu 890ddd
DVAPI TPixelD toPixelD(const TPixel64 &);
Toshihiro Shimizu 890ddd
DVAPI TPixelD toPixelD(const TPixelGR8 &);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// nel caso in cui il tipo di destinazione sia il parametro di un template
Toshihiro Shimizu 890ddd
// es. template<pixel> ....</pixel>
Toshihiro Shimizu 890ddd
// si fa cosi':
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// PIXEL c = PixelConverter<pixel>::from(c1)</pixel>
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
class PixelConverter {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  inline static T from(const TPixel32 &pix);
Shinya Kitaoka 120a6e
  inline static T from(const TPixel64 &pix);
Shinya Kitaoka 120a6e
  inline static T from(const TPixelD &pix);
Shinya Kitaoka 120a6e
  inline static T from(const TPixelGR8 &pix);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <>
Shinya Kitaoka 120a6e
class PixelConverter<tpixel32> {</tpixel32>
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  inline static TPixel32 from(const TPixel32 &pix) { return pix; }
Shinya Kitaoka 120a6e
  inline static TPixel32 from(const TPixel64 &pix) { return toPixel32(pix); }
Shinya Kitaoka 120a6e
  inline static TPixel32 from(const TPixelD &pix) { return toPixel32(pix); }
Shinya Kitaoka 120a6e
  inline static TPixel32 from(const TPixelGR8 &pix) { return toPixel32(pix); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <>
Shinya Kitaoka 120a6e
class PixelConverter<tpixel64> {</tpixel64>
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  inline static TPixel64 from(const TPixel32 &pix) { return toPixel64(pix); }
Shinya Kitaoka 120a6e
  inline static TPixel64 from(const TPixel64 &pix) { return pix; }
Shinya Kitaoka 120a6e
  inline static TPixel64 from(const TPixelD &pix) { return toPixel64(pix); }
Shinya Kitaoka 120a6e
  inline static TPixel64 from(const TPixelGR8 &pix) { return toPixel64(pix); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <>
Shinya Kitaoka 120a6e
class PixelConverter<tpixeld> {</tpixeld>
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  inline static TPixelD from(const TPixel32 &pix) { return toPixelD(pix); }
Shinya Kitaoka 120a6e
  inline static TPixelD from(const TPixel64 &pix) { return toPixelD(pix); }
Shinya Kitaoka 120a6e
  inline static TPixelD from(const TPixelD &pix) { return pix; }
Shinya Kitaoka 120a6e
  inline static TPixelD from(const TPixelGR8 &pix) { return toPixelD(pix); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void add(T &pixout, const T &pixin, double v) {
Shinya Kitaoka 120a6e
  TINT32 r, g, b, m;
Shinya Kitaoka 120a6e
  r        = pixout.r + tround(pixin.r * v);
Shinya Kitaoka 120a6e
  g        = pixout.g + tround(pixin.g * v);
Shinya Kitaoka 120a6e
  b        = pixout.b + tround(pixin.b * v);
Shinya Kitaoka 120a6e
  m        = pixout.m + tround(pixin.m * v);
Shinya Kitaoka 120a6e
  pixout.r = tcrop<tint32>(r, 0, T::maxChannelValue);</tint32>
Shinya Kitaoka 120a6e
  pixout.g = tcrop<tint32>(g, 0, T::maxChannelValue);</tint32>
Shinya Kitaoka 120a6e
  pixout.b = tcrop<tint32>(b, 0, T::maxChannelValue);</tint32>
Shinya Kitaoka 120a6e
  pixout.m = tcrop<tint32>(m, 0, T::maxChannelValue);</tint32>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void sub(T &pixout, const T &pixin, double v) {
Shinya Kitaoka 120a6e
  TINT32 r, g, b, m;
Shinya Kitaoka 120a6e
  r        = pixout.r - (pixin.r * v);
Shinya Kitaoka 120a6e
  g        = pixout.g - (pixin.g * v);
Shinya Kitaoka 120a6e
  b        = pixout.b - (pixin.b * v);
Shinya Kitaoka 120a6e
  m        = pixout.m - (pixin.m * v);
Shinya Kitaoka 120a6e
  pixout.r = tcrop<tint32>(r, 0, T::maxChannelValue);</tint32>
Shinya Kitaoka 120a6e
  pixout.g = tcrop<tint32>(g, 0, T::maxChannelValue);</tint32>
Shinya Kitaoka 120a6e
  pixout.b = tcrop<tint32>(b, 0, T::maxChannelValue);</tint32>
Shinya Kitaoka 120a6e
  pixout.m = tcrop<tint32>(m, 0, T::maxChannelValue);</tint32>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Multiplies \b pixout by \b pixin. Passed parameter \b v stands for a further
Shinya Kitaoka 120a6e
//! additive
Shinya Kitaoka 120a6e
//! component on pixin.
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void mult(T &pixout, const T &pixin, double v) {
Shinya Kitaoka 120a6e
  double r, g, b, m;
Shinya Kitaoka 120a6e
  r = pixin.r + v;
Shinya Kitaoka 120a6e
  g = pixin.g + v;
Shinya Kitaoka 120a6e
  b = pixin.b + v;
Shinya Kitaoka 120a6e
  m = pixin.m + v;
Shinya Kitaoka 120a6e
  pixout.r =
Shinya Kitaoka 120a6e
      (r < 0) ? 0 : ((r < T::maxChannelValue)
Shinya Kitaoka 120a6e
                         ? troundp(r * (pixout.r / (double)T::maxChannelValue))
Shinya Kitaoka 120a6e
                         : pixout.r);
Shinya Kitaoka 120a6e
  pixout.g =
Shinya Kitaoka 120a6e
      (g < 0) ? 0 : ((g < T::maxChannelValue)
Shinya Kitaoka 120a6e
                         ? troundp(g * (pixout.g / (double)T::maxChannelValue))
Shinya Kitaoka 120a6e
                         : pixout.g);
Shinya Kitaoka 120a6e
  pixout.b =
Shinya Kitaoka 120a6e
      (b < 0) ? 0 : ((b < T::maxChannelValue)
Shinya Kitaoka 120a6e
                         ? troundp(b * (pixout.b / (double)T::maxChannelValue))
Shinya Kitaoka 120a6e
                         : pixout.b);
Shinya Kitaoka 120a6e
  pixout.m =
Shinya Kitaoka 120a6e
      (m < 0) ? 0 : ((m < T::maxChannelValue)
Shinya Kitaoka 120a6e
                         ? troundp(m * (pixout.m / (double)T::maxChannelValue))
Shinya Kitaoka 120a6e
                         : pixout.m);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Substitutes \b pixout components with those of \b pixin, when the latters
Shinya Kitaoka 120a6e
//! are greater.
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void lighten(T &pixout, const T &pixin, double v) {
Shinya Kitaoka 120a6e
  pixout.r = pixin.r > pixout.r ? pixin.r : pixout.r;
Shinya Kitaoka 120a6e
  pixout.g = pixin.g > pixout.g ? pixin.g : pixout.g;
Shinya Kitaoka 120a6e
  pixout.b = pixin.b > pixout.b ? pixin.b : pixout.b;
Shinya Kitaoka 120a6e
  pixout.m = pixin.m > pixout.m ? pixin.m : pixout.m;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Substitutes \b pixout components with those of \b pixin, when the latters
Shinya Kitaoka 120a6e
//! are smaller.
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void darken(T &pixout, const T &pixin, double v) {
Shinya Kitaoka 120a6e
  pixout.r = pixin.r < pixout.r ? pixin.r : pixout.r;
Shinya Kitaoka 120a6e
  pixout.g = pixin.g < pixout.g ? pixin.g : pixout.g;
Shinya Kitaoka 120a6e
  pixout.b = pixin.b < pixout.b ? pixin.b : pixout.b;
Shinya Kitaoka 120a6e
  pixout.m = pixin.m < pixout.m ? pixin.m : pixout.m;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif