Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / как напечатать PNG'шку без артефактов? / 6 сообщений из 6, страница 1 из 1
20.04.2015, 18:10
    #38940935
A+
A+
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как напечатать PNG'шку без артефактов?
Есть такой код:
Код: 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
20.04.2015, 18:14
    #38940940
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как напечатать PNG'шку без артефактов?
У меня есть сильные сомнения что указанные хинты влияют на печать.
Есть смысл поэкспериментировать с DPI при печати.
http://stackoverflow.com/a/18315152

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

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

Иначе разговор ниочём получается. Гадание на гуще.
...
Рейтинг: 0 / 0
21.04.2015, 10:45
    #38941344
A+
A+
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как напечатать PNG'шку без артефактов?
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
Форумы / Java [игнор отключен] [закрыт для гостей] / как напечатать PNG'шку без артефактов? / 6 сообщений из 6, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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