final double twidth = tx2 - tx1;
final double theight = ty2 - ty1;
+ final double txStep = twidth / realWidth;
+ final double tyStep = theight / realWidth;
+
+ double tx = tx1 + txStep * (x1 - realX1);
+ double ty = ty1 + tyStep * (x1 - realX1);
+
+ final int[] texPixels = textureBitmap.pixels;
+ final int texW = textureBitmap.width;
+ final int texH = textureBitmap.height;
+ final int texWMinus1 = texW - 1;
+ final int texHMinus1 = texH - 1;
+
for (int x = x1; x < x2; x++) {
- final double distance = x - realX1;
+ int itx = (int) tx;
+ int ity = (int) ty;
+
+ if (itx < 0) itx = 0;
+ else if (itx > texWMinus1) itx = texWMinus1;
+
+ if (ity < 0) ity = 0;
+ else if (ity > texHMinus1) ity = texHMinus1;
+
+ final int srcPixel = texPixels[ity * texW + itx];
+ final int srcAlpha = (srcPixel >> 24) & 0xff;
+
+ if (srcAlpha != 0) {
+ if (srcAlpha == 255) {
+ renderBufferPixels[renderBufferOffset] = srcPixel;
+ } else {
+ final int backgroundAlpha = 255 - srcAlpha;
+
+ final int srcR = (srcPixel >> 16) & 0xff;
+ final int srcG = (srcPixel >> 8) & 0xff;
+ final int srcB = srcPixel & 0xff;
- final double tx = tx1 + ((twidth * distance) / realWidth);
- final double ty = ty1 + ((theight * distance) / realWidth);
+ final int destPixel = renderBufferPixels[renderBufferOffset];
+ final int destR = (destPixel >> 16) & 0xff;
+ final int destG = (destPixel >> 8) & 0xff;
+ final int destB = destPixel & 0xff;
- final int textureOffset = textureBitmap.getAddress((int) tx,
- (int) ty);
+ final int r = ((destR * backgroundAlpha) + (srcR * srcAlpha)) / 256;
+ final int g = ((destG * backgroundAlpha) + (srcG * srcAlpha)) / 256;
+ final int b = ((destB * backgroundAlpha) + (srcB * srcAlpha)) / 256;
- textureBitmap.drawPixel(textureOffset, renderBufferPixels,
- renderBufferOffset);
+ renderBufferPixels[renderBufferOffset] = (r << 16) | (g << 8) | b;
+ }
+ }
+ tx += txStep;
+ ty += tyStep;
renderBufferOffset++;
}
final TextureBitmap downScaled = new TextureBitmap(newWidth, newHeight,
originalBitmap.multiplicationFactor / 2d);
- final ColorAccumulator accumulator = new ColorAccumulator();
+ final int[] srcPixels = originalBitmap.pixels;
+ final int[] dstPixels = downScaled.pixels;
+ final int srcW = originalBitmap.width;
+ final int srcH = originalBitmap.height;
+ final int srcWMinus1 = srcW - 1;
+ final int srcHMinus1 = srcH - 1;
+
+ for (int y = 0; y < newHeight; y++) {
+ final int srcYBase = y * 2;
+ final int srcY1 = Math.min(srcYBase, srcHMinus1);
+ final int srcY2 = Math.min(srcYBase + 1, srcHMinus1);
+ final int row1Offset = srcY1 * srcW;
+ final int row2Offset = srcY2 * srcW;
- for (int y = 0; y < newHeight; y++)
for (int x = 0; x < newWidth; x++) {
- accumulator.reset();
- accumulator.accumulate(originalBitmap, x * 2, y * 2);
- accumulator.accumulate(originalBitmap, (x * 2) + 1, y * 2);
- accumulator.accumulate(originalBitmap, x * 2, (y * 2) + 1);
- accumulator
- .accumulate(originalBitmap, (x * 2) + 1, (y * 2) + 1);
- accumulator.storeResult(downScaled, x, y);
+ final int srcXBase = x * 2;
+ final int srcX1 = Math.min(srcXBase, srcWMinus1);
+ final int srcX2 = Math.min(srcXBase + 1, srcWMinus1);
+
+ final int p0 = srcPixels[row1Offset + srcX1];
+ final int p1 = srcPixels[row1Offset + srcX2];
+ final int p2 = srcPixels[row2Offset + srcX1];
+ final int p3 = srcPixels[row2Offset + srcX2];
+
+ final int a = (((p0 >>> 24) + (p1 >>> 24) + (p2 >>> 24) + (p3 >>> 24)) >> 2);
+ final int r = ((((p0 >> 16) & 0xff) + ((p1 >> 16) & 0xff) + ((p2 >> 16) & 0xff) + ((p3 >> 16) & 0xff)) >> 2);
+ final int g = ((((p0 >> 8) & 0xff) + ((p1 >> 8) & 0xff) + ((p2 >> 8) & 0xff) + ((p3 >> 8) & 0xff)) >> 2);
+ final int b = (((p0 & 0xff) + (p1 & 0xff) + (p2 & 0xff) + (p3 & 0xff)) >> 2);
+
+ dstPixels[y * newWidth + x] = (a << 24) | (r << 16) | (g << 8) | b;
}
+ }
return downScaled;
}
* @return The upscaled bitmap
*/
public TextureBitmap upscaleBitmap(final TextureBitmap originalBitmap) {
- final int newWidth = originalBitmap.width * 2;
- final int newHeight = originalBitmap.height * 2;
+ final int srcW = originalBitmap.width;
+ final int srcH = originalBitmap.height;
+ final int newWidth = srcW * 2;
+ final int newHeight = srcH * 2;
+ final int srcWMinus1 = srcW - 1;
+ final int srcHMinus1 = srcH - 1;
final TextureBitmap upScaled = new TextureBitmap(newWidth, newHeight,
originalBitmap.multiplicationFactor * 2d);
- final ColorAccumulator accumulator = new ColorAccumulator();
-
- for (int y = 0; y < originalBitmap.height; y++)
- for (int x = 0; x < originalBitmap.width; x++) {
- accumulator.reset();
- accumulator.accumulate(originalBitmap, x, y);
- accumulator.storeResult(upScaled, x * 2, y * 2);
-
- accumulator.reset();
- accumulator.accumulate(originalBitmap, x, y);
- accumulator.accumulate(originalBitmap, x + 1, y);
- accumulator.storeResult(upScaled, (x * 2) + 1, y * 2);
-
- accumulator.reset();
- accumulator.accumulate(originalBitmap, x, y);
- accumulator.accumulate(originalBitmap, x, y + 1);
- accumulator.storeResult(upScaled, x * 2, (y * 2) + 1);
-
- accumulator.reset();
- accumulator.accumulate(originalBitmap, x, y);
- accumulator.accumulate(originalBitmap, x + 1, y);
- accumulator.accumulate(originalBitmap, x, y + 1);
- accumulator.accumulate(originalBitmap, x + 1, y + 1);
- accumulator.storeResult(upScaled, (x * 2) + 1, (y * 2) + 1);
+ final int[] src = originalBitmap.pixels;
+ final int[] dst = upScaled.pixels;
+
+ for (int y = 0; y < srcH; y++) {
+ final int srcRowOffset = y * srcW;
+ final int nextRowOffset = Math.min(y + 1, srcHMinus1) * srcW;
+ final int dstRow0Offset = (y * 2) * newWidth;
+ final int dstRow1Offset = (y * 2 + 1) * newWidth;
+
+ for (int x = 0; x < srcW; x++) {
+ final int nx = Math.min(x + 1, srcWMinus1);
+
+ final int p00 = src[srcRowOffset + x];
+ final int p10 = src[srcRowOffset + nx];
+ final int p01 = src[nextRowOffset + x];
+ final int p11 = src[nextRowOffset + nx];
+
+ dst[dstRow0Offset + x * 2] = p00;
+ dst[dstRow0Offset + x * 2 + 1] = avg2(p00, p10);
+ dst[dstRow1Offset + x * 2] = avg2(p00, p01);
+ dst[dstRow1Offset + x * 2 + 1] = avg4(p00, p10, p01, p11);
}
+ }
return upScaled;
}
+ private static int avg2(final int p0, final int p1) {
+ return (((((p0 >>> 24) + (p1 >>> 24)) >> 1) << 24)
+ | (((((p0 >> 16) & 0xff) + ((p1 >> 16) & 0xff)) >> 1) << 16)
+ | (((((p0 >> 8) & 0xff) + ((p1 >> 8) & 0xff)) >> 1) << 8)
+ | (((p0 & 0xff) + (p1 & 0xff)) >> 1));
+ }
+
+ private static int avg4(final int p0, final int p1, final int p2, final int p3) {
+ return ((((p0 >>> 24) + (p1 >>> 24) + (p2 >>> 24) + (p3 >>> 24)) >> 2) << 24)
+ | (((((p0 >> 16) & 0xff) + ((p1 >> 16) & 0xff) + ((p2 >> 16) & 0xff) + ((p3 >> 16) & 0xff)) >> 2) << 16)
+ | (((((p0 >> 8) & 0xff) + ((p1 >> 8) & 0xff) + ((p2 >> 8) & 0xff) + ((p3 >> 8) & 0xff)) >> 2) << 8)
+ | (((p0 & 0xff) + (p1 & 0xff) + (p2 & 0xff) + (p3 & 0xff)) >> 2);
+ }
+
/**
* A helper class that accumulates color values for a given area of a bitmap.
*/