Libraryless. Click here for Pure Java version (6331L/39K).
| 1 | import jdk.incubator.vector.*; | 
| 2 | |
| 3 | // TODO: image w/h not divisible by 8 | 
| 4 | |
| 5 | final sclass BWIntegralImage_doubleVectorized implements MakesBufferedImage, IBWIntegralImage {
 | 
| 6 | // dual logarithm of block size & corresponding int vector species | 
| 7 | replace blockShift with 3. | 
| 8 | replace species with IntVector.SPECIES_256. | 
| 9 | replace blockSize with (1 << blockShift). | 
| 10 | |
| 11 | int w, h; // actual image size | 
| 12 | int blockW, blockH; // width and height of block array | 
| 13 | Block[] blocks; | 
| 14 | ifdef BWIntegralImage_CountAccesses | 
| 15 | long accesses; | 
| 16 | endifdef | 
| 17 | |
| 18 |   sclass Block {
 | 
| 19 | int[] rowAndColSums = new[blockSize*2]; // length 16 | 
| 20 | int sum; | 
| 21 | int[] data; // length 64 if calculated | 
| 22 | } | 
| 23 | |
| 24 |   *() {}
 | 
| 25 |   *(File f) { this(loadImage2(f)); }
 | 
| 26 | |
| 27 |   *(MakesBufferedImage img) { this(toBufferedImage(img)); }
 | 
| 28 | |
| 29 |   *(BufferedImage image) ctex {
 | 
| 30 | alloc(image.getWidth(), image.getHeight()); | 
| 31 | |
| 32 | // Grab image | 
| 33 | // TODO: could use grayscale color model here (faster?) | 
| 34 | int[] data = new[w*h]; | 
| 35 | PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, w, h, data, 0, w); | 
| 36 | if (!pixelGrabber.grabPixels()) | 
| 37 |       fail("Could not grab pixels");
 | 
| 38 | |
| 39 | // for brightness of pixels, | 
| 40 | // for now we cheat by just using one of the channels | 
| 41 | |
| 42 | // calculate sums in each block | 
| 43 | |
| 44 | int iBlock = 0; | 
| 45 |     for by to blockH: {
 | 
| 46 | int iLine = (by << blockShift)*w; | 
| 47 |       for bx to blockW: {
 | 
| 48 | Block block = blocks[iBlock++]; | 
| 49 | int[] sums = block.rowAndColSums; | 
| 50 | |
| 51 | IntVector vColSums = by == 0 ? IntVector.zero(species) : IntVector.fromArray(species, getBlock(bx, by-1).rowAndColSums, blockSize); | 
| 52 | int[] leftSums = bx == 0 ? null : getBlock(bx-1, by).rowAndColSums; | 
| 53 | |
| 54 |         for (int y = 0; y < blockSize; y++) {
 | 
| 55 | IntVector v = IntVector.fromArray(species, data, y << blockShift); | 
| 56 | int leftSum = leftSums != null ? leftSums[y] : 0; | 
| 57 | sums[y] = v.reduceLanes(VectorOperators.ADD)+leftSum; | 
| 58 | v = v.add(leftSum); | 
| 59 | vColSums = vColSums.add(v); | 
| 60 | } | 
| 61 | vColSums.intoArray(sums, blockSize); | 
| 62 | block.sum = vColSums.reduceLanes(VectorOperators.ADD); | 
| 63 | } | 
| 64 | } | 
| 65 | } | 
| 66 | |
| 67 |   int blockSum(int bx, int by) {
 | 
| 68 | ret bx < 0 || by < 0 ? 0 : getBlock(bx, by).sum; | 
| 69 | } | 
| 70 | |
| 71 |   Block getBlock(int bx, int by) { ret blocks[by*blockW+bx]; }
 | 
| 72 | |
| 73 |   int[] getBlockData(int bx, int by) {
 | 
| 74 | Block block = getBlock(bx, by); | 
| 75 | if (block.data == null) | 
| 76 | calcData(bx, by, block); | 
| 77 | ret block.data; | 
| 78 | } | 
| 79 | |
| 80 |   void calcData(int bx, int by, Block block) {
 | 
| 81 | todo(); | 
| 82 | } | 
| 83 | |
| 84 |   private void alloc(int w, int h) {
 | 
| 85 | if ((w % blockSize) != 0 || (h % blockSize) != 0) | 
| 86 |       fail("Need image dimensions divisible by " + blockSize + ": " + w + "*" + h);
 | 
| 87 | |
| 88 | this.w = w; | 
| 89 | this.h = h; | 
| 90 | blockW = ratioRoundUp(w, blockSize); | 
| 91 | blockH = ratioRoundUp(h, blockSize); | 
| 92 | //int dataLength = blockSize*blockSize; | 
| 93 | blocks = repF_array Block(blockW*blockH, () -> new Block); | 
| 94 | } | 
| 95 | |
| 96 | // get sum value at x, y | 
| 97 | // pixels outside of image are considered black | 
| 98 |   public int getIIValue(int x, int y) {
 | 
| 99 | ifdef BWIntegralImage_CountAccesses | 
| 100 | ++accesses; | 
| 101 | endifdef | 
| 102 | if (x < 0 || y < 0 || x >= w || y >= h) ret 0; | 
| 103 | int idx = ((x & (blockSize-1)) << blockSize) | (y & (blockSize-1)); | 
| 104 | ret idx == 0 ? getBlock(x >> blockShift, y >> blockShift).sum | 
| 105 | : getBlockData(x >> blockShift, y >> blockShift)[idx]; | 
| 106 | } | 
| 107 | |
| 108 |   public double getPixelAverage(int x1, int y1, int x2, int y2) {
 | 
| 109 | int area = (x2-x1)*(y2-y1); | 
| 110 | ret doubleRatio(bwIntegralImage_sumRect(this, x1, y1, x2, y2), area); | 
| 111 | } | 
| 112 | |
| 113 |   int getPixel(int x, int y) {
 | 
| 114 | ret bwIntegralImage_sumRect(this, x, y, x+1, y+1); | 
| 115 | } | 
| 116 | |
| 117 |   int getPixel(Pt p) { ret getPixel(p.x, p.y); }
 | 
| 118 | |
| 119 |   public int getWidth() { ret w; }
 | 
| 120 |   public int getHeight() { ret h; }
 | 
| 121 | |
| 122 | // unoptimized | 
| 123 |   public BufferedImage getBufferedImage() {
 | 
| 124 | ret scaleDownUsingIntegralImageBW(this, w, h).getBufferedImage(); | 
| 125 | } | 
| 126 | } | 
Began life as a copy of #1030523
download show line numbers debug dex old transpilations
Travelled to 4 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt
No comments. add comment
| Snippet ID: | #1030531 | 
| Snippet name: | BWIntegralImage_doubleVectorized [pre-calcs 8x8 blocks using Vector API, dev.] | 
| Eternal ID of this version: | #1030531/25 | 
| Text MD5: | d2ebc86355a9d7ac84974072dc4b5104 | 
| Transpilation MD5: | ff645708e94ec500942aec9e96456eab | 
| Author: | stefan | 
| Category: | javax / imaging | 
| Type: | JavaX fragment (include) | 
| Public (visible to everyone): | Yes | 
| Archived (hidden from active list): | No | 
| Created/modified: | 2021-01-06 20:18:18 | 
| Source code size: | 4048 bytes / 126 lines | 
| Pitched / IR pitched: | No / No | 
| Views / Downloads: | 481 / 820 | 
| Version history: | 24 change(s) | 
| Referenced in: | [show references] |