[Java] उचित एंटीलिअसिंग के बिना यह रेखा क्यों गाई गई है?


Answers

आप जो व्यवहार देखते हैं वह इस तथ्य से संबंधित नहीं है कि लाइन कैनवास के बाहर शुरू होती है। यदि आप एक कैनवास के अंदर पूरी तरह से रेखा का उपयोग करते हैं, तो आप उसी व्यवहार का पालन करेंगे।

समस्या एक छोटी सी ढलान dy/dx=1/90 , एक छोटी सी चौड़ाई ( 2 ) और एन्टीलायसिंग एल्गोरिदम के संयोजन से आ रही है।

एंटीलिअसिंग के बिना

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                       RenderingHints.VALUE_ANTIALIAS_OFF);

एंटीअलियासिंग के साथ

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                       RenderingHints.VALUE_ANTIALIAS_ON);

आपके द्वारा देखे जाने वाला व्यवहार पूर्णतः सामान्य है और एंटीअलियासिंग एल्गोरिथम के कारण है।

Question

मैं एक रेखा को प्रस्तुत करने की कोशिश कर रहा हूं, लेकिन अगर लाइन वास्तविक कैनवास सीमा से बाहर शुरू होती है, तो मुझे अजीब व्यवहार मिलता है।

उदाहरण के लिए, मैं कभी-कभी एक उचित रेखा के बजाय इस छवि को प्राप्त करता हूं:

उचित रेखा इस तरह दिखाई देगी:

इस नमूना को बनाने के लिए रननबल कोड यहां दिया गया है:

import java.awt.image.*;
import javax.imageio.ImageIO;
import java.io.File;
import java.awt.*;
import java.awt.geom.*;

public class Render {
    public static void main(String[] args) throws Exception {
        BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = (Graphics2D) image.getGraphics();

        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 100, 100);

        g.setColor(Color.BLACK);
        g.setStroke(new BasicStroke(2));
        g.draw(new Line2D.Double(-92, 37, 88, 39));

        g.dispose();
        ImageIO.write(image, "png", new File("output.png"));
    }
}

मैंने कई अलग-अलग रेंडरिंग संकेतों का उपयोग करने की कोशिश की, लेकिन कोई भी संयोजन इस समस्या से छुटकारा नहीं मिला। अपराधी क्या हो सकता है?

संपादित करें :

RenderingHints.VALUE_STROKE_NORMALIZE के साथ यहां छवि है:

छवि के स्केल संस्करण ( g.scale(10,10) ):




मेरी राय में, यह कैनवास के बाहर आपकी लाइन को प्रारंभ करते समय एंटीअलियाज़िंग एल्गोरिथ्म में एक बग है

रैंडरिंगहंट्स के साथ बहुत कुछ खेलना, पिक्सेल द्वारा रेखा पिक्सेल को हिलाने और ढलान, लंबाई, कैनवास के बाहर के भाग और कुछ मानों का विश्लेषण करने के बाद, मैं निष्कर्ष पर आया, कि यदि आप वास्तव में गहरा नहीं होना चाहते हैं जिस तरह से हाथ में एंटिलाइज़िंग एल्गोरिथ्म काम करता है, आप शायद एक उचित समाधान से संतुष्ट हो जाएंगे:

  1. अंतिम कैनवास के चारों ओर एक विशाल सुरक्षित क्षेत्र के साथ शुरू करें
  2. छवि को सामान्य रूप से आकर्षित करें, बस सुरक्षित ज़ोन की सीमा से चले गए
  3. सुरक्षित ज़ोन को दूर करें

उदाहरण के लिए:

import java.awt.image.*;
import javax.imageio.ImageIO;
import java.io.File;
import java.awt.*;
import java.awt.geom.*;

public class Render {
    public static void main(String[] args) throws Exception {

        // YOUR DESIRED SIZE OF CANVAS
        int size = 100;
        // THE SAFEZONE AROUND THE CANVAS
        int safezone = 1000;

        // THE IMAGE GETS INITIALIZED WITH SAFEZONE APPLIED
        BufferedImage image = new BufferedImage(size+safezone, size+safezone, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = (Graphics2D) image.getGraphics();

        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        g.setColor(Color.WHITE);

        // THE IMAGE GETS FILLED, DON'T FORGET THE SAFEZONE
        g.fillRect(0, 0, size+safezone, size+safezone);

        // THE ORIGINAL VALUES WITH THE SAFEZONE APPLIED
        int x1 = -92 + safezone/2;
        int x2 = 88 + safezone/2;
        int y1 = 37 + safezone/2;
        int y2 = 39 + safezone/2;

        g.setColor(Color.BLACK);
        g.setStroke(new BasicStroke(2));
        g.draw(new Line2D.Double(x1, y1, x2, y2));

        g.dispose();

        // CROP THE IMAGE
        image = image.getSubimage(safezone/2, safezone/2, size, size);
        ImageIO.write(image, "png", new File("output.png"));
    }
}

यह आपको देगा:

अपने सटीक मूल्यों का उपयोग करते समय कोड को आपकी ज़रूरतों के लिए फिट किया जाना चाहिए, लेकिन उदाहरण के लिए, यह काम करता है।

हालांकि यह एक सुंदर समाधान नहीं है, परिणाम हैं और मुझे आशा है कि यह मदद करता है! :)