Example #1
0
static void Interp(const ImageData *image, DBL xcoor, DBL ycoor, RGBFTColour& colour, int *index, bool premul)
{
    int iycoor, ixcoor, i;
    int Corners_Index[4];
    RGBFTColour Corner_Colour[4];
    DBL Corner_Factors[4];

    xcoor += 0.5;
    ycoor += 0.5;

    iycoor = (int)ycoor;
    ixcoor = (int)xcoor;

    no_interpolation(image, (DBL)ixcoor,     (DBL)iycoor,     Corner_Colour[0], &Corners_Index[0], premul);
    no_interpolation(image, (DBL)ixcoor - 1, (DBL)iycoor,     Corner_Colour[1], &Corners_Index[1], premul);
    no_interpolation(image, (DBL)ixcoor,     (DBL)iycoor - 1, Corner_Colour[2], &Corners_Index[2], premul);
    no_interpolation(image, (DBL)ixcoor - 1, (DBL)iycoor - 1, Corner_Colour[3], &Corners_Index[3], premul);

    if(image->Interpolation_Type == BILINEAR)
        bilinear(Corner_Factors, xcoor, ycoor);
    else if(image->Interpolation_Type == NORMALIZED_DIST)
        norm_dist(Corner_Factors, xcoor, ycoor);
    else
        POV_ASSERT(false);

    // We're using double precision for the colors here to avoid higher-than-1.0 results due to rounding errors,
    // which would otherwise lead to stray dot artifacts when clamped to [0..1] range for a color_map or similar.
    // (Note that strictly speaking we don't avoid such rounding errors, but rather make them small enough that
    // subsequent rounding to single precision will take care of them.)
    PreciseRGBFTColour temp_colour;
    DBL temp_index = 0;
    for (i = 0; i < 4; i ++)
    {
        temp_colour += PreciseRGBFTColour(Corner_Colour[i]) * Corner_Factors[i];
        temp_index  += Corners_Index[i]                     * Corner_Factors[i];
    }
    colour = RGBFTColour(temp_colour);
    *index = (int)temp_index;
}
Example #2
0
static void image_colour_at(IMAGE *Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index)
{
  switch (Image->Interpolation_Type)
  {
    case NO_INTERPOLATION:

      no_interpolation(Image, xcoor, ycoor, colour, index);

      break;

    default:

      Interp(Image, xcoor, ycoor, colour, index);

      break;
  }
}
Example #3
0
static void InterpolateBicubic(const ImageData *image, DBL xcoor, DBL  ycoor, RGBFTColour& colour, int *index, bool premul)
{
    int iycoor, ixcoor;
    int cornerIndex;
    RGBFTColour cornerColour;
    DBL factor;
    DBL factorsX[4];
    DBL factorsY[4];

    xcoor += 0.5;
    ycoor += 0.5;

    iycoor = (int)ycoor;
    ixcoor = (int)xcoor;

    cubic(factorsX, xcoor);
    cubic(factorsY, ycoor);

    // We're using double precision for the colors here to avoid higher-than-1.0 results due to rounding errors,
    // which would otherwise lead to stray dot artifacts when clamped to [0..1] range for a color_map or similar.
    // (Note that strictly speaking we don't avoid such rounding errors, but rather make them small enough that
    // subsequent rounding to single precision will take care of them.)
    // (Note that bicubic interpolation may still give values outside the range [0..1] at high-contrast edges;
    // this is an inherent property of this interpolation method, and is therefore accepted here.)
    PreciseRGBFTColour tempColour;
    DBL tempIndex = 0;
    for (int i = 0; i < 4; i ++)
    {
        for (int j = 0; j < 4; j ++)
        {
            cornerColour.Clear();
            no_interpolation(image, (DBL)ixcoor + i-2, (DBL)iycoor + j-2, cornerColour, &cornerIndex, premul);
            factor = factorsX[i] * factorsY[j];
            tempColour += PreciseRGBFTColour(cornerColour) * factor;
            tempIndex  += cornerIndex                      * factor;
        }
    }
    colour = RGBFTColour(tempColour);
    *index = (int)tempIndex;
}
Example #4
0
static void Interp(IMAGE *Image, DBL xcoor, DBL  ycoor, COLOUR colour, int *index)
{
  int iycoor, ixcoor, i;
  int Corners_Index[4];
  DBL Index_Crn[4];
  COLOUR Corner_Colour[4];
  DBL Red_Crn[4];
  DBL Green_Crn[4];
  DBL Blue_Crn[4];
  DBL Filter_Crn[4];
  DBL Transm_Crn[4];
  DBL val1, val2, val3, val4, val5;

  val1 = val2 = val3 = val4 = val5 = 0.0;

  iycoor = (int)ycoor;
  ixcoor = (int)xcoor;

  for (i = 0; i < 4; i++)
  {
    Make_ColourA(Corner_Colour[i], 0.0, 0.0, 0.0, 0.0, 0.0);
  }

  /* OK, now that you have the corners, what are you going to do with them? */

  if (Image->Interpolation_Type == BILINEAR)
  {
    no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor, Corner_Colour[0], &Corners_Index[0]);
    no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor, Corner_Colour[1], &Corners_Index[1]);
    no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor - 1, Corner_Colour[2], &Corners_Index[2]);
    no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor - 1, Corner_Colour[3], &Corners_Index[3]);

    for (i = 0; i < 4; i++)
    {
      Red_Crn[i] = Corner_Colour[i][pRED];
      Green_Crn[i] = Corner_Colour[i][pGREEN];
      Blue_Crn[i] = Corner_Colour[i][pBLUE];
      Filter_Crn[i] = Corner_Colour[i][pFILTER];
      Transm_Crn[i] = Corner_Colour[i][pTRANSM];

      // Debug_Info("Crn %d = %lf %lf %lf\n",i,Red_Crn[i],Blue_Crn[i],Green_Crn[i]);
    }

    val1 = bilinear(Red_Crn, xcoor, ycoor);
    val2 = bilinear(Green_Crn, xcoor, ycoor);
    val3 = bilinear(Blue_Crn, xcoor, ycoor);
    val4 = bilinear(Filter_Crn, xcoor, ycoor);
    val5 = bilinear(Transm_Crn, xcoor, ycoor);
  }

  if (Image->Interpolation_Type == NORMALIZED_DIST)
  {
    no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor - 1, Corner_Colour[0], &Corners_Index[0]);
    no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor - 1, Corner_Colour[1], &Corners_Index[1]);
    no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor, Corner_Colour[2], &Corners_Index[2]);
    no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor, Corner_Colour[3], &Corners_Index[3]);

    for (i = 0; i < 4; i++)
    {
      Red_Crn[i] = Corner_Colour[i][pRED];
      Green_Crn[i] = Corner_Colour[i][pGREEN];
      Blue_Crn[i] = Corner_Colour[i][pBLUE];
      Filter_Crn[i] = Corner_Colour[i][pFILTER];
      Transm_Crn[i] = Corner_Colour[i][pTRANSM];

      // Debug_Info("Crn %d = %lf %lf %lf\n",i,Red_Crn[i],Blue_Crn[i],Green_Crn[i]);
    }

    val1 = norm_dist(Red_Crn, xcoor, ycoor);
    val2 = norm_dist(Green_Crn, xcoor, ycoor);
    val3 = norm_dist(Blue_Crn, xcoor, ycoor);
    val4 = norm_dist(Filter_Crn, xcoor, ycoor);
    val5 = norm_dist(Transm_Crn, xcoor, ycoor);
  }

  colour[pRED] += val1;
  colour[pGREEN] += val2;
  colour[pBLUE] += val3;
  colour[pFILTER] += val4;
  colour[pTRANSM] += val5;

  // Debug_Info("Final = %lf %lf %lf\n",val1,val2,val3);
  // use bilinear for index try average later

  for (i = 0; i < 4; i++)
  {
    Index_Crn[i] = (DBL)Corners_Index[i];
  }

  if (Image->Interpolation_Type == BILINEAR)
  {
    *index = (int)(bilinear(Index_Crn, xcoor, ycoor) + 0.5);
  }

  if (Image->Interpolation_Type == NORMALIZED_DIST)
  {
    *index = (int)(norm_dist(Index_Crn, xcoor, ycoor) + 0.5);
  }
}
Example #5
0
void image_colour_at(const ImageData *image, DBL xcoor, DBL ycoor, RGBFTColour& colour, int *index, bool premul)
{
    *index = -1;

    bool doProperTransmitAll = image->data->HasTransparency() &&
                               !image->AllTransmitLegacyMode &&
                               !image->data->IsIndexed() && ( (image->AllTransmit != 0.0) || (image->AllFilter != 0.0) );

    // If either source or destination uses premultiplied alpha, make sure interpolation is done in premultiplied space
    // as it makes the mathematical operations cleaner -- unless the alpha channel is modulated by "transmit all" or
    // "filter all", in which case we prefer non-premultiplied space.
    bool getPremul = doProperTransmitAll ? (premul && image->data->IsPremultiplied()) :
                                           (premul || image->data->IsPremultiplied());

    switch(image->Interpolation_Type)
    {
        case NO_INTERPOLATION:
            no_interpolation(image, xcoor, ycoor, colour, index, getPremul);
            break;
        case BICUBIC:
            InterpolateBicubic(image, xcoor, ycoor, colour, index, getPremul);
            break;
        default:
            Interp(image, xcoor, ycoor, colour, index, getPremul);
            break;
    }
    bool havePremul = getPremul;

    if (!premul && havePremul)
    {
        // We fetched premultiplied data, but caller expects it non-premultiplied, so we need to fix that.
        // As "transmit/filter all" handling also works best on non-premultiplied data, we're doing this now.
        AlphaUnPremultiply(colour.rgb(), colour.FTtoA());
        havePremul = false;
    }

    if (doProperTransmitAll)
    {
        COLC imageAlpha = colour.FTtoA();

        if (imageAlpha != 0.0)  // No need to apply "filter/transmit all" if the image is fully transparent here anyway.
        {


            colour.transm() += image->AllTransmit * imageAlpha;
            colour.filter() += image->AllFilter   * imageAlpha;

            if (havePremul)
            {
                // We have premultiplied data here, and the caller expects it to stay that way (otherwise we'd already
                // have converted to non-premultiplied by now), so we need to fix the premultiplication of the colour
                // according to our modifications to the transparency components.
                COLC alphaCorrection = colour.FTtoA() / imageAlpha;
                AlphaPremultiply(colour.rgb(), alphaCorrection);
            }
        }
    }

    if (premul && !havePremul)
    {
        // We have non-premultiplied data here, but caller expects it premultiplied, so we need to fix that
        // As "transmit/filter all" handling works best on non-premultiplied data, we haven't done this earlier.
        AlphaPremultiply(colour.rgb(), colour.FTtoA());
    }
}