| /* match PDFs |
| * |
| * Copyright: 1991, N. Dessipris. |
| * |
| * Author: Nicos Dessipris |
| * Written on: 19/07/1990 |
| * Modified on: 26/03/1991 |
| * |
| * 1/3/01 JC |
| * - bleurg! rewritten, now does 16 bits as well, bugs removed, faster, |
| * smaller |
| * 24/3/10 |
| * - gtkdoc |
| * - small cleanups |
| */ |
| |
| /* |
| |
| This file is part of VIPS. |
| |
| VIPS is free software; you can redistribute it and/or modify |
| it under the terms of the GNU Lesser 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 Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser 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 |
| |
| */ |
| |
| /* |
| |
| These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk |
| |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif /*HAVE_CONFIG_H*/ |
| #include <vips/intl.h> |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <assert.h> |
| |
| #include <vips/vips.h> |
| |
| #ifdef WITH_DMALLOC |
| #include <dmalloc.h> |
| #endif /*WITH_DMALLOC*/ |
| |
| /* |
| #define DEBUG |
| */ |
| |
| /* |
| #define PIM_RINT |
| */ |
| |
| /* Match two normalised cumulative histograms. |
| */ |
| static int |
| match( IMAGE *in, IMAGE *ref, IMAGE *out ) |
| { |
| const int inpx = in->Xsize * in->Ysize; |
| const int refpx = ref->Xsize * ref->Ysize; |
| const int bands = in->Bands; |
| |
| unsigned int *inbuf; /* in and ref, padded to same size */ |
| unsigned int *refbuf; |
| unsigned int *outbuf; /* Always output as uint */ |
| |
| int px; /* Number of pixels */ |
| int max; /* px * bands */ |
| |
| int i, j; |
| |
| if( im_iocheck( in, out ) || |
| im_iocheck( ref, out ) || |
| im_check_uncoded( "im_histspec", in ) || |
| im_check_format( "im_histspec", in, IM_BANDFMT_UINT ) || |
| im_check_coding_same( "im_histspec", in, ref ) || |
| im_check_format_same( "im_histspec", in, ref ) || |
| im_check_bands_same( "im_histspec", in, ref ) || |
| im_check_hist( "im_histspec", in ) || |
| im_check_hist( "im_histspec", ref ) ) |
| return( -1 ); |
| |
| /* How big? |
| */ |
| if( inpx <= 256 && refpx <= 256 ) |
| px = 256; |
| else if( inpx <= 65536 && refpx <= 65536 ) |
| px = 65536; |
| max = px * bands; |
| |
| /* Unpack to equal-sized buffers. |
| */ |
| inbuf = IM_ARRAY( out, max, unsigned int ); |
| refbuf = IM_ARRAY( out, max, unsigned int ); |
| outbuf = IM_ARRAY( out, max, unsigned int ); |
| if( !inbuf || !refbuf || !outbuf ) |
| return( -1 ); |
| for( i = 0; i < inpx * bands; i++ ) |
| inbuf[i] = ((unsigned int *)in->data)[i]; |
| for( ; i < max; i++ ) |
| inbuf[i] = 0; |
| for( i = 0; i < refpx * bands; i++ ) |
| refbuf[i] = ((unsigned int *)ref->data)[i]; |
| for( ; i < max; i++ ) |
| refbuf[i] = 0; |
| |
| for( j = 0; j < bands; j++ ) { |
| /* Track up refbuf[] with this. |
| */ |
| int ri = j; |
| int limit = max - bands; |
| |
| for( i = j; i < max; i += bands ) { |
| unsigned int inv = inbuf[i]; |
| |
| for( ; ri < limit; ri += bands ) |
| if( inv <= refbuf[ri] ) |
| break; |
| |
| if( ri < limit ) { |
| /* Simple rounding. |
| */ |
| double mid = refbuf[ri] + |
| refbuf[ri + bands] / 2.0; |
| |
| if( inv < mid ) |
| outbuf[i] = ri/bands; |
| else |
| outbuf[i] = ri/bands + 1; |
| } |
| else |
| outbuf[i] = refbuf[ri]; |
| } |
| } |
| |
| if( im_cp_descv( out, in, ref, NULL ) ) |
| return( -1 ); |
| out->Xsize = px; |
| out->Ysize = 1; |
| out->Type = IM_TYPE_HISTOGRAM; |
| if( im_setupout( out ) ) |
| return( -1 ); |
| |
| if( im_writeline( 0, out, (PEL *) outbuf ) ) |
| return( -1 ); |
| |
| return( 0 ); |
| } |
| |
| /** |
| * im_histspec: |
| * @in: input image |
| * @ref: reference histogram |
| * @out: output image |
| * |
| * Creates a lut which, when applied to the image from which histogram @in was |
| * formed, will produce an image whose PDF matches that of the image from |
| * which @ref was formed. |
| * |
| * See also: im_hsp(), im_histgr(), im_maplut(). |
| * |
| * Returns: 0 on success, -1 on error |
| */ |
| int |
| im_histspec( IMAGE *in, IMAGE *ref, IMAGE *out ) |
| { |
| IMAGE *t[5]; |
| int px; |
| int fmt; |
| |
| if( im_check_uint( "im_histspec", in ) || |
| im_check_uint( "im_histspec", ref ) ) |
| return( -1 ); |
| |
| /* Match hists. |
| */ |
| if( im_open_local_array( out, t, 5, "im_histspec", "p" ) || |
| im_histeq( in, t[0] ) || |
| im_clip2fmt( t[0], t[1], IM_BANDFMT_UINT ) || |
| im_histeq( ref, t[2] ) || |
| im_clip2fmt( t[2], t[3], IM_BANDFMT_UINT ) || |
| match( t[1], t[3], t[4] ) ) |
| return( -1 ); |
| |
| /* Clip type down. |
| */ |
| px = t[4]->Xsize * t[4]->Ysize; |
| if( px <= 256 ) |
| fmt = IM_BANDFMT_UCHAR; |
| else if( px <= 65536 ) |
| fmt = IM_BANDFMT_USHORT; |
| else |
| fmt = IM_BANDFMT_UINT; |
| |
| if( im_clip2fmt( t[4], out, fmt ) ) |
| return( -1 ); |
| |
| return( 0 ); |
| } |
| |