File Coverage

rubthru.im
Criterion Covered Total %
statement 100 112 89.2
branch 74 116 63.7
condition n/a
subroutine n/a
pod n/a
total 174 228 76.3


line stmt bran cond sub pod time code
1             #include "imager.h"
2              
3             static int
4 15           rubthru_targ_noalpha(i_img *im, i_img *src,
5             i_img_dim tx, i_img_dim ty,
6             i_img_dim src_minx, i_img_dim src_miny,
7             i_img_dim src_maxx, i_img_dim src_maxy) {
8             i_img_dim x, y, tty;
9             int alphachan;
10             int ch;
11 15           i_img_dim width = src_maxx - src_minx;
12             int want_channels;
13              
14 15           i_clear_error();
15              
16 15 100         if (im->channels == 3 && (src->channels == 4 || src->channels == 2)) {
    100          
    100          
17 8           want_channels = 4;
18 8           alphachan = 3;
19             }
20 7 100         else if (im->channels == 1 && (src->channels == 4 || src->channels == 2)) {
    100          
    100          
21 3           want_channels = 2;
22 3           alphachan = 1;
23             }
24             else {
25 4           i_copyto(im, src, src_minx, src_miny, src_maxx, src_maxy, tx, ty);
26 4           return 1;
27             }
28              
29 20 100         #code im->bits <= 8 && src->bits <= 8
    100          
30             IM_WORK_T alpha;
31             IM_COLOR *src_line, *dest_line;
32            
33 11           src_line = mymalloc(sizeof(IM_COLOR) * width);
34 11           dest_line = mymalloc(sizeof(IM_COLOR) * width);
35              
36 11           tty = ty;
37 691 100         for(y = src_miny; y < src_maxy; y++) {
    100          
38 680           IM_COLOR *srcp = src_line;
39 680           IM_COLOR *destp = dest_line;
40 680           IM_GLIN(src, src_minx, src_maxx, y, src_line);
41 680           IM_GLIN(im, tx, tx + width, tty, dest_line);
42 680           if (src->channels != want_channels)
43 180           IM_ADAPT_COLORS(want_channels, src->channels, src_line, width);
44              
45 45880 100         for(x = src_minx; x < src_maxx; x++) {
    100          
46 45200           alpha = srcp->channel[alphachan];
47 158000 100         for (ch = 0; ch < im->channels; ++ch) {
    100          
48 225600           IM_WORK_T samp = (alpha * srcp->channel[ch]
49 112800           + (IM_SAMPLE_MAX - alpha) * destp->channel[ch])/IM_SAMPLE_MAX;
50 112800 50         destp->channel[ch] = IM_LIMIT(samp);
    50          
    50          
51             }
52 45200           ++srcp;
53 45200           ++destp;
54             }
55 680           IM_PLIN(im, tx, tx + width, tty, dest_line);
56 680           tty++;
57             }
58 11           myfree(src_line);
59 11           myfree(dest_line);
60             #/code
61              
62 11           return 1;
63             }
64              
65             static int
66 9           rubthru_targ_alpha(i_img *im, i_img *src, i_img_dim tx, i_img_dim ty,
67             i_img_dim src_minx, i_img_dim src_miny,
68             i_img_dim src_maxx, i_img_dim src_maxy) {
69             i_img_dim x, y, ttx, tty;
70             int want_channels;
71             int alphachan;
72             int ch;
73             int targ_alpha_chan;
74 9           i_img_dim width = src_maxx - src_minx;
75            
76 9 100         if (im->channels == 4 && (src->channels == 4 || src->channels == 2)) {
    100          
    100          
77 3           alphachan = 3;
78 3           want_channels = 4;
79             }
80 6 100         else if (im->channels == 2 && (src->channels == 4 || src->channels == 2)) {
    100          
    100          
81 2           alphachan = 1;
82 2           want_channels = 2;
83             }
84             else {
85 4           i_copyto(im, src, src_minx, src_miny, src_maxx, src_maxy, tx, ty);
86 4           return 1;
87             }
88              
89 5           targ_alpha_chan = im->channels - 1;
90              
91 10 50         #code im->bits <= 8 && src->bits <= 8
    50          
92             IM_WORK_T src_alpha, orig_alpha, dest_alpha, remains;
93             IM_COLOR *src_line, *dest_line;
94              
95 5           src_line = mymalloc(sizeof(IM_COLOR) * width);
96 5           dest_line = mymalloc(sizeof(IM_COLOR) * width);
97              
98 5           tty = ty;
99 206 100         for(y = src_miny; y < src_maxy; y++) {
    0          
100             i_img_dim min_x, max_x;
101 201           IM_COLOR *srcp = src_line;
102 201           IM_COLOR *destp = dest_line;
103 201           IM_GLIN(src, src_minx, src_maxx, y, src_line);
104 201           if (src->channels != want_channels)
105 100           IM_ADAPT_COLORS(want_channels, src->channels, src_line, width);
106 201           min_x = src_minx;
107 201           max_x = src_maxx;
108              
109 204 50         while (min_x < max_x && srcp->channel[alphachan] == 0) {
    100          
    0          
    0          
110 3           ++min_x;
111 3           ++srcp;
112             }
113 202 50         while (max_x > min_x && src_line[max_x-1 - src_minx].channel[alphachan] == 0) {
    100          
    0          
    0          
114 1           --max_x;
115             }
116              
117 201 50         if (max_x > min_x) {
    0          
118 201           i_img_dim work_left = tx + min_x - src_minx;
119 201           i_img_dim work_width = max_x - min_x;
120 201           ttx = work_left;
121 201           IM_GLIN(im, work_left, work_left + work_width, tty, dest_line);
122            
123 10207 100         for(x = min_x; x < max_x; x++) {
    0          
124 10006           src_alpha = srcp->channel[alphachan];
125 10006 50         if (src_alpha) {
    0          
126 10006           remains = IM_SAMPLE_MAX - src_alpha;
127 10006           orig_alpha = destp->channel[targ_alpha_chan];
128 10006           dest_alpha = src_alpha + (remains * orig_alpha) / IM_SAMPLE_MAX;
129            
130 30024 100         for (ch = 0; ch < im->channels-1; ++ch) {
    0          
131 20018           IM_WORK_T samp =
132 20018           ( src_alpha * srcp->channel[ch]
133 20018           + remains * destp->channel[ch] * orig_alpha / IM_SAMPLE_MAX
134             ) / dest_alpha;
135 20018 50         destp->channel[ch] = IM_LIMIT(samp);
    0          
    0          
136             }
137             /* dest's alpha */
138 10006           destp->channel[targ_alpha_chan] = dest_alpha;
139             }
140 10006           ++srcp;
141 10006           ++destp;
142 10006           ttx++;
143             }
144 201           IM_PLIN(im, work_left, work_left + work_width, tty, dest_line);
145             }
146 201           tty++;
147             }
148 5           myfree(dest_line);
149 5           myfree(src_line);
150             #/code
151 5           return 1;
152             }
153              
154             /*
155             =item i_rubthru(C, C, C, C, C, C, C, C)
156              
157             =category Image
158              
159             Takes the sub image C[C, C)[C, C)> and
160             overlays it at (C,C) on the image object.
161              
162             The alpha channel of each pixel in C is used to control how much
163             the existing color in C is replaced, if it is 255 then the color
164             is completely replaced, if it is 0 then the original color is left
165             unmodified.
166              
167             =cut
168             */
169              
170             int
171 24           i_rubthru(i_img *im, i_img *src, i_img_dim tx, i_img_dim ty, i_img_dim src_minx, i_img_dim src_miny,
172             i_img_dim src_maxx, i_img_dim src_maxy) {
173 24 50         if (src_minx < 0) {
174 0           tx -= src_minx;
175 0           src_minx = 0;
176             }
177 24 50         if (src_miny < 0) {
178 0           ty -= src_miny;
179 0           src_miny = 0;
180             }
181 24 50         if (tx < 0) {
182 0           src_minx -= tx;
183 0           tx = 0;
184             }
185 24 50         if (ty < 0) {
186 0           src_miny -= ty;
187 0           ty = 0;
188             }
189 24 50         if (src_maxx > src->xsize) {
190 0           src_maxx = src->xsize;
191             }
192 24 50         if (src_maxy > src->ysize) {
193 0           src_maxy = src->ysize;
194             }
195 24 50         if (tx >= im->xsize || ty >= im->ysize
    50          
196 24 50         || src_minx >= src_maxx || src_miny >= src_maxy) {
    50          
197 0           i_clear_error();
198             /* just do nothing, attempting to rubthrough outside the target isn't
199             worth being an error */
200 0           return 1;
201             }
202              
203 24 100         if (im->channels == 1 || im->channels == 3)
    100          
204 15           return rubthru_targ_noalpha(im, src, tx, ty, src_minx, src_miny,
205             src_maxx, src_maxy);
206             else
207 9           return rubthru_targ_alpha(im, src, tx, ty, src_minx, src_miny,
208             src_maxx, src_maxy);
209             }