Esempio n. 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);
}
Esempio n. 2
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());
    }
}