Formatting update
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / renderer / raster / texture / TextureBitmap.java
1 /*
2  * Sixth 3D engine. Author: Svjatoslav Agejenko. 
3  * This project is released under Creative Commons Zero (CC0) license.
4  */
5 package eu.svjatoslav.sixth.e3d.renderer.raster.texture;
6
7 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
8
9 public class TextureBitmap {
10
11     /**
12      * Byte order: ABGR
13      */
14     public final byte[] bytes;
15
16     public final int width;
17
18     public final int height;
19
20     public double multiplicationFactor;
21
22     public TextureBitmap(final int width, final int height, final byte[] bytes,
23                          final double multiplicationFactor) {
24
25         this.width = width;
26         this.height = height;
27         this.bytes = bytes;
28         this.multiplicationFactor = multiplicationFactor;
29     }
30
31     public TextureBitmap(final int width, final int height,
32                          final double multiplicationFactor) {
33
34         this(width, height, new byte[width * height * 4], multiplicationFactor);
35     }
36
37     public void drawPixel(int textureOffset,
38                           final byte[] targetRenderingAreaBytes, int targetRenderingAreaOffset) {
39
40         final int textureAlpha = bytes[textureOffset] & 0xff;
41
42         if (textureAlpha == 0)
43             return;
44
45         if (textureAlpha == 255) {
46             // skip reading of background for fully opaque pixels
47             targetRenderingAreaBytes[targetRenderingAreaOffset] = (byte) 255;
48
49             targetRenderingAreaOffset++;
50             textureOffset++;
51             targetRenderingAreaBytes[targetRenderingAreaOffset] = bytes[textureOffset];
52
53             targetRenderingAreaOffset++;
54             textureOffset++;
55             targetRenderingAreaBytes[targetRenderingAreaOffset] = bytes[textureOffset];
56
57             targetRenderingAreaOffset++;
58             textureOffset++;
59             targetRenderingAreaBytes[targetRenderingAreaOffset] = bytes[textureOffset];
60             return;
61         }
62
63         final int backgroundAlpha = 255 - textureAlpha;
64         textureOffset++;
65
66         targetRenderingAreaBytes[targetRenderingAreaOffset] = (byte) 255;
67         targetRenderingAreaOffset++;
68
69         targetRenderingAreaBytes[targetRenderingAreaOffset] = (byte) ((((targetRenderingAreaBytes[targetRenderingAreaOffset] & 0xff) * backgroundAlpha) + ((bytes[textureOffset] & 0xff) * textureAlpha)) / 256);
70         textureOffset++;
71         targetRenderingAreaOffset++;
72
73         targetRenderingAreaBytes[targetRenderingAreaOffset] = (byte) ((((targetRenderingAreaBytes[targetRenderingAreaOffset] & 0xff) * backgroundAlpha) + ((bytes[textureOffset] & 0xff) * textureAlpha)) / 256);
74         textureOffset++;
75         targetRenderingAreaOffset++;
76
77         targetRenderingAreaBytes[targetRenderingAreaOffset] = (byte) ((((targetRenderingAreaBytes[targetRenderingAreaOffset] & 0xff) * backgroundAlpha) + ((bytes[textureOffset] & 0xff) * textureAlpha)) / 256);
78     }
79
80     public void drawPixel(final int x, final int y, final Color color) {
81         int address = getAddress(x, y);
82
83         bytes[address] = (byte) color.a;
84
85         address++;
86         bytes[address] = (byte) color.b;
87
88         address++;
89         bytes[address] = (byte) color.g;
90
91         address++;
92         bytes[address] = (byte) color.r;
93     }
94
95     public void drawRectangle(int x1, final int y1, int x2, final int y2,
96                               final Color color) {
97
98         if (x1 > x2) {
99             final int tmp = x1;
100             x1 = x2;
101             x2 = tmp;
102         }
103
104         if (y1 > y2) {
105             final int tmp = x1;
106             x1 = x2;
107             x2 = tmp;
108         }
109
110         for (int y = y1; y < y2; y++)
111             for (int x = x1; x < x2; x++)
112                 drawPixel(x, y, color);
113     }
114
115     public void fillColor(final Color color) {
116         int address = 0;
117         while (address < bytes.length) {
118             bytes[address] = (byte) color.a;
119             address++;
120
121             bytes[address] = (byte) color.b;
122             address++;
123
124             bytes[address] = (byte) color.g;
125             address++;
126
127             bytes[address] = (byte) color.r;
128             address++;
129         }
130     }
131
132     public int getAddress(int x, int y) {
133         if (x < 0)
134             x = 0;
135
136         if (x >= width)
137             x = width - 1;
138
139         if (y < 0)
140             y = 0;
141
142         if (y >= height)
143             y = height - 1;
144
145         return ((y * width) + x) * 4;
146     }
147 }