Beispiel #1
0
void GetEncodedRGBAValue(const Image* img, unsigned int x, unsigned int y, const GammaCurvePtr& g, unsigned int max, unsigned int& red, unsigned int& green, unsigned int& blue, unsigned int& alpha, DitherHandler& dh, bool premul)
{
	bool doPremultiply   = premul && !img->IsPremultiplied() && img->HasTransparency(); // need to apply premultiplication if encoded data should be premul'ed but container content isn't
	bool doUnPremultiply = !premul && img->IsPremultiplied() && img->HasTransparency(); // need to undo premultiplication if other way round
	float fRed, fGreen, fBlue, fAlpha;
	img->GetRGBAValue(x, y, fRed, fGreen, fBlue, fAlpha);
	if (doPremultiply)
	{
		// Data has been stored premultiplied, but should be encoded non-premultiplied.
		// No need for special handling of color components greater than alpha.
		// Need to convert from premultiplied to non-premultiplied encoding.
		AlphaPremultiply(fRed, fGreen, fBlue, fAlpha);
	}
	else if (doUnPremultiply)
	{
		// Data has been stored premultiplied, but should be encoded non-premultiplied.
		// Clipping will happen /before/ re-multiplying with alpha (because the latter is done in the viewer), which is equivalent to clipping
		// pre-multiplied components to be no greater than alpha, thereby "killing" highlights on transparent objects;
		// compensate for this by boosting opacity of any exceptionally bright pixels.
		float fBright = RGBColour(fRed, fGreen, fBlue).greyscale();
		if (fBright > fAlpha)
			fAlpha = min(1.0f, fBright);
		// Need to convert from premultiplied to non-premultiplied encoding.
		AlphaUnPremultiply(fRed, fGreen, fBlue, fAlpha);
	}
	else if (!premul)
	{
		// Data has been stored un-premultiplied and should be encoded that way.
		// Clipping will happen /before/ multiplying with alpha (because the latter is done in the viewer), which is equivalent to clipping
		// pre-multiplied components to be no greater than alpha, thereby "killing" highlights on transparent objects;
		// compensate for this by boosting opacity of any exceptionally bright pixels.
		float fBright = RGBColour(fRed, fGreen, fBlue).greyscale();
		if (fBright > 1.0)
		{
			float fFactor = fBright;
			if (fFactor * fAlpha > 1.0)
				fFactor = 1.0/fAlpha;
			// this keeps the product of alpha*color constant
			fAlpha *= fFactor;
			fRed   /= fFactor;
			fGreen /= fFactor;
			fBlue  /= fFactor;
		}
		// No need for converting between premultiplied and un-premultiplied encoding.
	}
	// else no need to worry about premultiplication
	DitherHandler::OffsetInfo linOff, encOff;
	dh.getOffset(x,y,linOff,encOff);
	red   = IntEncode(g,fRed   + linOff.red,   max, encOff.red,   linOff.red);
	green = IntEncode(g,fGreen + linOff.green, max, encOff.green, linOff.green);
	blue  = IntEncode(g,fBlue  + linOff.blue,  max, encOff.blue,  linOff.blue);
	alpha = IntEncode(fAlpha   + linOff.alpha, max, encOff.alpha, linOff.alpha);
	dh.setError(x,y,linOff);
}
Beispiel #2
0
void GetEncodedGrayAValue(const Image* img, unsigned int x, unsigned int y, const GammaCurvePtr& g, float& fGray, float& fAlpha, bool premul)
{
	bool doPremultiply   = premul && !img->IsPremultiplied() && img->HasTransparency(); // need to apply premultiplication if encoded data should be premul'ed but container content isn't
	bool doUnPremultiply = !premul && img->IsPremultiplied() && img->HasTransparency(); // need to undo premultiplication if other way round
	img->GetGrayAValue(x, y, fGray, fAlpha);
	if (doPremultiply)
		AlphaPremultiply(fGray, fAlpha);
	else if (doUnPremultiply)
		AlphaUnPremultiply(fGray, fAlpha);
	// else no need to worry about premultiplication
	fGray = GammaCurve::Encode(g,fGray);
}
Beispiel #3
0
void SetEncodedRGBAValue(Image* img, unsigned int x, unsigned int y, const GammaCurvePtr& g, float fRed, float fGreen, float fBlue, float fAlpha, bool premul)
{
	bool doPremultiply   = !premul && (img->IsPremultiplied() || !img->HasTransparency()); // need to apply premultiplication if encoded data isn't PM'ed but container content should be
	bool doUnPremultiply = premul && !img->IsPremultiplied() && img->HasTransparency(); // need to undo premultiplication if other way round
	fRed   = GammaCurve::Decode(g,fRed);
	fGreen = GammaCurve::Decode(g,fGreen);
	fBlue  = GammaCurve::Decode(g,fBlue);
	if (doPremultiply)
		AlphaPremultiply(fRed, fGreen, fBlue, fAlpha);
	else if (doUnPremultiply)
		AlphaUnPremultiply(fRed, fGreen, fBlue, fAlpha);
	// else no need to worry about premultiplication
	img->SetRGBAValue(x, y, fRed, fGreen, fBlue, fAlpha);
}
Beispiel #4
0
void SetEncodedGrayAValue(Image* img, unsigned int x, unsigned int y, const GammaCurvePtr& g, unsigned int max, unsigned int gray, unsigned int alpha, bool premul)
{
	bool doPremultiply   = (alpha != max) && !premul && (img->IsPremultiplied() || !img->HasTransparency()); // need to apply premultiplication if encoded data isn't PM'ed but container content should be
	bool doUnPremultiply = (alpha != max) && premul && !img->IsPremultiplied() && img->HasTransparency(); // need to undo premultiplication if other way round
	if (!doPremultiply && !doUnPremultiply && !img->IsIndexed() && img->GetMaxIntValue() == max && GammaCurve::IsNeutral(g))
		// avoid potential re-quantization in case we have a pretty match between encoded data and container
		img->SetGrayAValue(x, y, gray, alpha);
	else
	{
		float fAlpha = IntDecode(alpha,max);
		float fGray  = IntDecode(g,gray,max);
		if (doPremultiply)
			AlphaPremultiply(fGray, fAlpha);
		else if (doUnPremultiply)
			AlphaUnPremultiply(fGray, fAlpha);
		// else no need to worry about premultiplication
		img->SetGrayAValue(x, y, fGray, fAlpha);
	}
}
Beispiel #5
0
void AlphaUnPremultiply(RGBTColour& colour)
{
    AlphaUnPremultiply(colour.red(), colour.green(), colour.blue(), colour.alpha());
}
Beispiel #6
0
void AlphaUnPremultiply(RGBFTColour& colour)
{
    AlphaUnPremultiply(colour.red(), colour.green(), colour.blue(), colour.FTtoA());
}
Beispiel #7
0
void AlphaUnPremultiply(RGBColour& colour, float fAlpha)
{
    AlphaUnPremultiply(colour.red(), colour.green(), colour.blue(), fAlpha);
}
Beispiel #8
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());
    }
}