Coverage Report

Created: 2025-12-31 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvips/libvips/morphology/countlines.c
Line
Count
Source
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 <glib/gi18n-lib.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
36
G_DEFINE_TYPE(VipsCountlines, vips_countlines, VIPS_TYPE_MORPHOLOGY);
73
36
74
36
static int
75
36
vips_countlines_build(VipsObject *object)
76
36
{
77
0
  VipsMorphology *morphology = VIPS_MORPHOLOGY(object);
78
0
  VipsCountlines *countlines = (VipsCountlines *) object;
79
0
  VipsImage *in = morphology->in;
80
0
  VipsImage **t = (VipsImage **) vips_object_local_array(object, 7);
81
82
0
  double nolines;
83
84
0
  if (VIPS_OBJECT_CLASS(vips_countlines_parent_class)->build(object))
85
0
    return -1;
86
87
  /* Compiler warnings.
88
   */
89
0
  nolines = 1;
90
91
0
  switch (countlines->direction) {
92
0
  case VIPS_DIRECTION_HORIZONTAL:
93
0
    if (!(t[0] = vips_image_new_matrixv(1, 2, -1.0, 1.0)) ||
94
0
      vips_moreeq_const1(in, &t[1], 128, NULL) ||
95
0
      vips_conv(t[1], &t[2], t[0],
96
0
        "precision", VIPS_PRECISION_INTEGER,
97
0
        NULL) ||
98
0
      vips_project(t[2], &t[3], &t[4], NULL) ||
99
0
      vips_avg(t[3], &nolines, NULL))
100
0
      return -1;
101
0
    break;
102
103
0
  case VIPS_DIRECTION_VERTICAL:
104
0
    if (!(t[0] = vips_image_new_matrixv(2, 1, -1.0, 1.0)) ||
105
0
      vips_moreeq_const1(in, &t[1], 128, NULL) ||
106
0
      vips_conv(t[1], &t[2], t[0],
107
0
        "precision", VIPS_PRECISION_INTEGER,
108
0
        NULL) ||
109
0
      vips_project(t[2], &t[3], &t[4], NULL) ||
110
0
      vips_avg(t[4], &nolines, NULL))
111
0
      return -1;
112
0
    break;
113
114
0
  default:
115
0
    g_assert_not_reached();
116
0
  }
117
118
0
  g_object_set(object, "nolines", nolines / 255.0, NULL);
119
120
0
  return 0;
121
0
}
122
123
static void
124
vips_countlines_class_init(VipsCountlinesClass *class)
125
18
{
126
18
  GObjectClass *gobject_class = G_OBJECT_CLASS(class);
127
18
  VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS(class);
128
129
18
  VIPS_DEBUG_MSG("vips_countlines_class_init\n");
130
131
18
  gobject_class->set_property = vips_object_set_property;
132
18
  gobject_class->get_property = vips_object_get_property;
133
134
18
  vobject_class->nickname = "countlines";
135
18
  vobject_class->description = _("count lines in an image");
136
18
  vobject_class->build = vips_countlines_build;
137
138
18
  VIPS_ARG_DOUBLE(class, "nolines", 2,
139
18
    _("Nolines"),
140
18
    _("Number of lines"),
141
18
    VIPS_ARGUMENT_REQUIRED_OUTPUT,
142
18
    G_STRUCT_OFFSET(VipsCountlines, nolines),
143
18
    0, 10000000, 0.0);
144
145
18
  VIPS_ARG_ENUM(class, "direction", 3,
146
18
    _("Direction"),
147
18
    _("Countlines left-right or up-down"),
148
18
    VIPS_ARGUMENT_REQUIRED_INPUT,
149
18
    G_STRUCT_OFFSET(VipsCountlines, direction),
150
18
    VIPS_TYPE_DIRECTION, VIPS_DIRECTION_HORIZONTAL);
151
18
}
152
153
static void
154
vips_countlines_init(VipsCountlines *countlines)
155
0
{
156
0
}
157
158
/**
159
 * vips_countlines: (method)
160
 * @in: input image
161
 * @nolines: (out): output average number of lines
162
 * @direction: count lines horizontally or vertically
163
 * @...: `NULL`-terminated list of optional named arguments
164
 *
165
 * Function which calculates the number of transitions
166
 * between black and white for the horizontal or the vertical
167
 * direction of an image.  black<128 , white>=128
168
 * The function calculates the number of transitions for all
169
 * Xsize or Ysize and returns the mean of the result
170
 * Input should be one band, 8-bit.
171
 *
172
 * ::: seealso
173
 *     [method@Image.morph], [method@Image.conv].
174
 *
175
 * Returns: 0 on success, -1 on error.
176
 */
177
int
178
vips_countlines(VipsImage *in, double *nolines,
179
  VipsDirection direction, ...)
180
0
{
181
0
  va_list ap;
182
0
  int result;
183
184
0
  va_start(ap, direction);
185
0
  result = vips_call_split("countlines", ap, in, nolines, direction);
186
0
  va_end(ap);
187
188
0
  return result;
189
0
}