File Coverage

trim.im
Criterion Covered Total %
statement 71 104 68.2
branch 83 186 44.6
condition n/a
subroutine n/a
pod n/a
total 154 290 53.1


line stmt bran cond sub pod time code
1             #define IMAGER_NO_CONTEXT
2             #include "imager.h"
3             #include "imageri.h"
4              
5             IMAGER_STATIC_INLINE int
6 3168           match_one_color(const i_sample_t *testme, const i_trim_colors_t *test) {
7 3168 100         if (test->c1.channel[0] > testme[0] || test->c2.channel[0] < testme[0])
    100          
8 670           return 0;
9 2498 100         if (test->c1.channel[1] > testme[1] || test->c2.channel[1] < testme[1])
    100          
10 204           return 0;
11 2294 50         if (test->c1.channel[2] > testme[2] || test->c2.channel[2] < testme[2])
    100          
12 8           return 0;
13 2286           return 1;
14             }
15              
16             IMAGER_STATIC_INLINE int
17 0           match_one_fcolor(const i_fsample_t *testme, const i_trim_colors_t *test) {
18 0 0         if (test->cf1.channel[0] > testme[0] || test->cf2.channel[0] < testme[0])
    0          
19 0           return 0;
20 0 0         if (test->cf1.channel[1] > testme[1] || test->cf2.channel[1] < testme[1])
    0          
21 0           return 0;
22 0 0         if (test->cf1.channel[2] > testme[2] || test->cf2.channel[2] < testme[2])
    0          
23 0           return 0;
24 0           return 1;
25             }
26              
27             IMAGER_STATIC_INLINE int
28 2340           match_any_color(const i_sample_t *testme, const i_trim_colors_t *tests, int count) {
29             int i;
30 3222 100         for (i = 0; i < count; ++i) {
31 3168 100         if (match_one_color(testme, tests+i))
32 2286           return 1;
33             }
34 54           return 0;
35             }
36              
37             IMAGER_STATIC_INLINE int
38 0           match_any_fcolor(const i_fsample_t *testme, const i_trim_colors_t *tests, int count) {
39             int i;
40 0 0         for (i = 0; i < count; ++i) {
41 0 0         if (match_one_fcolor(testme, tests+i))
42 0           return 1;
43             }
44 0           return 0;
45             }
46              
47             #!define MATCH_ANY_COLOR match_any_color match_any_fcolor
48              
49             static const int gray_chans[4] = { 0, 0, 0, 1 };
50              
51             #define TEST_COLOR(s) \
52             (color_count && MATCH_ANY_COLOR((s), colors, color_count) || \
53             check_alpha && (s)[3] <= work_threshold)
54              
55 12           static int
56             trim_rect_simple(i_img *im, double transp_threshold, int color_count,
57             const i_trim_colors_t *colors, i_img_dim *left, i_img_dim *top,
58 12           i_img_dim *right, i_img_dim *bottom) {
59 12 50         const int color_chans = i_img_color_channels(im);
60 12           const int *chans = color_chans == 1 ? gray_chans : NULL;
61 12 100         const int has_alpha = i_img_has_alpha(im);
    50          
62 12 100         const int check_alpha = has_alpha && transp_threshold < 1.0;
63             const int chan_count = check_alpha ? 4 : 3;
64             i_img_dim x, y;
65 12 50         #code im->bits <= 8
66 12           IM_SAMPLE_T *samps = mymalloc(sizeof(IM_SAMPLE_T) * im->ysize * chan_count);
67             #if IM_EIGHT_BIT
68 12           const IM_WORK_T work_threshold = floor(IM_SAMPLE_MAX * transp_threshold);
69             #else
70 0           const IM_WORK_T work_threshold = transp_threshold;
71             #endif
72              
73             /* scan down from top */
74 32 50         for (y = 0; y < im->ysize; ++y) {
    0          
75             IM_SAMPLE_T *s;
76 32           IM_GSAMP(im, 0, im->xsize, y, samps, chans, chan_count);
77 472 100         for (x = 0, s = samps; x < im->xsize; ++x, s += chan_count) {
    0          
78 452 100         if (!TEST_COLOR(s))
    100          
    100          
    100          
    0          
    0          
    0          
    0          
79             break;
80             }
81 32 100         if (x < im->xsize)
    0          
82 12           break;
83             }
84 12           *top = y;
85 12 50         if (y < im->ysize) {
    0          
86             /* scan from the bottom */
87 52 50         for (y = im->ysize-1; y >= 0; --y) {
    0          
88             IM_SAMPLE_T *s;
89 52           IM_GSAMP(im, 0, im->xsize, y, samps, chans, chan_count);
90 892 100         for (x = 0, s = samps; x < im->xsize; ++x, s += chan_count) {
    0          
91 852 100         if (!TEST_COLOR(s))
    100          
    100          
    100          
    0          
    0          
    0          
    0          
92             break;
93             }
94 52 100         if (x < im->xsize)
    0          
95 12           break;
96             }
97 12           *bottom = im->ysize - y - 1;
98            
99             /* we've trimmed top and bottom, now the sides */
100 12           *left = *right = im->xsize;
101 192 100         for (y = *top; y < im->ysize - *bottom && (*left || *right); ++y) {
    50          
    0          
    0          
    0          
    0          
102             IM_SAMPLE_T *s;
103 180           IM_GSAMP(im, 0, im->xsize, y, samps, chans, chan_count);
104 676 100         for (x = 0, s = samps; x < *left; ++x, s += chan_count) {
    0          
105 512 100         if (!TEST_COLOR(s)) {
    100          
    100          
    100          
    0          
    0          
    0          
    0          
106 16           *left = x;
107 16           break;
108             }
109             }
110 868 100         for (x = im->xsize - 1, s = samps + chan_count * im->xsize;
    0          
111 688           x >= im->xsize - *right; --x, s -= chan_count) {
112 706 100         if (!TEST_COLOR(s-chan_count)) {
    100          
    100          
    100          
    0          
    0          
    0          
    0          
113 18           *right = im->xsize - x - 1;
114 18           break;
115             }
116             }
117             }
118             }
119             else {
120             /* whole image can be trimmed */
121 0           *left = im->xsize;
122 0           *right = *bottom = 0;
123             }
124 12           myfree(samps);
125             #/code
126              
127 12           return 1;
128             }
129              
130             int
131 12           i_trim_rect(i_img *im, double transp_threshold, int color_count, const i_trim_colors_t *colors,
132             i_img_dim *left, i_img_dim *top, i_img_dim *right, i_img_dim *bottom) {
133 12           dIMCTXim(im);
134 12           i_trim_colors_t *tcolors = NULL;
135             i_trim_colors_t *tcolorp;
136             const i_trim_colors_t *colorp;
137 12           int tcolor_count = 0;
138             int result;
139              
140 12 100         if (color_count) {
141 11           tcolors = mymalloc(sizeof(i_trim_colors_t) * color_count);
142 11           tcolorp = tcolors;
143             /* convert 8-bit to float colors, or float colors to 8-bit depending on the
144             image type.
145             */
146 11 50         if (im->bits <= 8) {
147             int i, ch;
148 41 100         for (i = 0, colorp = colors; i < color_count; ++i, ++colorp) {
149 30 50         if (colorp->is_float) {
150 0 0         for (ch = 0; ch < 3; ++ch) {
151 0           tcolorp->c1.channel[ch] = ceil(colorp->cf1.channel[ch] * 255);
152 0           tcolorp->c2.channel[ch] = floor(colorp->cf2.channel[ch] * 255);
153             }
154             }
155             else {
156 30           *tcolorp = *colorp;
157             }
158 120 100         for (ch = 0; ch < 3; ++ch) {
159 90 50         if (tcolorp->c1.channel[ch] > tcolorp->c2.channel[ch])
160 0           break;
161             }
162 30 50         if (ch == 3) {
163 30           ++tcolorp, ++tcolor_count;
164             }
165             }
166             /* TODO optimize where the image is greyscale to remove color ranges that don't
167             overlap the greyscale line
168             */
169             }
170             else {
171             int i, ch;
172 0 0         for (i = 0, colorp = colors; i < color_count; ++i, ++colorp) {
173 0 0         if (!colorp->is_float) {
174 0 0         for (ch = 0; ch < 3; ++ch) {
175 0           tcolorp->cf1.channel[ch] = colorp->c1.channel[ch] / 255.0;
176 0           tcolorp->cf2.channel[ch] = colorp->c2.channel[ch] / 255.0;
177             }
178             }
179             else {
180 0           *tcolorp = *colors;
181             }
182 0 0         for (ch = 0; ch < 3; ++ch) {
183 0 0         if (tcolorp->cf1.channel[ch] > tcolorp->cf2.channel[ch])
184 0           break;
185             }
186 0 0         if (ch == 3) {
187 0           ++tcolorp, ++tcolor_count;
188             }
189             }
190             /* TODO optimize where the image is greyscale to remove color ranges that don't
191             overlap the greyscale line
192             */
193             }
194             }
195            
196 12           i_clear_error();
197              
198 12 50         if (transp_threshold > 1.0 && tcolor_count == 0) {
    0          
199             /* nothing to do */
200 0           *left = *top = *right = *bottom = 0;
201 0           result = 1;
202             }
203             else {
204 12           result = trim_rect_simple(im, transp_threshold, tcolor_count, tcolors, left, top,
205             right, bottom);
206             }
207              
208 12           myfree(tcolors);
209 12           return result;
210             }