/* $Id: cpl_image_resample-test.c,v 1.29 2008/02/07 10:54:01 llundin Exp $ * * This file is part of the ESO Common Pipeline Library * Copyright (C) 2001-2004 European Southern Observatory * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * $Author: llundin $ * $Date: 2008/02/07 10:54:01 $ * $Revision: 1.29 $ * $Name: $ */ /*----------------------------------------------------------------------------- Includes -----------------------------------------------------------------------------*/ #include #include #include "cpl_image_io.h" #include "cpl_vector.h" #include "cpl_image_gen.h" #include "cpl_memory.h" #include "cpl_image_resample.h" #include "cpl_tools.h" /*----------------------------------------------------------------------------- Defines -----------------------------------------------------------------------------*/ #ifndef IMAGESZ #define IMAGESZ 512 #endif /*----------------------------------------------------------------------------- Private function prototypes -----------------------------------------------------------------------------*/ static void check_id_kernel(cpl_image *, const cpl_image *, cpl_polynomial *, cpl_polynomial *, cpl_kernel, cpl_vector *, double, double); /*----------------------------------------------------------------------------- Main -----------------------------------------------------------------------------*/ int main(void) { cpl_image * imf; cpl_image * imd; cpl_image * imtmp; cpl_image * dx ; cpl_image * dy ; cpl_image * warped; cpl_polynomial * pu; cpl_polynomial * pv; cpl_vector * xyprofile; const double xyradius = 2.2; /* 2.3 gives much higher rounding ? */ int expo[2]; cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING); /* Insert tests below */ /* First create a test image */ cpl_msg_info("", "Create double and float test images."); imd = cpl_image_fill_test_create(IMAGESZ, IMAGESZ); imf = cpl_image_cast(imd, CPL_TYPE_FLOAT); xyprofile = cpl_vector_new(1 + xyradius * CPL_KERNEL_TABSPERPIX); cpl_test_nonnull( xyprofile); cpl_msg_info("", "Rotate a DOUBLE image with a polynomial-warp"); /* The rotation: (u,v) = (y, N+1-x) */ pu = cpl_polynomial_new(2); pv = cpl_polynomial_new(2); expo[0] = 0; expo[1] = 0; cpl_polynomial_set_coeff(pv, expo, 1+IMAGESZ); expo[0] = 0; expo[1] = 1; cpl_polynomial_set_coeff(pu, expo, 1); expo[0] = 1; expo[1] = 0; cpl_polynomial_set_coeff(pv, expo, -1); if (cpl_msg_get_level() <= CPL_MSG_DEBUG) { cpl_polynomial_dump(pu, stdout); cpl_polynomial_dump(pv, stdout); } warped = cpl_image_new(IMAGESZ, IMAGESZ, CPL_TYPE_DOUBLE); /* These kernels preserve the actual pixel-values */ check_id_kernel(warped, imd, pu, pv, CPL_KERNEL_TANH, xyprofile, xyradius, DBL_EPSILON); check_id_kernel(warped, imd, pu, pv, CPL_KERNEL_SINC, xyprofile, xyradius, DBL_EPSILON); check_id_kernel(warped, imd, pu, pv, CPL_KERNEL_SINC2, xyprofile, xyradius, DBL_EPSILON); check_id_kernel(warped, imd, pu, pv, CPL_KERNEL_LANCZOS, xyprofile, xyradius, DBL_EPSILON); check_id_kernel(warped, imd, pu, pv, CPL_KERNEL_HANN, xyprofile, xyradius, DBL_EPSILON); check_id_kernel(warped, imd, pu, pv, CPL_KERNEL_HAMMING, xyprofile, xyradius, DBL_EPSILON); cpl_image_delete(warped); cpl_test_zero( cpl_vector_set_size(xyprofile, CPL_KERNEL_DEF_SAMPLES)); cpl_test_zero( cpl_vector_fill_kernel_profile(xyprofile, CPL_KERNEL_DEFAULT, CPL_KERNEL_DEF_WIDTH) ); /* Define the following polynomials : */ /* x = 0.945946.u + -0.135135.v + -6.75676 */ /* y = -0.202703.u + 0.743243.v + -12.8378 */ expo[0] = 1; expo[1] = 0; cpl_polynomial_set_coeff(pu, expo, 0.945946); expo[0] = 0; expo[1] = 1; cpl_polynomial_set_coeff(pu, expo, -0.135135); expo[0] = 0; expo[1] = 0; cpl_polynomial_set_coeff(pu, expo, -6.75676); expo[0] = 1; expo[1] = 0; cpl_polynomial_set_coeff(pv, expo, -0.202703); expo[0] = 0; expo[1] = 1; cpl_polynomial_set_coeff(pv, expo, 0.743243); expo[0] = 0; expo[1] = 0; cpl_polynomial_set_coeff(pv, expo, -12.8378); cpl_msg_info("", "Apply the polynomial warping to the DOUBLE image."); /* Apply polynomial warping on the DOUBLE image */ warped = cpl_image_new(IMAGESZ/3, IMAGESZ*2, CPL_TYPE_DOUBLE); cpl_test( warped ); cpl_test_zero( cpl_image_warp_polynomial(warped, imd, pu, pv, xyprofile, 2, xyprofile, 2) ); cpl_image_multiply_scalar(warped, 0.0) ; /* Apply polynomial warping on the FLOAT image */ cpl_test_zero( cpl_image_warp_polynomial(warped, imf, pu, pv, xyprofile, 2, xyprofile, 2) ); cpl_image_multiply_scalar(warped, 0.0) ; cpl_polynomial_delete(pu); cpl_polynomial_delete(pv); /* Test cpl_image_warp() */ dx = cpl_image_new(cpl_image_get_size_x(warped), cpl_image_get_size_y(warped), CPL_TYPE_DOUBLE) ; dy = cpl_image_new(cpl_image_get_size_x(warped), cpl_image_get_size_y(warped), CPL_TYPE_DOUBLE) ; cpl_image_add_scalar(dx, 1.0) ; cpl_image_add_scalar(dy, -2.0) ; cpl_test_zero( cpl_image_warp(warped, imd, dx, dy, xyprofile, 2, xyprofile, 2)); cpl_image_multiply_scalar(warped, 0.0) ; cpl_test_zero( cpl_image_warp(warped, imf, dx, dy, xyprofile, 2, xyprofile, 2)); cpl_image_multiply_scalar(warped, 0.0) ; cpl_image_delete(dx) ; cpl_image_delete(dy) ; cpl_image_delete(warped); cpl_vector_delete(xyprofile); /* Test sub-sampling on imf and imd */ cpl_msg_info("", "Sub sample imf and imd"); imtmp = cpl_image_extract_subsample(imf, 2, 2); cpl_test_nonnull( imtmp ); cpl_image_delete(imtmp); imtmp = cpl_image_extract_subsample(imd, 2, 2); cpl_test_nonnull( imtmp ); cpl_image_delete(imtmp); cpl_image_delete(imf); cpl_image_delete(imd); /* End of tests */ return cpl_test_end(0); } /*----------------------------------------------------------------------------*/ /** @internal @brief Check if a rotation with the kernel preserves the pixel values @param temp Preallocated image for interpolation @param image Image to rotate @param pu Polynomial Pu(x,y) = y @param pv Polynomial Pv(x,y) = N+1-x @param kernel Kernel type to test @param xyprofile Interpolation weight as a function of the distance @param xyradius Positive inclusion radius @param tol Tolerance on pixel preservataion @return Number of failures @note This function will fail assert() on invalid input */ /*----------------------------------------------------------------------------*/ static void check_id_kernel(cpl_image * temp, const cpl_image * image, cpl_polynomial * pu, cpl_polynomial * pv, cpl_kernel kernel, cpl_vector * xyprofile, double xyradius, double tol) { cpl_msg_info("check_id_kernel", "Rotating with kernel-radius (%d): %g", kernel, xyradius); assert( !cpl_vector_fill_kernel_profile(xyprofile, kernel, xyradius) ); assert( !cpl_image_warp_polynomial(temp, image, pu, pv, xyprofile, xyradius, xyprofile, xyradius) ); /* Rotate back */ assert( !cpl_image_turn(temp, 1) ); /* Subtract reference */ assert( !cpl_image_subtract(temp, image)); cpl_test_leq(sqrt(cpl_image_get_sqflux(temp))/(IMAGESZ*IMAGESZ), tol); return; }