2 * Sixth - System for data storage, computation, exploration and interaction.
3 * Copyright ©2012-2016, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
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.
10 package eu.svjatoslav.sixth.e3d.renderer.raster.texture;
12 import eu.svjatoslav.sixth.e3d.gui.RenderingContext;
15 import java.awt.image.BufferedImage;
16 import java.awt.image.DataBufferByte;
17 import java.awt.image.WritableRaster;
19 public class Texture {
21 public final TextureBitmap primaryBitmap;
22 public final java.awt.Graphics2D graphics;
23 TextureBitmap[] upSampled;
24 TextureBitmap[] downSampled = new TextureBitmap[8];
26 public Texture(final int width, final int height, final int maxUpscale) {
27 upSampled = new TextureBitmap[maxUpscale];
29 final BufferedImage bufferedImage = new BufferedImage(width, height,
30 RenderingContext.bufferedImageType);
32 final WritableRaster raster = bufferedImage.getRaster();
33 final DataBufferByte dbi = (DataBufferByte) raster.getDataBuffer();
34 graphics = (Graphics2D) bufferedImage.getGraphics();
36 graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
37 RenderingHints.VALUE_ANTIALIAS_ON);
39 graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
40 RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
42 primaryBitmap = new TextureBitmap(width, height, dbi.getData(), 1);
45 public int detectDownscaleFactorForZoom(final double zoom) {
47 for (int i = 0; i < downSampled.length; i++) {
53 return downSampled.length - 1;
56 public int detectUpscaleFactorForZoom(final double zoom) {
58 for (int i = 0; i < upSampled.length; i++) {
64 return upSampled.length - 1;
67 public TextureBitmap downscaleBitmap(final TextureBitmap originalBitmap) {
68 int newWidth = originalBitmap.width / 2;
69 int newHeight = originalBitmap.height / 2;
71 // Enforce minimum width and height
77 final TextureBitmap downScaled = new TextureBitmap(newWidth, newHeight,
78 originalBitmap.multiplicationFactor / 2d);
80 final ColorAccumulator accumulator = new ColorAccumulator();
82 for (int y = 0; y < newHeight; y++)
83 for (int x = 0; x < newWidth; x++) {
85 accumulator.accumulate(originalBitmap, x * 2, y * 2);
86 accumulator.accumulate(originalBitmap, (x * 2) + 1, y * 2);
87 accumulator.accumulate(originalBitmap, x * 2, (y * 2) + 1);
89 .accumulate(originalBitmap, (x * 2) + 1, (y * 2) + 1);
90 accumulator.storeResult(downScaled, x, y);
96 public TextureBitmap getDownscaledBitmap(final int scaleFactor) {
97 if (downSampled[scaleFactor] == null) {
99 TextureBitmap largerBitmap;
100 if (scaleFactor == 0)
101 largerBitmap = primaryBitmap;
103 largerBitmap = getDownscaledBitmap(scaleFactor - 1);
105 downSampled[scaleFactor] = downscaleBitmap(largerBitmap);
108 return downSampled[scaleFactor];
111 public TextureBitmap getUpscaledBitmap(final int scaleFactor) {
112 if (upSampled[scaleFactor] == null) {
114 TextureBitmap smallerBitmap;
115 if (scaleFactor == 0)
116 smallerBitmap = primaryBitmap;
118 smallerBitmap = getUpscaledBitmap(scaleFactor - 1);
120 upSampled[scaleFactor] = upscaleBitmap(smallerBitmap);
123 return upSampled[scaleFactor];
126 public TextureBitmap getZoomedBitmap(final double zoomLevel) {
129 final int downscaleFactor = detectDownscaleFactorForZoom(zoomLevel);
130 return getDownscaledBitmap(downscaleFactor);
131 } else if (zoomLevel > 2) {
132 final int upscaleFactor = detectUpscaleFactorForZoom(zoomLevel);
134 if (upscaleFactor < 0)
135 return primaryBitmap;
137 return getUpscaledBitmap(upscaleFactor);
140 // System.out.println(zoomLevel);
141 return primaryBitmap;
144 public void resetResampledBitmapCache() {
145 for (int i = 0; i < upSampled.length; i++)
148 for (int i = 0; i < downSampled.length; i++)
149 downSampled[i] = null;
152 public TextureBitmap upscaleBitmap(final TextureBitmap originalBitmap) {
153 final int newWidth = originalBitmap.width * 2;
154 final int newHeight = originalBitmap.height * 2;
156 final TextureBitmap upScaled = new TextureBitmap(newWidth, newHeight,
157 originalBitmap.multiplicationFactor * 2d);
159 final ColorAccumulator accumulator = new ColorAccumulator();
161 for (int y = 0; y < originalBitmap.height; y++)
162 for (int x = 0; x < originalBitmap.width; x++) {
164 accumulator.accumulate(originalBitmap, x, y);
165 accumulator.storeResult(upScaled, x * 2, y * 2);
168 accumulator.accumulate(originalBitmap, x, y);
169 accumulator.accumulate(originalBitmap, x + 1, y);
170 accumulator.storeResult(upScaled, (x * 2) + 1, y * 2);
173 accumulator.accumulate(originalBitmap, x, y);
174 accumulator.accumulate(originalBitmap, x, y + 1);
175 accumulator.storeResult(upScaled, x * 2, (y * 2) + 1);
178 accumulator.accumulate(originalBitmap, x, y);
179 accumulator.accumulate(originalBitmap, x + 1, y);
180 accumulator.accumulate(originalBitmap, x, y + 1);
181 accumulator.accumulate(originalBitmap, x + 1, y + 1);
182 accumulator.storeResult(upScaled, (x * 2) + 1, (y * 2) + 1);
188 public class ColorAccumulator {
189 public int r, g, b, a;
190 public int pixelCount = 0;
192 public void accumulate(final TextureBitmap bitmap, final int x,
194 int address = bitmap.getAddress(x, y);
196 a += bitmap.bytes[address] & 0xff;
199 b += bitmap.bytes[address] & 0xff;
202 g += bitmap.bytes[address] & 0xff;
205 r += bitmap.bytes[address] & 0xff;
210 public void reset() {
218 public void storeResult(final TextureBitmap bitmap, final int x,
220 int address = bitmap.getAddress(x, y);
222 bitmap.bytes[address] = (byte) (a / pixelCount);
225 bitmap.bytes[address] = (byte) (b / pixelCount);
228 bitmap.bytes[address] = (byte) (g / pixelCount);
231 bitmap.bytes[address] = (byte) (r / pixelCount);