/* modify pixel according to color-modifying image-copy attributes
 *
 * needs defines
 *  - parameter names:
 *     - PIXMOD_PIXSRC:      [struct VG_PixelColor] - source pixel
 *     - PIXMOD_PIXDST:      [struct VG_PixelColor] - destination pixel (only needed when blending)
 *     - PIXMOD_IATTR_PIXEL: [struct VG_ImagecopyAttrPixel *] - pixel-modifying part of image-copy attributes (.pixel)
 *     - PIXMOD_PIXRET:      [struct VG_PixelColor] - returning pixel
 */

{ unsigned char pixmod_src_a;

  (PIXMOD_PIXRET) = (PIXMOD_PIXSRC);

  /* +++ pixel modification +++ */

  if ((PIXMOD_IATTR_PIXEL) != NULL) {

    /* +++ brightness +++ */
    if ((PIXMOD_IATTR_PIXEL)->brightness != 100 && (PIXMOD_IATTR_PIXEL)->brightness >= 0 && (PIXMOD_IATTR_PIXEL)->brightness <= VG_MAX_BRIGHTNESS) {
      if ((PIXMOD_IATTR_PIXEL)->brightness > 100) {
        unsigned int i;
        i = (unsigned int)(PIXMOD_PIXRET).r * (PIXMOD_IATTR_PIXEL)->brightness / 100;
        if (i > 255) { i = 255; }
        (PIXMOD_PIXRET).r = (unsigned char)i;
        i = (unsigned int)(PIXMOD_PIXRET).g * (PIXMOD_IATTR_PIXEL)->brightness / 100;
        if (i > 255) { i = 255; }
        (PIXMOD_PIXRET).g = (unsigned char)i;
        i = (unsigned int)(PIXMOD_PIXRET).b * (PIXMOD_IATTR_PIXEL)->brightness / 100;
        if (i > 255) { i = 255; }
        (PIXMOD_PIXRET).b = (unsigned char)i;
      } else {
        (PIXMOD_PIXRET).r = (PIXMOD_PIXRET).r * (PIXMOD_IATTR_PIXEL)->brightness / 100;
        (PIXMOD_PIXRET).g = (PIXMOD_PIXRET).g * (PIXMOD_IATTR_PIXEL)->brightness / 100;
        (PIXMOD_PIXRET).b = (PIXMOD_PIXRET).b * (PIXMOD_IATTR_PIXEL)->brightness / 100;
      }
    }

    /* +++ colorizing +++ */
    if ((PIXMOD_IATTR_PIXEL)->colorize_percent > 0 && (PIXMOD_IATTR_PIXEL)->colorize_percent <= 100) {
      if ((PIXMOD_IATTR_PIXEL)->colorize_color != VG_COLOR_TRANSPARENT && (PIXMOD_IATTR_PIXEL)->colorize_color >= 0) {
        int percent = (PIXMOD_IATTR_PIXEL)->colorize_percent / 3;
        struct VG_PixelColor pixmod_colorize_rgb;
        unsigned int pixmod_ipix;
        GET_RGBA((PIXMOD_IATTR_PIXEL)->colorize_color,
                 &pixmod_colorize_rgb.r, &pixmod_colorize_rgb.g, &pixmod_colorize_rgb.b, &pixmod_colorize_rgb.a);
        /* red */
        if (pixmod_colorize_rgb.r < 128) {
          pixmod_ipix = (PIXMOD_PIXRET).r * 8 / (8 + (percent * (127 - pixmod_colorize_rgb.r) / 127));
        } else {
          pixmod_ipix = (PIXMOD_PIXRET).r * (8 + percent * (pixmod_colorize_rgb.r - 128) / 127) / 8;
        }
        if (pixmod_ipix > 255) { pixmod_ipix = 255; }
        (PIXMOD_PIXRET).r = pixmod_ipix;
        /* green */
        if (pixmod_colorize_rgb.g < 128) {
          pixmod_ipix = (PIXMOD_PIXRET).g * 8 / (8 + (percent * (127 - pixmod_colorize_rgb.g) / 127));
        } else {
          pixmod_ipix = (PIXMOD_PIXRET).g * (8 + percent * (pixmod_colorize_rgb.g - 128) / 127) / 8;
        }
        if (pixmod_ipix > 255) { pixmod_ipix = 255; }
        (PIXMOD_PIXRET).g = pixmod_ipix;
        /* blue */
        if (pixmod_colorize_rgb.b < 128) {
          pixmod_ipix = (PIXMOD_PIXRET).b * 8 / (8 + (percent * (127 - pixmod_colorize_rgb.b) / 127));
        } else {
          pixmod_ipix = (PIXMOD_PIXRET).b * (8 + percent * (pixmod_colorize_rgb.b - 128) / 127) / 8;
        }
        if (pixmod_ipix > 255) { pixmod_ipix = 255; }
        (PIXMOD_PIXRET).b = pixmod_ipix;
      }
    }

    /* +++ color change +++ */
    if ((PIXMOD_IATTR_PIXEL)->pixelcolor == VG_PIXELCOLOR_INVERT) {
      /* invert color */
      (PIXMOD_PIXRET).r = 255 - (PIXMOD_PIXRET).r;
      (PIXMOD_PIXRET).g = 255 - (PIXMOD_PIXRET).g;
      (PIXMOD_PIXRET).b = 255 - (PIXMOD_PIXRET).b;
    } else if ((PIXMOD_IATTR_PIXEL)->pixelcolor == VG_PIXELCOLOR_GREY) {
      /* convert to grey color */
      (PIXMOD_PIXRET).r = (PIXMOD_PIXRET).g = (PIXMOD_PIXRET).b =
        ((unsigned int)(PIXMOD_PIXRET).r + (unsigned int)(PIXMOD_PIXRET).g + (unsigned int)(PIXMOD_PIXRET).b) / 3;
    }

    /* +++ individual function +++ */
    if ((PIXMOD_IATTR_PIXEL)->cbf != NULL) {
      (PIXMOD_PIXRET) = (PIXMOD_IATTR_PIXEL)->cbf((PIXMOD_PIXRET));
    }
  }

  /* +++ opaqueness +++ */

#ifdef PIXMOD_PIXDST
  if ((PIXMOD_IATTR_PIXEL) != NULL && (PIXMOD_IATTR_PIXEL)->opaqueness < 100 && (PIXMOD_IATTR_PIXEL)->opaqueness >= 0) {
    pixmod_src_a = (PIXMOD_PIXRET).a * (PIXMOD_IATTR_PIXEL)->opaqueness / 100;
  } else {
    pixmod_src_a = (PIXMOD_PIXRET).a;
  }
  if (pixmod_src_a == 0) {
    (PIXMOD_PIXRET) = (PIXMOD_PIXDST);
  } else if (pixmod_src_a < 255) {
    unsigned int pixmod_ipix;
    /* red */
    pixmod_ipix = ((PIXMOD_PIXRET).r * pixmod_src_a / 255) + ((PIXMOD_PIXDST).r * (255 - pixmod_src_a) / 255);
    if (pixmod_ipix > 255) { pixmod_ipix = 255; }
    (PIXMOD_PIXRET).r = (unsigned char)pixmod_ipix;
    /* green */
    pixmod_ipix = ((PIXMOD_PIXRET).g * pixmod_src_a / 255) + ((PIXMOD_PIXDST).g * (255 - pixmod_src_a) / 255);
    if (pixmod_ipix > 255) { pixmod_ipix = 255; }
    (PIXMOD_PIXRET).g = (unsigned char)pixmod_ipix;
    /* blue */
    pixmod_ipix = ((PIXMOD_PIXRET).b * pixmod_src_a / 255) + ((PIXMOD_PIXDST).b * (255 - pixmod_src_a) / 255);
    if (pixmod_ipix > 255) { pixmod_ipix = 255; }
    (PIXMOD_PIXRET).b = (unsigned char)pixmod_ipix;
    /* alpha */
    pixmod_ipix = pixmod_src_a + ((PIXMOD_PIXDST).a * (255 - pixmod_src_a) / 255);
    if (pixmod_ipix > 255) { pixmod_ipix = 255; }
    (PIXMOD_PIXRET).a = (unsigned char)pixmod_ipix;
  }
#else
  if ((PIXMOD_IATTR_PIXEL) != NULL && (PIXMOD_IATTR_PIXEL)->opaqueness < 100 && (PIXMOD_IATTR_PIXEL)->opaqueness >= 0) {
    struct VG_PixelColor pixmod_pxtrans;
    GET_RGBA(VG_COLOR_TRANSPARENT, &pixmod_pxtrans.r, &pixmod_pxtrans.g, &pixmod_pxtrans.b, &pixmod_pxtrans.a);
    pixmod_src_a = (PIXMOD_PIXRET).a * (PIXMOD_IATTR_PIXEL)->opaqueness / 100;
    if (pixmod_src_a == 0) {
      (PIXMOD_PIXRET) = pixmod_pxtrans;
    } else if (pixmod_src_a < 255) {
      unsigned int pixmod_ipix;
      /* red */
      pixmod_ipix = ((PIXMOD_PIXRET).r * pixmod_src_a / 255);
      if (pixmod_ipix > 255) { pixmod_ipix = 255; }
      (PIXMOD_PIXRET).r = (unsigned char)pixmod_ipix;
      /* green */
      pixmod_ipix = ((PIXMOD_PIXRET).g * pixmod_src_a / 255);
      if (pixmod_ipix > 255) { pixmod_ipix = 255; }
      (PIXMOD_PIXRET).g = (unsigned char)pixmod_ipix;
      /* blue */
      pixmod_ipix = ((PIXMOD_PIXRET).b * pixmod_src_a / 255);
      if (pixmod_ipix > 255) { pixmod_ipix = 255; }
      (PIXMOD_PIXRET).b = (unsigned char)pixmod_ipix;
      /* alpha */
      (PIXMOD_PIXRET).a = pixmod_src_a;
    }
  }
#endif
}
