Java 2D – Hiệu ứng transparency

Trong phần này của Java 2D, chúng ta nói về tính transparent. Chúng tôi cung cấp một số định nghĩa cơ bản và một số ví dụ về hiệu ứng transparent.

Định nghĩa về transparency

Transparancy là chất lượng của việc có thể nhìn qua chất liệu. Cách hiểu dễ nhất về transparency là bạn hãy tưởng tượng về 1 mảnh thủy tinh hoặc nước. Về mặt kĩ thuật, khi tia sáng đi qua thủy tinh và bạn có thể nhìn thấy vật thể đằng sau miếng thủy tinh.

Trong đồ họa máy tính, chúng ta có thể đạt được hiệu ứng transparent bằng việc sử dụng tổ hợp alpha. Tổ hợp alpha là quá trình tổ hợp 1 image với 1 background để tạo ra hiệu ứng transparent. Quá trình tổ hợp sử dụng kênh alpha. Kênh alpha là 1 layer 8-bit trong định dạng file đồ họa và được sử dụng cho việc thể hiện transparent. 8-bit mô tả được 2^8 = 256 mức độ transparency.

Class AlphaComposite được sử dụng để làm việc với transparency trong Java 2D. Nó implement các quy tắc cho việc tổ hợp alpha để phối hợp giữa pixel nguồn và đích để tạo ra hiệu ứng blending và transparency với đồ họa và ảnh. Để tạo AlphaComposite, chúng ta phải cung cấp 2 giá trị: rule designator và giá trị alpha. Rule chỉ định chúng ta kết hợp pixel nguồn và đích như thế nào. Thường giá trị rule designator là AlphaComposite.SRC_OVER. Giá trị alpha có phạm vi từ 0.0f (hoàn toàn trong suốt) tới 1.0f (hoàn toàn đục)

Hình chữ nhật transparency

Đây là ví dụ vẽ 10 hình chữ nhật với mức độ transparent khác nhau.

package net.vncoding;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

class Surface extends JPanel {    
    
    private void doDrawing(Graphics g) {        
        
        Graphics2D g2d = (Graphics2D) g.create();
        
        g2d.setPaint(Color.blue);

        for (int i = 1; i <= 10; i++) {
            
            float alpha = i * 0.1f;
            AlphaComposite alcom = AlphaComposite.getInstance(
                    AlphaComposite.SRC_OVER, alpha);
            g2d.setComposite(alcom);
            g2d.fillRect(50 * i, 20, 40, 40);
        }        
        
        g2d.dispose();
    }
        
    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        doDrawing(g);
    }
}

public class TransparentRectanglesEx extends JFrame {
    
    public TransparentRectanglesEx() {
        
        initUI();
    }
    
    private void initUI() {
                
        add(new Surface());
        
        setTitle("Transparent rectangles");
        setSize(590, 120);
        setLocationRelativeTo(null);            
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                TransparentRectanglesEx ex = new TransparentRectanglesEx();
                ex.setVisible(true);
            }
        });
    }
}

Giải thích:
Trong ví dụ này, chúng ta vẽ 10 hình chữ nhật với mức độ transparent khác nhau.

float alpha = i * 0.1f;

Giá trị alpha được update trong vòng lặp

AlphaComposite alcom = AlphaComposite.getInstance(
        AlphaComposite.SRC_OVER, alpha);

Phương thức AlphaComposite.getInstance() tạo object AlphaComposite với rule SRC_OVER và giá trị alpha.

g2d.setComposite(alcom);

Phương thức setComposite() set thuộc tính composite cho object Graphics2D.

Kết quả:

Java2D - Hiệu ứng Transparent
Java2D – Hiệu ứng Transparent

Làm mờ ảnh

Trong ví dụ tiếp theo, chúng ta làm mờ ảnh. Ảnh sẽ dần dần trở lên trong suốt cho đến khi hoàn toàn không nhìn thấy

package net.vncoding;

import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

class Surface extends JPanel
        implements ActionListener {

    private Image img;
    private Timer timer;
    private float alpha = 1f;
    
    private final int DELAY = 40;
    private final int INITIAL_DELAY = 500;

    public Surface() {

        loadImage();
        setSurfaceSize();
        initTimer();
    }

    private void loadImage() {

        img = new ImageIcon("mushrooms.jpg").getImage();
    }

    private void setSurfaceSize() {

        int h = img.getHeight(this);
        int w = img.getWidth(this);
        setPreferredSize(new Dimension(w, h));
    }

    private void initTimer() {

        timer = new Timer(DELAY, this);
        timer.setInitialDelay(INITIAL_DELAY);
        timer.start();
    }

    private void doDrawing(Graphics g) {

        Graphics2D g2d = (Graphics2D) g.create();

        AlphaComposite acomp = AlphaComposite.getInstance(
                AlphaComposite.SRC_OVER, alpha);
        g2d.setComposite(acomp);
        g2d.drawImage(img, 0, 0, null);

        g2d.dispose();
    }

    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        doDrawing(g);
    }

    private void step() {
        
        alpha += -0.01f;

        if (alpha <= 0) {

            alpha = 0;
            timer.stop();
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        step();
        repaint();
    }
}

public class FadeOutEx extends JFrame {

    public FadeOutEx() {

        initUI();
    }

    private void initUI() {

        add(new Surface());

        pack();

        setTitle("Fade out");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                FadeOutEx ex = new FadeOutEx();
                ex.setVisible(true);
            }
        });
    }
}

Giải thích:
Với AlphaComposite, chúng ta làm ảnh mờ dần trên panel.

private void setSurfaceSize() {
    
    int h = img.getHeight(this);
    int w = img.getWidth(this);
    setPreferredSize(new Dimension(w, h));        
}

Phương thức setSurfaceSize() tính kích thước image và set kích thước image trên panel. Kích thước với việc kết hợp của phương thức pack() sẽ hiển thị cửa sổ với kích thước đủ lớn để chứa toàn bộ image.

private void initTimer() {

    timer = new Timer(DELAY, this);
    timer.setInitialDelay(INITIAL_DELAY);
    timer.start();
}

Phương thức initTimer() khởi động bộ timer. Bộ timer kích hoạt xử lí sự kiện sau khi khởi tạo delay. 1 sự kiện được tạo ra giữa các khoảng delay. Trong phương thức xử lí sự kiện, chúng ta thay đổi giá trị alpha và vẽ lại panel.

AlphaComposite acomp = AlphaComposite.getInstance(
        AlphaComposite.SRC_OVER, alpha);
g2d.setComposite(acomp);
g2d.drawImage(img, 0, 0, null); 

Đoạn code này vẽ image với mới độ transprency tăng dần.

private void step() {
    
    alpha += -0.01f;

    if (alpha <= 0) {

        alpha = 0;
        timer.stop();
    }
}

Phương thức step() mô tả chu kì làm mờ ảnh. Giá trị alpha giảm dần. Chú ý: giá trị alpha không được âm. Khi alpha = 0, bộ timer dừng.

repaint();

Phương thức repaint() vẽ lại các component. Nó gọi phương thức paint() của component. Sau đó, lần lượt gọi phương thức paintComponent().

Kết quả:

Java2D - Hiệu ứng làm mờ image
Java2D – Hiệu ứng làm mờ image

Demo màn hình waiting

Trong ví dụ này, chúng ta sử dụng hiệu ứng tạo demo waiting. Chúng ta vẽ 8 line được làm mờ dần, sẽ tạo ra ảo giác như các line đang chuyển động. Hiệu ứng này thường được sử dụng cho task loading image, hoặc streaming video qua internet.


Giải thích:
Chúng ta vẽ 8 line với 8 giá trị alpha khác nhau.

private final double[][] trs = { 
...
};

Đây là mảng 2 chiều với giá trị transparency được sử dụng trong ví dụ này. Có 8 hàng, mỗi hàng 1 trạng thái. Mỗi line sử dụng các giá trị này liên tục.

g2d.setStroke(new BasicStroke(STROKE_WIDTH, BasicStroke.CAP_ROUND,
        BasicStroke.JOIN_ROUND));

Chúng ta tạo các line dày hơn 1 chút để dễ quan sát hiệu ứng hơn. Trong ví dụ này, line được vẽ kiểu bo tròn 2 đầu mút.

g2d.rotate(Math.PI/4f);
g2d.drawLine(0, -10, 0, -40);

Kết quả:

Java 2D - Demo màn hình waiting
Java 2D – Demo màn hình waiting

Be the first to comment

Leave a Reply