~ubuntu-branches/ubuntu/trusty/digikam/trusty

« back to all changes in this revision

Viewing changes to extra/libkdcraw/libraw/internal/wf_filtering.cpp

  • Committer: Package Import Robot
  • Author(s): Rohan Garg
  • Date: 2012-11-26 18:24:20 UTC
  • mfrom: (1.9.1) (3.1.23 experimental)
  • Revision ID: package-import@ubuntu.com-20121126182420-qoy6z0nx4ai0wzcl
Tags: 4:3.0.0~beta3-0ubuntu1
* New upstream release
  - Add build-deps :  libhupnp-dev, libqtgstreamer-dev, libmagickcore-dev
* Merge from debian, remaining changes:
  - Make sure libqt4-opengl-dev, libgl1-mesa-dev and libglu1-mesa-dev only
    install on i386,amd64 and powerpc
  - Depend on libtiff-dev instead of libtiff4-dev
  - Drop digikam breaks/replaces kipi-plugins-common since we're past the
    LTS release now
  - digikam to recommend mplayerthumbs | ffmpegthumbs. We currently only
    have latter in the archives, even though former is also supposed to
    be part of kdemultimedia. (LP: #890059)
  - kipi-plugins to recommend www-browser rather than konqueror directly
    since 2.8 no direct usage of konqueror is present in the flickr
    plugin anymore (LP: #1011211)
  - Keep kubuntu_mysqld_executable_name.diff
  - Don't install libkipi translations
  - Keep deps on libcv-dev, libcvaux-dev
  - Keep split packaging of libraries
  - Replace icons from KDE 3 time in debian/xpm.d/*.xpm with the new
    versions (LP: #658047)
* Update debian/not-installed

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   WF debanding code
 
3
   Copyright 2011 by Yan Vladimirovich
 
4
 
 
5
   Used in LibRaw with author permission.
 
6
 
 
7
LibRaw is free software; you can redistribute it and/or modify
 
8
it under the terms of the one of three licenses as you choose:
 
9
 
 
10
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
 
11
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
 
12
 
 
13
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
 
14
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
 
15
 
 
16
3. LibRaw Software License 27032010
 
17
   (See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
 
18
 
 
19
   This file is generated from Dave Coffin's dcraw.c
 
20
   dcraw.c -- Dave Coffin's raw photo decoder
 
21
   Copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net
 
22
 
 
23
   Look into dcraw homepage (probably http://cybercom.net/~dcoffin/dcraw/)
 
24
   for more information
 
25
*/
 
26
 
 
27
 
 
28
#define P1 imgdata.idata
 
29
#define S imgdata.sizes
 
30
#define O imgdata.params
 
31
#define C imgdata.color
 
32
#define T imgdata.thumbnail
 
33
#define IO libraw_internal_data.internal_output_params
 
34
#define ID libraw_internal_data.internal_data
 
35
 
 
36
 
 
37
int LibRaw::wf_remove_banding()
 
38
{
 
39
#define WF_IMGMODE_BAYER4PLANE 4
 
40
#define WF_IMGMODE_BAYER1PLANE 1
 
41
 
 
42
#define WF_GREENMODE_IND   0
 
43
#define WF_GREENMODE_GX_XG 1
 
44
#define WF_GREENMODE_XG_GX 2
 
45
 
 
46
#define WF_DEBANDING_OK          0
 
47
#define WF_DEBANDING_NOTBAYER2X2 1
 
48
#define WF_DEBANDING_TOOSMALL    2
 
49
 
 
50
#define WF_GAUSS_PIRAMID_SIZE 4
 
51
 
 
52
#define WF_MAXTRESHOLD 65536
 
53
 
 
54
#define WF_BAYERSRC(row, col, c) ((ushort(*)[4])imgdata.image)[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][c] 
 
55
#define WF_BAYERGAU(l, row, col) (gauss_pyramid[l])[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)] 
 
56
#define WF_BAYERDFG(l, row, col) (difwg_pyramid[l])[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)] 
 
57
        
 
58
#define MIN(a,b) ((a) < (b) ? (a) : (b))
 
59
#define MAX(a,b) ((a) > (b) ? (a) : (b))
 
60
 
 
61
#define WF_i_1TO4 for(int i=0; i<4; i++)
 
62
 
 
63
        // too small?
 
64
 
 
65
        if (S.width<128 || S.height<128)
 
66
                return WF_DEBANDING_TOOSMALL;
 
67
 
 
68
        // is 2x2 bayer? 
 
69
 
 
70
        int bayer2x2flag=-1;
 
71
 
 
72
        for(int row_shift=0; row_shift<=8; row_shift+=2)
 
73
        {
 
74
                for(int col_shift=0; col_shift<=8; col_shift+=2)
 
75
                {
 
76
                        if ((FC(0,0)!=FC(row_shift,   col_shift))   ||
 
77
                                (FC(1,0)!=FC(row_shift+1, col_shift))   ||
 
78
                                (FC(0,1)!=FC(row_shift,   col_shift+1)) ||
 
79
                                (FC(1,1)!=FC(row_shift+1, col_shift+1)))
 
80
                        {
 
81
                                bayer2x2flag=0;
 
82
                        }
 
83
                }
 
84
        }
 
85
 
 
86
        if (bayer2x2flag==0)
 
87
                return WF_DEBANDING_NOTBAYER2X2;
 
88
 
 
89
        int    x_green_flag = -1;
 
90
 
 
91
        int    width_d2,    height_d2;
 
92
        int    width_p1_d2, height_p1_d2;
 
93
 
 
94
        width_d2  = S.width/2;
 
95
        height_d2 = S.height/2;
 
96
        
 
97
        width_p1_d2  = (S.width+1)/2;
 
98
        height_p1_d2 = (S.height+1)/2;
 
99
 
 
100
        ushort  val_max_c[4]={0,0,0,0};
 
101
        ushort  val_max;
 
102
 
 
103
        ushort  dummy_pixel=0;
 
104
        ushort *dummy_line;
 
105
 
 
106
        dummy_line = (ushort*)calloc(S.width, sizeof(ushort)*4);
 
107
 
 
108
        for(int i=0; i<S.width*4; i++)
 
109
                dummy_line[i]=0;
 
110
 
 
111
        // Searching max value for increasing bit-depth
 
112
 
 
113
        for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
 
114
        {
 
115
                int     row, row_p1;
 
116
                ushort *src[4];
 
117
                ushort *src_first, *src_plast, *src_last;
 
118
                
 
119
                row    = row_d2*2;
 
120
                row_p1 = row+1;
 
121
 
 
122
                WF_i_1TO4 src[i] = &WF_BAYERSRC((i<2)?row:row_p1, i&1, FC((i<2)?row:row_p1, i&1));
 
123
 
 
124
                if (row_p1==S.height)
 
125
                        src[2]=src[3]=dummy_line;
 
126
 
 
127
                src_first   = &WF_BAYERSRC(row,   0,               FC(row,   0));
 
128
                src_plast   = &WF_BAYERSRC(row,   width_d2*2-2,    FC(row,   0));
 
129
                src_last    = &WF_BAYERSRC(row,   width_p1_d2*2-2, FC(row,   0));
 
130
 
 
131
                do
 
132
                {
 
133
                        // Do
 
134
 
 
135
                        WF_i_1TO4 val_max_c[i]=MAX(val_max_c[i], *src[i]);
 
136
 
 
137
                        // Next 4 pixel or exit
 
138
 
 
139
                        if     (src[0]<src_plast)
 
140
                        {
 
141
                                WF_i_1TO4 src[i]+=8;
 
142
                        }
 
143
                        else if(src[0]>src_first && src[0]<src_last)
 
144
                        {
 
145
                                WF_i_1TO4 src[i]=i&1?&dummy_pixel:src[i]+8;
 
146
                        }
 
147
                        else break;
 
148
 
 
149
                }
 
150
                while(1);
 
151
        }
 
152
 
 
153
        val_max=MAX(MAX(val_max_c[0], val_max_c[1]), MAX(val_max_c[2], val_max_c[3]));
 
154
        
 
155
        // end of searching max value
 
156
 
 
157
        if (val_max==0)
 
158
                return WF_DEBANDING_OK;
 
159
                
 
160
        int data_shift;
 
161
        int data_mult;
 
162
        int val_max_s;
 
163
 
 
164
        data_shift = 15;
 
165
        val_max_s  = val_max;
 
166
 
 
167
        if (val_max_s >= (1 << 8)) { val_max_s >>= 8; data_shift -=  8; }
 
168
        if (val_max_s >= (1 << 4)) { val_max_s >>= 4; data_shift -=  4; }
 
169
        if (val_max_s >= (1 << 2)) { val_max_s >>= 2; data_shift -=  2; }
 
170
        if (val_max_s >= (1 << 1)) {                  data_shift -=  1; }
 
171
  
 
172
        data_mult = 1<<data_shift;
 
173
        val_max <<= data_shift;
 
174
                
 
175
        // Bit shift
 
176
 
 
177
        for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
 
178
        {
 
179
                int     row, row_p1;
 
180
                ushort *src[4];
 
181
                ushort *src_first, *src_plast, *src_last;
 
182
                
 
183
                row    = row_d2*2;
 
184
                row_p1 = row+1;
 
185
 
 
186
                WF_i_1TO4 src[i] = &WF_BAYERSRC((i<2)?row:row_p1, i&1, FC((i<2)?row:row_p1, i&1));
 
187
 
 
188
                if (row_p1==S.height)
 
189
                        src[2]=src[3]=dummy_line;
 
190
 
 
191
                src_first   = &WF_BAYERSRC(row,   0,               FC(row,   0));
 
192
                src_plast   = &WF_BAYERSRC(row,   width_d2*2-2,    FC(row,   0));
 
193
                src_last    = &WF_BAYERSRC(row,   width_p1_d2*2-2, FC(row,   0));
 
194
 
 
195
                do
 
196
                {
 
197
                        // Do
 
198
 
 
199
                        WF_i_1TO4 (*src[i])<<=data_shift;
 
200
 
 
201
                        // Next 4 pixel or exit
 
202
 
 
203
                        if     (src[0]<src_plast)
 
204
                        {
 
205
                                WF_i_1TO4 src[i]+=8;
 
206
                        }
 
207
                        else if(src[0]>src_first && src[0]<src_last)
 
208
                        {
 
209
                                WF_i_1TO4 src[i]=i&1?&dummy_pixel:src[i]+8;
 
210
                        }
 
211
                        else break;
 
212
 
 
213
                }
 
214
                while(1);
 
215
        }
 
216
 
 
217
        ushort *gauss_pyramid[WF_GAUSS_PIRAMID_SIZE];
 
218
        ushort *difwg_pyramid[WF_GAUSS_PIRAMID_SIZE];
 
219
 
 
220
        for(int i=0; i<WF_GAUSS_PIRAMID_SIZE; i++)
 
221
        {
 
222
                gauss_pyramid[i] = (ushort*)calloc(S.width*S.height, sizeof(ushort));
 
223
                difwg_pyramid[i] = (ushort*)calloc(S.width*S.height, sizeof(ushort));
 
224
        }
 
225
 
 
226
        int radius3x3 [4]={3,  3,  3,  0}; // as gau r=24
 
227
        int radius3x14[4]={14, 14, 14, 0}; // as gau r=420
 
228
        int radius3x45[4]={45, 45, 45, 0}; // as gau r=4140
 
229
 
 
230
        // Making 4-level gaussian pyramid
 
231
 
 
232
        if (x_green_flag)
 
233
        {
 
234
                wf_bayer4_green_blur   (0,          imgdata.image,    WF_IMGMODE_BAYER4PLANE, gauss_pyramid[0], WF_IMGMODE_BAYER1PLANE);
 
235
                wf_bayer4_igauss_filter(1,          gauss_pyramid[0], WF_IMGMODE_BAYER1PLANE, gauss_pyramid[0], WF_IMGMODE_BAYER1PLANE);
 
236
        }
 
237
        else
 
238
        {
 
239
                wf_bayer4_igauss_filter(1,          imgdata.image,    WF_IMGMODE_BAYER4PLANE, gauss_pyramid[0], WF_IMGMODE_BAYER1PLANE);
 
240
        }
 
241
 
 
242
        wf_bayer4_block_filter (radius3x3,  gauss_pyramid[0], WF_IMGMODE_BAYER1PLANE, gauss_pyramid[1], WF_IMGMODE_BAYER1PLANE); // as gau r=24
 
243
        wf_bayer4_block_filter (radius3x14, gauss_pyramid[0], WF_IMGMODE_BAYER1PLANE, gauss_pyramid[2], WF_IMGMODE_BAYER1PLANE); // as gau r=420
 
244
        wf_bayer4_block_filter (radius3x45, gauss_pyramid[0], WF_IMGMODE_BAYER1PLANE, gauss_pyramid[3], WF_IMGMODE_BAYER1PLANE); // as gau r=4140 
 
245
 
 
246
        
 
247
        // Energy multiplyers for laplasyan pyramid
 
248
 
 
249
        float dfg_mult[WF_GAUSS_PIRAMID_SIZE]={1.560976, 8.196011, 180.413773, 3601.427246/3.0};
 
250
 
 
251
/*      dif_mult[0]=1.0/wf_filter_energy(0, 0,   0,    1);
 
252
        dif_mult[1]=1.0/wf_filter_energy(0, 1,   0,   24);
 
253
        dif_mult[2]=1.0/wf_filter_energy(0, 24,  0,  420);
 
254
        dif_mult[3]=1.0/wf_filter_energy(0, 420, 0, 4140);*/
 
255
 
 
256
        float dfg_mulg[WF_GAUSS_PIRAMID_SIZE]={1.235223, 19.813868, 365.148407, 7208.362793/3.0};
 
257
 
 
258
/*      dif_mulg[0]=1.0/wf_filter_energy(0, 0,    1,    1);
 
259
        dif_mulg[1]=1.0/wf_filter_energy(1, 1,    1,   24);
 
260
        dif_mulg[2]=1.0/wf_filter_energy(1, 24,   1,  420);
 
261
        dif_mulg[3]=1.0/wf_filter_energy(1, 420,  1, 4140);*/
 
262
 
 
263
        float    dfg_mlcc[WF_GAUSS_PIRAMID_SIZE][4];
 
264
        long int dfg_dmax[WF_GAUSS_PIRAMID_SIZE][4];
 
265
 
 
266
        int green_mode;
 
267
 
 
268
        if      ( x_green_flag && (imgdata.idata.cdesc[FC(0, 0)] == imgdata.idata.cdesc[FC(1, 1)]) )
 
269
                green_mode = WF_GREENMODE_GX_XG;
 
270
        else if ( x_green_flag && (imgdata.idata.cdesc[FC(0, 1)] == imgdata.idata.cdesc[FC(1, 0)]) )
 
271
                green_mode = WF_GREENMODE_XG_GX;
 
272
        else
 
273
                green_mode = WF_GREENMODE_IND;
 
274
        
 
275
        for(int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
276
        {
 
277
                switch (green_mode)
 
278
                {
 
279
                        case WF_GREENMODE_GX_XG:
 
280
 
 
281
                                dfg_mlcc[l][0]=dfg_mlcc[l][3]=dfg_mulg[l];
 
282
                                dfg_dmax[l][0]=dfg_dmax[l][3]=65535/dfg_mulg[l];
 
283
 
 
284
                                dfg_mlcc[l][1]=dfg_mlcc[l][2]=dfg_mult[l];
 
285
                                dfg_dmax[l][1]=dfg_dmax[l][2]=65535/dfg_mult[l];
 
286
                                
 
287
                                break;
 
288
 
 
289
                        case WF_GREENMODE_XG_GX:
 
290
 
 
291
                                dfg_mlcc[l][1]=dfg_mlcc[l][2]=dfg_mulg[l];
 
292
                                dfg_dmax[l][1]=dfg_dmax[l][2]=65535/dfg_mulg[l];
 
293
 
 
294
                                dfg_mlcc[l][0]=dfg_mlcc[l][3]=dfg_mult[l];
 
295
                                dfg_dmax[l][0]=dfg_dmax[l][3]=65535/dfg_mult[l];
 
296
                                
 
297
                                break;
 
298
                        
 
299
                        case WF_GREENMODE_IND:
 
300
 
 
301
                                dfg_mlcc[l][0]=dfg_mlcc[l][1]=dfg_mlcc[l][2]=dfg_mlcc[l][3]=dfg_mult[l];
 
302
                                dfg_dmax[l][0]=dfg_dmax[l][1]=dfg_dmax[l][2]=dfg_dmax[l][3]=65535/dfg_mult[l];
 
303
                                
 
304
                                break;
 
305
                }
 
306
        }
 
307
 
 
308
        // laplasyan energy
 
309
 
 
310
        for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
 
311
        {
 
312
                int     row, row_p1;
 
313
                ushort *src[4];
 
314
 
 
315
                ushort *gau[WF_GAUSS_PIRAMID_SIZE][4];
 
316
                ushort *dfg[WF_GAUSS_PIRAMID_SIZE][4];
 
317
 
 
318
                row    = row_d2*2;
 
319
                row_p1 = row+1;
 
320
 
 
321
                WF_i_1TO4 src[i] = &WF_BAYERSRC((i<2)?row:row_p1, i&1, FC((i<2)?row:row_p1, i&1));
 
322
 
 
323
                if (row_p1==S.height)
 
324
                        src[2]=src[3]=dummy_line;
 
325
 
 
326
                for(int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
327
                {
 
328
                        WF_i_1TO4 gau[l][i] = &WF_BAYERGAU(l, (i<2)?row:row_p1, i&1);
 
329
 
 
330
                        WF_i_1TO4 dfg[l][i] = &WF_BAYERDFG(l, (i<2)?row:row_p1, i&1);
 
331
 
 
332
                        if ((row+1)==S.height)
 
333
                                dfg[l][2]=dfg[l][3]=gau[l][2]=gau[l][3]=dummy_line;
 
334
                }
 
335
 
 
336
                ushort *src_first, *src_last, *src_last2;
 
337
 
 
338
                src_first   = &WF_BAYERSRC(row,   0,               FC(row,   0));
 
339
                src_last    = &WF_BAYERSRC(row,   width_d2*2-2,    FC(row,   0));
 
340
                src_last2   = &WF_BAYERSRC(row,   width_p1_d2*2-2, FC(row,   0));
 
341
 
 
342
                do
 
343
                {
 
344
                        long int val_gau[4];
 
345
                        long int val_dif[4];
 
346
                        long int val_src[4];
 
347
 
 
348
                        WF_i_1TO4 val_src[i]=*src[i];
 
349
 
 
350
                        for(int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
351
                        {
 
352
                                WF_i_1TO4 val_gau[i]=*gau[l][i];
 
353
                                WF_i_1TO4 val_dif[i]=val_src[i]-val_gau[i];
 
354
                                WF_i_1TO4 val_src[i]=val_gau[i];
 
355
                                WF_i_1TO4 val_dif[i]*=val_dif[i];
 
356
 
 
357
                                WF_i_1TO4
 
358
                                        if(val_dif[i]<dfg_dmax[l][i])
 
359
                                        {
 
360
                                                val_dif[i]*=dfg_mlcc[l][i];
 
361
                                                *dfg[l][i] =val_dif[i];
 
362
                                        }
 
363
                                        else
 
364
                                        {
 
365
                                                *dfg[l][i]=65535;
 
366
                                        }
 
367
                        }
 
368
 
 
369
                        // Next 4 pixel or exit
 
370
 
 
371
                        if     (src[0]<src_last)
 
372
                        {
 
373
                                WF_i_1TO4 src[i]+=8;
 
374
 
 
375
                                for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
376
                                        WF_i_1TO4 gau[l][i]+=2;
 
377
 
 
378
                                for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
379
                                        WF_i_1TO4 dfg[l][i]+=2;
 
380
                        }
 
381
                        else if(src[0]>src_first && src[0]<src_last2)
 
382
                        {
 
383
                                WF_i_1TO4 src[i]=i&1?&dummy_pixel:src[i]+8;
 
384
 
 
385
                                for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
386
                                        WF_i_1TO4 gau[l][i]=i&1?&dummy_pixel:gau[l][i]+2;
 
387
 
 
388
                                for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
389
                                        WF_i_1TO4 dfg[l][i]=i&1?&dummy_pixel:dfg[l][i]+2;
 
390
                        }
 
391
                        else break;
 
392
                }
 
393
                while(1);
 
394
        }
 
395
        
 
396
        int radius2x32 [3]={32, 32, 0};
 
397
        int radius2x56 [3]={56, 56, 0};
 
398
        int radius2x90 [3]={90, 90, 0};
 
399
        int radius2x104[3]={104, 104, 0};
 
400
 
 
401
        if (x_green_flag)
 
402
        {
 
403
                for(int i=0;i<4;i++)
 
404
                        wf_bayer4_green_blur   (0,           difwg_pyramid[i], WF_IMGMODE_BAYER1PLANE, difwg_pyramid[i], WF_IMGMODE_BAYER1PLANE);
 
405
        }
 
406
 
 
407
        wf_bayer4_block_filter (radius2x32,  difwg_pyramid[0], WF_IMGMODE_BAYER1PLANE, difwg_pyramid[0], WF_IMGMODE_BAYER1PLANE);
 
408
        wf_bayer4_block_filter (radius2x56,  difwg_pyramid[1], WF_IMGMODE_BAYER1PLANE, difwg_pyramid[1], WF_IMGMODE_BAYER1PLANE);
 
409
        wf_bayer4_block_filter (radius2x90,  difwg_pyramid[2], WF_IMGMODE_BAYER1PLANE, difwg_pyramid[2], WF_IMGMODE_BAYER1PLANE);
 
410
        wf_bayer4_block_filter (radius2x104, difwg_pyramid[3], WF_IMGMODE_BAYER1PLANE, difwg_pyramid[3], WF_IMGMODE_BAYER1PLANE);
 
411
 
 
412
        float (*banding_col)[4];
 
413
        float (*banding_row)[4];
 
414
        float (*banding_col_count)[4];
 
415
        float (*banding_row_count)[4];
 
416
 
 
417
        banding_col       = (float(*)[4])calloc(height_p1_d2, sizeof(float)*4);
 
418
        banding_col_count = (float(*)[4])calloc(height_p1_d2, sizeof(float)*4);
 
419
 
 
420
        banding_row       = (float(*)[4])calloc(width_p1_d2, sizeof(float)*4);
 
421
        banding_row_count = (float(*)[4])calloc(width_p1_d2, sizeof(float)*4);
 
422
 
 
423
        for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
 
424
                WF_i_1TO4 banding_col[row_d2][i]=banding_col_count[row_d2][i]=0;
 
425
 
 
426
        for(int col_d2=0; col_d2<width_p1_d2; col_d2++)
 
427
                WF_i_1TO4 banding_row[col_d2][i]=banding_row_count[col_d2][i]=0;
 
428
 
 
429
        long int val_accepted;
 
430
        float    treshold[4];
 
431
 
 
432
        WF_i_1TO4 treshold[i]=imgdata.params.wf_deband_treshold[FC(i>>1,i&1)];
 
433
 
 
434
        val_accepted = val_max-3*MAX(MAX(treshold[0],treshold[1]),MAX(treshold[2],treshold[3]));
 
435
 
 
436
        float (*tr_weight)[4];
 
437
 
 
438
        tr_weight=(float(*)[4])calloc(WF_MAXTRESHOLD*4, sizeof(float));
 
439
 
 
440
        WF_i_1TO4 treshold[i]*=data_mult;
 
441
 
 
442
        for(int v=0; v<WF_MAXTRESHOLD; v++)
 
443
        {
 
444
                for(int i=0; i<4; i++)
 
445
                {
 
446
                        if (v<treshold[i]*treshold[i])
 
447
                                tr_weight[v][i] = 1.0;
 
448
                        else if (v*5<6*treshold[i]*treshold[i])
 
449
                                tr_weight[v][i] = 6.0-5.0*float(v)/(treshold[i]*treshold[i]);
 
450
                        else
 
451
                                tr_weight[v][i] = 0.0;
 
452
                }
 
453
        }
 
454
 
 
455
        for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
 
456
        {
 
457
                int     row, row_p1;
 
458
                ushort *src[4];
 
459
 
 
460
                ushort *gau[WF_GAUSS_PIRAMID_SIZE][4];
 
461
                ushort *dfg[WF_GAUSS_PIRAMID_SIZE][4];
 
462
 
 
463
                row    = row_d2*2;
 
464
                row_p1 = row+1;
 
465
 
 
466
                WF_i_1TO4 src[i] = &WF_BAYERSRC((i<2)?row:row_p1, i&1, FC((i<2)?row:row_p1, i&1));
 
467
 
 
468
                if (row_p1==S.height)
 
469
                        src[2]=src[3]=dummy_line;
 
470
 
 
471
                for(int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
472
                {
 
473
                        WF_i_1TO4 gau[l][i] = &WF_BAYERGAU(l, (i<2)?row:row_p1, i&1);
 
474
 
 
475
                        WF_i_1TO4 dfg[l][i] = &WF_BAYERDFG(l, (i<2)?row:row_p1, i&1);
 
476
 
 
477
                        if (row_p1==S.height)
 
478
                                dfg[l][2]=dfg[l][3]=gau[l][2]=gau[l][3]=dummy_line;
 
479
                }
 
480
 
 
481
                ushort *src_first, *src_last, *src_last2;
 
482
 
 
483
                src_first   = &WF_BAYERSRC(row,   0,               FC(row,   0));
 
484
                src_last    = &WF_BAYERSRC(row,   width_d2*2-2,    FC(row,   0));
 
485
                src_last2   = &WF_BAYERSRC(row,   width_p1_d2*2-2, FC(row,   0));
 
486
 
 
487
                int col_d2 = 0;
 
488
 
 
489
                do
 
490
                {
 
491
                        float val_src[4];
 
492
 
 
493
                        float bsum[4]={0,0,0,0};
 
494
                        float wsum[4]={0,0,0,0};
 
495
 
 
496
                        WF_i_1TO4 val_src[i]=*src[i];
 
497
 
 
498
                        for(int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
499
                        {
 
500
                                float val_dif[4];
 
501
                                float val_gau[4];
 
502
                                float wght[4];
 
503
 
 
504
                                WF_i_1TO4 val_gau[i] =  *gau[l][i];
 
505
                                WF_i_1TO4 val_dif[i] =  val_src[i]-val_gau[i];
 
506
                                WF_i_1TO4 val_src[i] =  val_gau[i];
 
507
 
 
508
                                WF_i_1TO4 wght[i]    =  tr_weight[*dfg[l][i]][i];
 
509
                                WF_i_1TO4 wsum[i]    += wght[i];
 
510
                                WF_i_1TO4 bsum[i]    += wght[i]*val_dif[i];
 
511
                        }
 
512
 
 
513
                        //WF_i_1TO4 *src[i]=bsum[i];
 
514
 
 
515
                        WF_i_1TO4 wsum[i]*=wsum[i];
 
516
 
 
517
                        WF_i_1TO4 banding_col      [row_d2][i] += bsum[i]*wsum[i];
 
518
                        WF_i_1TO4 banding_col_count[row_d2][i] += wsum[i];
 
519
 
 
520
                        WF_i_1TO4 banding_row      [col_d2][i] += bsum[i]*wsum[i];
 
521
                        WF_i_1TO4 banding_row_count[col_d2][i] += wsum[i];
 
522
 
 
523
                        // Next 4 pixel or exit
 
524
 
 
525
                        if     (src[0]<src_last)
 
526
                        {
 
527
                                WF_i_1TO4 src[i]+=8;
 
528
 
 
529
                                for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
530
                                        WF_i_1TO4 gau[l][i]+=2;
 
531
 
 
532
                                for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
533
                                        WF_i_1TO4 dfg[l][i]+=2;
 
534
                        }
 
535
                        else if(src[0]>src_first && src[0]<src_last2)
 
536
                        {
 
537
                                WF_i_1TO4 src[i]=i&1?&dummy_pixel:src[i]+8;
 
538
 
 
539
                                for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
540
                                        WF_i_1TO4 gau[l][i]=i&1?&dummy_pixel:gau[l][i]+2;
 
541
 
 
542
                                for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
 
543
                                        WF_i_1TO4 dfg[l][i]=i&1?&dummy_pixel:dfg[l][i]+2;
 
544
                        }
 
545
                        else break;
 
546
 
 
547
                        col_d2++;
 
548
                }
 
549
                while(1);
 
550
        }
 
551
 
 
552
        float bsum[4], bmean[4];
 
553
 
 
554
        int (*banding_col_i)[4];
 
555
        int (*banding_row_i)[4];
 
556
 
 
557
        banding_col_i = (int(*)[4])calloc(height_p1_d2, sizeof(int)*4);
 
558
        banding_row_i = (int(*)[4])calloc(width_p1_d2,  sizeof(int)*4);
 
559
        
 
560
        // cols
 
561
 
 
562
        WF_i_1TO4 bsum[i]=bmean[i]=0;
 
563
 
 
564
        for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
 
565
                for(int i=0; i<4; i++)
 
566
                {
 
567
                        if (banding_col_count[row_d2][i]>0)
 
568
                        {
 
569
                                banding_col[row_d2][i]=banding_col[row_d2][i]/banding_col_count[row_d2][i];
 
570
                                bsum[i]+=banding_col[row_d2][i];
 
571
                        }
 
572
                }
 
573
 
 
574
        WF_i_1TO4 bmean[i]=bsum[i]/(i<2?height_d2:height_p1_d2);
 
575
                
 
576
        for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
 
577
                for(int i=0; i<4; i++)
 
578
                        banding_col_i[row_d2][i]=int(banding_col[row_d2][i]-bmean[i]);
 
579
 
 
580
        // rows
 
581
 
 
582
        WF_i_1TO4 bsum[i]=bmean[i]=0;
 
583
 
 
584
        for(int col_d2=0; col_d2<width_p1_d2; col_d2++)
 
585
                for(int i=0; i<4; i++)
 
586
                {
 
587
                        if (banding_row_count[col_d2][i]>0)
 
588
                        {
 
589
                                banding_row[col_d2][i]=(banding_row[col_d2][i]/banding_row_count[col_d2][i]);
 
590
                                bsum[i]+=banding_row[col_d2][i];
 
591
                        }
 
592
                }
 
593
 
 
594
        WF_i_1TO4 bmean[i]=bsum[i]/(i<2?width_d2:width_p1_d2);
 
595
 
 
596
        for(int col_d2=0; col_d2<width_p1_d2; col_d2++)
 
597
                for(int i=0; i<4; i++)
 
598
                        if (banding_row_count[col_d2][i]>0)
 
599
                                banding_row_i[col_d2][i]=int(banding_row[col_d2][i]-bmean[i]);
 
600
 
 
601
        for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
 
602
        {
 
603
                int     row, row_p1;
 
604
                ushort *src[4];
 
605
                ushort *src_first, *src_plast, *src_last;
 
606
                
 
607
                row    = row_d2*2;
 
608
                row_p1 = row+1;
 
609
 
 
610
                WF_i_1TO4 src[i] = &WF_BAYERSRC((i<2)?row:row_p1, i&1, FC((i<2)?row:row_p1, i&1));
 
611
 
 
612
                if (row_p1==S.height)
 
613
                        src[2]=src[3]=dummy_line;
 
614
 
 
615
                src_first   = &WF_BAYERSRC(row,   0,               FC(row,   0));
 
616
                src_plast   = &WF_BAYERSRC(row,   width_d2*2-2,    FC(row,   0));
 
617
                src_last    = &WF_BAYERSRC(row,   width_p1_d2*2-2, FC(row,   0));
 
618
 
 
619
                int col_d2=0;
 
620
 
 
621
                do
 
622
                {
 
623
                        // Do
 
624
 
 
625
                        int val_new[4];
 
626
 
 
627
                        WF_i_1TO4 val_new[i]=*src[i];
 
628
                        WF_i_1TO4 val_new[i]-=banding_col_i[row_d2][i];
 
629
                        WF_i_1TO4 val_new[i]-=banding_row_i[col_d2][i];
 
630
 
 
631
                        for(int i=0; i<4; i++)
 
632
                        {
 
633
                                if (*src[i]>=val_accepted)
 
634
                                {
 
635
                                        val_new[i]=*src[i]>>data_shift;
 
636
                                }
 
637
                                else
 
638
                                {
 
639
                                        if      (val_new[i]>val_max)
 
640
                                                val_new[i]=val_max;
 
641
                                        else if (val_new[i]<0)
 
642
                                                val_new[i]=0;
 
643
 
 
644
                                        val_new[i]>>=data_shift;
 
645
                                }
 
646
                        }
 
647
 
 
648
                        WF_i_1TO4 *src[i]=val_new[i];
 
649
 
 
650
                        // Next 4 pixel or exit
 
651
 
 
652
                        if     (src[0]<src_plast)
 
653
                        {
 
654
                                WF_i_1TO4 src[i]+=8;
 
655
                        }
 
656
                        else if(src[0]>src_first && src[0]<src_last)
 
657
                        {
 
658
                                WF_i_1TO4 src[i]=i&1?&dummy_pixel:src[i]+8;
 
659
                        }
 
660
                        else break;
 
661
 
 
662
                        col_d2++;
 
663
                }
 
664
                while(1);
 
665
        }
 
666
 
 
667
        free(banding_col_i);
 
668
        free(banding_row_i);
 
669
 
 
670
        free(tr_weight);
 
671
        
 
672
        free(banding_col);
 
673
        free(banding_col_count);
 
674
 
 
675
        free(banding_row);
 
676
        free(banding_row_count);
 
677
 
 
678
        for(int i=0; i<WF_GAUSS_PIRAMID_SIZE; i++)
 
679
        {
 
680
                free(gauss_pyramid[i]);
 
681
                free(difwg_pyramid[i]);
 
682
        }
 
683
 
 
684
        free(dummy_line);
 
685
        
 
686
}
 
687
 
 
688
double LibRaw::wf_filter_energy(int r1_greenmode, int r1, int r2_greenmode, int r2)
 
689
{
 
690
        /* 
 
691
                This function caclulates energy of laplasyan piramid level.
 
692
                Laplasyan level is difference between two 2D gaussian (exactly, binominal) convolutions with radius r1 and r2
 
693
                Convolution is done on bayer data, 4 channels, and if (greenmode), additive on green channel.
 
694
        
 
695
                Not optimized, because now it's used only for precalculations.
 
696
        */
 
697
 
 
698
 
 
699
#define WF_MAXFILTERSIZE 10000
 
700
 
 
701
        int rmin, rmax;
 
702
        int rmin_greenmode, rmax_greenmode;
 
703
 
 
704
        if (r1>r2)
 
705
        {
 
706
                rmax=r1;
 
707
                rmin=r2;
 
708
                rmax_greenmode=r1_greenmode;
 
709
                rmin_greenmode=r2_greenmode;
 
710
        }
 
711
        else
 
712
        {
 
713
                rmax=r2;
 
714
                rmin=r1;
 
715
                rmax_greenmode=r2_greenmode;
 
716
                rmin_greenmode=r1_greenmode;
 
717
        }
 
718
 
 
719
 
 
720
        int rmin_x2_p1, rmax_x2_p1;
 
721
        rmin_x2_p1=rmin*2+1;
 
722
        rmax_x2_p1=rmax*2+1;
 
723
 
 
724
        double gau_kernel_rmin[WF_MAXFILTERSIZE];
 
725
        double gau_kernel_rmax[WF_MAXFILTERSIZE];
 
726
 
 
727
        for(int i=0; i<rmax_x2_p1; i++)
 
728
                gau_kernel_rmin[i]=0;
 
729
 
 
730
        gau_kernel_rmin[1]=1.0;
 
731
                                
 
732
        for(int i=2; i<=rmin_x2_p1; i++)
 
733
        {
 
734
                for(int j=i; j>0; j--)
 
735
                        gau_kernel_rmin[j]=0.5*(gau_kernel_rmin[j]+gau_kernel_rmin[j-1]);
 
736
        }
 
737
 
 
738
        for(int i=0; i<=rmax_x2_p1; i++)
 
739
                gau_kernel_rmax[i]=gau_kernel_rmin[i];
 
740
 
 
741
        for(int i=rmin_x2_p1+1; i<=rmax_x2_p1; i++)
 
742
        {
 
743
                for(int j=i; j>0; j--)
 
744
                        gau_kernel_rmax[j]=0.5*(gau_kernel_rmax[j]+gau_kernel_rmax[j-1]);
 
745
        }
 
746
 
 
747
        double wmin_sum, wmax_sum, energy_sum;
 
748
 
 
749
        wmin_sum=0;
 
750
        wmax_sum=0;
 
751
        energy_sum=0;
 
752
 
 
753
        for(int row=-rmax*2-1; row<=rmax*2+1; row++)
 
754
        {
 
755
                for(int col=-rmax*2-1; col<=rmax*2+1; col++)
 
756
                {
 
757
                        double wght_rmax=0;
 
758
                        double wght_rmin=0;
 
759
 
 
760
#define WF_WMAX(row, col) (((abs(row)<=rmax*2)&&(abs(col)<=rmax*2))?gau_kernel_rmax[abs(row)/2+rmax+1]*gau_kernel_rmax[abs(col)/2+rmax+1]:0)
 
761
#define WF_WMIN(row, col) (((abs(row)<=rmin*2)&&(abs(col)<=rmin*2))?gau_kernel_rmin[abs(row)/2+rmin+1]*gau_kernel_rmin[abs(col)/2+rmin+1]:0)
 
762
 
 
763
                        if ( ((row&1)==0) && ((col&1)==0))
 
764
                        {
 
765
                                wght_rmax = WF_WMAX(row, col);
 
766
                                wght_rmin = WF_WMIN(row, col);
 
767
                        }
 
768
 
 
769
                        if (rmax_greenmode)
 
770
                        {
 
771
                                if ( ((row&1)==0) && ((col&1)==0))
 
772
                                        wght_rmax = 0.5*wght_rmax;
 
773
                                else if ( ((row&1)==1) && ((col&1)==1))
 
774
                                {
 
775
                                        wght_rmax = 0.125*(WF_WMAX(row-1, col-1)+WF_WMAX(row-1, col+1)+WF_WMAX(row+1, col-1)+WF_WMAX(row+1, col+1));
 
776
                                }
 
777
                        }
 
778
 
 
779
                        if (rmin_greenmode)
 
780
                        {
 
781
                                if ( ((row&1)==0) && ((col&1)==0))
 
782
                                        wght_rmin = 0.5*wght_rmin;
 
783
                                else if ( ((row&1)==1) && ((col&1)==1))
 
784
                                {
 
785
                                        wght_rmin = 0.125*(WF_WMIN(row-1, col-1)+WF_WMIN(row-1, col+1)+WF_WMIN(row+1, col-1)+WF_WMIN(row+1, col+1));
 
786
                                }
 
787
                        }
 
788
 
 
789
                        wmin_sum+=wght_rmin;
 
790
                        wmax_sum+=wght_rmax;
 
791
 
 
792
                        energy_sum+=(wght_rmax-wght_rmin)*(wght_rmax-wght_rmin);
 
793
                }
 
794
                
 
795
        }
 
796
 
 
797
        return energy_sum;
 
798
}
 
799
 
 
800
void LibRaw::wf_bayer4_green_blur(int mode, void* src_image, int src_imgmode, void* dst_image, int dst_imgmode)
 
801
{
 
802
        /* 
 
803
                This function filters green (or any "diagonal") channel of bayer4 data with "X" kernel,
 
804
 
 
805
                1 1
 
806
                 4
 
807
                1 1
 
808
        */
 
809
 
 
810
#define WF_BAYERSRC4(row, col, c) ((ushort(*)[4])src_image)[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][c] 
 
811
#define WF_BAYERSRC1(row, col)    ((ushort*)src_image)     [((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)] 
 
812
#define WF_BAYERDST4(row, col, c) ((ushort(*)[4])dst_image)[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][c] 
 
813
#define WF_BAYERDST1(row, col)    ((ushort*)dst_image)     [((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)]
 
814
 
 
815
        int green_mode;
 
816
 
 
817
        if ( imgdata.idata.cdesc[FC(0, 0)] == imgdata.idata.cdesc[FC(1, 1)] )
 
818
                green_mode = WF_GREENMODE_GX_XG;
 
819
        else if ( imgdata.idata.cdesc[FC(0, 1)] == imgdata.idata.cdesc[FC(1, 0)] )
 
820
                green_mode = WF_GREENMODE_XG_GX;
 
821
        else
 
822
                green_mode = WF_GREENMODE_IND;
 
823
 
 
824
        int src_h_shift, dst_h_shift, src_h_shift_x2;
 
825
 
 
826
        if      (src_imgmode == WF_IMGMODE_BAYER1PLANE)
 
827
                src_h_shift = 2 >> IO.shrink;
 
828
        else if (src_imgmode == WF_IMGMODE_BAYER4PLANE)
 
829
                src_h_shift = 8 >> IO.shrink;
 
830
 
 
831
        src_h_shift_x2 = src_h_shift*2;
 
832
 
 
833
        if      (dst_imgmode == WF_IMGMODE_BAYER1PLANE)
 
834
                dst_h_shift = 2 >> IO.shrink;
 
835
        else if (dst_imgmode == WF_IMGMODE_BAYER4PLANE)
 
836
                dst_h_shift = 8 >> IO.shrink;
 
837
 
 
838
        int row, col;
 
839
 
 
840
        long int *line_filtered;
 
841
 
 
842
        line_filtered = (long int*) calloc(S.width, sizeof(*line_filtered));
 
843
        
 
844
        ushort *src, *src_c, *src_u1, *src_u2, *src_d1, *src_d2, *dst_c, *src_ca, *dst_ca, *dst_rb; 
 
845
        int start_col, start_col_left, row_up, row_dn;
 
846
 
 
847
        if ( green_mode != WF_GREENMODE_IND)
 
848
        {
 
849
                for(row=0; row<S.height; row++)
 
850
                {
 
851
 
 
852
                        if (row == 0)
 
853
                                row_up = 1;
 
854
                        else
 
855
                                row_up = row-1;
 
856
 
 
857
                        if (row == S.height-1)
 
858
                                row_dn = S.height-2;
 
859
                        else
 
860
                                row_dn = row+1;
 
861
 
 
862
                        if ( green_mode == WF_GREENMODE_GX_XG )
 
863
                                start_col = row & 1;
 
864
                        else
 
865
                                start_col = ( row+1 ) & 1;
 
866
 
 
867
                        if ( start_col == 0 )
 
868
                                start_col_left = 1;
 
869
                        else
 
870
                                start_col_left = 0;
 
871
 
 
872
                        switch (src_imgmode)
 
873
                        {
 
874
                                case WF_IMGMODE_BAYER1PLANE:
 
875
 
 
876
                                        src_c  = &WF_BAYERSRC1(row,    start_col);
 
877
                                        src_u1 = &WF_BAYERSRC1(row_up, start_col_left);
 
878
                                        src_d1 = &WF_BAYERSRC1(row_dn, start_col_left);
 
879
                                        src_u2 = &WF_BAYERSRC1(row_up, start_col+1);
 
880
                                        src_d2 = &WF_BAYERSRC1(row_dn, start_col+1);
 
881
 
 
882
                                        break;
 
883
 
 
884
                                case WF_IMGMODE_BAYER4PLANE:
 
885
 
 
886
                                        src_c  = &WF_BAYERSRC4(row,    start_col,      FC(row,   start_col));
 
887
                                        src_u1 = &WF_BAYERSRC4(row_up, start_col_left, FC(row_up, start_col_left));
 
888
                                        src_d1 = &WF_BAYERSRC4(row_dn, start_col_left, FC(row_dn, start_col_left));
 
889
                                        src_u2 = &WF_BAYERSRC4(row_up, start_col+1,    FC(row_up, start_col+1));
 
890
                                        src_d2 = &WF_BAYERSRC4(row_dn, start_col+1,    FC(row_dn, start_col+1));
 
891
 
 
892
                                        break;
 
893
                        }
 
894
 
 
895
                        long int sum_l1, sum_l2;
 
896
 
 
897
                        sum_l1 = *src_u1 + *src_d1;
 
898
                        sum_l2 = *src_u2 + *src_d2;                     
 
899
                        
 
900
                        if (start_col == 0)
 
901
                        {
 
902
                                // Edges
 
903
 
 
904
                                line_filtered[start_col] = sum_l1 + sum_l2 + (*src_c)*4;
 
905
 
 
906
                                src_u2 += src_h_shift;
 
907
                                src_d2 += src_h_shift;                          
 
908
 
 
909
                                sum_l2 = *src_u2 + *src_d2;
 
910
 
 
911
                                src_c += src_h_shift;
 
912
                                start_col=2;
 
913
                        }
 
914
 
 
915
                        int width_m_3 = S.width-3;
 
916
 
 
917
                        // Main
 
918
 
 
919
                        for (col=start_col; col<width_m_3; col+=2)
 
920
                        {
 
921
                                line_filtered[col] = sum_l1 + sum_l2 + 4*(*src_c);
 
922
 
 
923
                                src_u1 += src_h_shift_x2;
 
924
                                src_d1 += src_h_shift_x2;
 
925
 
 
926
                                sum_l1 = *src_u1 + *src_d1;
 
927
 
 
928
                                src_c += src_h_shift;
 
929
                                col+=2;
 
930
 
 
931
                                line_filtered[col] = sum_l1 + sum_l2 + 4*(*src_c);
 
932
 
 
933
                                src_u2 += src_h_shift_x2;
 
934
                                src_d2 += src_h_shift_x2;
 
935
 
 
936
                                sum_l2 = *src_u2 + *src_d2; 
 
937
 
 
938
                                src_c += src_h_shift;
 
939
                        }
 
940
                        
 
941
                        // Right edge
 
942
 
 
943
                        if      (col == S.width-1)
 
944
                        {
 
945
                                line_filtered[col] = 2*sum_l1 + 4*(*src_c);
 
946
                        }
 
947
                        else if (col == S.width-2)
 
948
                        {
 
949
                                line_filtered[col] = sum_l1 + sum_l2 + 4*(*src_c);
 
950
                        }
 
951
                        else if (col == S.width-3)
 
952
                        {
 
953
                                line_filtered[col] = sum_l1 + sum_l2 + 4*(*src_c);
 
954
                                
 
955
                                src_c += src_h_shift;
 
956
                                col+=2;
 
957
 
 
958
                                line_filtered[col] = 2*sum_l2 + 4*(*src_c);
 
959
                        }
 
960
 
 
961
                        if (row>0)
 
962
                        {
 
963
 
 
964
                                if ( green_mode == WF_GREENMODE_GX_XG )
 
965
                                        start_col = ( row+1 ) & 1;
 
966
                                else
 
967
                                        start_col = row & 1;
 
968
                                
 
969
 
 
970
                                switch (dst_imgmode)
 
971
                                {
 
972
                                        case WF_IMGMODE_BAYER1PLANE:
 
973
                                                dst_c  = &WF_BAYERDST1(row-1,    start_col);
 
974
                                                break;
 
975
 
 
976
                                        case WF_IMGMODE_BAYER4PLANE:
 
977
                                                dst_c  = &WF_BAYERDST4(row-1,    start_col, FC(row-1, start_col));
 
978
                                                break;
 
979
                                }
 
980
 
 
981
                                for (col=start_col;  col<S.width; col+=2)
 
982
                                {
 
983
                                        *dst_c=(line_filtered[col])>>3;
 
984
                                        dst_c+=dst_h_shift;
 
985
                                }
 
986
 
 
987
                                if (src_image != dst_image)
 
988
                                {
 
989
                                        // copy red or blue channel
 
990
 
 
991
                                        if ( green_mode == WF_GREENMODE_GX_XG )
 
992
                                                start_col = row & 1;
 
993
                                        else
 
994
                                                start_col = (row+1) & 1;
 
995
                                        
 
996
                                        switch (src_imgmode)
 
997
                                        {
 
998
                                                case WF_IMGMODE_BAYER1PLANE:
 
999
                                                        src     = &WF_BAYERSRC1(row-1, start_col);
 
1000
                                                        break;
 
1001
 
 
1002
                                                case WF_IMGMODE_BAYER4PLANE:
 
1003
                                                        src     = &WF_BAYERSRC4(row-1, start_col, FC(row-1, start_col));
 
1004
                                                        break;
 
1005
                                        }
 
1006
 
 
1007
                                        switch (dst_imgmode)
 
1008
                                        {
 
1009
                                                case WF_IMGMODE_BAYER1PLANE:
 
1010
                                                        dst_rb  = &WF_BAYERDST1(row-1, start_col);
 
1011
                                                        break;
 
1012
 
 
1013
                                                case WF_IMGMODE_BAYER4PLANE:
 
1014
                                                        dst_rb  = &WF_BAYERDST4(row-1, start_col, FC(row-1, start_col));
 
1015
                                                        break;
 
1016
                                        }
 
1017
 
 
1018
                                        for (col=start_col;  col<S.width; col+=2)
 
1019
                                        {
 
1020
                                                *dst_rb=*src;
 
1021
                                                src   +=src_h_shift;
 
1022
                                                dst_rb+=dst_h_shift;
 
1023
                                        }
 
1024
                                }
 
1025
                        }
 
1026
                }
 
1027
 
 
1028
                if ( green_mode == WF_GREENMODE_GX_XG )
 
1029
                        start_col = ( row+1 ) & 1;
 
1030
                else
 
1031
                        start_col = row & 1;
 
1032
                                
 
1033
 
 
1034
                switch (dst_imgmode)
 
1035
                {
 
1036
                        case WF_IMGMODE_BAYER1PLANE:
 
1037
                                dst_c  = &WF_BAYERDST1(row-1,    start_col);
 
1038
                                break;
 
1039
 
 
1040
                        case WF_IMGMODE_BAYER4PLANE:
 
1041
                                dst_c  = &WF_BAYERDST4(row-1,    start_col, FC(row-1, start_col));
 
1042
                                break;
 
1043
                }
 
1044
 
 
1045
                for (col=start_col;  col<S.width; col+=2)
 
1046
                {
 
1047
                        *dst_c=(line_filtered[col])>>3;
 
1048
                        dst_c+=dst_h_shift;
 
1049
                }
 
1050
 
 
1051
                if (src_image != dst_image)
 
1052
                {
 
1053
                        // copy red or blue channel
 
1054
                        
 
1055
                        if ( green_mode == WF_GREENMODE_GX_XG )
 
1056
                                start_col = row & 1;
 
1057
                        else
 
1058
                                start_col = (row+1) & 1;
 
1059
                                
 
1060
                        switch (src_imgmode)
 
1061
                        {
 
1062
                                case WF_IMGMODE_BAYER1PLANE:
 
1063
                                        src     = &WF_BAYERSRC1(row-1, start_col);
 
1064
                                        break;
 
1065
 
 
1066
                                case WF_IMGMODE_BAYER4PLANE:
 
1067
                                        src     = &WF_BAYERSRC4(row-1, start_col, FC(row-1, start_col));
 
1068
                                        break;
 
1069
                        }
 
1070
 
 
1071
                        switch (dst_imgmode)
 
1072
                        {
 
1073
                                case WF_IMGMODE_BAYER1PLANE:
 
1074
                                        dst_rb  = &WF_BAYERDST1(row-1, start_col);
 
1075
                                        break;
 
1076
                                
 
1077
                                case WF_IMGMODE_BAYER4PLANE:
 
1078
                                        dst_rb  = &WF_BAYERDST4(row-1, start_col, FC(row-1, start_col));
 
1079
                                        break;
 
1080
                        }
 
1081
                        
 
1082
                        for (col=start_col;  col<S.width; col+=2)
 
1083
                        {
 
1084
                                *dst_rb=*src;
 
1085
                                src   +=src_h_shift;
 
1086
                                dst_rb+=dst_h_shift;
 
1087
                        }
 
1088
                }
 
1089
        }
 
1090
 
 
1091
        free(line_filtered);
 
1092
}
 
1093
 
 
1094
void LibRaw::wf_bayer4_igauss_filter(int radius, void* src_image, int src_imgmode, void* dst_image, int dst_imgmode)
 
1095
{
 
1096
        /* 
 
1097
           This function filter source bayer4 data with gauss (binominal), 4 channels independently.
 
1098
        */
 
1099
           
 
1100
#define WF_BAYERSRC4(row, col, c) ((ushort(*)[4])src_image)[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][c] 
 
1101
#define WF_BAYERSRC1(row, col)    ((ushort*)src_image)     [((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)] 
 
1102
#define WF_BAYERDST4(row, col, c) ((ushort(*)[4])dst_image)[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][c] 
 
1103
#define WF_BAYERDST1(row, col)    ((ushort*)dst_image)     [((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)]
 
1104
 
 
1105
        if (radius <= 0 || radius > 8)
 
1106
           return;
 
1107
 
 
1108
        long int (*line_filtered)[4];
 
1109
 
 
1110
        long int gauss_conv_kernel[9][4];
 
1111
 
 
1112
        long int gauss_conv_kernel_c[8][9] = 
 
1113
        {
 
1114
                {32768, 16384},
 
1115
                {24576, 16384, 4096},
 
1116
                {20480, 15360, 6144, 1024},
 
1117
                {17920, 14336, 7168, 2048, 256},
 
1118
                {16128, 13440, 7680, 2880, 640,  64},
 
1119
                {14784, 12672, 7920, 3520, 1056, 192, 16},
 
1120
                {13728, 12012, 8008, 4004, 1456, 364, 56,  4},
 
1121
                {12870, 11440, 8008, 4368, 1820, 560, 120, 16, 1},
 
1122
        };
 
1123
 
 
1124
        int line_memory_len = (MAX(S.height, S.width)+1)/2+radius*2+1;
 
1125
    line_filtered       = (long int(*)[4]) calloc(line_memory_len, sizeof(long int[4]));
 
1126
 
 
1127
        int src_h_shift, src_v_shift;
 
1128
        int dst_h_shift, dst_v_shift;
 
1129
 
 
1130
        if      (src_imgmode == WF_IMGMODE_BAYER1PLANE)
 
1131
                src_h_shift = 2 >> IO.shrink;
 
1132
        else if (src_imgmode == WF_IMGMODE_BAYER4PLANE)
 
1133
                src_h_shift = 8 >> IO.shrink;
 
1134
 
 
1135
        src_v_shift = S.width*src_h_shift;
 
1136
 
 
1137
        if      (dst_imgmode == WF_IMGMODE_BAYER1PLANE)
 
1138
                dst_h_shift = 2 >> IO.shrink;
 
1139
        else if (dst_imgmode == WF_IMGMODE_BAYER4PLANE)
 
1140
                dst_h_shift = 8 >> IO.shrink;
 
1141
 
 
1142
        dst_v_shift = S.width*dst_h_shift;
 
1143
 
 
1144
        int width_d2  = S.width  / 2;
 
1145
        int height_d2 = S.height / 2;
 
1146
 
 
1147
        int i, j;
 
1148
 
 
1149
        for (j=0; j<=radius; j++)
 
1150
        {
 
1151
                for (i=0; i<4; i++)
 
1152
                {
 
1153
                        gauss_conv_kernel[j][i] = gauss_conv_kernel_c[radius-1][j];
 
1154
                }
 
1155
        }
 
1156
 
 
1157
        int row,  col;
 
1158
        int rowf, colf;
 
1159
 
 
1160
        ushort   *src  [4], *dst[4];
 
1161
        long int  src_c[4];
 
1162
 
 
1163
        // Horizontal 
 
1164
 
 
1165
        int right_edge[4];
 
1166
 
 
1167
        for (i=0; i<4; i++)
 
1168
        {
 
1169
                int padding = i<2 && (S.width & 1 == 1) ? 1 : 0;
 
1170
                right_edge[i]=width_d2 + radius + padding;
 
1171
        }
 
1172
        
 
1173
        for(row=0; row<S.height; row+=2)
 
1174
        {
 
1175
                int row_p1=MIN(row+1, S.height-1);
 
1176
 
 
1177
                switch (src_imgmode)
 
1178
                {
 
1179
                        case WF_IMGMODE_BAYER1PLANE:
 
1180
 
 
1181
                                src[0] = &WF_BAYERSRC1(row,    0);
 
1182
                                src[1] = &WF_BAYERSRC1(row_p1, 0);
 
1183
                                src[2] = &WF_BAYERSRC1(row,    1);
 
1184
                                src[3] = &WF_BAYERSRC1(row_p1, 1);
 
1185
                                break;
 
1186
 
 
1187
                        case WF_IMGMODE_BAYER4PLANE:
 
1188
 
 
1189
                                src[0] = &WF_BAYERSRC4(row,    0, FC(0,      0));
 
1190
                                src[1] = &WF_BAYERSRC4(row_p1, 0, FC(row_p1, 0));
 
1191
                                src[2] = &WF_BAYERSRC4(row,    1, FC(0,      1));
 
1192
                                src[3] = &WF_BAYERSRC4(row_p1, 1, FC(row_p1, 1));
 
1193
                                break;
 
1194
                }
 
1195
 
 
1196
                colf = radius;
 
1197
 
 
1198
                for (int j=0; j<line_memory_len; j++)
 
1199
                {
 
1200
                        for(i=0;i<4;i++)
 
1201
                                line_filtered[j][i]=0;
 
1202
                }
 
1203
                
 
1204
                for(col=0; col<S.width-1; col+=2)
 
1205
                {
 
1206
 
 
1207
                        int col1, col2;
 
1208
 
 
1209
                        col1=col2=colf;
 
1210
 
 
1211
                        for (i=0; i<4; i++)
 
1212
                                src_c[i]=*src[i];
 
1213
 
 
1214
                        for (i=0; i<4; i++)
 
1215
                                line_filtered[colf][i]+=gauss_conv_kernel[0][i]*(src_c[i]);
 
1216
 
 
1217
                        for(int j=1; j<=radius; j++)
 
1218
                        {
 
1219
                                col1++;
 
1220
                                col2--;
 
1221
                        
 
1222
                                for (i=0; i<4; i++)
 
1223
                                {
 
1224
                                        long int g;
 
1225
 
 
1226
                                        g = gauss_conv_kernel[j][i]*src_c[i];
 
1227
 
 
1228
                                        line_filtered[col1][i]+=g;
 
1229
                                        line_filtered[col2][i]+=g;
 
1230
                                }
 
1231
                        }
 
1232
 
 
1233
                        colf++;
 
1234
 
 
1235
                        for (i=0; i<4; i++)
 
1236
                                src[i]+=src_h_shift;
 
1237
                }
 
1238
 
 
1239
                // width is odd number
 
1240
 
 
1241
                if (col == S.width-1)
 
1242
                {
 
1243
                        int col1, col2;
 
1244
 
 
1245
                        col1=col2=colf;
 
1246
 
 
1247
                        for (i=0; i<2; i++)
 
1248
                                src_c[i]=*src[i];
 
1249
 
 
1250
                        for (i=0; i<2; i++)
 
1251
                                line_filtered[colf][i]+=gauss_conv_kernel[0][i]*(src_c[i]);
 
1252
 
 
1253
                        for(int j=1; j<=radius; j++)
 
1254
                        {
 
1255
                                col1++;
 
1256
                                col2--;
 
1257
                        
 
1258
                                for (i=0; i<2; i++)
 
1259
                                {
 
1260
                                        long int g;
 
1261
 
 
1262
                                        g = gauss_conv_kernel[j][i]*src_c[i];
 
1263
 
 
1264
                                        line_filtered[col1][i]+=g;
 
1265
                                        line_filtered[col2][i]+=g;
 
1266
                                }
 
1267
                        }
 
1268
 
 
1269
                        colf++;
 
1270
 
 
1271
                        for (i=0; i<2; i++)
 
1272
                                src[i]+=src_h_shift;
 
1273
                }
 
1274
 
 
1275
                // Edges mirroring
 
1276
 
 
1277
                for(j=0; j<radius; j++)
 
1278
                {
 
1279
                        for (i=0; i<4; i++)
 
1280
                        {
 
1281
                                line_filtered[radius+j         ][i]+=line_filtered[radius-j-1     ][i];
 
1282
                                line_filtered[right_edge[i]-1-j][i]+=line_filtered[right_edge[i]+j][i];
 
1283
                        }
 
1284
                }
 
1285
                
 
1286
                switch (dst_imgmode)
 
1287
                {
 
1288
                        case WF_IMGMODE_BAYER1PLANE:
 
1289
                        
 
1290
                                dst[0] = &WF_BAYERDST1(row,    0);
 
1291
                                dst[1] = &WF_BAYERDST1(row_p1, 0);
 
1292
                                dst[2] = &WF_BAYERDST1(row,    1);
 
1293
                                dst[3] = &WF_BAYERDST1(row_p1, 1);
 
1294
                                break;
 
1295
 
 
1296
                        case WF_IMGMODE_BAYER4PLANE:
 
1297
                
 
1298
                                dst[0] = &WF_BAYERDST4(row,    0, FC(0,      0));
 
1299
                                dst[1] = &WF_BAYERDST4(row_p1, 0, FC(row_p1, 0));
 
1300
                                dst[2] = &WF_BAYERDST4(row,    1, FC(0,      1));
 
1301
                                dst[3] = &WF_BAYERDST4(row_p1, 1, FC(row_p1, 1));
 
1302
                                break;
 
1303
                }
 
1304
 
 
1305
                colf = radius;
 
1306
 
 
1307
                for(col=0; col<S.width-1; col+=2)
 
1308
                {
 
1309
                        for(i=0; i<4; i++)
 
1310
                        {
 
1311
                                *dst[i]=line_filtered[colf][i]>>16;
 
1312
                                dst[i]+=dst_h_shift;
 
1313
                        }
 
1314
 
 
1315
                        colf++;
 
1316
                }
 
1317
 
 
1318
                if (col == S.width-1)
 
1319
                {
 
1320
                        for(i=0; i<2; i++)
 
1321
                                *dst[i]=line_filtered[colf][i]>>16;
 
1322
                }
 
1323
        }
 
1324
 
 
1325
 
 
1326
        // Vertical
 
1327
 
 
1328
        int lower_edge[4];
 
1329
 
 
1330
        for (i=0; i<4; i++)
 
1331
        {
 
1332
                int padding = i<2 && (S.height & 1 == 1) ? 1 : 0;
 
1333
                lower_edge[i]=height_d2 + radius + padding;
 
1334
        }
 
1335
 
 
1336
 
 
1337
        for(col=0; col<S.width; col+=2)
 
1338
        {
 
1339
                int col_p1=MIN(col+1, S.width-1);       
 
1340
 
 
1341
                switch (dst_imgmode)
 
1342
                {
 
1343
                        case WF_IMGMODE_BAYER1PLANE:
 
1344
 
 
1345
                                src[0] = &WF_BAYERDST1(0, col);
 
1346
                                src[1] = &WF_BAYERDST1(0, col_p1);
 
1347
                                src[2] = &WF_BAYERDST1(1, col);
 
1348
                                src[3] = &WF_BAYERDST1(1, col_p1);
 
1349
                                break;
 
1350
 
 
1351
                        case WF_IMGMODE_BAYER4PLANE:
 
1352
 
 
1353
                                src[0] = &WF_BAYERDST4(0, col,    FC(0,      0));
 
1354
                                src[1] = &WF_BAYERDST4(0, col_p1, FC(0, col_p1));
 
1355
                                src[2] = &WF_BAYERDST4(1, col,    FC(1,      0));
 
1356
                                src[3] = &WF_BAYERDST4(1, col_p1, FC(1, col_p1));
 
1357
                                break;
 
1358
                }
 
1359
 
 
1360
                rowf = radius;
 
1361
 
 
1362
                for (int j=0; j<line_memory_len; j++)
 
1363
                {
 
1364
                        for(i=0;i<4;i++)
 
1365
                                line_filtered[j][i]=0;
 
1366
                }
 
1367
                
 
1368
                for(row=0; row<S.height-1; row+=2)
 
1369
                {
 
1370
 
 
1371
                        int row1, row2;
 
1372
 
 
1373
                        row1=row2=rowf;
 
1374
 
 
1375
                        for (i=0; i<4; i++)
 
1376
                                src_c[i]=*src[i];
 
1377
 
 
1378
                        for (i=0; i<4; i++)
 
1379
                                line_filtered[rowf][i]+=gauss_conv_kernel[0][i]*(src_c[i]);
 
1380
 
 
1381
                        for(int j=1; j<=radius; j++)
 
1382
                        {
 
1383
                                row1++;
 
1384
                                row2--;
 
1385
                        
 
1386
                                long int g[4];
 
1387
 
 
1388
                                for (i=0; i<4; i++)
 
1389
                                {
 
1390
 
 
1391
                                        g[i] = gauss_conv_kernel[j][i]*src_c[i];
 
1392
 
 
1393
                                        line_filtered[row1][i]+=g[i];
 
1394
                                        line_filtered[row2][i]+=g[i];
 
1395
                                }
 
1396
                        }
 
1397
 
 
1398
                        rowf++;
 
1399
 
 
1400
                        for (i=0; i<4; i++)
 
1401
                                src[i]+=dst_v_shift;
 
1402
                }
 
1403
 
 
1404
                // height is odd number
 
1405
 
 
1406
                if (row == S.height-1)
 
1407
                {
 
1408
                        int row1, row2;
 
1409
 
 
1410
                        row1=row2=rowf;
 
1411
 
 
1412
                        for (i=0; i<2; i++)
 
1413
                                src_c[i]=*src[i];
 
1414
 
 
1415
                        for (i=0; i<2; i++)
 
1416
                                line_filtered[rowf][i]+=gauss_conv_kernel[0][i]*(src_c[i]);
 
1417
 
 
1418
                        for(int j=1; j<=radius; j++)
 
1419
                        {
 
1420
                                row1++;
 
1421
                                row2--;
 
1422
                        
 
1423
                                long int g[4];
 
1424
 
 
1425
                                for (i=0; i<2; i++)
 
1426
                                {
 
1427
 
 
1428
                                        g[i] = gauss_conv_kernel[j][i]*src_c[i];
 
1429
 
 
1430
                                        line_filtered[row1][i]+=g[i];
 
1431
                                        line_filtered[row2][i]+=g[i];
 
1432
                                }
 
1433
                        }
 
1434
 
 
1435
                        rowf++;
 
1436
 
 
1437
                        for (i=0; i<2; i++)
 
1438
                                src[i]+=dst_v_shift;
 
1439
                }
 
1440
 
 
1441
                // Edge mirroring
 
1442
 
 
1443
                for(int j=0; j<radius; j++)
 
1444
                {
 
1445
                        for (int i=0; i<4; i++)
 
1446
                        {
 
1447
                                line_filtered[radius+j][i]         +=line_filtered[radius-j-1][i];
 
1448
                                line_filtered[lower_edge[i]-1-j][i]+=line_filtered[lower_edge[i]+j][i];
 
1449
                        }
 
1450
                }
 
1451
 
 
1452
 
 
1453
                switch (dst_imgmode)
 
1454
                {
 
1455
                        case WF_IMGMODE_BAYER1PLANE:
 
1456
                        
 
1457
                                dst[0] = &WF_BAYERDST1(0, col);
 
1458
                                dst[1] = &WF_BAYERDST1(0, col_p1);
 
1459
                                dst[2] = &WF_BAYERDST1(1, col);
 
1460
                                dst[3] = &WF_BAYERDST1(1, col_p1);
 
1461
                                break;
 
1462
 
 
1463
                        case WF_IMGMODE_BAYER4PLANE:
 
1464
                
 
1465
                                dst[0] = &WF_BAYERDST4(0, col,    FC(0, 0));
 
1466
                                dst[1] = &WF_BAYERDST4(0, col_p1, FC(0, col_p1));
 
1467
                                dst[2] = &WF_BAYERDST4(1, col,    FC(1, 0));
 
1468
                                dst[3] = &WF_BAYERDST4(1, col_p1, FC(1, col_p1));
 
1469
                                break;
 
1470
                }
 
1471
 
 
1472
                rowf = radius;
 
1473
 
 
1474
                for(row=0; row<S.height-1; row+=2)
 
1475
                {
 
1476
                        for(i=0; i<4; i++)
 
1477
                        {
 
1478
                                *dst[i]=line_filtered[rowf][i]>>16;
 
1479
                                dst[i]+=dst_v_shift;
 
1480
                        }
 
1481
 
 
1482
                        rowf++;
 
1483
                }
 
1484
 
 
1485
                if (row == S.height-1)
 
1486
                {
 
1487
                        for(i=0; i<2; i++)
 
1488
                                *dst[i]=line_filtered[rowf][i]>>16;
 
1489
                }
 
1490
   }
 
1491
 
 
1492
   free(line_filtered);
 
1493
}
 
1494
 
 
1495
void LibRaw::wf_bayer4_block_filter(int* radius_list, void* src_image, int src_imgmode, void* dst_image, int dst_imgmode)
 
1496
{
 
1497
#define WF_BLOCKFILTER_MAXF 8
 
1498
 
 
1499
#define WF_BAYERSRC4(row,col,c) ((ushort(*)[4])src_image)[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][c] 
 
1500
#define WF_BAYERSRC1(row,col)   ((ushort*)src_image)     [((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)] 
 
1501
#define WF_BAYERDST4(row,col,c) ((ushort(*)[4])dst_image)[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][c] 
 
1502
#define WF_BAYERDST1(row,col)   ((ushort*)dst_image)     [((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)] 
 
1503
 
 
1504
        int filter_itrtns_num = 0;
 
1505
        
 
1506
        int block_radius      [WF_BLOCKFILTER_MAXF]; 
 
1507
        int block_radius_x2   [WF_BLOCKFILTER_MAXF];
 
1508
        int block_radius_x2_p1[WF_BLOCKFILTER_MAXF];
 
1509
 
 
1510
        int block_radius_max = 0;
 
1511
        int block_radius_max_x2;
 
1512
        int block_radius_max_x2_p1;
 
1513
 
 
1514
        for(int i=0; (i<WF_BLOCKFILTER_MAXF) && (radius_list[i]!=0); i++)
 
1515
        {
 
1516
                block_radius      [i]=radius_list[i];
 
1517
                block_radius_x2   [i]=block_radius[i]*2;
 
1518
                block_radius_x2_p1[i]=block_radius_x2[i]+1;
 
1519
 
 
1520
                if(block_radius_max<block_radius[i])
 
1521
                        block_radius_max=block_radius[i];
 
1522
 
 
1523
                filter_itrtns_num++;
 
1524
        }
 
1525
 
 
1526
        long int divider[WF_BLOCKFILTER_MAXF];
 
1527
        long int div_multiplication;
 
1528
 
 
1529
        div_multiplication=block_radius_x2_p1[0];
 
1530
 
 
1531
        for(int i=1; i<filter_itrtns_num; i++)
 
1532
        {
 
1533
                if (div_multiplication*((long int)block_radius_x2_p1[i])<65535)
 
1534
                {
 
1535
                        div_multiplication*=block_radius_x2_p1[i];
 
1536
                        divider[i-1]=1;
 
1537
                }
 
1538
                else
 
1539
                {
 
1540
                        divider[i-1]=block_radius_x2_p1[i];
 
1541
                }
 
1542
        }
 
1543
 
 
1544
        divider[filter_itrtns_num-1]=div_multiplication;
 
1545
 
 
1546
        block_radius_max_x2    = block_radius_max*2;
 
1547
        block_radius_max_x2_p1 = block_radius_max_x2+1;
 
1548
        
 
1549
        int line_memory_len;
 
1550
 
 
1551
        long int (*source_line)[4];
 
1552
        long int (*line_block_filtered)[4];
 
1553
 
 
1554
        line_memory_len = (MAX(S.height, S.width)+1)/2+block_radius_max_x2_p1*2;
 
1555
 
 
1556
        line_block_filtered=(long int(*)[4]) calloc(line_memory_len, sizeof(long int[4]));
 
1557
        source_line        =(long int(*)[4]) calloc(line_memory_len, sizeof(long int[4]));
 
1558
        
 
1559
 
 
1560
        int   src_h_shift, dst_h_shift, src_v_shift, dst_v_shift;
 
1561
 
 
1562
        if      (src_imgmode == WF_IMGMODE_BAYER1PLANE)
 
1563
                src_h_shift = 2 >> IO.shrink;
 
1564
        else if (src_imgmode == WF_IMGMODE_BAYER4PLANE)
 
1565
                src_h_shift = 8 >> IO.shrink;
 
1566
 
 
1567
        src_v_shift = S.width*src_h_shift;
 
1568
 
 
1569
        if      (dst_imgmode == WF_IMGMODE_BAYER1PLANE)
 
1570
                dst_h_shift = 2 >> IO.shrink;
 
1571
        else if (dst_imgmode == WF_IMGMODE_BAYER4PLANE)
 
1572
                dst_h_shift = 8 >> IO.shrink;
 
1573
 
 
1574
        dst_v_shift = S.width*dst_h_shift;
 
1575
 
 
1576
        int width_d2     = S.width  / 2;
 
1577
        int height_d2    = S.height / 2;
 
1578
 
 
1579
        int width_p1_d2  = (S.width+1)  / 2;
 
1580
        int height_p1_d2 = (S.height+1) / 2;
 
1581
 
 
1582
        ushort   *src[4], *dst[4];
 
1583
 
 
1584
        long int  (*src_plus)[4], (*src_minus)[4];
 
1585
        long int  block_sum[4];
 
1586
        
 
1587
        int row, col;
 
1588
 
 
1589
        int right_edge[4], lower_edge[4];
 
1590
 
 
1591
        for(row=0; row<S.height; row+=2)
 
1592
        {
 
1593
                int row_p1=MIN(row+1, S.height-1);
 
1594
 
 
1595
                switch (src_imgmode)
 
1596
                {
 
1597
                        case WF_IMGMODE_BAYER1PLANE:
 
1598
 
 
1599
                                src[0] = &WF_BAYERSRC1(row,    0);
 
1600
                                src[1] = &WF_BAYERSRC1(row_p1, 0);
 
1601
                                src[2] = &WF_BAYERSRC1(row,    1);
 
1602
                                src[3] = &WF_BAYERSRC1(row_p1, 1);
 
1603
                                break;
 
1604
 
 
1605
                        case WF_IMGMODE_BAYER4PLANE:
 
1606
 
 
1607
                                src[0] = &WF_BAYERSRC4(row,    0, FC(0,      0));
 
1608
                                src[1] = &WF_BAYERSRC4(row_p1, 0, FC(row_p1, 0));
 
1609
                                src[2] = &WF_BAYERSRC4(row,    1, FC(0,      1));
 
1610
                                src[3] = &WF_BAYERSRC4(row_p1, 1, FC(row_p1, 1));
 
1611
                                break;
 
1612
                }
 
1613
 
 
1614
                for(col=0; col<width_d2; col++)
 
1615
                {
 
1616
                        for (int i=0; i<4; i++)
 
1617
                        {
 
1618
                                source_line[col][i]=*src[i];
 
1619
                                src[i] += src_h_shift;
 
1620
                        }
 
1621
                }
 
1622
 
 
1623
                if (S.width & 1 == 1)
 
1624
                {
 
1625
                        for (int i=0; i<2; i++)
 
1626
                        {                  
 
1627
                                source_line[width_d2][i]=*src[i];
 
1628
                        }
 
1629
 
 
1630
                        for (int i=2; i<4; i++)
 
1631
                        {                  
 
1632
                                source_line[width_d2][i]=0;
 
1633
                        }
 
1634
                }
 
1635
 
 
1636
                for(int f=0; f<filter_itrtns_num; f++)
 
1637
                {
 
1638
                        src_minus=src_plus=source_line;
 
1639
 
 
1640
                        for (int i=0; i<4; i++)
 
1641
                                block_sum[i]=0;
 
1642
 
 
1643
                        for(col=0; col<block_radius_x2_p1[f]; col++)
 
1644
                        {
 
1645
                                for (int i=0; i<4; i++)
 
1646
                                {
 
1647
                                        block_sum[i]+=(*src_plus)[i];
 
1648
                                        line_block_filtered[col][i]=block_sum[i];
 
1649
                                }
 
1650
 
 
1651
                                src_plus++;
 
1652
                        }
 
1653
 
 
1654
                        for(col=block_radius_x2_p1[f]; col<width_p1_d2; col++)
 
1655
                        {
 
1656
                                for (int i=0; i<4; i++)
 
1657
                                {                  
 
1658
                                        block_sum[i]+=(*src_plus)[i];
 
1659
                                        block_sum[i]-=(*src_minus)[i];
 
1660
                                        line_block_filtered[col][i]=block_sum[i];
 
1661
                                }
 
1662
 
 
1663
                                src_plus++;
 
1664
                                src_minus++;
 
1665
                        }
 
1666
 
 
1667
                        for(col=width_p1_d2; col<width_p1_d2+block_radius_x2_p1[f]; col++)
 
1668
                        {
 
1669
                                for (int i=0; i<4; i++)
 
1670
                                {
 
1671
                                        block_sum[i]-=(*src_minus)[i];
 
1672
                                        line_block_filtered[col][i]=block_sum[i];
 
1673
                                }
 
1674
 
 
1675
                                src_minus++;
 
1676
                        }
 
1677
 
 
1678
                        // Edge mirroring
 
1679
 
 
1680
                        for (int i=0; i<4; i++)
 
1681
                        {
 
1682
                                int padding = i<2 && (S.width & 1 == 1) ? 1 : 0;
 
1683
                                right_edge[i]=width_d2 + block_radius[f] + padding;
 
1684
                        }
 
1685
 
 
1686
                        for(int j=0; j<block_radius[f]; j++)
 
1687
                        {
 
1688
                                for (int i=0; i<4; i++)
 
1689
                                {
 
1690
                                        line_block_filtered[block_radius[f]+j][i]+=line_block_filtered[block_radius[f]-j-1][i];
 
1691
                                        line_block_filtered[right_edge[i]-1-j][i]+=line_block_filtered[right_edge[i]+j][i];
 
1692
                                }
 
1693
                        }
 
1694
 
 
1695
                        if (divider[f]==1)
 
1696
                        {
 
1697
                                for(col=0; col<width_d2; col++)
 
1698
                                {
 
1699
                                        for (int i=0; i<4; i++)
 
1700
                                                source_line[col][i]=line_block_filtered[col+block_radius[f]][i];
 
1701
                                }
 
1702
 
 
1703
                                if (S.width & 1 == 1)
 
1704
                                {
 
1705
                                        for (int i=0; i<2; i++)
 
1706
                                                source_line[width_d2][i]=line_block_filtered[width_d2+block_radius[f]][i];
 
1707
 
 
1708
                                        for (int i=2; i<4; i++)
 
1709
                                                source_line[width_d2][i]=0;
 
1710
                                }
 
1711
                        }
 
1712
                        else
 
1713
                        {
 
1714
                                for(col=0; col<width_d2; col++)
 
1715
                                {
 
1716
                                        for (int i=0; i<4; i++)
 
1717
                                                source_line[col][i]=line_block_filtered[col+block_radius[f]][i]/divider[f];
 
1718
                                }
 
1719
 
 
1720
                                if (S.width & 1 == 1)
 
1721
                                {
 
1722
                                        for (int i=0; i<2; i++)
 
1723
                                                source_line[width_d2][i]=line_block_filtered[width_d2+block_radius[f]][i]/divider[f];
 
1724
 
 
1725
                                        for (int i=2; i<4; i++)
 
1726
                                                source_line[width_d2][i]=0;
 
1727
                                }
 
1728
                        }
 
1729
                }
 
1730
 
 
1731
                switch (dst_imgmode)
 
1732
                {
 
1733
                        case WF_IMGMODE_BAYER1PLANE:
 
1734
 
 
1735
                                dst[0] = &WF_BAYERDST1(row,    0);
 
1736
                                dst[1] = &WF_BAYERDST1(row_p1, 0);
 
1737
                                dst[2] = &WF_BAYERDST1(row,    1);
 
1738
                                dst[3] = &WF_BAYERDST1(row_p1, 1);
 
1739
                                break;
 
1740
 
 
1741
                        case WF_IMGMODE_BAYER4PLANE:
 
1742
 
 
1743
                                dst[0] = &WF_BAYERDST4(row,    0, FC(0,      0));
 
1744
                                dst[1] = &WF_BAYERDST4(row_p1, 0, FC(row_p1, 0));
 
1745
                                dst[2] = &WF_BAYERDST4(row,    1, FC(0,      1));
 
1746
                                dst[3] = &WF_BAYERDST4(row_p1, 1, FC(row_p1, 1));
 
1747
                                break;
 
1748
                }
 
1749
 
 
1750
                for(col=0; col<width_d2; col++)
 
1751
                {
 
1752
                        for (int i=0; i<4; i++)
 
1753
                        {                  
 
1754
                                *dst[i]=source_line[col][i];
 
1755
                                dst[i]+=dst_h_shift;
 
1756
                        }
 
1757
                }
 
1758
 
 
1759
                if (S.width & 1 == 1)
 
1760
                {
 
1761
                        for (int i=0; i<2; i++)
 
1762
                                *dst[i]=source_line[col][i];
 
1763
                }
 
1764
        }
 
1765
 
 
1766
        for(col=0; col<S.width; col+=2)
 
1767
        {
 
1768
                int col_p1=MIN(col+1, S.width-1);
 
1769
 
 
1770
                switch (dst_imgmode)
 
1771
                {
 
1772
                        case WF_IMGMODE_BAYER1PLANE:
 
1773
 
 
1774
                                src[0] = &WF_BAYERDST1(0, col);
 
1775
                                src[1] = &WF_BAYERDST1(0, col_p1);
 
1776
                                src[2] = &WF_BAYERDST1(1, col);
 
1777
                                src[3] = &WF_BAYERDST1(1, col_p1);
 
1778
                                break;
 
1779
 
 
1780
                        case WF_IMGMODE_BAYER4PLANE:
 
1781
 
 
1782
                                src[0] = &WF_BAYERDST4(0, col,    FC(0,      0));
 
1783
                                src[1] = &WF_BAYERDST4(0, col_p1, FC(0, col_p1));
 
1784
                                src[2] = &WF_BAYERDST4(1, col,    FC(1,      0));
 
1785
                                src[3] = &WF_BAYERDST4(1, col_p1, FC(1, col_p1));
 
1786
                                break;
 
1787
                }
 
1788
 
 
1789
                for(row=0; row<height_d2; row++)
 
1790
                {
 
1791
                        for (int i=0; i<4; i++)
 
1792
                        {
 
1793
                                source_line[row][i]=*src[i];
 
1794
                                src[i] += dst_v_shift;
 
1795
                        }
 
1796
                }
 
1797
                
 
1798
                if (S.height & 1 == 1)
 
1799
                {
 
1800
                        for (int i=0; i<2; i++)
 
1801
                        {                  
 
1802
                                source_line[height_d2][i]=*src[i];
 
1803
                        }
 
1804
 
 
1805
                        for (int i=2; i<4; i++)
 
1806
                        {                  
 
1807
                                source_line[height_d2][i]=0;
 
1808
                        }
 
1809
                }
 
1810
 
 
1811
                for(int f=0; f<filter_itrtns_num; f++)
 
1812
                {
 
1813
                        src_minus=src_plus=source_line;
 
1814
 
 
1815
                        for (int i=0; i<4; i++)
 
1816
                                block_sum[i]=0;
 
1817
 
 
1818
                        for(row=0; row<block_radius_x2_p1[f]; row++)
 
1819
                        {
 
1820
                                for (int i=0; i<4; i++)
 
1821
                                {
 
1822
                                        block_sum[i]+=(*src_plus)[i];
 
1823
                                        line_block_filtered[row][i]=block_sum[i];
 
1824
                                }
 
1825
 
 
1826
                                src_plus++;
 
1827
                        }
 
1828
 
 
1829
                        for(row=block_radius_x2_p1[f]; row<height_p1_d2; row++)
 
1830
                        {
 
1831
                                for (int i=0; i<4; i++)
 
1832
                                {                  
 
1833
                                        block_sum[i]+=(*src_plus)[i];
 
1834
                                        block_sum[i]-=(*src_minus)[i];
 
1835
                                        line_block_filtered[row][i]=block_sum[i];
 
1836
                                }
 
1837
 
 
1838
                                src_plus++;
 
1839
                                src_minus++;
 
1840
                        }
 
1841
 
 
1842
                        for(row=height_p1_d2; row<height_p1_d2+block_radius_x2_p1[f]; row++)
 
1843
                        {
 
1844
                                for (int i=0; i<4; i++)
 
1845
                                {
 
1846
                                        block_sum[i]-=(*src_minus)[i];
 
1847
                                        line_block_filtered[row][i]=block_sum[i];
 
1848
                                }
 
1849
 
 
1850
                                src_minus++;
 
1851
                        }
 
1852
 
 
1853
                        // Edge mirroring
 
1854
 
 
1855
                        for (int i=0; i<4; i++)
 
1856
                        {
 
1857
                                int padding = (i<2) && (S.height & 1 == 1) ? 1 : 0;
 
1858
                                lower_edge[i]=height_d2 + block_radius[f] + padding;
 
1859
                        }
 
1860
 
 
1861
                        for(int j=0; j<block_radius[f]; j++)
 
1862
                        {
 
1863
                                for (int i=0; i<4; i++)
 
1864
                                {
 
1865
                                        line_block_filtered[block_radius[f]+j][i]+=line_block_filtered[block_radius[f]-j-1][i];
 
1866
                                        line_block_filtered[lower_edge[i]-1-j][i]+=line_block_filtered[lower_edge[i]+j][i];
 
1867
                                }
 
1868
                        }
 
1869
 
 
1870
                        if (divider[f]==1)
 
1871
                        {
 
1872
                                for(row=0; row<height_d2; row++)
 
1873
                                {
 
1874
                                        for (int i=0; i<4; i++)
 
1875
                                                source_line[row][i]=line_block_filtered[row+block_radius[f]][i];
 
1876
                                }
 
1877
 
 
1878
                                if (S.height & 1 == 1)
 
1879
                                {
 
1880
                                        for (int i=0; i<2; i++)
 
1881
                                                source_line[height_d2][i]=line_block_filtered[height_d2+block_radius[f]][i];
 
1882
 
 
1883
                                        for (int i=2; i<4; i++)
 
1884
                                                source_line[height_d2][i]=0;
 
1885
                                }
 
1886
                        }
 
1887
                        else
 
1888
                        {
 
1889
                                for(row=0; row<height_d2; row++)
 
1890
                                {
 
1891
                                        for (int i=0; i<4; i++)
 
1892
                                                source_line[row][i]=line_block_filtered[row+block_radius[f]][i]/divider[f];
 
1893
                                }
 
1894
 
 
1895
                                if (S.height & 1 == 1)
 
1896
                                {
 
1897
                                        for (int i=0; i<2; i++)
 
1898
                                                source_line[height_d2][i]=line_block_filtered[height_d2+block_radius[f]][i]/divider[f];
 
1899
 
 
1900
                                        for (int i=2; i<4; i++)
 
1901
                                                source_line[height_d2][i]=0;
 
1902
                                }
 
1903
                        }
 
1904
                }
 
1905
 
 
1906
                switch (dst_imgmode)
 
1907
                {
 
1908
                        case WF_IMGMODE_BAYER1PLANE:
 
1909
 
 
1910
                                dst[0] = &WF_BAYERDST1(0, col);
 
1911
                                dst[1] = &WF_BAYERDST1(0, col_p1);
 
1912
                                dst[2] = &WF_BAYERDST1(1, col);
 
1913
                                dst[3] = &WF_BAYERDST1(1, col_p1);
 
1914
                                break;
 
1915
 
 
1916
                        case WF_IMGMODE_BAYER4PLANE:
 
1917
 
 
1918
                                dst[0] = &WF_BAYERDST4(0, col,    FC(0,      0));
 
1919
                                dst[1] = &WF_BAYERDST4(0, col_p1, FC(0, col_p1));
 
1920
                                dst[2] = &WF_BAYERDST4(1, col,    FC(1,      0));
 
1921
                                dst[3] = &WF_BAYERDST4(1, col_p1, FC(1, col_p1));
 
1922
                                break;
 
1923
                }
 
1924
 
 
1925
                for(row=0; row<height_d2; row++)
 
1926
                {
 
1927
                        for (int i=0; i<4; i++)
 
1928
                        {                  
 
1929
                                *dst[i]=source_line[row][i];
 
1930
                                dst[i]+=dst_v_shift;
 
1931
                        }
 
1932
                }
 
1933
 
 
1934
                if (S.height & 1 == 1)
 
1935
                {
 
1936
                        for (int i=0; i<2; i++)
 
1937
                                *dst[i]=source_line[height_d2][i];
 
1938
                }
 
1939
        }
 
1940
 
 
1941
        free(line_block_filtered);
 
1942
        free(source_line);
 
1943
}
 
1944
#undef P1
 
1945
#undef S
 
1946
#undef O
 
1947
#undef C
 
1948
#undef T
 
1949
#undef IO
 
1950
#undef ID