import jdk.incubator.vector.*; final sclass BWIntegralImage_vectorized implements MakesBufferedImage, IBWIntegralImage { int w, h; int vecShift; // vector size used as dual log int[] data; // 1 entry per pixel ifdef BWIntegralImage_CountAccesses long accesses; endifdef *() {} *(File f) { this(loadImage2(f)); } *(MakesBufferedImage img) { this(toBufferedImage(img)); } //*(BufferedImage img) { this(BWImage(img)); } *(BufferedImage image) ctex { alloc(image.getWidth(), image.getHeight()); // Just grab directly into data array PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, w, h, data, 0, w); if (!pixelGrabber.grabPixels()) fail("Could not grab pixels"); VectorSpecies species = IntVector.SPECIES_PREFERRED; vecShift = dualLog(species.length()); int upperBound = species.loopBound(w); // for brightness of pixels, // for now we cheat by just using one of the channels // first row int i = 0, sum = 0; for (; i < upperBound; i += species.length()) { IntVector v = IntVector.fromArray(species, data, i); v = v.and(255).add(sum); v.intoArray(data, i); sum += v.reduceLanes(VectorOperators.ADD); } for (; i < w; i++) data[i] = (data[i] & 255) + sum; // subsequent rows int i = w; for (int y = 1; y < h; y++) { sum = 0; int x = 0; for (; x < upperBound; x += species.length(), i += species.length()) { IntVector v = IntVector.fromArray(species, data, i); IntVector v_last = IntVector.fromArray(species, data, i-w); v = v.and(255).add(v_last).add(sum); v.intoArray(data, i); sum += v.reduceLanes(VectorOperators.ADD); } for (; x < w; x++, i++) data[i] = (data[i] & 255) + sum; } } private void alloc(int w, int h) { this.w = w; this.h = h; if (w*h > 8*1024*1024) fail("Image too large (more than 8 MP): " + w + "*" + h); data = new int[w*h]; } // pixels outside of image are considered black int get(int x, int y) { ifdef BWIntegralImage_CountAccesses ++accesses; endifdef ret x < 0 || y < 0 || x >= w || y >= h ? 0 : data[min(y, h-1)*w+min(x, w-1)]; } public double getPixelAverage(int x1, int y1, int x2, int y2) { int area = (x2-x1)*(y2-y1); ret doubleRatio(bwIntegralImage_sumRect(this, x1, y1, x2, y2), area); } int getPixel(int x, int y) { ret bwIntegralImage_sumRect(this, x, y, x+1, y+1); } int getPixel(Pt p) { ret getPixel(p.x, p.y); } public int getWidth() { ret w; } public int getHeight() { ret h; } // unoptimized public BufferedImage getBufferedImage() { ret scaleDownUsingIntegralImageBW(this, w).getBufferedImage(); } }