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