void removeBackdrop()

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);
                }
            }
        }
    }