예제 #1
0
static void no_interpolation(const ImageData *image, DBL xcoor, DBL ycoor, RGBFTColour& colour, int *index, bool premul)
{
    int iycoor, ixcoor;

    if(image->Once_Flag)
    {
        // image is to be seen only once, so when taking samples for interpolation
        // coordinates should not wrap around; instead, take the samples from the nearest
        // pixel right at the edge of the image

        if(xcoor < 0.0)
            ixcoor = 0;
        else if(xcoor >= (DBL)image->iwidth)
            ixcoor = image->iwidth - 1;
        else
            ixcoor = (int)xcoor;

        if(ycoor < 0.0)
            iycoor = 0;
        else if(ycoor >= (DBL)image->iheight)
            iycoor = image->iheight - 1;
        else
            iycoor = (int)ycoor;
    }
    else
    {
        // image is to be repeated, so when taking samples for interpolation
        // have coordinates wrap around

        ixcoor = (int)wrap(xcoor, (DBL)image->iwidth);
        iycoor = (int)wrap(ycoor, (DBL)image->iheight);
    }

    image->data->GetRGBFTValue(ixcoor, iycoor, colour, premul);

    if(image->data->IsIndexed() == false)
    {
        *index = -1;

        if (image->AllTransmitLegacyMode)
        {
            // Legacy versions applied "transmit/filter all" before interpolation,
            // and with little respect to an image's inherent alpha information.
            colour.transm() += image->AllTransmit;
            colour.filter() += image->AllFilter;
        }
    }
    else
        *index = image->data->GetIndexedValue(ixcoor, iycoor);
}
예제 #2
0
DBL image_pattern(const Vector3d& EPoint, const BasicPattern* pPattern)
{
    DBL xcoor = 0.0, ycoor = 0.0;
    int index = -1;
    RGBFTColour colour;
    const ImageData *image = dynamic_cast<const ImagePatternImpl*>(pPattern)->pImage;
    DBL Value;

    colour.Clear();

    // going to have to change this
    // need to know if bump point is off of image for all 3 points

    if(map_pos(EPoint, pPattern, &xcoor, &ycoor))
        return 0.0;
    else
        image_colour_at(image, xcoor, ycoor, colour, &index); // TODO ALPHA - we should decide whether we prefer premultiplied or non-premultiplied alpha

    if((index == -1) || image->Use)
    {
        if(image->Use == USE_ALPHA)
        {
            // use alpha channel or red channel
            if(image->data->HasTransparency() == true)
                Value = colour.transm();
            else
                Value = colour.red();   // otherwise, just use the red channel
        }
        else
            // use grey-scaled version of the color
            Value = colour.Greyscale();
    }
    else
        Value = index / 255.0;

    if(Value < 0)
        Value = 0;
    else if(Value > 1.0)
        Value = 1.0;

    return Value;
}
예제 #3
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());
    }
}