使用Apache PDFBox时,如何将图像集中到另一个图像中

发布于 2025-02-07 06:33:17 字数 6908 浏览 0 评论 0原文

我使用Apache提取字形图像。目前,此功能正常工作,但我遇到的问题是,某些字形图像不能适当地适合我正在创建的新图像的中心,无论我多么努力,我都不会得到结果!

请注意以下代码。我已经根据部分对他们评论了它们,以了解这些代码的工作过程。

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;

import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.PDVectorFont;
import org.apache.pdfbox.pdmodel.fontPane.PDFont;
import org.apache.pdfbox.pdmodel.fontPane.PDSimpleFont;
import org.apache.pdfbox.pdmodel.fontPane.PDType1CFont;

import org.apache.pdfbox.pdmodel.fontpane.FontPane;
import org.apache.pdfbox.preflight.font.SimpleFontValidator;
import org.apache.pdfbox.pdmodel.font.PDType1CFont;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.TableCellRenderer;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import org.apache.pdfbox.debugger.PDFDebugger;
import org.apache.pdfbox.debugger.ui.HighResolutionImageIcon;



public class GlyphExtractor {

    private static final AffineTransform DEFAULT_TRANSFORM = GraphicsEnvironment.getLocalGraphicsEnvironment().
    getDefaultScreenDevice().getDefaultConfiguration().getDefaultTransform();

    public static void main(String[] args) throws IOException{

        String filename = "14010316.pdf";

        //Load file as a pdfDocument
        PDDocument document = PDDocument.load(new File(filename));

        //Get the first page of file
        PDPage page = document.getPage(0);

        //Get all page resources from page one
        PDResources pageResources = page.getResources();

        //Get page font named F1 (this font is embeded into pdf as resource) and cast it to a font type
        COSName f1Name = COSName.getPDFName("F1");
        org.apache.pdfbox.pdmodel.font.PDFont fontF1 = pageResources.getFont(f1Name);
        PDType1CFont fontPane = (PDType1CFont) fontF1;


        //Iterate over all font glyphs and store it into an object
        int totalAvailableGlyph = 0;
        Object[][] glyphs = new Object[256][4];

        for (int index = 0; index <= 255; index++)
        {
            glyphs[index][0] = index;
            if (fontPane.getEncoding().contains(index) || fontPane.toUnicode(index) != null)
            {
                String glyphName = fontPane.getEncoding().getName(index);
                glyphs[index][1] = glyphName;
                glyphs[index][2] = fontPane.toUnicode(index);
                try
                {
                    if (fontPane instanceof PDVectorFont)
                    {
                        
                        // using names didn't work with the file from PDFBOX-3445
                        glyphs[index][3] = ((PDVectorFont) fontPane).getPath(index);
                    }
                    else
                    {
                        // type 1 font isn't a vector font in 2.0
                        glyphs[index][3] = fontPane.getPath(glyphName);
                    }
                }
                catch (IOException ex)
                {
                    
                }
                totalAvailableGlyph++;
            }
            else
            {
                glyphs[index][1] = "None";
                glyphs[index][2] = "None";
                glyphs[index][3] = fontPane.getPath(".notdef");
            }
        }

        //Iterate ove all glyphs and generate image for each glyph image
        for (int index = 0; index <= 255; index++)
        {
            String glyphName = (String) glyphs[index][1];

            if(glyphName == "None" || glyphName == ".notdef" || glyphName == "space"){
                continue;
            }

            //Get the General path pf glyph from glyphs Object and get the 2D bound of it
            GeneralPath path = (GeneralPath) glyphs[index][3];
            Rectangle2D bounds2D = path.getBounds2D();
    
            //Generate new image and save it into disk (into a folder named images)
            BufferedImage bim = renderGlyph(path, bounds2D, 512, 512);
            File outputfile = new File("./images", String.format("page%s-%s-%s.png", 0 + 1, index, glyphName));
            ImageIO.write(bim, "png", outputfile);
        }

        System.out.println(totalAvailableGlyph);
    }

    //Render Glyphfs Function
    private static BufferedImage renderGlyph(GeneralPath path, Rectangle2D bounds2D, int ImageWidth, int ImageHeight)
        {
            //Create New Buffer Image With Given Height and Width
            BufferedImage bim = new BufferedImage(
                    ImageWidth,
                    ImageHeight,
                    BufferedImage.TYPE_INT_RGB);

            Graphics2D g = (Graphics2D) bim.getGraphics();
            g.setBackground(Color.white);
            g.clearRect(0, 0, bim.getWidth(), bim.getHeight());


            double scale = 0.5;

            // flip
            g.scale(1, -1);
            g.translate(0, -bim.getHeight());

            // horizontal center
            g.translate(((bim.getWidth() - bounds2D.getWidth() * scale) / 2) * DEFAULT_TRANSFORM.getScaleX(), 0);

            // DEFAULT_TRANSFORM.getScaleX() & DEFAULT_TRANSFORM.getScaleY() is 1
            g.scale(scale * DEFAULT_TRANSFORM.getScaleX(), scale * DEFAULT_TRANSFORM.getScaleY());


            /**
             * My Problem Is HERE...
             * How to Calculate the best height for positioning glyph into buffred image?
             */
            float finalHeight = (float) ((float) ((bim.getHeight() - bounds2D.getHeight()) / 2 ) + bounds2D.getHeight());
            // Adjust for negative y min bound
            g.translate(0, finalHeight - 50);

            //finally add glyph to image and return the image binary file to save into disk
            g.setColor(Color.black);
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.fill(path);
            g.dispose();
            return bim;
        }
}

I used Apache to extract glyph images. At the moment this feature works fine but the problem I have is that some of the glyph images do not fit properly in the center of the new image I am creating and no matter how hard I try I will not get results!

Please pay attention to the following codes. I have commented on them section by section to understand the working process of these codes.

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;

import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.PDVectorFont;
import org.apache.pdfbox.pdmodel.fontPane.PDFont;
import org.apache.pdfbox.pdmodel.fontPane.PDSimpleFont;
import org.apache.pdfbox.pdmodel.fontPane.PDType1CFont;

import org.apache.pdfbox.pdmodel.fontpane.FontPane;
import org.apache.pdfbox.preflight.font.SimpleFontValidator;
import org.apache.pdfbox.pdmodel.font.PDType1CFont;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.TableCellRenderer;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import org.apache.pdfbox.debugger.PDFDebugger;
import org.apache.pdfbox.debugger.ui.HighResolutionImageIcon;



public class GlyphExtractor {

    private static final AffineTransform DEFAULT_TRANSFORM = GraphicsEnvironment.getLocalGraphicsEnvironment().
    getDefaultScreenDevice().getDefaultConfiguration().getDefaultTransform();

    public static void main(String[] args) throws IOException{

        String filename = "14010316.pdf";

        //Load file as a pdfDocument
        PDDocument document = PDDocument.load(new File(filename));

        //Get the first page of file
        PDPage page = document.getPage(0);

        //Get all page resources from page one
        PDResources pageResources = page.getResources();

        //Get page font named F1 (this font is embeded into pdf as resource) and cast it to a font type
        COSName f1Name = COSName.getPDFName("F1");
        org.apache.pdfbox.pdmodel.font.PDFont fontF1 = pageResources.getFont(f1Name);
        PDType1CFont fontPane = (PDType1CFont) fontF1;


        //Iterate over all font glyphs and store it into an object
        int totalAvailableGlyph = 0;
        Object[][] glyphs = new Object[256][4];

        for (int index = 0; index <= 255; index++)
        {
            glyphs[index][0] = index;
            if (fontPane.getEncoding().contains(index) || fontPane.toUnicode(index) != null)
            {
                String glyphName = fontPane.getEncoding().getName(index);
                glyphs[index][1] = glyphName;
                glyphs[index][2] = fontPane.toUnicode(index);
                try
                {
                    if (fontPane instanceof PDVectorFont)
                    {
                        
                        // using names didn't work with the file from PDFBOX-3445
                        glyphs[index][3] = ((PDVectorFont) fontPane).getPath(index);
                    }
                    else
                    {
                        // type 1 font isn't a vector font in 2.0
                        glyphs[index][3] = fontPane.getPath(glyphName);
                    }
                }
                catch (IOException ex)
                {
                    
                }
                totalAvailableGlyph++;
            }
            else
            {
                glyphs[index][1] = "None";
                glyphs[index][2] = "None";
                glyphs[index][3] = fontPane.getPath(".notdef");
            }
        }

        //Iterate ove all glyphs and generate image for each glyph image
        for (int index = 0; index <= 255; index++)
        {
            String glyphName = (String) glyphs[index][1];

            if(glyphName == "None" || glyphName == ".notdef" || glyphName == "space"){
                continue;
            }

            //Get the General path pf glyph from glyphs Object and get the 2D bound of it
            GeneralPath path = (GeneralPath) glyphs[index][3];
            Rectangle2D bounds2D = path.getBounds2D();
    
            //Generate new image and save it into disk (into a folder named images)
            BufferedImage bim = renderGlyph(path, bounds2D, 512, 512);
            File outputfile = new File("./images", String.format("page%s-%s-%s.png", 0 + 1, index, glyphName));
            ImageIO.write(bim, "png", outputfile);
        }

        System.out.println(totalAvailableGlyph);
    }

    //Render Glyphfs Function
    private static BufferedImage renderGlyph(GeneralPath path, Rectangle2D bounds2D, int ImageWidth, int ImageHeight)
        {
            //Create New Buffer Image With Given Height and Width
            BufferedImage bim = new BufferedImage(
                    ImageWidth,
                    ImageHeight,
                    BufferedImage.TYPE_INT_RGB);

            Graphics2D g = (Graphics2D) bim.getGraphics();
            g.setBackground(Color.white);
            g.clearRect(0, 0, bim.getWidth(), bim.getHeight());


            double scale = 0.5;

            // flip
            g.scale(1, -1);
            g.translate(0, -bim.getHeight());

            // horizontal center
            g.translate(((bim.getWidth() - bounds2D.getWidth() * scale) / 2) * DEFAULT_TRANSFORM.getScaleX(), 0);

            // DEFAULT_TRANSFORM.getScaleX() & DEFAULT_TRANSFORM.getScaleY() is 1
            g.scale(scale * DEFAULT_TRANSFORM.getScaleX(), scale * DEFAULT_TRANSFORM.getScaleY());


            /**
             * My Problem Is HERE...
             * How to Calculate the best height for positioning glyph into buffred image?
             */
            float finalHeight = (float) ((float) ((bim.getHeight() - bounds2D.getHeight()) / 2 ) + bounds2D.getHeight());
            // Adjust for negative y min bound
            g.translate(0, finalHeight - 50);

            //finally add glyph to image and return the image binary file to save into disk
            g.setColor(Color.black);
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.fill(path);
            g.dispose();
            return bim;
        }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文