1 /* count lines
2  *
3  * Copyright: 1990, N. Dessipris.
4  *
5  * Author: Nicos Dessipris
6  * Written on: 02/05/1990
7  * Modified on :
8  *
9  * 19/9/95 JC
10  *	- tidied up
11  * 23/10/10
12  * 	- gtk-doc
13  * 17/1/14
14  * 	- redone as a class, now just a convenience function
15  */
16 
17 /*
18 
19     This file is part of VIPS.
20 
21     VIPS is free software; you can redistribute it and/or modify
22     it under the terms of the GNU Lesser General Public License as published by
23     the Free Software Foundation; either version 2 of the License, or
24     (at your option) any later version.
25 
26     This program is distributed in the hope that it will be useful,
27     but WITHOUT ANY WARRANTY; without even the implied warranty of
28     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29     GNU Lesser General Public License for more details.
30 
31     You should have received a copy of the GNU Lesser General Public License
32     along with this program; if not, write to the Free Software
33     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34     02110-1301  USA
35 
36  */
37 
38 /*
39 
40     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
41 
42  */
43 
44 /*
45 #define VIPS_DEBUG
46  */
47 
48 #ifdef HAVE_CONFIG_H
49 #include <config.h>
50 #endif /*HAVE_CONFIG_H*/
51 #include <vips/intl.h>
52 
53 #include <stdio.h>
54 #include <string.h>
55 #include <stdlib.h>
56 
57 #include <vips/vips.h>
58 #include <vips/internal.h>
59 #include <vips/debug.h>
60 
61 #include "pmorphology.h"
62 
63 typedef struct _VipsCountlines {
64 	VipsMorphology parent_instance;
65 
66 	double nolines;
67 	VipsDirection direction;
68 } VipsCountlines;
69 
70 typedef VipsMorphologyClass VipsCountlinesClass;
71 
72 G_DEFINE_TYPE( VipsCountlines, vips_countlines, VIPS_TYPE_MORPHOLOGY );
73 
74 static int
vips_countlines_build(VipsObject * object)75 vips_countlines_build( VipsObject *object )
76 {
77 	VipsMorphology *morphology = VIPS_MORPHOLOGY( object );
78 	VipsCountlines *countlines = (VipsCountlines *) object;
79 	VipsImage *in = morphology->in;
80 	VipsImage **t = (VipsImage **) vips_object_local_array( object, 7 );
81 
82 	double nolines;
83 
84 	if( VIPS_OBJECT_CLASS( vips_countlines_parent_class )->build( object ) )
85 		return( -1 );
86 
87 	/* Compiler warnings.
88 	 */
89 	nolines = 1;
90 
91 	switch( countlines->direction ) {
92 	case VIPS_DIRECTION_HORIZONTAL:
93 		if( !(t[0] = vips_image_new_matrixv( 1, 2, -1.0, 1.0 )) ||
94 			vips_moreeq_const1( in, &t[1], 128, NULL ) ||
95 			vips_conv( t[1], &t[2], t[0],
96 				"precision", VIPS_PRECISION_INTEGER,
97 				NULL ) ||
98 			vips_project( t[2], &t[3], &t[4], NULL ) ||
99 			vips_avg( t[3], &nolines, NULL ) )
100 			return( -1 );
101 		break;
102 
103 	case VIPS_DIRECTION_VERTICAL:
104 		if( !(t[0] = vips_image_new_matrixv( 2, 1, -1.0, 1.0 )) ||
105 			vips_moreeq_const1( in, &t[1], 128, NULL ) ||
106 			vips_conv( t[1], &t[2], t[0],
107 				"precision", VIPS_PRECISION_INTEGER,
108 				NULL ) ||
109 			vips_project( t[2], &t[3], &t[4], NULL ) ||
110 			vips_avg( t[4], &nolines, NULL ) )
111 			return( -1 );
112 		break;
113 
114 	default:
115 		g_assert_not_reached();
116 	}
117 
118 	g_object_set( object, "nolines", nolines / 255.0, NULL );
119 
120 	return( 0 );
121 }
122 
123 static void
vips_countlines_class_init(VipsCountlinesClass * class)124 vips_countlines_class_init( VipsCountlinesClass *class )
125 {
126 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
127 	VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
128 
129 	VIPS_DEBUG_MSG( "vips_countlines_class_init\n" );
130 
131 	gobject_class->set_property = vips_object_set_property;
132 	gobject_class->get_property = vips_object_get_property;
133 
134 	vobject_class->nickname = "countlines";
135 	vobject_class->description = _( "count lines in an image" );
136 	vobject_class->build = vips_countlines_build;
137 
138 	VIPS_ARG_DOUBLE( class, "nolines", 2,
139 		_( "Nolines" ),
140 		_( "Number of lines" ),
141 		VIPS_ARGUMENT_REQUIRED_OUTPUT,
142 		G_STRUCT_OFFSET( VipsCountlines, nolines ),
143 		0, 10000000, 0.0 );
144 
145 	VIPS_ARG_ENUM( class, "direction", 3,
146 		_( "direction" ),
147 		_( "Countlines left-right or up-down" ),
148 		VIPS_ARGUMENT_REQUIRED_INPUT,
149 		G_STRUCT_OFFSET( VipsCountlines, direction ),
150 		VIPS_TYPE_DIRECTION, VIPS_DIRECTION_HORIZONTAL );
151 
152 }
153 
154 static void
vips_countlines_init(VipsCountlines * countlines)155 vips_countlines_init( VipsCountlines *countlines )
156 {
157 }
158 
159 /**
160  * vips_countlines: (method)
161  * @in: input image
162  * @nolines: (out): output average number of lines
163  * @direction: count lines horizontally or vertically
164  * @...: %NULL-terminated list of optional named arguments
165  *
166  * Function which calculates the number of transitions
167  * between black and white for the horizontal or the vertical
168  * direction of an image.  black<128 , white>=128
169  * The function calculates the number of transitions for all
170  * Xsize or Ysize and returns the mean of the result
171  * Input should be one band, 8-bit.
172  *
173  * See also: vips_morph(), vips_conv().
174  *
175  * Returns: 0 on success, -1 on error.
176  */
177 int
vips_countlines(VipsImage * in,double * nolines,VipsDirection direction,...)178 vips_countlines( VipsImage *in, double *nolines,
179 	VipsDirection direction, ... )
180 {
181 	va_list ap;
182 	int result;
183 
184 	va_start( ap, direction );
185 	result = vips_call_split( "countlines", ap, in, nolines, direction );
186 	va_end( ap );
187 
188 	return( result );
189 }
190