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