Java 在书的图像中加粗文本

Java 在书的图像中加粗文本,java,image-processing,Java,Image Processing,我需要一些算法,使文字粗体的书籍图像。换句话说,我有一个书页的图片,我想把文本加粗以增强阅读能力 我的图像是透明的,只包含文本,没有任何其他像素。用一个小y差多次绘制图像会使文本加粗 class tmpPanel extends JPanel { private File pngFile; private int boldSize = 5; public tmpPanel() { addMouseListener(new MouseListener()

我需要一些算法,使文字粗体的书籍图像。换句话说,我有一个书页的图片,我想把文本加粗以增强阅读能力


我的图像是透明的,只包含文本,没有任何其他像素。

用一个小y差多次绘制图像会使文本加粗

class tmpPanel extends JPanel {

    private File pngFile;
    private int boldSize = 5;

    public tmpPanel() {
        addMouseListener(new MouseListener() {

            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    ++boldSize;
                    repaint();
                } else if (e.getButton() == MouseEvent.BUTTON3) {
                    --boldSize;
                    repaint();
                }
            }

            @Override
            public void mousePressed(MouseEvent e) {
                mouseClicked(e);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
            }

            @Override
            public void mouseEntered(MouseEvent e) {
            }

            @Override
            public void mouseExited(MouseEvent e) {
            }
        });
    }

    public void setPngFile(File pngFile) {
        this.pngFile = pngFile;
    }

    @Override
    public void paint(Graphics g) {
        try {
            super.paint(g); //To change body of generated methods, choose Tools | Templates.
            Graphics2D d = (Graphics2D) g;
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, getWidth(), getHeight());
            BufferedImage image = ImageIO.read(pngFile);
            for (int i = 0; i < boldSize; ++i)
            g.drawImage(image, 0, i, getWidth(), getHeight(), null);
        } catch (IOException ex) {
            Logger.getLogger(tmpPanel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
类tmpPanel扩展了JPanel{
私有文件pngFile;
私有int boldSize=5;
公共tmpPanel(){
addMouseListener(新MouseListener(){
@凌驾
公共无效mouseClicked(MouseEvent e){
如果(例如getButton()==MouseEvent.BUTTON1){
++粗体字;
重新油漆();
}else if(e.getButton()==MouseEvent.BUTTON3){
--粗体字;
重新油漆();
}
}
@凌驾
公共无效鼠标按下(MouseEvent e){
鼠标滑动(e);
}
@凌驾
公共无效MouseEvent(MouseEvent e){
}
@凌驾
公共无效鼠标事件(鼠标事件e){
}
@凌驾
公共无效mouseExited(MouseEvent e){
}
});
}
公共无效设置pngFile(文件pngFile){
this.pngFile=pngFile;
}
@凌驾
公共空间涂料(图g){
试一试{
super.paint(g);//若要更改生成方法的主体,请选择工具|模板。
图形2d=(图形2d)g;
g、 setColor(Color.WHITE);
g、 fillRect(0,0,getWidth(),getHeight());
BuffereImage image=ImageIO.read(pngFile);
用于(int i=0;i
最佳解决方案:使用@bazz dee idea(膨胀过滤器):

  • 阈值图像
  • 把它放大
  • 它的时间是O(N^2),内存是4N,其中N是一个图像的大小。代码取自和此答案

    类tmpPanel扩展了JPanel{
    私有文件pngFile;
    私有int boldSize=1;
    布尔值nightMode=true;
    私有静态最终整数arr[][]=新整数[1377][886];//图像的宽度、高度
    公共tmpPanel(){
    addMouseListener(新MouseListener(){
    @凌驾
    公共无效mouseClicked(MouseEvent e){
    }
    @凌驾
    公共无效鼠标按下(MouseEvent e){
    如果(例如getButton()==MouseEvent.BUTTON1){
    ++粗体字;
    重新油漆();
    }else if(e.getButton()==MouseEvent.BUTTON3){
    --粗体字;
    重新油漆();
    }
    }
    @凌驾
    公共无效MouseEvent(MouseEvent e){
    }
    @凌驾
    公共无效鼠标事件(鼠标事件e){
    }
    @凌驾
    公共无效mouseExited(MouseEvent e){
    }
    });
    }
    公共无效设置pngFile(文件pngFile){
    this.pngFile=pngFile;
    }
    私有空洞扩张(int[][]图像,int k){
    图像=曼哈顿(图像);
    对于(int i=0;i0){
    image[i][j]=Math.min(image[i][j],image[i][j-1]+1);
    }
    }
    }
    }
    //从右下到左上遍历
    对于(int i=image.length-1;i>=0;i--){
    对于(int j=image[i]。长度-1;j>=0;j--){
    //或者是我们第一次通过时的情况
    //或者南部比像素多一个像素
    如果(i+1<图像长度){
    image[i][j]=Math.min(image[i][j],image[i+1][j]+1);
    }
    //或者比东边的像素多一个
    if(j+1<图像[i].长度){
    image[i][j]=Math.min(image[i][j],image[i][j+1]+1);
    }
    }
    }
    返回图像;
    }
    @凌驾
    公共空间涂料(图g){
    试一试{
    super.paint(g);//若要更改生成方法的主体,请选择工具|模板。
    BuffereImage image=ImageIO.read(pngFile);
    BuffereImage res=新的BuffereImage(image.getWidth(),image.getHeight(),image.getType());
    Graphics2D=(Graphics2D)res.createGraphics();
    d、 setColor(Color.WHITE);
    d、 fillRect(0,0,res.getWidth(),res.getHeight());
    d、 drawImage(图像,0,0,res.getWidth(),res.getHeight(),null);
    res=阈值图像(res,128);
    WritableRaster raster=res.getRaster();
    如果(粗体大小>0){
    对于(int i=0;iclass tmpPanel extends JPanel {
    
        private File pngFile;
        private int boldSize = 1;
        boolean nightMode = true;
        private static final int arr[][] = new int[1377][886]; //width, hight of image
    
        public tmpPanel() {
            addMouseListener(new MouseListener() {
    
                @Override
                public void mouseClicked(MouseEvent e) {
    
                }
    
                @Override
                public void mousePressed(MouseEvent e) {
                    if (e.getButton() == MouseEvent.BUTTON1) {
                        ++boldSize;
                        repaint();
                    } else if (e.getButton() == MouseEvent.BUTTON3) {
                        --boldSize;
                        repaint();
                    }
                }
    
                @Override
                public void mouseReleased(MouseEvent e) {
                }
    
                @Override
                public void mouseEntered(MouseEvent e) {
                }
    
                @Override
                public void mouseExited(MouseEvent e) {
                }
            });
        }
    
        public void setPngFile(File pngFile) {
            this.pngFile = pngFile;
        }
    
        private void dilate(int[][] image, int k) {
            image = manhattan(image);
            for (int i = 0; i < image.length; i++) {
                for (int j = 0; j < image[i].length; j++) {
                    image[i][j] = (image[i][j] <= k) ? 1 : 0;
                }
            }
        }
    
        /**
         * Converts an image to a binary one based on given threshold
         *
         * @param image the image to convert. Remains untouched.
         * @param threshold the threshold in [0,255]
         * @return a new BufferedImage instance of TYPE_BYTE_GRAY with only 0'S and
         * 255's
         */
        public BufferedImage thresholdImage(BufferedImage image, int threshold) {
            BufferedImage result = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
            result.getGraphics().drawImage(image, 0, 0, null);
            WritableRaster raster = result.getRaster();
            int[] pixels = new int[image.getWidth()];
            for (int y = 0; y < image.getHeight(); y++) {
                raster.getPixels(0, y, image.getWidth(), 1, pixels);
                for (int i = 0; i < pixels.length; i++) {
                    if (pixels[i] < threshold) {
                        pixels[i] = 1;
                    } else {
                        pixels[i] = 0;
                    }
                }
                raster.setPixels(0, y, image.getWidth(), 1, pixels);
            }
            return result;
        }
    
        private int[][] manhattan(int[][] image) {
            // traverse from top left to bottom right
            for (int i = 0; i < image.length; i++) {
                for (int j = 0; j < image[i].length; j++) {
                    if (image[i][j] == 1) {
                        // first pass and pixel was on, it gets a zero
                        image[i][j] = 0;
                    } else {
                    // pixel was off
                        // It is at most the sum of the lengths of the array
                        // away from a pixel that is on
                        image[i][j] = image.length + image[i].length;
                        // or one more than the pixel to the north
                        if (i > 0) {
                            image[i][j] = Math.min(image[i][j], image[i - 1][j] + 1);
                        }
                        // or one more than the pixel to the west
                        if (j > 0) {
                            image[i][j] = Math.min(image[i][j], image[i][j - 1] + 1);
                        }
                    }
                }
            }
            // traverse from bottom right to top left
            for (int i = image.length - 1; i >= 0; i--) {
                for (int j = image[i].length - 1; j >= 0; j--) {
                // either what we had on the first pass
                    // or one more than the pixel to the south
                    if (i + 1 < image.length) {
                        image[i][j] = Math.min(image[i][j], image[i + 1][j] + 1);
                    }
                    // or one more than the pixel to the east
                    if (j + 1 < image[i].length) {
                        image[i][j] = Math.min(image[i][j], image[i][j + 1] + 1);
                    }
                }
            }
            return image;
        }
    
        @Override
        public void paint(Graphics g) {
            try {
                super.paint(g); //To change body of generated methods, choose Tools | Templates.
                BufferedImage image = ImageIO.read(pngFile);
                BufferedImage res = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
                Graphics2D d = (Graphics2D) res.createGraphics();
                d.setColor(Color.WHITE);
                d.fillRect(0, 0, res.getWidth(), res.getHeight());
                d.drawImage(image, 0, 0, res.getWidth(), res.getHeight(), null);
                res = thresholdImage(res, 128);
                WritableRaster raster = res.getRaster();
                if (boldSize > 0) {
                    for (int i = 0; i < res.getHeight(); ++i)
                        raster.getPixels(0, i, res.getWidth(), 1, arr[i]);
                    dilate(arr, boldSize);
                    for (int i = 0; i < res.getHeight(); ++i) {
                        for (int j = 0; j < res.getWidth(); ++j)
                            if (arr[i][j] == 1)
                                arr[i][j] = nightMode ? 255 : 0;
                            else
                                arr[i][j] = nightMode ? 0 : 255;
                        raster.setPixels(0, i, res.getWidth(), 1, arr[i]);
                    }
                }
                g.drawImage(res, 0, 0, getWidth(), getHeight(), null);
                //for (int i = 0; i < boldSize; ++i)
                    //g.drawImage(image, 0, i, getWidth(), getHeight(), null);
            } catch (IOException ex) {
                Logger.getLogger(tmpPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }