diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/im_process.def | 1 | ||||
| -rw-r--r-- | src/lua5/im_process.lua | 1 | ||||
| -rw-r--r-- | src/lua5/imlua_process.c | 19 | ||||
| -rw-r--r-- | src/process/im_arithmetic_bin.cpp | 144 | 
4 files changed, 163 insertions, 2 deletions
diff --git a/src/im_process.def b/src/im_process.def index 07bba47..7e637e9 100644 --- a/src/im_process.def +++ b/src/im_process.def @@ -73,6 +73,7 @@ EXPORTS    imProcessBitwiseOp    imProcessBlendConst    imProcessBlend +  imProcessCompose    imProcessCalcRotateSize    imProcessDifusionErrThreshold    imProcessDirectConv diff --git a/src/lua5/im_process.lua b/src/lua5/im_process.lua index d74c6b1..8d866a4 100644 --- a/src/lua5/im_process.lua +++ b/src/lua5/im_process.lua @@ -255,6 +255,7 @@ end  TwoSourcesOneDest("ProcessBlendConst")  ThreeSourcesOneDest("ProcessBlend") +TwoSourcesOneDest("ProcessCompose")  OneSourceTwoDests("ProcessSplitComplex")  TwoSourcesOneDest("ProcessMergeComplex", nil, nil, nil, im.CFLOAT) diff --git a/src/lua5/imlua_process.c b/src/lua5/imlua_process.c index 198d0e5..299155a 100644 --- a/src/lua5/imlua_process.c +++ b/src/lua5/imlua_process.c @@ -2,7 +2,7 @@   * \brief IM Lua 5 Binding   *   * See Copyright Notice in im_lib.h - * $Id: imlua_process.c,v 1.9 2010/01/06 20:16:30 scuri Exp $ + * $Id: imlua_process.c,v 1.10 2010/01/08 03:49:05 scuri Exp $   */  #include <memory.h> @@ -1703,6 +1703,22 @@ static int imluaProcessBlend (lua_State *L)  }  /*****************************************************************************\ + im.ProcessCompose +\*****************************************************************************/ +static int imluaProcessCompose(lua_State *L) +{ +  imImage *src_image1 = imlua_checkimage(L, 1); +  imImage *src_image2 = imlua_checkimage(L, 2); +  imImage *dst_image = imlua_checkimage(L, 4); + +  imlua_match(L, src_image1, src_image2); +  imlua_match(L, src_image1, dst_image); + +  imProcessCompose(src_image1, src_image2, dst_image); +  return 0; +} + +/*****************************************************************************\   im.ProcessSplitComplex  \*****************************************************************************/  static int imluaProcessSplitComplex (lua_State *L) @@ -2990,6 +3006,7 @@ static const luaL_reg improcess_lib[] = {    {"ProcessArithmeticConstOp", imluaProcessArithmeticConstOp},    {"ProcessBlendConst", imluaProcessBlendConst},    {"ProcessBlend", imluaProcessBlend}, +  {"ProcessCompose", imluaProcessCompose},    {"ProcessSplitComplex", imluaProcessSplitComplex},    {"ProcessMergeComplex", imluaProcessMergeComplex},    {"ProcessMultipleMean", imluaProcessMultipleMean}, diff --git a/src/process/im_arithmetic_bin.cpp b/src/process/im_arithmetic_bin.cpp index 494b6c0..575e650 100644 --- a/src/process/im_arithmetic_bin.cpp +++ b/src/process/im_arithmetic_bin.cpp @@ -2,7 +2,7 @@   * \brief Binary Arithmetic Operations   *   * See Copyright Notice in im_lib.h - * $Id: im_arithmetic_bin.cpp,v 1.2 2009/10/01 02:56:58 scuri Exp $ + * $Id: im_arithmetic_bin.cpp,v 1.3 2010/01/08 03:49:05 scuri Exp $   */ @@ -262,6 +262,148 @@ void imProcessBlend(const imImage* src_image1, const imImage* src_image2, const    }  } +#define COMPOSE_OVER(_SRC, _SRC_ALPHA, _DST, _TMP_MULTI, _TMP_ALPHA) (T)(((_SRC_ALPHA)*(_SRC) + (_TMP_MULTI)*(_DST)) / (_TMP_ALPHA)) +#define ALPHA_BLEND(_src,_dst,_alpha) (T)(((_src) * (_alpha) + (_dst) * (max - (_alpha))) / max) + +template <class T, class TA> +static inline T compose_op(const T& v1, const T& v2, const T& alpha1, const T& alpha2, const TA& max) +{ +  if (alpha1 != max)   /* some transparency */                                                                      +  {                                                                                                                     +    if (alpha1 != 0) /* source not full transparent */                                                              +    {                                                                                                                   +      if (alpha2 == 0) /* destiny full transparent */                                                             +      {                                                                                                                 +        return v1;                                                                                            +      }                                                                                                                 +      else if (alpha2 == max) /* destiny opaque */                                                                +      {                                                                                                                 +        return ALPHA_BLEND(v1, v2, alpha1);                                                    +      }                                                                                                                 +      else /* (0<alpha2<max && 0<alpha1<max) destiny and source are semi-transparent */                       +      {                                                                                                                 +        /* Closed Compositing SRC over DST  (see smith95a.pdf)        */                                                +        /* Colors NOT Premultiplied by Alpha                          */                                                +        /* DST = SRC * SRC_ALPHA + DST * DST_ALPHA * (1 - SRC_ALPHA)  */                                                +        /* DST_ALPHA = SRC_ALPHA + DST_ALPHA * (1 - SRC_ALPHA)        */                                                +        /* DST /= DST_ALPHA */                                                                                          +        TA _tmp_multi = alpha2 * (max - alpha1);                                                             +        TA _tmp_src_alpha = alpha1*max;                                                                            +        TA _tmp_alpha = _tmp_src_alpha + _tmp_multi;                                                                   +        return COMPOSE_OVER(v1, _tmp_src_alpha, v2, _tmp_multi, _tmp_alpha);                      +      }                                                                                                                 +    }                                                                                                                   +    else  /* (alpha1 == 0) source full transparent */                                                               +    {                                                                                                                   +      return v2;                                                                                            +    }                                                                                                                   +  }                                                                                                                     +  else  /* (alpha1 == max) source has no alpha = opaque */                                                          +  {                                                                                                                     +    return v1;                                                                                                +  }                                                                                                                     +} + +template <class T, class TA> +static inline T compose_alpha_op(const T& alpha1, const T& alpha2, const TA& max) +{ +  if (alpha1 != max)   /* some transparency */                                                                      +  {                                                                                                                     +    if (alpha1 != 0) /* source not full transparent */                                                              +    {                                                                                                                   +      if (alpha2 == 0) /* destiny full transparent */                                                             +      {                                                                                                                 +        return alpha1;                                                                                      +      }                                                                                                                 +      else if (alpha2 == max) /* destiny opaque */                                                                +      {                                                                                                                 +        /* alpha2 is not changed */                                                                               +        return alpha2; +      }                                                                                                                 +      else /* (0<alpha2<max && 0<alpha1<max) destiny and source are semi-transparent */                       +      {                                                                                                                 +        /* Closed Compositing SRC over DST  (see smith95a.pdf)        */                                                +        /* Colors NOT Premultiplied by Alpha                          */                                                +        /* DST = SRC * SRC_ALPHA + DST * DST_ALPHA * (1 - SRC_ALPHA)  */                                                +        /* DST_ALPHA = SRC_ALPHA + DST_ALPHA * (1 - SRC_ALPHA)        */                                                +        /* DST /= DST_ALPHA */                                                                                          +        TA _tmp_multi = alpha2 * (max - alpha1);                                                             +        TA _tmp_src_alpha = alpha1*max;                                                                            +        TA _tmp_alpha = _tmp_src_alpha + _tmp_multi;                                                                   +        return (T)(_tmp_alpha / max); +      }                                                                                                                 +    }                                                                                                                   +    else  /* (alpha1 == 0) source full transparent */                                                               +    {                                                                                                                   +      /* alpha2 is not changed */                                                                                 +      return alpha2; +    }                                                                                                                   +  }                                                                                                                     +  else  /* (alpha1 == max) source has no alpha = opaque */                                                          +  {                                                                                                                     +    return (unsigned char)max;   /* set destiny as opaque */                                                    +  }                                                                                                                     +} + +template <class T, class TA>  +static void DoCompose(T *map1, T *map2, T *alpha1, T *alpha2, T *map, int count, TA max) +{ +  for (int i = 0; i < count; i++) +    map[i] = compose_op(map1[i], map2[i], alpha1[i], alpha2[i], max); +} + +template <class T, class TA>  +static void DoComposeAlpha(T *alpha1, T *alpha2, T *dst_alpha, int count, TA max) +{ +  for (int i = 0; i < count; i++) +    dst_alpha[i] = compose_alpha_op(alpha1[i], alpha2[i], max); +} + +void imProcessCompose(const imImage* src_image1, const imImage* src_image2, imImage* dst_image) +{ +  int count = src_image1->count,  +      src_alpha = src_image1->depth; + +  if (!src_image1->has_alpha || !src_image2->has_alpha || !dst_image->has_alpha) +    return; + +  for (int i = 0; i < src_image1->depth; i++) +  { +    switch(src_image1->data_type) +    { +    case IM_BYTE: +      DoCompose((imbyte*)src_image1->data[i], (imbyte*)src_image2->data[i], (imbyte*)src_image1->data[src_alpha], (imbyte*)src_image2->data[src_alpha], (imbyte*)dst_image->data[i], count, (int)255); +      break; +    case IM_USHORT: +      DoCompose((imushort*)src_image1->data[i], (imushort*)src_image2->data[i], (imushort*)src_image1->data[src_alpha], (imushort*)src_image2->data[src_alpha], (imushort*)dst_image->data[i], count, (int)65535); +      break; +    case IM_INT: +      DoCompose((int*)src_image1->data[i], (int*)src_image2->data[i], (int*)src_image1->data[src_alpha], (int*)src_image2->data[src_alpha], (int*)dst_image->data[i], count, (int)2147483647); +      break; +    case IM_FLOAT: +      DoCompose((float*)src_image1->data[i], (float*)src_image2->data[i], (float*)src_image1->data[src_alpha], (float*)src_image2->data[src_alpha], (float*)dst_image->data[i], count, 1.0f); +      break; +    } +  } + +  /* one more for the alpha channel */ +  switch(src_image1->data_type) +  { +  case IM_BYTE: +    DoComposeAlpha((imbyte*)src_image1->data[src_alpha], (imbyte*)src_image2->data[src_alpha], (imbyte*)dst_image->data[src_alpha], count, (int)255); +    break; +  case IM_USHORT: +    DoComposeAlpha((imushort*)src_image1->data[src_alpha], (imushort*)src_image2->data[src_alpha], (imushort*)dst_image->data[src_alpha], count, (int)65535); +    break; +  case IM_INT: +    DoComposeAlpha((int*)src_image1->data[src_alpha], (int*)src_image2->data[src_alpha], (int*)dst_image->data[src_alpha], count, (int)2147483647); +    break; +  case IM_FLOAT: +    DoComposeAlpha((float*)src_image1->data[src_alpha], (float*)src_image2->data[src_alpha], (float*)dst_image->data[src_alpha], count, 1.0f); +    break; +  } +} +  static void DoBinaryConstOpCpxReal(imcfloat *map1, float value, imcfloat *map, int count, int op)  {    int i;  | 
