Arhn - архитектура программирования

Разница между рисованием на JPanel через paintComponent и буферизованное изображение

Я экспериментировал с двумя разными методами рисования одной и той же формы: первое изображение рисуется путем переопределения метода JPanel paintComponent(Graphics g) и использования g.drawOval(..) и т. д. Второе изображение рисуется путем создания буферизованного изображения и рисования на нем с помощью графики буферизованного изображения. Как добиться одинакового качества рендеринга при обоих подходах? Я пробовал использовать много разных советов по рендерингу, но ни один из них не дал такого же качества. Я также пытался повысить резкость с помощью ядра и фильтрации, но все равно не смог.

private void createImage() {
        image = new BufferedImage(IMG_SIZE, IMG_SIZE, BufferedImage.TYPE_INT_ARGB);
        Graphics2D gr = image.createGraphics();

        gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        gr.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        gr.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        //something along the way
        gr.drawOval(.....);
        gr.drawLine(.....);
        gr.drawOval(.....);

        panel.repaint();
        gr.dispose();
}



public void paintComponent(Graphics g) {
    super.paintComponent(g);
    setBackground(backgroundColor);
    if (USE_BUFFERED_IMAGE) {
        g.drawImage(image, startX, startY, null);
    } else {
        //something along the way
        g.drawOval(.....);
        g.drawLine(.....);
        g.drawOval(.....);
    }
}

Рисование с использованием графики JPanel paintComponent

Рисование с использованием графики Buffered Image, затем рисование в Jpanel с помощью drawimage

ИЗМЕНИТЬ

Я нашел свое решение, получив почти все настройки графики панели и применив их к графике буферизованного изображения. Не используя только одни и те же подсказки рендеринга или минимальные воспроизводимые примеры подходов. Здесь импорт заключается в том, что графика панели масштабирует все на 1,25, а затем масштабирует до оригинала перед отображением на панели.

Вот пример, это не совсем мой код, это просто пример, чтобы дать вам представление-

private void createImages(Paint paint, RenderingHints hints,
                         AffineTransform transform, Stroke stroke,
                        Composite composite, GraphicsConfiguration config ){

        image = config.createCompatibleImage(IMG_SIZE, IMG_SIZE, 
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D gr = image.createGraphics();
        // same options
        gr.setPaint(paint);
        gr.setRenderingHints(hints);
        gr.setTransform(transform);
        gr.setStroke(stroke);
        gr.setComposite(composite);

        //something along the way
        gr.drawOval(.....);
        gr.drawLine(.....);
        gr.drawOval(.....);

        panel.repaint();
        gr.dispose();
}



public void paintComponent(Graphics g) {
    super.paintComponent(g);
    setBackground(backgroundColor);
    if (USE_BUFFERED_IMAGE) {
       
        Graphics2D g2 = (Graphics2D)g;
        createImages(g2.getPaint(), g2.getRenderingHints(),g2.getTransform(),
                     g2.getStroke(),g2.getComposite(), g2.getDeviceConfiguration());
         //scaling down is important because your drawings get scaled to 1.25
         // by panels graphics' transformation
         g.drawImage(image, startX, startY,(int)(IMG_SIZE*0.8),(int)(IMG_SIZE*0.8),  null);
    } else {
        //something along the way
        g.drawOval(.....);
        g.drawLine(.....);
        g.drawOval(.....);
    }
}

  • По большей части вы не можете, тем более что изображение имеет фиксированный размер, и при рисовании внутри вашего компонента, размер которого может варьироваться в зависимости от его родительского макета, изображение масштабируется, что еще больше ухудшает качество. Одна глупая идея, которую вы могли бы попробовать, — нарисовать каждый отдельный пиксель вашего изображения в виде прямоугольника 1 x 1 с указанным цветом пикселя внутри вашего компонента рисования. Хотя это ужасно для производительности, если ваше изображение статично, возможно, оно того стоит? 07.03.2021
  • Предпочтительным подходом является использование метода paintComponent JPanel для рисования в вашем графическом интерфейсе. Если вам нужен BufferedImage, вы можете создать его с помощью метода JPanel printAll. 07.03.2021
  • Как добиться одинакового качества рендеринга при обоих подходах? - Используйте одни и те же подсказки рендеринга. Например, метод paintComponent() по умолчанию не использует сглаживание. Таким образом, графика, нарисованная в BufferedImage, будет выглядеть иначе, чем графика, нарисованная в paintComponent. Опубликуйте правильный минимально воспроизводимый пример, демонстрирующий проблему. Начните с простого рисования одного овала и заставьте его работать одинаково, используя оба подхода. Затем сделайте картину более сложной. Так легче отлаживать. Кроме того, не изменяйте свойство (фон) компонента в этом методе рисования. 07.03.2021
  • Используйте те же подсказки рендеринга, моя проблема в том, что я не знаю, какая подсказка рендеринга используется в JPanel. Кроме того, как я уже упоминал, я пробовал много подсказок рендеринга, но все равно не смог добиться таких же результатов. 07.03.2021
  • PrintAll кажется решением моей проблемы, я обновлю свое сообщение, если смогу справиться с тем, что пытаюсь сделать. Я использую буферизованное изображение, чтобы иметь возможность перетаскивать изображение без рендеринга сложного рисунка каждый раз, что может занять некоторое время. 07.03.2021
  • Спасибо всем за вашу помощь, я нашел свое решение, как я объяснил выше. 08.03.2021

Ответы:


1

Я нашел свое решение, получив почти все настройки графики панели и применив их к графике буферизованного изображения. Здесь импорт заключается в том, что графика панели масштабирует все на 1,25, а затем масштабирует до оригинала перед отображением на панели.

Вот пример, это не совсем мой код, это просто пример, чтобы дать вам представление-

private void createImages(Paint paint, RenderingHints hints,
                         AffineTransform transform, Stroke stroke,
                        Composite composite, GraphicsConfiguration config ){

        image = config.createCompatibleImage(IMG_SIZE, IMG_SIZE, 
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D gr = image.createGraphics();
        // same options
        gr.setPaint(paint);
        gr.setRenderingHints(hints);
        gr.setTransform(transform);
        gr.setStroke(stroke);
        gr.setComposite(composite);

        //something along the way
        gr.drawOval(.....);
        gr.drawLine(.....);
        gr.drawOval(.....);

        panel.repaint();
        gr.dispose();
}



public void paintComponent(Graphics g) {
    super.paintComponent(g);
    setBackground(backgroundColor);
    if (USE_BUFFERED_IMAGE) {
       
        Graphics2D g2 = (Graphics2D)g;
        createImages(g2.getPaint(), g2.getRenderingHints(),g2.getTransform(),
                     g2.getStroke(),g2.getComposite(), g2.getDeviceConfiguration());
         //scaling down is important because your drawings get scaled to 1.25
         // by panels graphics' transformation
         g.drawImage(image, startX, startY,(int)(IMG_SIZE*0.8),(int)(IMG_SIZE*0.8),  null);
    } else {
        //something along the way
        g.drawOval(.....);
        g.drawLine(.....);
        g.drawOval(.....);
    }
}
08.03.2021
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..