/* * Copyright (c) 2011-2016, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package boofcv.alg.interpolate.impl; import boofcv.misc.AutoTypeImage; import boofcv.misc.CodeGeneratorBase; import boofcv.misc.CodeGeneratorUtil; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; /** * Generator for bilinear interpolation * * @author Peter Abeles */ public class GenerateBilinearRectangle extends CodeGeneratorBase { String className; PrintStream out; AutoTypeImage image; @Override public void generate() throws FileNotFoundException { createType(AutoTypeImage.F32); createType(AutoTypeImage.U8); createType(AutoTypeImage.S16); } private void createType( AutoTypeImage type ) throws FileNotFoundException { className = "BilinearRectangle_"+type.name(); image = type; createFile(); } private void createFile() throws FileNotFoundException { out = new PrintStream(new FileOutputStream(className + ".java")); printPreamble(); printTheRest(); out.println("}"); } private void printPreamble() { out.print(CodeGeneratorUtil.copyright); out.print("package boofcv.alg.interpolate.impl;\n"); out.println(); out.print("import boofcv.alg.interpolate.InterpolateRectangle;\n" + "import boofcv.struct.image."+image.getSingleBandName()+";\n"); if( image.getSingleBandName().compareTo("GrayF32") != 0 ) out.println("import boofcv.struct.image.GrayF32;"); out.println(); out.println(); out.print("/**\n" + " * <p>\n" + " * Performs bilinear interpolation to extract values between pixels in an image.\n" + " * Image borders are detected and handled appropriately.\n" + " * </p>\n" + " *\n" + " * <p>\n" + " * NOTE: This code was automatically generated using {@link GenerateBilinearRectangle}.\n" + " * </p>\n" + " *\n" + " * @author Peter Abeles\n" + " */\n" + "public class "+className+" implements InterpolateRectangle<"+image.getSingleBandName()+"> {\n" + "\n" + "\tprivate "+image.getSingleBandName()+" orig;\n" + "\n" + "\tprivate "+image.getDataType()+" data[];\n" + "\tprivate int stride;\n" + "\n" + "\tpublic "+className+"("+image.getSingleBandName()+" image) {\n" + "\t\tsetImage(image);\n" + "\t}\n" + "\n" + "\tpublic "+className+"() {\n" + "\t}\n\n"); } private void printTheRest() { String bitWise = image.getBitWise(); out.print("\t@Override\n" + "\tpublic void setImage("+image.getSingleBandName()+" image) {\n" + "\t\tthis.orig = image;\n" + "\t\tthis.data = orig.data;\n" + "\t\tthis.stride = orig.getStride();\n" + "\t}\n" + "\n" + "\t@Override\n" + "\tpublic "+image.getSingleBandName()+" getImage() {\n" + "\t\treturn orig;\n" + "\t}\n" + "\n" + "\t@Override\n" + "\tpublic void region(float tl_x, float tl_y, GrayF32 output ) {\n" + "\t\tif( tl_x < 0 || tl_y < 0 || tl_x + output.width > orig.width || tl_y + output.height > orig.height ) {\n" + "\t\t\tthrow new IllegalArgumentException(\"Region is outside of the image\");\n" + "\t\t}\n" + "\t\tint xt = (int) tl_x;\n" + "\t\tint yt = (int) tl_y;\n" + "\t\tfloat ax = tl_x - xt;\n" + "\t\tfloat ay = tl_y - yt;\n" + "\n" + "\t\tfloat bx = 1.0f - ax;\n" + "\t\tfloat by = 1.0f - ay;\n" + "\n" + "\t\tfloat a0 = bx * by;\n" + "\t\tfloat a1 = ax * by;\n" + "\t\tfloat a2 = ax * ay;\n" + "\t\tfloat a3 = bx * ay;\n" + "\n" + "\t\tint regWidth = output.width;\n" + "\t\tint regHeight = output.height;\n" + "\t\tfinal float results[] = output.data;\n" + "\t\tboolean borderRight = false;\n" + "\t\tboolean borderBottom = false;\n" + "\n" + "\t\t// make sure it is in bounds or if its right on the image border\n" + "\t\tif (xt + regWidth >= orig.width || yt + regHeight >= orig.height) {\n" + "\t\t\tif( (xt + regWidth > orig.width || yt + regHeight > orig.height) )\n" + "\t\t\t\tthrow new IllegalArgumentException(\"requested region is out of bounds\");\n" + "\t\t\tif( xt+regWidth == orig.width ) {\n" + "\t\t\t\tregWidth--;\n" + "\t\t\t\tborderRight = true;\n" + "\t\t\t}\n" + "\t\t\tif( yt+regHeight == orig.height ) {\n" + "\t\t\t\tregHeight--;\n" + "\t\t\t\tborderBottom = true;\n" + "\t\t\t}\n" + "\t\t}\n" + "\n" + "\t\t// perform the interpolation while reducing the number of times the image needs to be accessed\n" + "\t\tfor (int i = 0; i < regHeight; i++) {\n" + "\t\t\tint index = orig.startIndex + (yt + i) * stride + xt;\n" + "\t\t\tint indexResults = output.startIndex + i*output.stride;\n" + "\n" + "\t\t\tfloat XY = data[index]"+bitWise+";\n" + "\t\t\tfloat Xy = data[index + stride]"+bitWise+";\n" + "\n" + "\t\t\tint indexEnd = index + regWidth;\n" + "\t\t\t// for( int j = 0; j < regWidth; j++, index++ ) {\n" + "\t\t\tfor (; index < indexEnd; index++) {\n" + "\t\t\t\tfloat xY = data[index + 1]"+bitWise+";\n" + "\t\t\t\tfloat xy = data[index + stride + 1]"+bitWise+";\n" + "\n" + "\t\t\t\tfloat val = a0 * XY + a1 * xY + a2 * xy + a3 * Xy;\n" + "\n" + "\t\t\t\tresults[indexResults++] = val;\n" + "\t\t\t\tXY = xY;\n" + "\t\t\t\tXy = xy;\n" + "\t\t\t}\n" + "\t\t}\n" + "\t\t\n" + "\t\t// if touching the image border handle the special case\n" + "\t\tif( borderBottom || borderRight )\n" + "\t\t\thandleBorder(output, xt, yt, ax, ay, bx, by, regWidth, regHeight, results, borderRight, borderBottom);\n" + "\t}\n" + "\n" + "\tprivate void handleBorder( GrayF32 output,\n" + "\t\t\t\t\t\t\t int xt, int yt,\n" + "\t\t\t\t\t\t\t float ax, float ay, float bx, float by,\n" + "\t\t\t\t\t\t\t int regWidth, int regHeight, float[] results,\n" + "\t\t\t\t\t\t\t boolean borderRight, boolean borderBottom) {\n" + "\n" + "\t\tif( borderRight ) {\n" + "\t\t\tfor( int y = 0; y < regHeight; y++ ) {\n" + "\t\t\t\tint index = orig.startIndex + (yt + y) * stride + xt + regWidth;\n" + "\t\t\t\tint indexResults = output.startIndex + y*output.stride + regWidth;\n" + "\n" + "\t\t\t\tfloat XY = data[index]"+bitWise+";\n" + "\t\t\t\tfloat Xy = data[index + stride]"+bitWise+";\n" + "\n" + "\t\t\t\tresults[indexResults] = by*XY + ay*Xy;\n" + "\t\t\t}\n" + "\n" + "\t\t\tif( borderBottom ) {\n" + "\t\t\t\toutput.set(regWidth,regHeight, orig.get(xt+ regWidth,yt+regHeight));\n" + "\t\t\t} else {\n" + "\t\t\t\tfloat XY = orig.get(xt+ regWidth,yt+regHeight-1);\n" + "\t\t\t\tfloat Xy = orig.get(xt+ regWidth,yt+regHeight);\n" + "\n" + "\t\t\t\toutput.set(regWidth,regHeight-1, by*XY + ay*Xy);\n" + "\t\t\t}\n" + "\t\t}\n" + "\t\tif( borderBottom ) {\n" + "\t\t\tfor( int x = 0; x < regWidth; x++ ) {\n" + "\t\t\t\tint index = orig.startIndex + (yt + regHeight) * stride + xt + x;\n" + "\t\t\t\tint indexResults = output.startIndex + regHeight *output.stride + x;\n" + "\n" + "\t\t\t\tfloat XY = data[index]"+bitWise+";\n" + "\t\t\t\tfloat Xy = data[index + 1]"+bitWise+";\n" + "\n" + "\t\t\t\tresults[indexResults] = bx*XY + ax*Xy;\n" + "\t\t\t}\n" + "\n" + "\t\t\tif( !borderRight ) {\n" + "\t\t\t\tfloat XY = orig.get(xt+regWidth-1,yt+ regHeight);\n" + "\t\t\t\tfloat Xy = orig.get(xt+regWidth, regHeight);\n" + "\n" + "\t\t\t\toutput.set(regWidth-1, regHeight, by*XY + ay*Xy);\n" + "\t\t\t}\n" + "\t\t}\n" + "\t}\n"); } public static void main( String args[] ) throws FileNotFoundException { GenerateBilinearRectangle gen = new GenerateBilinearRectangle(); gen.generate(); } }