Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 22

BỘ GIÁO DỤC VÀ ĐÀO TẠO

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ TP. HCM

ĐỒ ÁN MÔN HỌC
ĐỒ HỌA MÁY TÍNH

JAVA GRAPHIC 2D

Ngành : CÔNG NGHỆ THÔNG TIN

Giảng viên hướng dẫn : Ths. NGUYỄN THỊ ANH THƯ


Sinh viên thực hiện : NGUYỄN QUANG HUY
MSSV: 16111060130 Lớp: 16DTHA1
Sinh viên thực hiện : PHẠM ĐẶNG ĐỨC HUY
MSSV: 16111060132 Lớp: 16DTHA1
Sinh viên thực hiện : ĐOÀN QUANG KHẢI
MSSV: 16111060136 Lớp: 16DTHA1
Sinh viên thực hiện : NGUYỄN LÊ HOÀNG HUY
MSSV: 16111060459 Lớp: 16DTHA2
Sinh viên thực hiện : TRƯƠNG MINH HUY
MSSV: 16111060133 Lớp: 16DTHA2

TP. Hồ Chí Minh, 2019


2

MỤC LỤC
Đề mục Trang
Trang bìa
MỤC LỤC.......................................................................................................................... 2
LỜI MỞ ĐẦU....................................................................................................................3
CHƯƠNG 1. GIỚI THIỆU VỀ GRAPHICS 2D TRONG JAVA.......................................4
1.1. Định nghĩa về graphics 2D..................................................................................4
1.2. Thao tác..............................................................................................................4
1.3. Hình ảnh hai mô hình..........................................................................................4
CHƯƠNG 2. GIỚI THIỆU VỀ SHAPES TRONG JAVA.................................................5
2.1. Định nghĩa về shapes trong java.........................................................................5
2.2. Gói Java java.awt.geom......................................................................................5
2.3. Lớp Line 2D........................................................................................................6
2.4. Lớp Point2D.......................................................................................................6
2.5. Các lớp khác của java.awt.geom.........................................................................7
2.6. Lớp Path2D.........................................................................................................8
2.7. Thêm hình img trong java...................................................................................9
CHƯƠNG 3. GIỚI THIỆU VỀ STROKE AND FILL.....................................................10
3.1. Định nghĩa........................................................................................................10
3.2. BasicStroke.......................................................................................................11
CHƯƠNG 4. GIỚI THIỆU VỀ TRANSFORMS.............................................................12
4.1. Định nghĩa:.......................................................................................................12
CHƯƠNG 5. GIỚI THIỆU VỀ BUFFEREDIMAGE AND PIXEL.................................15
5.1. Định nghĩa........................................................................................................15
CHƯƠNG 6. DEMO........................................................................................................18
6.1. java2d/GraphicsStarter.java..............................................................................18
6.2. java2d/AnimationStarter.java............................................................................19
6.3. java2d/EventsStarter.java..................................................................................19
6.4. java2d/PaintDemo.java.....................................................................................20
6.5. java2d/JavaPixelManipulation.java...................................................................20
CHƯƠNG 7. KẾT LUẬN RÚT RA.................................................................................20
CHƯƠNG 8. PHÂN CÔNG CÔNG VIỆC VÀ TÀI LIỆU THAM KHẢO......................21
3
4

LỜI MỞ ĐẦU

Theo xu hướng của thời đại cộng nghệ 4.0 hiện nay, ngành công nghệ
thông tin là một trong những ngành hết sức quan trọng trên con đường hội
nhập và phát triển. Sản phẩm công nghệ hiện nay càng chịu sự đánh giá khắc khe
hơn từ phía những người dùng, đặc biệt là về sản phầm đồ họa được nhận rất nhiều sự
đánh giá từ những người dùng.

Xuất phát từ những lý do trên, cùng với sự hướng dẫn của cô Nguyễn Thị Anh
Thư, chúng em thực hiện nghiên cứu về graphics 2D để vận dụng những kiến thức đã
tự tìm hiểu từ những nguồn tài nguyên có sẵn, xây dựng một tự Games giải trí.

Do chưa có nhiều kinh nghiệm thực tiễn, nên đề tài thực hiện của em còn nhiều
thiếu sót, em mong nhận được sự đánh giá và nhận xét của thầy để đề tài được hoàn
thiện hơn.

Chúng em xin chân thành cảm ơn!


5

CHƯƠNG 1. GIỚI THIỆU VỀ GRAPHICS 2D TRONG JAVA


1.1. Định nghĩa về graphics 2D
Graphics2d là hình thức đồ họa trực quan sử dụng hình ảnh để trình bày thông
tin, dữ liệu hoặc kiến thức những thông tin phức tạp nhanh chóng và rõ ràng giúp
người đọc dễ hiểu.

Java là một ngôn ngữ hướng đối tượng. API của nó được định nghĩa là một tập
hợp lớn các lớp, Thực tế các thao tác vẽ trong API đồ họa ban đầu hầu hết được chứa
trong lớp có tên Đồ họa. Trong API mới hơn, các thao tác vẽ là các phương thức trong
một lớp có tên Graphics2D, là một lớp con của Đồ họa, do đó tất cả các hoạt động vẽ
ban đầu vẫn có sẵn.

1.2. Thao tác


Một hệ thống đồ họa cần một nơi để vẽ. Trong Java, bề mặt vẽ thường là một
đối tượng của lớp JPanel, đại diện cho một khu vực hình chữ nhật trên màn hình. Lớp
JPanel có một phương thức có tên paintComponent () để vẽ nội dung của nó. Để tạo
một bề mặt vẽ, bạn có thể tạo một lớp con của JPanel và cung cấp định nghĩa cho
phương thức paintComponent () của nó.

Tất cả các vẽ nên được thực hiện bên trong paintComponent (); khi cần thay đổi
nội dung của bản vẽ, bạn có thể gọi phương thức Bảng điều khiển repaint () để kích
hoạt lệnh gọi paintComponent ().

1.3. Hình ảnh hai mô hình


Phương thức paintComponent () có tham số loại Đồ họa, nhưng tham số đó là
được truyền cho phương thức này thực sự là một đối tượng của loại Graphics2D và nó
có thể được truyền kiểu
Graphics2D để có quyền truy cập vào các khả năng đồ họa tiên tiến hơn. Vì
vậy, định nghĩa của
Phương thức paintComponent () thường trông giống như thế này:
Bảo vệ void paintComponent (Đồ họa g)
{
Đồ họa2D g2;
6

g2 = (Đồ họa2D) g; // Nhập kiểu tham số vào Graphics2D.


. // Vẽ bằng g2.
}
Trong phần còn lại của phần này, tôi sẽ giả sử rằng g2 là một biến kiểu
Graphics2D và tôi sẽ thảo luận về một số điều mà bạn có thể làm với nó. Để làm ví
dụ đầu tiên, tôi lưu ý rằng Graphics2D hỗ trợ khử răng cưa, nhưng nó không được
bật theo mặc định. Nó có thể được kích hoạt trong một bối cảnh đồ họa.
g2 với lệnh khá đáng sợ
g2.setRenderingHint (RenderingH gợi ý.KEY ANTIALIASING,
RenderingH gợi ý.VALUE ANTIALIAS ON);
Đối với các ví dụ đơn giản về đồ họa trong các chương trình Java hoàn chỉnh,
bạn có thể xem mẫu:
Ví dụ :
Các chương trình java2d / GraphicsStarter.java và java2d /
AnimationStarter .java. Khung tối thiểu để vẽ hình ảnh tĩnh và hoạt hình, tương
ứng, sử dụng Graphics2D.
Chương trình java2d / EventsStarter.java là một khung tương tự để làm việc với
chuột và khóa.

CHƯƠNG 2. GIỚI THIỆU VỀ SHAPES TRONG JAVA


2.1. Định nghĩa về shapes trong java
Đồ họa ban đầu được thực hiện bằng cách sử dụng tọa độ nguyên, với phép đo
bằng pixel. Điều này hoạt động tốt trong hệ tọa độ chuẩn, nhưng không phù hợp khi sử
dụng tọa độ số thực, vì đơn vị đo trong hệ tọa độ như vậy sẽ không bằng pixel. Chúng
ta cần có thể chỉ định hình dạng bằng cách sử dụng số thực.
Gói Java java.awt.geom cung cấp hỗ trợ cho các hình dạng được xác định bằng
cách sử dụng tọa độ số thực. Ví dụ, lớp Line2D trong gói đó đại diện cho các phân
đoạn dòng có điểm cuối được cho là cặp số thực.
2.2. Gói Java java.awt.geom
Java có hai kiểu số thực: double và float.
7

Kiểu double có thể biểu thị một phạm vi số lớn hơn số float, với số chữ số có
nghĩa lớn hơn và gấp đôi là loại được sử dụng phổ biến hơn. Trong thực tế, giá trị
double đơn giản là dễ sử dụng hơn trong Java.
Kiểu float thường có đủ độ chính xác cho các ứng dụng đồ họa và chúng có lợi
thế là chiếm ít không gian hơn trong bộ nhớ. Hơn nữa, phần cứng đồ họa máy tính
thường sử dụng giá trị float bên trong.
Từ những kiểu trên, gói java.awt.geom thực sự cung cấp hai phiên bản của mỗi
hình dạng, một sử dụng tọa độ của kiểu float và một sử dụng tọa độ của kiểu double.
2.3. Lớp Line 2D
Line2D là một lớp trừu tượng. Nó có hai lớp con, một lớp biểu thị các dòng sử
dụng tọa độ float và một lớp sử dụng tọa độ kép.
Phần kỳ lạ nhất là các lớp con này được định nghĩa là các lớp lồng nhau bên
trong Line2D: Line2D.Float và Line2D.Double. Điều này có nghĩa là bạn có thể khai
báo một biến loại Line2D, nhưng để tạo một đối tượng, bạn cần sử dụng
Line2D.Double hoặc Line2D.Float:
Line2D line1, line2;
line1 = new Line2D.Double(1,2,5,7); // Line from (1.0,2.0) to (5.0,7.0)
line2 = new Line2D.Float(2.7F,3.1F,1.5F,7.1F); // (2.7,3.1) to (1.5,7.1)
Lưu ý rằng khi sử dụng các hằng số kiểu float trong Java, bạn phải thêm “F”
làm hậu tố cho giá trị. Đây là một lý do tại sao Double dễ dàng hơn trong Java. Để đơn
giản, bạn có thể muốn sử dụng Line2D.Double. Tuy nhiên, Line2D.Float có thể cho
hiệu suất tốt hơn một chút.
2.4. Lớp Point2D
Lớp trừu tượng Point2D, với các lớp con cụ thể Point2D.Double và
Point2D.Float, biểu thị một điểm theo hai chiều, được chỉ định bởi hai tọa độ số thực.
Một điểm không phải là hình dạng; bạn không thể điền vào hoặc thay đổi nó. Một
điểm có thể được xây dựng từ hai số thực:
new Point2D.Double(1.2,3.7).
8

Nếu p là biến loại Point2D, bạn có thể sử dụng p.getX () và p.getY () để truy
xuất tọa độ của nó và bạn có thể sử dụng p.setX (x), p.setY (y) hoặc p.setLocation (x,
y) để đặt tọa độ của nó.
Nếu pd là một biến loại Point2D.Double, bạn cũng có thể tham chiếu trực tiếp
đến tọa độ là pd.x và pd.y (và tương tự cho Point2D.Float). Các lớp khác trong
java.awt.geom cung cấp nhiều cách tương tự để thao túng các thuộc tính của chúng và
tôi đã thắng cố gắng liệt kê tất cả chúng ở đây.
2.5. Các lớp khác của java.awt.geom
Có một loạt các lớp đại diện cho các hình dạng hình học, bao gồm Line2D,
Oval2D, RoundRonymous2D, Ellipse2D, Arc2D và Path2D. Tất cả đều là các lớp trừu
tượng và mỗi lớp chứa một cặp các lớp con, chẳng hạn như Rectangle2D.Double and
Rectangle2D.Float.
Một số hình dạng, chẳng hạn như hình chữ nhật, có nội thất có thể được lấp
đầy; hình dạng như vậy cũng có những phác thảo có thể được xây dựng. Một số hình
dạng, chẳng hạn như đường, hoàn toàn là một chiều và chỉ có thể được xây dựng. Bên
cạnh các dòng, hình chữ nhật có lẽ là hình dạng đơn giản nhất.
Rectangle2D có một điểm góc (x, y), chiều rộng và chiều cao và có thể được
xây dựng từ dữ liệu đó.
new Rectangle2D.Double(x,y,w,h)
Điểm góc (x, y) chỉ định giá trị x - và y tối thiểu trong hình chữ nhật. Đối với hệ
tọa độ pixel thông thường, (x, y) là góc trên bên trái. Tuy nhiên, trong một hệ tọa độ
trong đó giá trị tối thiểu của y nằm ở dưới cùng, (x, y) sẽ là góc dưới bên trái. Các
Một biến r có kiểu Rectangle2D.Double có các biến thể hiện công khai r.x, r.y,
r.width, và r.height. Nếu chiều rộng hoặc chiều cao nhỏ hơn hoặc bằng 0, sẽ không có
gì được vẽ khi hình chữ nhật được lấp đầy hoặc xây dựng. Một nhiệm vụ phổ biến là
xác định một hình chữ nhật từ hai điểm góc (x1, y1) và (x2, y2).
Điều này có thể được thực hiện bằng cách tạo một hình chữ nhật có chiều cao
và chiều rộng bằng 0 và sau đó thêm điểm thứ hai vào hình chữ nhật.
Thêm một điểm vào hình chữ nhật làm cho hình chữ nhật phát triển vừa đủ để
bao gồm điểm đó:
9

Rectangle2D.Double r = new Rectangle2D.Double(x1,y1,0,0);


r.add(x2,y2);
Các lớp Line2D, Ellipse2D, RoundRonymous2D và Arc2D tạo ra các hình dạng
cơ bản khác và hoạt động tương tự như Rectangle2D. Bạn có thể kiểm tra tài liệu API
Java để biết chi tiết.
2.6. Lớp Path2D
Nó đại diện cho các đường dẫn chung được tạo thành từ các phân đoạn có thể là
các đường và đường cong Bezier. Các đường dẫn được tạo bằng các phương thức
tương tự như các chương trình con moveTo và lineTo. Để tạo một đường dẫn, bạn bắt
đầu bằng cách xây dựng một đối tượng có kiểu Path2D.Double (hoặc Path2D.Float):
Path2D.Double p = new Path2D.Double();
Đường dẫn p trống khi lần đầu tiên được tạo. Bạn xây dựng đường dẫn bằng
cách di chuyển một cây bút tưởng tượng dọc theo đường dẫn mà bạn muốn tạo.
Phương thức p.moveTo (x, y) di chuyển bút đến điểm (x, y) mà không cần vẽ
gì. Nó được sử dụng để xác định điểm ban đầu của đường dẫn hoặc điểm bắt đầu của
một đoạn mới của đường dẫn.
Phương thức p.lineTo (x, y) vẽ một đường từ vị trí bút hiện tại đến (x, y), để bút
ở (x, y).
Phương thức p.close () có thể được sử dụng để đóng đường dẫn (hoặc đoạn hiện
tại của đường dẫn) bằng cách vẽ một đường trở về điểm bắt đầu của nó.
Ví dụ: đoạn mã sau tạo ra một tam giác có các đỉnh tại (0,5), (2, -3) và (-4,1):
Path2D.Double p = new Path2D.Double();
p.moveTo(0,5);
p.lineTo(2,-3);
p.lineTo(-4,1);
p.close();
Ngoài ra cũng có thể thêm các đoạn đường cong Bezier vào Path2D. Các đường
cong Bezier đã được thảo luận trong Tiểu mục 2.2.3. Bạn có thể thêm đường cong
Bezier hình khối vào Path2D p bằng phương thức:
p.curveTo( cx1, cy1, cx2, cy2, x, y );
10

Điều này thêm một đoạn đường cong bắt đầu tại vị trí bút hiện tại và kết thúc tại
(x, y), sử dụng (cx1, cy1) và (cx2, cy2) làm hai điểm kiểm soát cho đường cong.
Phương pháp để thêm một đoạn đường cong Bezier bậc hai vào một đường dẫn
là quadTo. Nó chỉ yêu cầu một điểm kiểm soát duy nhất:
p.quadTo( cx, cy, x, y );
Khi một đường tự giao nhau, phần bên trong của nó được xác định bằng cách
nhìn vào số quanh co. Có hai quy tắc có thể để xác định xem một điểm có phải là bên
trong hay không: hỏi xem số quanh co của đường cong về điểm đó có khác không hay
không, hoặc hỏi xem nó có phải là số chẵn hay không.
Có thể đặt quy tắc quanh co được sử dụng bởi Path2D p với
p.setWindingRule( Path2D.WIND NON ZERO );
p.setWindingrule( Path2D.WIND EVEN ODD );
Mặc định là WIND_NON_ZERO.
2.7. Thêm hình img trong java
Cuối cùng, có lưu ý rằng có thể vẽ một bản sao của hình ảnh vào bối cảnh đồ
họa. Hình ảnh có thể được tải từ một tập tin hoặc được tạo bởi chương trình. Tôi thảo
luận về khả năng thứ hai sau trong phần này. Một hình ảnh được đại diện bởi một đối
tượng của loại hình ảnh.
Trong thực tế, giả sử ở đây rằng đối tượng thuộc kiểu BufferedImage, là một
lớp con của Image. Nếu img là một đối tượng như vậy, thì :
g2.drawImage( img, x, y, null );
Nó sẽ vẽ hình ảnh với góc trên bên trái của nó tại điểm (x, y). (Tham số thứ tư
khó giải thích, nhưng nên được chỉ định là null cho BufferedImages.) Điều này vẽ hình
ảnh ở chiều rộng và chiều cao tự nhiên của nó, nhưng có thể chỉ định chiều rộng và
chiều cao khác nhau trong phương thức:
g2.drawImage( img, x, y, width, height, null );
Ngoài ra còn có một phương pháp để vẽ một chuỗi văn bản. Phương thức chỉ
định chuỗi và cơ sở của chuỗi. (Basepoint là góc dưới bên trái của chuỗi, bỏ qua các
“phần thụt” như đuôi trên chữ “g” (Ý chỗ này là nó sẽ bỏ qua cái dấu móc xuống của
chữ g ý , kiểu v ). Ví dụ:
11

g2.drawString( "Hello World", 100, 50 );


Hình ảnh và chuỗi có thể biến đổi theo cùng một cách với các hình dạng khác.
Chuyển đổi là cách duy nhất để có được văn bản và hình ảnh xoay. Ví dụ, đây là
những gì có thể xảy ra khi bạn áp dụng xoay cho một số văn bản và hình ảnh:

Nguồn: sách Introduction to Computer Graphics

CHƯƠNG 3. GIỚI THIỆU VỀ STROKE AND FILL


3.1. Định nghĩa
Khi có đối tượng là một hình khối. Có thể khoanh vùng hoặc tô điền vào cái
hình đó. Công cụ g2 cung cấp giải pháp để làm như vậy. Giải pháp đó gọi là draw.
Ví Dụ: g2.fill(shape);
g2.draw(shape)
Trong đó g2 là tên của hàm graphic2d
Shape có thể là dạng bất kỳ trong các dạng sau: Path2d,line2d, rectangle2d hoặc
các định dạng shape khác.
Hai cái cú pháp này thường dùng để tạo một đối tượng mới khi đối tượng đó là
hình ảnh mà chỉ được vẽ một lần.
Ví dụ: g2.draw( new Line2D. Double (-5, -5, 5, 5 ))
Và đương nhiên cũng có thể tạo một đối tượng hình dạng và sử dụng lại nhiều
lần.
12

Công cụ "pen" thường dùng để khoanh vùng những cái shape có định dạng
3.2. BasicStroke
Mặc định của Stroke là đường thẳng có độ rộng bằng 1.
Và được tính trong tọa độ đang dùng chứ không phải là 1 pixel.
Để vẽ đường thẳng có độ rộng khác có thể cài đặt lại bằng cú pháp:
Ví dụ: g2.setStroke ( new BasicStroke ( width ) )
Biến (width) là dạng float. Và cũng có thể giới hạn biến để điều khiển shape
trong cái khoanh vùng tại điểm cuối của nó và nơi mà 2 đối tượng giao nhau.
Ví dụ: g2.setStroke ( new BasicStroke ( 5.OF, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_BEVEL ) )
Stroke và fill ở đây có nghĩa là đặt màu cho những pixel cố định.
Trong java luật dùng để tô màu pixel là "paint".
Paint có thể là 1 màu đơn,1 gradients hoặc 1 bản màu.
Giống như những thứ khác trong java. Paint đc diễn tả là đối tượng, nếu paint là
đối tượng thì : g2.setPaint(paint) sẽ set paint dùng trong hàm g2 để giới hạn điều
hành việc vẽ, cho đến khi pain đc thay đổi (Và cũng có 2 phương pháp khác là
g2.setColor(c) chỉ hoạt động khi tô màu và tương tự là g2.setPaint(c).
Màu khối (solid color) đc diễn tả là 1 đối tượng dạng Color. Đc thể hiện bên
trong như là 1 RGBA color.
Màu mờ (làm mờ) được tạo thành toàn diện nhất bằng cú pháp: New
color(r,g,b). Trong đó, R,g,b là số nguyên từ 0 đến 255 thể hiện các màu đc hợp thành
từ đỏ, vàng và xanh dương. Để có được độ làm mờ phải thêm biến alpha.
New color(r,g,b,a). Trong đó a cũng là số nguyên từ 0~255.
Và cũng có hàm Color.getHSBcolor(h,s,b), để tạo 1 cái màu lấy từ HSB color
mode. Trong trường hợp màu nền, sự bão hòa, độ sáng của cái color đó có giá trị dạng
float. Và nó cũng diễn tả được màu được trộn từ nhiều màu như là color.WHITE ,
color.RED ,và color.YELLOW.
Ví du:
Ngoài màu khối. Java còn class GradientPaint để điên tả các đường gradient và
TexturePaint để diễn tả các bản màu.(Hình ảnh bản màu đc sử dụng giống như cách
13

trong 3d graphic đc gọi là texture). Trong những trường hợp này color đuợ nạp vào
pixel tùy thuộc vào tọa độ của pixel.
Để tạo TexturePaint, bạn cần phải có đối tượng bufferedImage để chỉ rõ hình
ảnh đó được dùng như là 1 bảng màu (patterns). Bạn sẽ thắc mắc là làm sao để tọa độ
của cái image đó được map và hiển thị lên tọa độ của màn hình.
Bằng cách chỉ định 1 hình chữ nhật trong đó giữ lại 1 bản copy của Image dùng
cú pháp sau:
New texturePaint ( image, rect).
Trong đó image là BufferedImage, Rect là Rectangle2D.
Bên ngoài hình chữ nhật đó image sẽ tiếp tục theo chiều ngang và chiều dọc.
GradientPaint dùng form:
New GradientPaint(x1,y1,color1,x2,y2,color2,cylic).
X1,x2,y1,y2 dạng float.
Color1,color2 dạng color. Cylic là Boolean. Gradient color sẽ thay đổi trên
đoạn thẳng từ điểm 1(x1,y1) đến điểm 2(x2,y2).
Màu sẽ là color 1 tại điểm cuối đầu tiền và color 2 tại điểm cuối thứ 2. Màu sẽ
không thay đổi trên đường thẳng vuông góc với đoạn được vẽ. Biến Boolean cylic
nói lên cái patterns có đc lập lại hay không.

CHƯƠNG 4. GIỚI THIỆU VỀ TRANSFORMS


4.1. Định nghĩa:
Java thực hiện các phương thức biến đổi hình học trong lớp Graphics2D. Ví dụ,
Gọi g2 là một Graphics2D, thì khi gọi g2.translate(1,3) sẽ thực hiện phép dịch chuyển
theo tọa độ là (1,3) cho các đối tượng được vẽ sau khi gọi phương thức này được gọi.
Đây là các phương thức tương tự đã được nói trong Phần 2.3:
• g2.scale (sx, sy) – co dãn hệ số sx theo chiều ngang và sy theo chiều dọc
• g2.rotate (r) – r sẽ là góc cố định và đơn vị góc của phương thức này phải là
radian. Một góc dương quay trục x dương theo hướng của trục y dương..
• g2.rotate (r, x, y) – quay góc r hướng về 2 điểm (x, y).
14

• g2.translate (dx, dy) – dịch chuyển về điểm dx theo chiều ngang và dy theo
chiều dọc.
• g2.shear (sx, sy) –biến dạng theo chiều ngang sx và chiều dọc sy
Sự biến đổi trong Java được biểu diễn dưới dạng một đối tượng của lớp
AffineTransform. Ta có thể khởi tạo phép biến đổi affine với phương thức constructor.
AffineTransform trns = new AffineTransform(a,b,c,d,e,f);
Đối tượng trns sẽ biến đổi một điểm (x,y) thành điểm (x1, y1)
x1 = a*x + c*y + e
y1 = b*x + d*y + f;
Có thể áp dụng đối tượng trns này cho bối cảnh đồ họa g2 bằng cách gọi
g2.transform(trns)
Bối cảnh đồ họa g2 bao gồm biến đổi affine hiện tại, là thành phần của tất cả
các biến đổi đã được áp dụng. Các lệnh như g2.rotate và g2.transform tùy chỉnh biến
đổi hiện tại. Ta có thể lấy một bản sao của biến đổi hiện tại bằng cách gọi
g2.getTransform (), trả về một đối tượng AffineTransform. Ta có thể gán biến đổi hiện
tại bằng cách sử dụng g2.setTransform (trns). Điều này thay thế biến đổi hiện tại trong
g2 bằng trns AffineTransform. (Lưu ý rằng g2.setTransform (trns) khác với
g2.transform (trns); lệnh thứ thất dùng để thay thế biến đổi hiện tại trong g2, trong khi
lệnh thứ hai sửa đổi biến đổi hiện tại bằng cách kết hợp nó với trns.)
Các phương thức getTransform và setTransform có thể được sử dụng để triển
khai mô hình phân cấp.Mô hình này được nói đến trong Phần 2.4, là trước khi vẽ một
đối tượng, ta nên lưu lại biến đổi hiện tại. Sau khi vẽ đối tượng, khôi phục biến đổi đã
lưu. Bất kỳ biến đổi mô hình bổ sung nào được áp dụng trong khi vẽ đối tượng và các
đối tượng con của nó sẽ không có hiệu ứng bên ngoài đối tượng. Trong Java, nó trông
giống như:
AffineTransform savedTransform = g2.getTransform();
drawObject();
g2.setTransform( savedTransform );
Đối với đồ họa phân cấp, chúng ta thực sự cần một ngăn xếp biến đổi. Tuy
nhiên, nếu hệ thống phân cấp được triển khai bằng chương trình con, thì đoạn mã trên
15

sẽ là một phần của chương trình con và giá trị của biến cục bộ đã lưu biến đổi sẽ được
lưu trữ trên ngăn xếp chương trình con. Thực tế, chúng ta sẽ sử dụng ngăn xếp chương
trình con để thực hiện ngăn xếp các biến đổi đã lưu.
Ngoài các phép biến đổi mô hình, các biến đổi được sử dụng để gán vào phép
biến đổi window-to-viewport để thiết lập hệ tọa độ và sẽ được sử dụng để vẽ. Điều này
thường được thực hiện trong Java ngay sau khi bối cảnh đồ họa được tạo, trước bất kỳ
thao tác vẽ nào. Nó có thể được thực hiện với phiên bản Java của hàm
applyWindowToViewportTransformation từ Tiểu mục 2.3.7. Xem chương trình mẫu
“java2d / GraphicsStarter.java” là 1 ví dụ.
Tôi sẽ đề cập thêm một lần sử dụng cho các đối tượng AffineTransform: Đôi
khi, bạn cần phải chuyển đổi rõ ràng tọa độ. Ví dụ, tọa độ đối tượng đã cho (x, y), tôi
có thể cần biết chúng thực sự sẽ ở đâu trên màn hình, theo tọa độ pixel. Đó là, tôi
muốn chuyển đổi (x, y) bằng biến đổi hiện tại để có tọa độ pixel tương ứng. Lớp
AffineTransform có một phương thức để áp dụng phép biến đổi affine cho một điểm.
Nó hoạt động với các đối tượng thuộc dạng Point2D. Đây là một ví dụ:
AffineTransform trns = g2.getTransform();
Point2D.Double originalPoint = new Point2D.Double(x,y);
Point2D.Double transformedPoint = new Point2D.Double();
trns.transform( originalPoint, transformedPoint );
// transformedPoint hiện chứa các chuỗi pixel tương ứng với (x,y)
int pixelX = (int)transformedPoint.x;
int pixelY = (int)transformedPoint.y;
Có 1 điều tôi đã từng sử dụng là khi làm việc với chuỗi. Thông thường khi hiển
thị một chuỗi trong một hệ tọa độ được chuyển đổi, tôi muốn chuyển đổi cơ sở của
một chuỗi, nhưng không phải là chính chuỗi đó. Đó là tôi muốn chuyển tác động đến
vị trí của chuỗi nhưng không phải kích thước hoặc xoay. Để thực hiện điều này, tôi sử
dụng kỹ thuật trên để lấy tọa độ pixel cho điểm gốc được chuyển đổi, sau đó vẽ chuỗi
ở các tọa độ đó, sử dụng một bản gốc,bối cảnh đồ họa chưa được dịch.
Các hoạt động đảo ngược đôi khi cũng cần thiết. Nghĩa là, tọa độ pixel đã cho
(px, py), tìm điểm (x, y) được chuyển thành (px, py) bằng một phép biến đổi affine đã
16

cho. Ví dụ: khi thực hiện tương tác chuột, bạn thường sẽ biết tọa độ pixel của chuột,
nhưng bạn sẽ muốn tìm điểm tương ứng trong hệ tọa độ đã chọn của riêng bạn. Đối
với điều đó, bạn cần một biến đổi nghịch đảo. Nghịch đảo của một biến đổi affine T là
một biến đổi khác tương ứng với biến đổi ngược lại. Nghĩa là, nếu T (x, y) = (px, py)
và nếu R là biến đổi nghịch đảo thì R (px, py) = (x, y). Trong Java, có thể thu được
biến đổi nghịch đảo của một trns AffineTransform

AffineTransform inverse = trns.createInverse();

(Lưu ý cuối cùng: Các phương thức vẽ cũ trước đó của đồ họa, như drawLine,
sẽ sử dụng tọa độ nguyên. Điều quan trọng cần lưu ý là bất kỳ hình dạng nào được vẽ
bằng các phương thức cũ này đều phải chịu sự biến đổi giống như các hình dạng như
Line2D được chỉ định với tọa độ số thực. Ví dụ: vẽ một dòng bằng g.drawLine
(1,2,5,7) sẽ có tác dụng tương tự như vẽ Line2D có điểm cuối (1.0,2.0) và (5.0,7.0).
Trong thực tế, tất cả các bản vẽ bị ảnh hưởng bởi sự chuyển đổi tọa độ.)

CHƯƠNG 5. GIỚI THIỆU VỀ BUFFEREDIMAGE AND PIXEL


5.1. Định nghĩa
Trong một số ứng dụng đồ họa, nó rất hữu ích để có thể làm việc với hình ảnh
không hiển thị trên màn hình. Gọi là một khung vẽ ngoài màn hình. Bạn cũng cần một
cách để nhanh chóng sao chép khung vẽ ngoài màn hình lên trên màn hình.
Ví dụ: sẽ thật hữu ích nếu lưu một bản sao của hình ảnh trên màn hình trong
một khung vẽ ngoài màn hình.
Canvas là bản sao chính thức của hình ảnh. Thay đổi hình ảnh được thực hiện
trên khung vẽ, sau đó sao chép vào màn hình. Một lý do để làm điều này là bạn có thể
vẽ thêm những thứ khác lên trên hình ảnh mà không thay đổi bản sao chính thức.
Ví dụ: bạn có thể vẽ một hộp xung quanh một vùng đã chọn trong hình ảnh trên
màn hình. Bạn có thể làm điều này mà không làm hỏng bản sao chính thức trong
khung vẽ ngoài màn hình. Để xóa hộp khỏi màn hình, bạn chỉ cần sao chép hình ảnh
canvas lên màn hình.
Trong Java, một khung ảnh ngoài màn hình có thể được triển khai như một đối
tượng của kiểu BufferedImage. BufferedImage đại diện cho một vùng trong bộ nhớ
17

nơi bạn có thể vẽ, giống hệt như cách bạn vẽ lên màn hình. Nghĩa là, bạn có thể có
được bối cảnh đồ họa g2 thuộc loại Grapics2D mà bạn có thể sử dụng để vẽ trên màn
hình.
BufferedImage là một hình ảnh và bạn có thể vẽ nó lên màn hình, hoặc vào bối
cảnh đồ họa nào khác giống như bất ký hình ảnh nào khác, nghĩa là bằng cách sử dụng
phương thức drawImage của bồi cảnh đồ họa mà bạn muốn hiển thị hình ảnh. Trong
một thiết lập điển hình có các biến:
 Buffered OSC; (canvas ngoài màn hình)
 Graphics2D OSG; (bối cảnh đồ họa để vẽ lên khung)

Các đối tượng được tạo bằng cách sử dụng, ví dụ:


 OSC = new BufferedImage(640,480,BufferedImage.TYPE INT RGB);
 OSG = OSC.createGraphics();

Hàm tạo cho BufferedImage chỉ định chiều rộng và chiều cao của hình ảnh
cùng với loại của nó. Kiểu này cho biết màu sắc nào có thể được hiển thị trong hình
ảnh và cách chúng được lưu trữ. Ở đây là TYPE INT RGB, có nghĩa là hình ảnh sử
dụng màu RGB thông thường với 8bit cho mỗi thành phần màu. Ba thành phần màu
cho một pixel được đóng gói thành một số nguyên duy nhất giá trị.
Trong một chương trình sử dụng BufferedImage để lưu trữ một bản sao của
hình ảnh trên màn hình, phương thức paintComponent thường có dạng:
protected void paintComponent(Graphics g) {
g.drawimage( OSC, 0, 0, null );
Graphics2D g2 = (Graphics2D)g.create();
.
. // Draw extra stuff on top of the image.
}
Một chương trình mẫu sử dụng kỹ thuật này là
java2dJavaPixelManipulation.java. Trong đó chương trình, người dùng có thể vẽ các
đường, hình chữ nhật và hình bầu dục bằng cách kéo chuột. Như con chuột di chuyển,
hình dạng được vẽ giữa điểm bắt đầu của chuột và vị trí hiện tại của nó. Như chuột di
18

chuyển, các phần của hình ảnh hiện tại có thể được che lại và phát hiện ra mà không
cần thay đổi hình ảnh hiện có. Trên thực tế, hình ảnh nằm trong một khung vẽ ngoài
màn hình và hình dạng người dùng đang vẽ thực sự được vẽ bởi paintComponent trên
nội dung của khung vẽ. Các hình dạng không được vẽ vào hình ảnh chính thức trong
khung vẽ cho đến khi người dùng nhả chuột và kết thúc
các hoạt động kéo.
Nhưng lý do chính của tôi để viết chương trình là để minh họa thao tác pixel,
nghĩa là tính toán với các thành phần màu của các pixel riêng lẻ. Lớp BufferedImage
có các phương thức để đọc và thiết lập màu của từng pixel. Một hình ảnh bao gồm các
hàng và cột pixel. Nếu OSC là BufferedImage, thì:
int color = OSC.getRGB(x,y)
Lấy số nguyên biểu thị màu của pixel trong số cột x và số hàng y. Mỗi thành
phần màu được lưu trữ trong trường 8 bit trong giá trị màu nguyên. Các màu riêng biệt
các thành phần có thể được trích xuất để xử lý bằng các toán tử thao tác bit Java:
int red = (color >> 16) & 255;
int green = (color >> 8) & 255;
int blue = color & 255;
Tương tự, với các giá trị thành phần màu đỏ, lục và lam trong phạm vi 0 đến
255, chúng ta có thể kết hợp các giá trị thành phần đó thành một số nguyên duy nhất
và sử dụng nó để đặt màu của pixel trong bức hình:
int color = (red << 16) | (green << 8) | blue;
OSC.setRGB(x,y,color);
Ngoài ra còn có các phương pháp để đọc và thiết lập màu sắc của toàn bộ khu
vực hình chữ nhật của pixel. Các thao tác pixel được sử dụng để thực hiện hai tính
năng của chương trình mẫu. Đầu tiên, có một công cụ Smudge. Khi người dùng kéo
bằng công cụ này, nó giống như bôi sơn ướt. Khi mà người dùng nhấp chuột lần đầu
tiên, các thành phần màu từ một hình vuông pixel nhỏ xung quanh vị trí chuột được
sao chép vào mảng. Khi người dùng di chuyển chuột, màu sắc từ các mảng là pha trộn
với màu của các pixel gần vị trí chuột. Đây là một hình chữ nhật nhỏ đã “smudged”.
19

Việc sử dụng thứ hai của thao tác pixel là trong việc triển khai các bộ lọc của
Cameron. Bộ lọc, trong chương trình này, là một thao tác sửa đổi hình ảnh bằng cách
thay thế màu của từng pixel bằng trung bình trọng số của các màu của hình vuông 3
nhân 3 pixel. Ví dụ, bộ lọc Blur Blur, sử dụng các trọng số bằng nhau cho tất cả các
pixel ở mức trung bình, do đó màu của pixel được thay đổi thành trung bình đơn giản
của các màu của pixel đó và các lân cận của nó. Sử dụng các trọng lượng khác nhau
cho mỗi pixel có thể tạo ra một số điểm nổi bật tác dụng.
Thao tác pixel trong chương trình mẫu tạo ra các hiệu ứng có thể đạt được với
đồ họa vector thuần túy. Tôi khuyến khích bạn tìm hiểu thêm bằng cách xem mã
nguồn. Bạn cũng có thể xem các bản demo trực tiếp trong phần tiếp theo, phần thực
hiện các hiệu ứng tương tự bằng đồ họa canvas HTML.
CHƯƠNG 6. DEMO
6.1. java2d/GraphicsStarter.java
20

6.2. java2d/AnimationStarter.java

6.3. java2d/EventsStarter.java
21

6.4. java2d/PaintDemo.java

6.5. java2d/JavaPixelManipulation.java

CHƯƠNG 7. KẾT LUẬN RÚT RA


 Java hỗ trợ rất nhiều cho việc code và sử lý các hình dạng và hình ảnh.
 Chúng ta có thể tạo ra được một chung trình paint đơn giản như trong demo.
 Sử dụng những animation để có thể di chuyển các vật thể .
 Đổi màu và viền cho các hình ảnh được tạo ra.
22

CHƯƠNG 8. PHÂN CÔNG CÔNG VIỆC VÀ TÀI LIỆU THAM


KHẢO
 Nguyễn Quang Huy (nhóm trưởng):
Tìm hiểu và trình bày về Shapes và demo java2d/AnimationStarter.java
 Phạm Đặng Đức Huy :
Tìm hiểu và trình bày về Graphics 2D và demo java2d/EventsStarter.java
 Đoàn Quang Khải:
Tìm hiểu và trình bày về stroke and fill và demo java2d/PaintDemo.java
 Nguyễn Lê Hoàng Huy:
Tìm hiểu về Transforms và demo java2d/GraphicsStarter.java
 Trương Minh Huy:
Tìm hiểu và trình bày về bufferedimage and pixels và demo
java2d/JavaPixelManipulation.java

You might also like