[libbluray-devel] BDGraphics: implement fast bilinear image scaling
Ian Curtis
git at videolan.org
Thu Apr 3 12:19:50 CEST 2014
libbluray | branch: master | Ian Curtis <i.curtis at gmail.com> | Thu Apr 3 13:10:14 2014 +0300| [3ee8d568655297f90282d9d99fe63b276126273d] | committer: hpi1
BDGraphics: implement fast bilinear image scaling
> http://git.videolan.org/gitweb.cgi/libbluray.git/?a=commit;h=3ee8d568655297f90282d9d99fe63b276126273d
---
.../bdj/java/java/awt/BDGraphicsBase.java | 120 ++++++++++++++++++--
1 file changed, 110 insertions(+), 10 deletions(-)
diff --git a/src/libbluray/bdj/java/java/awt/BDGraphicsBase.java b/src/libbluray/bdj/java/java/awt/BDGraphicsBase.java
index 8303e18..7bdaefa 100644
--- a/src/libbluray/bdj/java/java/awt/BDGraphicsBase.java
+++ b/src/libbluray/bdj/java/java/awt/BDGraphicsBase.java
@@ -1047,16 +1047,7 @@ abstract class BDGraphicsBase extends Graphics2D implements ConstrainableGraphic
// resize if needed
if (dw != sw || dh != sh) {
- BDImageConsumer scaledImage = new BDImageConsumer(null);
- AreaAveragingScaleFilter scaleFilter =
- new AreaAveragingScaleFilter(dw, dh);
- scaleFilter = (AreaAveragingScaleFilter)scaleFilter.getFilterInstance(scaledImage);
- scaleFilter.setDimensions(sw, sh);
- scaleFilter.setPixels(0, 0, sw, sh,
- bdImage.getColorModel(), rgbArray,
- sx + sy * bdImage.width, bdImage.width);
- scaleFilter.imageComplete(ImageConsumer.STATICIMAGEDONE);
- rgbArray = scaledImage.getBdBackBuffer();
+ rgbArray = resizeBilinear(rgbArray, (sy * stride) + sx, stride, sw, sh, dw, dh);
sx = 0;
sy = 0;
stride = dw;
@@ -1081,6 +1072,115 @@ abstract class BDGraphicsBase extends Graphics2D implements ConstrainableGraphic
return true;
}
+ /**
+ * Bilinear resize ARGB image.
+ *
+ * @param pixels Source image pixels.
+ * @param sw Source image width.
+ * @param sh Source image height.
+ * @param dw New width.
+ * @param dh New height.
+ * @return New array with size dw * dh.
+ */
+ private int[] resizeBilinear(int[] pixels, int offset, int scansize, int sw, int sh, int dw, int dh) {
+
+ int[] outImage = new int[dw * dh];
+
+ if (sw == 1 && sh == 1) {
+ Arrays.fill(outImage, pixels[offset]);
+ return outImage;
+ }
+
+ // a quick hack for 1D arrays, stretch them to make them 2D
+ if (sw == 1) {
+ int[] temp = new int[2 * sh];
+
+ for (int i = 0; i < sw * sh; i++) {
+ temp[(i * 2) + 0] = pixels[offset + i];
+ temp[(i * 2) + 1] = pixels[offset + i];
+ }
+
+ pixels = temp;
+ offset = 0;
+ sw = 2;
+
+ } else if (sh == 1) {
+ int[] temp = new int[sw * 2];
+
+ System.arraycopy(pixels, offset, temp, 0, sw);
+ System.arraycopy(pixels, offset, temp, sw, sw);
+
+ pixels = temp;
+ offset = 0;
+ sh = 2;
+ }
+
+ int a, b, c, d, x, y, index;
+ float x_ratio = ((float)(sw - 1)) / dw;
+ float y_ratio = ((float)(sh - 1)) / dh;
+ float x_diff, y_diff, blue, red, green, alpha;
+ int position = 0;
+ for (int i = 0; i < dh; i++) {
+ for (int j = 0; j < dw; j++) {
+ x = (int)(x_ratio * j);
+ y = (int)(y_ratio * i);
+ x_diff = (x_ratio * j) - x;
+ y_diff = (y_ratio * i) - y;
+ index = (y * scansize + x);
+ index += offset;
+
+ a = pixels[index];
+ b = pixels[index + 1];
+ c = pixels[index + scansize];
+ d = pixels[index + scansize + 1];
+
+ int aA = (a >> 24) & 0xff;
+ int bA = (b >> 24) & 0xff;
+ int cA = (c >> 24) & 0xff;
+ int dA = (d >> 24) & 0xff;
+
+ // blue element
+ // Yb = Ab(1-w)(1-h) + Bb(w)(1-h) + Cb(h)(1-w) + Db(wh)
+ blue = (a & 0xff) * (1-x_diff) * (1-y_diff) * aA +
+ (b & 0xff) * x_diff * (1-y_diff) * bA +
+ (c & 0xff) * (1-x_diff) * y_diff * cA +
+ (d & 0xff) * x_diff * y_diff * dA;
+
+ // green element
+ // Yg = Ag(1-w)(1-h) + Bg(w)(1-h) + Cg(h)(1-w) + Dg(wh)
+ green = ((a >> 8) & 0xff) * (1-x_diff) * (1-y_diff) * aA +
+ ((b >> 8) & 0xff) * x_diff * (1-y_diff) * bA +
+ ((c >> 8) & 0xff) * (1-x_diff) * y_diff * cA +
+ ((d >> 8) & 0xff) * x_diff * y_diff * dA;
+
+ // red element
+ // Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
+ red = ((a >> 16) & 0xff) * (1-x_diff) * (1-y_diff) * aA +
+ ((b >> 16) & 0xff) * x_diff * (1-y_diff) * bA +
+ ((c >> 16) & 0xff) * (1-x_diff) * y_diff * cA +
+ ((d >> 16) & 0xff) * x_diff * y_diff * dA;
+
+ // alpha element
+ // Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
+ alpha = ((a >> 24) & 0xff) * (1-x_diff) * (1-y_diff) +
+ ((b >> 24) & 0xff) * x_diff * (1-y_diff) +
+ ((c >> 24) & 0xff) * (1-x_diff) * y_diff +
+ ((d >> 24) & 0xff) * x_diff * y_diff;
+
+ blue /= alpha;
+ green /= alpha;
+ red /= alpha;
+
+ outImage[position++] =
+ ((((int)alpha) << 24) & 0xff000000) |
+ ((((int)red ) << 16) & 0x00ff0000) |
+ ((((int)green) << 8 ) & 0x0000ff00) |
+ ((((int)blue ) ) & 0x000000ff);
+ }
+ }
+ return outImage;
+ }
+
public Stroke getStroke() {
logger.unimplemented("getStroke");
throw new Error();
More information about the libbluray-devel
mailing list