1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| public static BufferedImage mipmapGammaCorrected(BufferedImage src, int level) { if (level < 1) { throw new IllegalArgumentException(); }
for (int i = 0; i < level; i++) { BufferedImage tmp = mipmapGammaCorrected(src); if (i != 0) src.flush(); src = tmp; } return src; }
public static BufferedImage mipmapGammaCorrected(BufferedImage src) { int wSrc = src.getWidth(); int hSrc = src.getHeight();
if (wSrc % 2 != 0 || hSrc % 2 != 0) { throw new IllegalStateException("dimensions must be multiple of 2"); }
int wDst = wSrc / 2; int hDst = hSrc / 2;
int[] argbFull = src.getRGB(0, 0, wSrc, hSrc, null, 0, wSrc);
int type = BufferedImage.TYPE_INT_RGB; if (src.getAlphaRaster() != null) { type = BufferedImage.TYPE_INT_ARGB;
int[] alphaFull = src.getAlphaRaster().getPixels(0, 0, wSrc, hSrc, (int[]) null); for (int i = 0; i < alphaFull.length; i++) { argbFull[i] = (alphaFull[i] << 24) | (argbFull[i] & 0x00FFFFFF); } }
BufferedImage half = new BufferedImage(wDst, hDst, type);
int[] argbHalf = new int[argbFull.length >>> 2];
for (int y = 0; y < hDst; y++) { for (int x = 0; x < wDst; x++) { int p0 = argbFull[((y << 1) | 0) * wSrc + ((x << 1) | 0)]; int p1 = argbFull[((y << 1) | 1) * wSrc + ((x << 1) | 0)]; int p2 = argbFull[((y << 1) | 1) * wSrc + ((x << 1) | 1)]; int p3 = argbFull[((y << 1) | 0) * wSrc + ((x << 1) | 1)];
int a = gammaCorrectedAverage(p0, p1, p2, p3, 24); int r = gammaCorrectedAverage(p0, p1, p2, p3, 16); int g = gammaCorrectedAverage(p0, p1, p2, p3, 8); int b = gammaCorrectedAverage(p0, p1, p2, p3, 0);
argbHalf[y * wDst + x] = (a << 24) | (r << 16) | (g << 8) | (b << 0); } }
half.setRGB(0, 0, wDst, hDst, argbHalf, 0, wDst); if (type == BufferedImage.TYPE_INT_ARGB) { int[] alpha = new int[argbHalf.length]; for (int i = 0; i < alpha.length; i++) alpha[i] = (argbHalf[i] >> 24) & 0xFF; half.getAlphaRaster().setPixels(0, 0, wDst, hDst, alpha); }
return half; }
static int gammaCorrectedAverage(int a, int b, int c, int d, int shift) { float x = ((a >> shift) & 0xFF) / 255.0f; float y = ((b >> shift) & 0xFF) / 255.0f; float z = ((c >> shift) & 0xFF) / 255.0f; float w = ((d >> shift) & 0xFF) / 255.0f;
float e = x * x + y * y + z * z + w * w; e = (float) Math.sqrt(e * 0.25f); return (int) (e * 255.0f); } |