powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / как напечатать PNG'шку без артефактов?
6 сообщений из 6, страница 1 из 1
как напечатать PNG'шку без артефактов?
    #38940935
A+
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
A+
Гость
Есть такой код:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
                            @Override
                            public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
                                if (pageIndex > prevPage) {
                                    return NO_SUCH_PAGE;
                                }
                                
                                // уберем артефакты: TODO
                                Graphics2D g2 = (Graphics2D) graphics;
                                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
                                g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
                                g2.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
                                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
                                
                                graphics.drawImage(img, 
                                    (int) pageFormat.getImageableX(), 
                                    (int) pageFormat.getImageableY(), 
                                    (int) pageFormat.getImageableWidth(), 
                                    (int) pageFormat.getImageableHeight(), 
                                    null);
                                
                                prevPage = pageIndex;
                                return PAGE_EXISTS;
                            }


где img:
Код: java
1.
                        final BufferedImage img = ImageIO.read(new ByteArrayInputStream(data));


- это содержимое качественной (без "разводов") PNG-картинки с разрешением ~ 200 DPI.
Контрастная черно-белая картинка - в основном текст + штрих-код.

Пытаюсь распечатать эту картинку на принтере с разрешением 600 DPI и получаю различные "разводы"/артефакты по краям "букв".
Уже разные хинты перепробовал.
Как исправить?
...
Рейтинг: 0 / 0
как напечатать PNG'шку без артефактов?
    #38940940
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня есть сильные сомнения что указанные хинты влияют на печать.
Есть смысл поэкспериментировать с DPI при печати.
http://stackoverflow.com/a/18315152

А лучше всего отмасштабировать картинку в нормальном редакторе и её использовать. Это не вариант?
...
Рейтинг: 0 / 0
как напечатать PNG'шку без артефактов?
    #38940981
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
A+, тут речь идёт о Java 2D printing API ?

Как вообще печатаешь-то? В уравнении 10 000 неизвестных.
...
Рейтинг: 0 / 0
как напечатать PNG'шку без артефактов?
    #38941010
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И действительно ли имеется острая нужда в рантайме масштабировать?
...
Рейтинг: 0 / 0
как напечатать PNG'шку без артефактов?
    #38941038
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Думаю что в студию нужно приложить эти самые загадочные артефакты.

Иначе разговор ниочём получается. Гадание на гуще.
...
Рейтинг: 0 / 0
как напечатать PNG'шку без артефактов?
    #38941344
A+
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
A+
Гость
mayton,
1. да. в первом куске кода можно узнать реализацию java.awt.print.Printable.
2. артефакты: http://hostingkartinok.com/show-image.php?id=41438d5c494a14c3d2411cfeb16b9ac9

Blazkowicz,
раньше печать работала так:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
                    // аттрибуты печати страницы:
                    DocAttributeSet das = getDocAttributes(data, pageRatio);

                    // теперь заготовим документ - в виде понятном принтеру:
                    Doc pdoc = new SimpleDoc(data, DocFlavor.BYTE_ARRAY.PNG, das);

                    // и задание
                    DocPrintJob job = ps.createPrintJob();
                    // создадим слушателя событий с принтера:
                    job.addPrintJobListener(new JobStatusListener(this));

                    // 6. Напечатаем эту страницу наконец
                    try {
                        job.print(pdoc, pras);
                    } catch (Throwable t) {
                        log.error("Printer ecxeption occured", t);
                        // принять решение: все оставшиеся страницы тоже ошибочны - их надо запросить по-новой!
                        increase(0, pages.size() - i, "PRINT_EXCEPTION\n");
                        // просто выйти - мы больше ничего не можем сделать!
                        break;
                    }


- где data - это уже содержимое PNG'шки - очень удобно: занимает мало места в оперативке + можно распечатать на разных принтерах (с разными разрешениями) + можно вывести картинку в файл, отредактировать ее при необходимости, и распечатать.
getDocAttributes - это метод, что просто заполняет "хинты" типа: ориентация бумаги, MediaPrintableArea,
MediaSize:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
    /**
     * Возвращает атрибуты (настройки) печати для указанной картинки на странице указанных пропорций.
     * 
     * @param data
     *            содержимое PNG-файла картинки, что надо напечатать
     * @param pageRatio
     *            соотношение высоты к ширине - для страницы, на которой собираемся печатать картинку
     * @return
     */
    private DocAttributeSet getDocAttributes(byte[] data, double pageRatio) {
        DocAttributeSet result = new HashDocAttributeSet();
        boolean rotate = false;
        
        // узнаем размеры картинки:
        int[] imageDimensions = getImageDimensions(data);
        if (imageDimensions != null) {
            int iW = imageDimensions[0];
            int iH = imageDimensions[1];
            
            double imageRatio = 1.0 * iH/iW;
            double rotatedImageRatio = 1.0*iW/iH;
            log.debug(String.format("pageRatio: %.2f, imageRatio: %.2f, rotatedImageRatio: %.2f, " +
                    "strict digression: %.2f, rotated digression: %.2f",
                    pageRatio,
                    imageRatio,
                    rotatedImageRatio,
                    Math.abs(1 - imageRatio/pageRatio),
                    Math.abs(1 - rotatedImageRatio/pageRatio)));
            if (Math.abs(1 - imageRatio/pageRatio) > Math.abs(1 - rotatedImageRatio/pageRatio)) {
                log.info("It was found that the image should be rotated!");
                rotate = true;
            }
            
            if (rotate) {
                log.debug("it was found that the orientation should be lanscape...");
            } else {
                log.debug("it was found that the orientation should be portrait...");
            }
        }
        
        OrientationRequested orientation = rotate ? OrientationRequested.LANDSCAPE : OrientationRequested.PORTRAIT;
        log.debug("adding orientation [name: {}, value: {}, to-string: {}] ...", 
            new Object[] {orientation.getName(), orientation.getValue(), orientation.toString()});
        result.add(orientation);
        log.debug("adding print quality...");
        result.add(PrintQuality.HIGH);
        
        MediaSizeName msn;
        MediaPrintableArea mpa;
        
        int x = 0;
        int y = 0;
        if (printer.getWidth() < printer.getHeight()) {
            x = printer.getWidth();
            y = printer.getHeight();
        } else {
            y = printer.getWidth();
            x = printer.getHeight();
        }
        log.debug("looking for media [x: {}, y: {}] MM...", new Object[] {x, y});
        msn = MediaSize.findMedia(x, y, Size2DSyntax.MM);
        
        mpa = new MediaPrintableArea(printer.getLeftMargin(), printer.getTopMargin(), 
            printer.getWidth() - printer.getLeftMargin() - printer.getRightMargin(), 
            printer.getHeight() - printer.getTopMargin() - printer.getBottomMargin(), 
            Size2DSyntax.MM);
        
        MediaSize ms = MediaSize.getMediaSizeForName(msn); // что же нашли?
        log.debug("closest match media is: msn [name: {}, value: {}, toString: {}, x: {} MM, y: {} MM]", 
            new Object[] {msn == null ? "(NULL)" : msn.getName(),
                msn == null ? "(NULL)" : msn.getValue(),
                msn == null ? "(NULL)" : msn.toString(),
                ms == null ? "(NULL)" : ms.getX(Size2DSyntax.MM),
                ms == null ? "(NULL)" : ms.getY(Size2DSyntax.MM)});
        log.debug("media printable area was set to (in millimeters): mpa [x: {}, y: {}, w: {}, h: {}, name: {}]",
            new Object [] {mpa.getX(Size2DSyntax.MM), mpa.getY(Size2DSyntax.MM), 
                mpa.getWidth(Size2DSyntax.MM), mpa.getHeight(Size2DSyntax.MM),
                mpa.getName()});
        
        result.add(mpa);
        if (msn != null) {
            result.add(msn);
        }
        
        return result;
    }



Все вроде бы работало хорошо на java 6 (может, просто функционал не так часто использовался), но после перехода на java 7 (может, и не связано) выяснилось, что у тех клиентов, у которых не совсем корректные драйвера для принтеров установлены, картинка печатается примерно в 4 раза меньше (линейные размеры меньше примерно в 2 раза).

Чтобы много не переделывать хотелось просто самому "рисовать" эту картинку на "полотне" бумаги принтера - т.е., не через javax.print.DocPrintJob, а через java.awt.print.PrinterJob - типа иметь больше контроля над процессом "рисования" (не доверяя части работы драйверу принтера). Пока безуспешно.
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / как напечатать PNG'шку без артефактов?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]