in pdfbox/src/main/java/org/apache/pdfbox/rendering/GroupGraphics.java [600:717]
void removeBackdrop(BufferedImage backdrop, int offsetX, int offsetY)
{
int groupWidth = groupImage.getWidth();
int groupHeight = groupImage.getHeight();
int backdropWidth = backdrop.getWidth();
int backdropHeight = backdrop.getHeight();
int groupType = groupImage.getType();
int groupAlphaType = groupAlphaImage.getType();
int backdropType = backdrop.getType();
DataBuffer groupDataBuffer = groupImage.getRaster().getDataBuffer();
DataBuffer groupAlphaDataBuffer = groupAlphaImage.getRaster().getDataBuffer();
DataBuffer backdropDataBuffer = backdrop.getRaster().getDataBuffer();
if (groupType == BufferedImage.TYPE_INT_ARGB &&
groupAlphaType == BufferedImage.TYPE_INT_ARGB &&
(backdropType == BufferedImage.TYPE_INT_ARGB || backdropType == BufferedImage.TYPE_INT_RGB) &&
groupDataBuffer instanceof DataBufferInt &&
groupAlphaDataBuffer instanceof DataBufferInt &&
backdropDataBuffer instanceof DataBufferInt)
{
// Optimized computation for int[] buffers.
int[] groupData = ((DataBufferInt)groupDataBuffer).getData();
int[] groupAlphaData = ((DataBufferInt)groupAlphaDataBuffer).getData();
int[] backdropData = ((DataBufferInt)backdropDataBuffer).getData();
boolean backdropHasAlpha = backdropType == BufferedImage.TYPE_INT_ARGB;
for (int y = 0; y < groupHeight; y++)
{
for (int x = 0; x < groupWidth; x++)
{
int index = x + y * groupWidth;
// alphagn is the total alpha of the group contents excluding backdrop.
int alphagn = (groupAlphaData[index] >> 24) & 0xFF;
if (alphagn == 0)
{
// Avoid division by 0 and set the result to fully transparent.
groupData[index] = 0;
continue;
}
int backdropX = x + offsetX;
int backdropY = y + offsetY;
int backdropRGB; // color of backdrop pixel
float alpha0; // alpha of backdrop pixel
if (backdropX >= 0 && backdropX < backdropWidth &&
backdropY >= 0 && backdropY < backdropHeight)
{
backdropRGB = backdropData[backdropX + backdropY * backdropWidth];
alpha0 = backdropHasAlpha ? ((backdropRGB >> 24) & 0xFF) : 255;
}
else
{
// Backdrop pixel is out of bounds. Use a transparent value.
backdropRGB = 0;
alpha0 = 0;
}
// Alpha factor alpha0 / alphagn - alpha0 is in range 0.0-1.0.
float alphaFactor = alpha0 / alphagn - alpha0 / 255.0f;
int groupRGB = groupData[index]; // color of group pixel
// Compute backdrop removal for RGB components.
int r = backdropRemoval(groupRGB, backdropRGB, 16, alphaFactor);
int g = backdropRemoval(groupRGB, backdropRGB, 8, alphaFactor);
int b = backdropRemoval(groupRGB, backdropRGB, 0, alphaFactor);
// Copy the result back to groupImage. The alpha of the result
// is equal to alphagn.
groupData[index] = (alphagn << 24) | (r << 16) | (g << 8) | b;
}
}
}
else
{
// Non-optimized computation for other types of color spaces and pixel buffers.
for (int y = 0; y < groupHeight; y++)
{
for (int x = 0; x < groupWidth; x++)
{
int alphagn = (groupAlphaImage.getRGB(x, y) >> 24) & 0xFF;
if (alphagn == 0)
{
groupImage.setRGB(x, y, 0);
continue;
}
int backdropX = x + offsetX;
int backdropY = y + offsetY;
int backdropRGB;
float alpha0;
if (backdropX >= 0 && backdropX < backdropWidth &&
backdropY >= 0 && backdropY < backdropHeight)
{
backdropRGB = backdrop.getRGB(backdropX, backdropY);
alpha0 = (backdropRGB >> 24) & 0xFF;
}
else
{
backdropRGB = 0;
alpha0 = 0;
}
int groupRGB = groupImage.getRGB(x, y);
float alphaFactor = alpha0 / alphagn - alpha0 / 255.0f;
int r = backdropRemoval(groupRGB, backdropRGB, 16, alphaFactor);
int g = backdropRemoval(groupRGB, backdropRGB, 8, alphaFactor);
int b = backdropRemoval(groupRGB, backdropRGB, 0, alphaFactor);
groupImage.setRGB(x, y, (alphagn << 24) | (r << 16) | (g << 8) | b);
}
}
}
}