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: | 263 / 549 |
Version history: | 24 change(s) |
Referenced in: | [show references] |