| Bitmap.java |
1 package fi.jyu.mit.graphics;
2
3 import java.awt.Graphics;
4 import java.awt.image.BufferedImage;
5 import java.awt.image.WritableRaster;
6 import java.io.File;
7 import java.net.URL;
8 import java.util.Hashtable;
9
10 import javax.imageio.ImageIO;
11
12
13 /**
14 * Yksinkertainen bitmapin piirto.
15 * Muunnosmatriisit vaikuttavat ainoastaan paikkaan (toistaiseksi).
16 * Bitmapista voidaan ottaa rakadata ja tehdä sille hienompia temppuja
17 * @see BufferedImage
18 * @author vesal
19 * @version 4.9.2010
20 */
21 public class Bitmap extends BasicShape {
22
23 private final RPoint upperLeft;
24 int imgWidth = 0;
25 int imgHeight = 0;
26
27 private BufferedImage rawImg;
28
29
30 /**
31 * Luodaan bitmap tiedostosta tai URLista jos nimi alkaa http
32 * @param x koordinaatti johon bitmap näytetään
33 * @param y koordinaatti johon bitmap näytetään
34 * @param z syvyyskoordinaatti johon bitmap näytetään
35 * @param filename tiedoston nimi, josta bitmap luetaan
36 */
37 public Bitmap(double x,double y, double z, String filename) {
38 super();
39 upperLeft = new RPoint(x,y,z);
40 try {
41 if ( filename.startsWith("http") )
42 rawImg = ImageIO.read(new URL(filename));
43 else
44 rawImg = ImageIO.read(new File(filename));
45 } catch (Exception e) {
46 // e.printStackTrace();
47 throw new NullPointerException("filename " + filename + " not found");
48 }
49 imgWidth = rawImg.getWidth(null);
50 imgHeight = rawImg.getHeight(null);
51 }
52
53
54 /**
55 * Luodaan bitmap tiedostosta
56 * @param x koordinaatti johon bitmap näytetään
57 * @param y koordinaatti johon bitmap näytetään
58 * @param filename tiedoston nimi, josta bitmap luetaan
59 */
60 public Bitmap(double x,double y, String filename) {
61 this(x,y,0,filename);
62 }
63
64
65 /**
66 * Luodaan tyhjä valkoinen bitmap
67 * @param x koordinaatti johon bitmap näytetään
68 * @param y koordinaatti johon bitmap näytetään
69 * @param z syvyyskoordinaatti johon bitmap näytetään
70 * @param w uuden kuvan leveys
71 * @param h uuden kuvan korkeus
72 */
73 public Bitmap(double x,double y, double z, int w, int h) {
74 super();
75 upperLeft = new RPoint(x,y,z);
76 rawImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
77 imgWidth = rawImg.getWidth(null);
78 imgHeight = rawImg.getHeight(null);
79 }
80
81
82 /**
83 * Luodaan tyhjä valkoinen bitmap
84 * @param x koordinaatti johon bitmap näytetään
85 * @param y koordinaatti johon bitmap näytetään
86 * @param w uuden kuvan leveys
87 * @param h uuden kuvan korkeus
88 */
89 public Bitmap(double x,double y, int w, int h) {
90 this(x,y,0,w,h);
91 }
92
93
94 /**
95 * Apumetodi kopion tekemiseksi raakasta kuvasta.
96 * @param image kuvatieto joka kopioidaan
97 * @return kopioitu kuvatieto
98 */
99 public static BufferedImage cloneBufferedImage(BufferedImage image) {
100 String[] pnames = image.getPropertyNames();
101 Hashtable<String, Object> cproperties = new Hashtable<String, Object>();
102 if (pnames != null) {
103 for (int i = 0; i < pnames.length; i++) {
104 cproperties.put(pnames[i], image.getProperty(pnames[i]));
105 }
106 }
107 WritableRaster wr = image.getRaster();
108 WritableRaster cwr = wr.createCompatibleWritableRaster();
109 cwr.setRect(wr);
110 BufferedImage cimage = new BufferedImage(image.getColorModel(),
111 cwr, image.isAlphaPremultiplied(), cproperties);
112 return cimage;
113 }
114
115
116 /**
117 * Luodaan uusi Bitmap vanhan aidoksi kopioiksi
118 * @param x koordinaatti johon bitmap näytetään
119 * @param y koordinaatti johon bitmap näytetään
120 * @param z syvyyskoordinaatti johon bitmap näytetään
121 * @param bm kopioitava kuva
122 */
123 public Bitmap(double x,double y, double z, Bitmap bm) {
124 super();
125 upperLeft = new RPoint(x,y,z);
126 rawImg = cloneBufferedImage(bm.getRawImage());
127 imgWidth = rawImg.getWidth(null);
128 imgHeight = rawImg.getHeight(null);
129 }
130
131
132 /**
133 * Luodaan uusi Bitmap vanhan aidoksi kopioiksi
134 * @param x koordinaatti johon bitmap näytetään
135 * @param y koordinaatti johon bitmap näytetään
136 * @param bm kopioitava kuva
137 */
138 public Bitmap(double x,double y, Bitmap bm) {
139 this(x,y,0,bm);
140 }
141
142
143 /**
144 * @param p pikseli jonka kirkkaus lasketaan
145 * @return pikselin kirkkaus arvona 0-255
146 */
147 public static int brightness(int p) {
148 int r = p & 0xff;
149 p >>= 8; r += p & 0xff;
150 p >>= 8; r += p & 0xff;
151 return r / 3;
152 }
153
154
155 /**
156 * @return kuvan leveys
157 */
158 public int getWidth() {
159 return imgWidth;
160 }
161
162
163 /**
164 * @return kuvan korkeus
165 */
166 public int getHeight() {
167 return imgHeight;
168 }
169
170
171 /**
172 * Palautetaan kuvan yhden pikselin väritiedot
173 * @param x pikselin x-koordinaatti
174 * @param y pikselin y-koordinaatti
175 * @return RGB ja alpha tieto pikselistä
176 */
177 public int getRGB(int x, int y) {
178 return rawImg.getRGB(x,y);
179 }
180
181
182 /**
183 * Asetetaan pikselin RGB ja alpha arvot
184 * @param x pikselin x-koordinaatti
185 * @param y pikselin y-koordinaatti
186 * @param rgb uusi RGB ja alpha arvo pikselille
187 */
188 public void setRGB(int x, int y, int rgb) {
189 rawImg.setRGB(x,y,rgb);
190 }
191
192
193 /**
194 * Muuttaa kolme väriä ja alpha-tiedon yhdeksi väritiedoksi
195 * @param r punaisen määrä (0-255)
196 * @param g vihreän määrä (0-255)
197 * @param b sinisen määrä (0-255)
198 * @param a alha-arvo
199 * @return tieto pakattuna yhteen 32-bit lukuun
200 */
201 public static int toRGB(int r,int g,int b,int a) {
202 return ( a << 24 ) | (r << 16) | (g << 8) | b;
203 }
204
205
206 /**
207 * Muuttaa kolme väriä
208 * @param r punaisen määrä (0-255)
209 * @param g vihreän määrä (0-255)
210 * @param b sinisen määrä (0-255)
211 * @return tieto pakattuna yhteen 32-bit lukuun
212 */
213 public static int packRGB(int r,int g,int b) {
214 return ( 255 << 24 ) | (r << 16) | (g << 8) | b;
215 }
216
217
218 /**
219 * @param c väri jota tutkitaan
220 * @return väristä otettu punaisen määrä (0-255)
221 */
222 public static int getRed(int c) {
223 return (c >> 16) & 0xff;
224 }
225
226
227 /**
228 * @param c väri jota tutkitaan
229 * @return väristä otettu vihreän määrä (0-255)
230 */
231 public static int getGreen(int c) {
232 return (c >> 8) & 0xff;
233 }
234
235
236 /**
237 * @param c väri jota tutkitaan
238 * @return väristä otettu sinisen määrä (0-255)
239 */
240 public static int getBlue(int c) {
241 return (c >> 0) & 0xff;
242 }
243
244
245 /**
246 * @param c väri jota tutkitaan
247 * @return väristä otettu alpha-arvo
248 */
249 public static int getA(int c) {
250 return (c >> 24) & 0xff;
251 }
252
253
254 /**
255 * @return viite raakaan kuvadata monimutkaisempaa käsittelyä varten
256 * @see BufferedImage
257 */
258 public BufferedImage getRawImage() {
259 return rawImg;
260 }
261
262
263 @Override
264 protected void drawShape(Graphics g, Matrix a) {
265 SPoint sp = new SPoint(0,0);
266 a.transform(upperLeft,sp);
267 g.drawImage(rawImg,sp.getX(),sp.getY(),null);
268 }
269
270
271 /**
272 * Muuttaa kuvan harmaasävyiksi
273 */
274 public void convertGrayScale() {
275 for (int y = 0; y < rawImg.getHeight(); y++) {
276 for (int x = 0; x < rawImg.getWidth(); x++) {
277 int c = rawImg.getRGB(x, y);
278 int b = Bitmap.brightness(c);
279 b = (b << 16) | (b << 8) | b;
280 rawImg.setRGB(x, y, b);
281 }
282 }
283 }
284
285
286 /**
287 * Tekee jokaiselle pikselille and operaation maskin kanssa.
288 * @param mask maski, jolla pikseliä muutetaan
289 */
290 public void andPixels(int mask) {
291 for (int y = 0; y < rawImg.getHeight(); y++) {
292 for (int x = 0; x < rawImg.getWidth(); x++) {
293 int c = rawImg.getRGB(x, y);
294 rawImg.setRGB(x, y, c & mask);
295 }
296 }
297 }
298
299
300 /**
301 * Tekee jokaiselle pikselille OR operaation maskin kanssa.
302 * @param mask maski, jolla pikseliä muutetaan
303 */
304 public void orPixels(int mask) {
305 for (int y = 0; y < rawImg.getHeight(); y++) {
306 for (int x = 0; x < rawImg.getWidth(); x++) {
307 int c = rawImg.getRGB(x, y);
308 rawImg.setRGB(x, y, c | mask);
309 }
310 }
311 }
312
313
314 /**
315 * Luodaan kuvasta 2-ulotteinen taulukko, johon kopioidaan kuvan pisteet
316 * @param ox - siirtymä x-suunnassa vasemmasta ylänurkasta
317 * @param oy - siirtymä y-suunnassa vasemmasta ylänurkasta
318 * @param w - alueen leveys josta kopioidaan
319 * @param h - alueen korkeus josta kopioidaan
320 * @return kuvan bittitieto 2.ulotteisena kokonaislukutaulukkona
321 */
322 public int[][] getData(int ox,int oy, int w, int h) {
323 int maxx = rawImg.getWidth()-ox;
324 int maxy = rawImg.getHeight()-oy;
325 if ( ox+w < maxx ) maxx = w;
326 if ( oy+h < maxy ) maxy = h;
327
328 int[][] data = new int[maxy][maxx];
329 for (int y = 0; y < maxy; y++)
330 for (int x = 0; x < maxx; x++)
331 data[y][x] = rawImg.getRGB(x+ox, y+oy);
332 return data;
333 }
334
335
336 /**
337 * @return kuvan bittitieto 2.ulotteisena kokonaislukutaulukkona
338 */
339 public int[][] getData() {
340 return getData(0,0,rawImg.getWidth(),rawImg.getHeight());
341 }
342
343
344 /**
345 * Asettaa bittidatantaulukon haluttuun kohtaan kuvassa.
346 * Jos kuva menee ulos , ei ulos meneviä pisteitä huomioida.
347 * Taulukossa saa olla erimittaisia rivejä
348 *
349 * @param ox - siirtymä x-suunnassa vasemmasta ylänurkasta
350 * @param oy - siirtymä y-suunnassa vasemmasta ylänurkasta
351 * @param w - alueen leveys johon kopioidaan
352 * @param h - alueen korkeus johon kopioidaan
353 * @param data - kopioitava taulukko
354 */
355 public void setData(int ox,int oy, int w, int h, int[][] data) {
356 //int[][] data = new int[rawImg.getHeight()][rawImg.getWidth()];
357 int imgw = rawImg.getWidth();
358 int imgh = rawImg.getHeight();
359 int maxy = data.length;
360 if ( h < maxy ) maxy = h;
361 if ( imgh < maxy+oy ) maxy = imgh-oy;
362 for (int y=0; y<maxy;y++) {
363 int maxx = data[y].length;
364 if ( w < maxx ) maxx = w;
365 if ( imgw < maxx+ox ) maxx = imgw-ox;
366 for (int x=0; x<maxx;x++)
367 rawImg.setRGB(ox+x, oy+y, data[y][x]);
368 }
369 }
370
371
372 /**
373 * Asettaa bittidatantaulukon haluttuun kohtaan kuvassa.
374 * Jos kuva menee ulos , ei ulos meneviä pisteitä huomioida.
375 * Taulukossa saa olla erimittaisia rivejä, 1. rivi määrää leveyden
376 *
377 * @param ox - siirtymä x-suunnassa vasemmasta ylänurkasta
378 * @param oy - siirtymä y-suunnassa vasemmasta ylänurkasta
379 * @param data - kopioitava taulukko
380 */
381 public void setData(int ox,int oy,int[][] data) {
382 setData(ox,oy,data[0].length,data.length,data);
383 }
384
385
386 }
387