ResizeProcessor implements SinglebandImageProcessor<Float, FImage> { public static FImage zoom(FImage in, FImage dst, ResizeFilterFunction filterf) { final int dstWidth = dst.getWidth(); final int dstHeight = dst.getHeight(); final int srcWidth = in.getWidth(); final int srcHeight = in.getHeight(); final double xscale = (double) dstWidth / (double) srcWidth; final double yscale = (double) dstHeight / (double) srcHeight; final float[] work = new float[in.height]; final PixelContributions[] contribY = new PixelContributions[dstHeight]; for (int i = 0; i < contribY.length; i++) { contribY[i] = new PixelContributions(); } final float maxValue = in.max(); final double fwidth = filterf.getSupport(); if (yscale < 1.0) { double width = fwidth / yscale; double fscale = 1.0 / yscale; if (width <= .5) { width = .5 + 1.0e-6; fscale = 1.0; } for (int i = 0; i < dstHeight; i++) { contribY[i].contributions = new PixelContribution[(int) (width * 2.0 + 1)]; contribY[i].numberOfContributors = 0; final double center = i / yscale; final int left = (int) Math.ceil(center - width); final int right = left + contribY[i].contributions.length - 1; double density = 0.0; for (int j = left; j <= right; j++) { double weight = center - j; weight = filterf.filter(weight / fscale) / fscale; int n; if (j < 0) { n = -j; } else if (j >= srcHeight) { n = (srcHeight - j) + srcHeight - 1; } else { n = j; } if (n >= srcHeight) { n = n % srcHeight; } else if (n < 0) { n = srcHeight - 1; } final int k = contribY[i].numberOfContributors++; contribY[i].contributions[k] = new PixelContribution(); contribY[i].contributions[k].pixel = n; contribY[i].contributions[k].weight = weight; density += weight; } if ((density != 0.0) && (density != 1.0)) { density = 1.0 / density; for (int k = 0; k < contribY[i].numberOfContributors; k++) { contribY[i].contributions[k].weight *= density; } } } } else { for (int i = 0; i < dstHeight; ++i) { contribY[i].contributions = new PixelContribution[(int) (fwidth * 2 + 1)]; contribY[i].numberOfContributors = 0; final double center = i / yscale; final double left = Math.ceil(center - fwidth); final double right = left + contribY[i].contributions.length - 1; for (int j = (int) left; j <= right; ++j) { double weight = center - j; weight = filterf.filter(weight); int n; if (j < 0) { n = -j; } else if (j >= srcHeight) { n = (srcHeight - j) + srcHeight - 1; } else { n = j; } if (n >= srcHeight) { n = n % srcHeight; } else if (n < 0) { n = srcHeight - 1; } final int k = contribY[i].numberOfContributors++; contribY[i].contributions[k] = new PixelContribution(); contribY[i].contributions[k].pixel = n; contribY[i].contributions[k].weight = weight; } } } for (int xx = 0; xx < dstWidth; xx++) { final PixelContributions contribX = new PixelContributions(); calc_x_contrib(contribX, xscale, fwidth, dst.width, in.width, filterf, xx); for (int k = 0; k < srcHeight; k++) { double weight = 0.0; boolean bPelDelta = false; final double pel = in.pixels[k][contribX.contributions[0].pixel]; for (int j = 0; j < contribX.numberOfContributors; j++) { final double pel2 = j == 0 ? pel : in.pixels[k][contribX.contributions[j].pixel]; if (pel2 != pel) { bPelDelta = true; } weight += pel2 * contribX.contributions[j].weight; } weight = bPelDelta ? Math.round(weight * 255) / 255f : pel; if (weight < 0) { weight = 0; } else if (weight > maxValue) { weight = maxValue; } work[k] = (float) weight; } for (int i = 0; i < dstHeight; i++) { double weight = 0.0; boolean bPelDelta = false; final double pel = work[contribY[i].contributions[0].pixel]; for (int j = 0; j < contribY[i].numberOfContributors; j++) { final double pel2 = j == 0 ? pel : work[contribY[i].contributions[j].pixel]; if (pel2 != pel) { bPelDelta = true; } weight += pel2 * contribY[i].contributions[j].weight; } weight = bPelDelta ? Math.round(weight * 255) / 255f : pel; if (weight < 0) { weight = 0; } else if (weight > maxValue) { weight = maxValue; } dst.pixels[i][xx] = (float) weight; } } return dst; } ResizeProcessor(Mode mode);  ResizeProcessor(float amount, ResizeFilterFunction ff);  ResizeProcessor(float newX, float newY, ResizeFilterFunction ff);  ResizeProcessor(float amount);  ResizeProcessor(float newX, float newY);  ResizeProcessor(int maxSize);  ResizeProcessor(int maxSizeArea, boolean area);  ResizeProcessor(int newX, int newY, boolean aspectRatio);  ResizeProcessor(int newX, int newY, boolean aspectRatio, ResizeFilterFunction filterf); @Override void processImage(FImage image); void setFilterFunction(ResizeFilterFunction filterFunction); static FImage resizeMax(FImage image, int maxDim, ResizeFilterFunction filterf); static FImage resizeMaxArea(FImage image, int maxArea, ResizeFilterFunction filterf); static FImage resizeMax(FImage image, int maxDim); static FImage resizeMaxArea(FImage image, int maxArea); static I doubleSize(I image); static FImage doubleSize(FImage image); static I halfSize(I image); static FImage halfSize(FImage image); static FImage resample(FImage in, int newX, int newY); static FImage resample(FImage in, int newX, int newY, boolean aspect); static FImage resample(FImage in, int newX, int newY, boolean aspect, ResizeFilterFunction filterf); static FImage zoomInplace(FImage in, int newX, int newY); static FImage zoomInplace(FImage in, int newX, int newY, ResizeFilterFunction filterf); static FImage zoom(FImage in, FImage dst, ResizeFilterFunction filterf); static FImage zoom(FImage in, Rectangle inRect, FImage dst, Rectangle dstRect); static FImage zoom(FImage in, Rectangle inRect, FImage dst, Rectangle dstRect, ResizeFilterFunction filterf); static final ResizeFilterFunction DEFAULT_FILTER; }
@Test public void testBoundedZoom() throws Exception { final FImage image = ImageUtilities.readF(ResizeProcessorTest.class .getResourceAsStream("/org/openimaj/image/data/sinaface.jpg")); FImage imageOut = new FImage(200, 100); final ResizeFilterFunction filter = new BSplineFilter(); final Rectangle inLoc = new Rectangle(30f, 30f, 100f, 100f); Rectangle outLoc = imageOut.getBounds(); ResizeProcessor.zoom( image, inLoc, imageOut, outLoc, filter ); imageOut = new FImage(20, 20); outLoc = imageOut.getBounds(); ResizeProcessor.zoom( image, inLoc, imageOut, outLoc, filter ); for (int i = 0; i < 10000; i++) { ResizeProcessor.zoom( image, inLoc, imageOut, outLoc, filter ); } for (int i = 0; i < 10000; i++) { final FImage imageExtracted = image.extractROI(inLoc); ResizeProcessor.zoom( imageExtracted, imageOut, filter ); } }