3
Copyright 2011 by Yan Vladimirovich
5
Used in LibRaw with author permission.
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:
10
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
11
(See file LICENSE.LGPL provided in LibRaw distribution archive for details).
13
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
14
(See file LICENSE.CDDL provided in LibRaw distribution archive for details).
16
3. LibRaw Software License 27032010
17
(See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
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
23
Look into dcraw homepage (probably http://cybercom.net/~dcoffin/dcraw/)
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
37
int LibRaw::wf_remove_banding()
39
#define WF_IMGMODE_BAYER4PLANE 4
40
#define WF_IMGMODE_BAYER1PLANE 1
42
#define WF_GREENMODE_IND 0
43
#define WF_GREENMODE_GX_XG 1
44
#define WF_GREENMODE_XG_GX 2
46
#define WF_DEBANDING_OK 0
47
#define WF_DEBANDING_NOTBAYER2X2 1
48
#define WF_DEBANDING_TOOSMALL 2
50
#define WF_GAUSS_PIRAMID_SIZE 4
52
#define WF_MAXTRESHOLD 65536
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)]
58
#define MIN(a,b) ((a) < (b) ? (a) : (b))
59
#define MAX(a,b) ((a) > (b) ? (a) : (b))
61
#define WF_i_1TO4 for(int i=0; i<4; i++)
65
if (S.width<128 || S.height<128)
66
return WF_DEBANDING_TOOSMALL;
72
for(int row_shift=0; row_shift<=8; row_shift+=2)
74
for(int col_shift=0; col_shift<=8; col_shift+=2)
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)))
87
return WF_DEBANDING_NOTBAYER2X2;
89
int x_green_flag = -1;
91
int width_d2, height_d2;
92
int width_p1_d2, height_p1_d2;
95
height_d2 = S.height/2;
97
width_p1_d2 = (S.width+1)/2;
98
height_p1_d2 = (S.height+1)/2;
100
ushort val_max_c[4]={0,0,0,0};
103
ushort dummy_pixel=0;
106
dummy_line = (ushort*)calloc(S.width, sizeof(ushort)*4);
108
for(int i=0; i<S.width*4; i++)
111
// Searching max value for increasing bit-depth
113
for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
117
ushort *src_first, *src_plast, *src_last;
122
WF_i_1TO4 src[i] = &WF_BAYERSRC((i<2)?row:row_p1, i&1, FC((i<2)?row:row_p1, i&1));
124
if (row_p1==S.height)
125
src[2]=src[3]=dummy_line;
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));
135
WF_i_1TO4 val_max_c[i]=MAX(val_max_c[i], *src[i]);
137
// Next 4 pixel or exit
139
if (src[0]<src_plast)
143
else if(src[0]>src_first && src[0]<src_last)
145
WF_i_1TO4 src[i]=i&1?&dummy_pixel:src[i]+8;
153
val_max=MAX(MAX(val_max_c[0], val_max_c[1]), MAX(val_max_c[2], val_max_c[3]));
155
// end of searching max value
158
return WF_DEBANDING_OK;
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; }
172
data_mult = 1<<data_shift;
173
val_max <<= data_shift;
177
for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
181
ushort *src_first, *src_plast, *src_last;
186
WF_i_1TO4 src[i] = &WF_BAYERSRC((i<2)?row:row_p1, i&1, FC((i<2)?row:row_p1, i&1));
188
if (row_p1==S.height)
189
src[2]=src[3]=dummy_line;
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));
199
WF_i_1TO4 (*src[i])<<=data_shift;
201
// Next 4 pixel or exit
203
if (src[0]<src_plast)
207
else if(src[0]>src_first && src[0]<src_last)
209
WF_i_1TO4 src[i]=i&1?&dummy_pixel:src[i]+8;
217
ushort *gauss_pyramid[WF_GAUSS_PIRAMID_SIZE];
218
ushort *difwg_pyramid[WF_GAUSS_PIRAMID_SIZE];
220
for(int i=0; i<WF_GAUSS_PIRAMID_SIZE; i++)
222
gauss_pyramid[i] = (ushort*)calloc(S.width*S.height, sizeof(ushort));
223
difwg_pyramid[i] = (ushort*)calloc(S.width*S.height, sizeof(ushort));
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
230
// Making 4-level gaussian pyramid
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);
239
wf_bayer4_igauss_filter(1, imgdata.image, WF_IMGMODE_BAYER4PLANE, gauss_pyramid[0], WF_IMGMODE_BAYER1PLANE);
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
247
// Energy multiplyers for laplasyan pyramid
249
float dfg_mult[WF_GAUSS_PIRAMID_SIZE]={1.560976, 8.196011, 180.413773, 3601.427246/3.0};
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);*/
256
float dfg_mulg[WF_GAUSS_PIRAMID_SIZE]={1.235223, 19.813868, 365.148407, 7208.362793/3.0};
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);*/
263
float dfg_mlcc[WF_GAUSS_PIRAMID_SIZE][4];
264
long int dfg_dmax[WF_GAUSS_PIRAMID_SIZE][4];
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;
273
green_mode = WF_GREENMODE_IND;
275
for(int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
279
case WF_GREENMODE_GX_XG:
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];
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];
289
case WF_GREENMODE_XG_GX:
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];
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];
299
case WF_GREENMODE_IND:
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];
310
for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
315
ushort *gau[WF_GAUSS_PIRAMID_SIZE][4];
316
ushort *dfg[WF_GAUSS_PIRAMID_SIZE][4];
321
WF_i_1TO4 src[i] = &WF_BAYERSRC((i<2)?row:row_p1, i&1, FC((i<2)?row:row_p1, i&1));
323
if (row_p1==S.height)
324
src[2]=src[3]=dummy_line;
326
for(int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
328
WF_i_1TO4 gau[l][i] = &WF_BAYERGAU(l, (i<2)?row:row_p1, i&1);
330
WF_i_1TO4 dfg[l][i] = &WF_BAYERDFG(l, (i<2)?row:row_p1, i&1);
332
if ((row+1)==S.height)
333
dfg[l][2]=dfg[l][3]=gau[l][2]=gau[l][3]=dummy_line;
336
ushort *src_first, *src_last, *src_last2;
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));
348
WF_i_1TO4 val_src[i]=*src[i];
350
for(int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
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];
358
if(val_dif[i]<dfg_dmax[l][i])
360
val_dif[i]*=dfg_mlcc[l][i];
361
*dfg[l][i] =val_dif[i];
369
// Next 4 pixel or exit
375
for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
376
WF_i_1TO4 gau[l][i]+=2;
378
for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
379
WF_i_1TO4 dfg[l][i]+=2;
381
else if(src[0]>src_first && src[0]<src_last2)
383
WF_i_1TO4 src[i]=i&1?&dummy_pixel:src[i]+8;
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;
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;
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};
404
wf_bayer4_green_blur (0, difwg_pyramid[i], WF_IMGMODE_BAYER1PLANE, difwg_pyramid[i], WF_IMGMODE_BAYER1PLANE);
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);
412
float (*banding_col)[4];
413
float (*banding_row)[4];
414
float (*banding_col_count)[4];
415
float (*banding_row_count)[4];
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);
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);
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;
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;
429
long int val_accepted;
432
WF_i_1TO4 treshold[i]=imgdata.params.wf_deband_treshold[FC(i>>1,i&1)];
434
val_accepted = val_max-3*MAX(MAX(treshold[0],treshold[1]),MAX(treshold[2],treshold[3]));
436
float (*tr_weight)[4];
438
tr_weight=(float(*)[4])calloc(WF_MAXTRESHOLD*4, sizeof(float));
440
WF_i_1TO4 treshold[i]*=data_mult;
442
for(int v=0; v<WF_MAXTRESHOLD; v++)
444
for(int i=0; i<4; i++)
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]);
451
tr_weight[v][i] = 0.0;
455
for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
460
ushort *gau[WF_GAUSS_PIRAMID_SIZE][4];
461
ushort *dfg[WF_GAUSS_PIRAMID_SIZE][4];
466
WF_i_1TO4 src[i] = &WF_BAYERSRC((i<2)?row:row_p1, i&1, FC((i<2)?row:row_p1, i&1));
468
if (row_p1==S.height)
469
src[2]=src[3]=dummy_line;
471
for(int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
473
WF_i_1TO4 gau[l][i] = &WF_BAYERGAU(l, (i<2)?row:row_p1, i&1);
475
WF_i_1TO4 dfg[l][i] = &WF_BAYERDFG(l, (i<2)?row:row_p1, i&1);
477
if (row_p1==S.height)
478
dfg[l][2]=dfg[l][3]=gau[l][2]=gau[l][3]=dummy_line;
481
ushort *src_first, *src_last, *src_last2;
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));
493
float bsum[4]={0,0,0,0};
494
float wsum[4]={0,0,0,0};
496
WF_i_1TO4 val_src[i]=*src[i];
498
for(int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
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];
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];
513
//WF_i_1TO4 *src[i]=bsum[i];
515
WF_i_1TO4 wsum[i]*=wsum[i];
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];
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];
523
// Next 4 pixel or exit
529
for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
530
WF_i_1TO4 gau[l][i]+=2;
532
for (int l=0; l<WF_GAUSS_PIRAMID_SIZE; l++)
533
WF_i_1TO4 dfg[l][i]+=2;
535
else if(src[0]>src_first && src[0]<src_last2)
537
WF_i_1TO4 src[i]=i&1?&dummy_pixel:src[i]+8;
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;
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;
552
float bsum[4], bmean[4];
554
int (*banding_col_i)[4];
555
int (*banding_row_i)[4];
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);
562
WF_i_1TO4 bsum[i]=bmean[i]=0;
564
for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
565
for(int i=0; i<4; i++)
567
if (banding_col_count[row_d2][i]>0)
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];
574
WF_i_1TO4 bmean[i]=bsum[i]/(i<2?height_d2:height_p1_d2);
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]);
582
WF_i_1TO4 bsum[i]=bmean[i]=0;
584
for(int col_d2=0; col_d2<width_p1_d2; col_d2++)
585
for(int i=0; i<4; i++)
587
if (banding_row_count[col_d2][i]>0)
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];
594
WF_i_1TO4 bmean[i]=bsum[i]/(i<2?width_d2:width_p1_d2);
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]);
601
for(int row_d2=0; row_d2<height_p1_d2; row_d2++)
605
ushort *src_first, *src_plast, *src_last;
610
WF_i_1TO4 src[i] = &WF_BAYERSRC((i<2)?row:row_p1, i&1, FC((i<2)?row:row_p1, i&1));
612
if (row_p1==S.height)
613
src[2]=src[3]=dummy_line;
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));
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];
631
for(int i=0; i<4; i++)
633
if (*src[i]>=val_accepted)
635
val_new[i]=*src[i]>>data_shift;
639
if (val_new[i]>val_max)
641
else if (val_new[i]<0)
644
val_new[i]>>=data_shift;
648
WF_i_1TO4 *src[i]=val_new[i];
650
// Next 4 pixel or exit
652
if (src[0]<src_plast)
656
else if(src[0]>src_first && src[0]<src_last)
658
WF_i_1TO4 src[i]=i&1?&dummy_pixel:src[i]+8;
673
free(banding_col_count);
676
free(banding_row_count);
678
for(int i=0; i<WF_GAUSS_PIRAMID_SIZE; i++)
680
free(gauss_pyramid[i]);
681
free(difwg_pyramid[i]);
688
double LibRaw::wf_filter_energy(int r1_greenmode, int r1, int r2_greenmode, int r2)
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.
695
Not optimized, because now it's used only for precalculations.
699
#define WF_MAXFILTERSIZE 10000
702
int rmin_greenmode, rmax_greenmode;
708
rmax_greenmode=r1_greenmode;
709
rmin_greenmode=r2_greenmode;
715
rmax_greenmode=r2_greenmode;
716
rmin_greenmode=r1_greenmode;
720
int rmin_x2_p1, rmax_x2_p1;
724
double gau_kernel_rmin[WF_MAXFILTERSIZE];
725
double gau_kernel_rmax[WF_MAXFILTERSIZE];
727
for(int i=0; i<rmax_x2_p1; i++)
728
gau_kernel_rmin[i]=0;
730
gau_kernel_rmin[1]=1.0;
732
for(int i=2; i<=rmin_x2_p1; i++)
734
for(int j=i; j>0; j--)
735
gau_kernel_rmin[j]=0.5*(gau_kernel_rmin[j]+gau_kernel_rmin[j-1]);
738
for(int i=0; i<=rmax_x2_p1; i++)
739
gau_kernel_rmax[i]=gau_kernel_rmin[i];
741
for(int i=rmin_x2_p1+1; i<=rmax_x2_p1; i++)
743
for(int j=i; j>0; j--)
744
gau_kernel_rmax[j]=0.5*(gau_kernel_rmax[j]+gau_kernel_rmax[j-1]);
747
double wmin_sum, wmax_sum, energy_sum;
753
for(int row=-rmax*2-1; row<=rmax*2+1; row++)
755
for(int col=-rmax*2-1; col<=rmax*2+1; col++)
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)
763
if ( ((row&1)==0) && ((col&1)==0))
765
wght_rmax = WF_WMAX(row, col);
766
wght_rmin = WF_WMIN(row, col);
771
if ( ((row&1)==0) && ((col&1)==0))
772
wght_rmax = 0.5*wght_rmax;
773
else if ( ((row&1)==1) && ((col&1)==1))
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));
781
if ( ((row&1)==0) && ((col&1)==0))
782
wght_rmin = 0.5*wght_rmin;
783
else if ( ((row&1)==1) && ((col&1)==1))
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));
792
energy_sum+=(wght_rmax-wght_rmin)*(wght_rmax-wght_rmin);
800
void LibRaw::wf_bayer4_green_blur(int mode, void* src_image, int src_imgmode, void* dst_image, int dst_imgmode)
803
This function filters green (or any "diagonal") channel of bayer4 data with "X" kernel,
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)]
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;
822
green_mode = WF_GREENMODE_IND;
824
int src_h_shift, dst_h_shift, src_h_shift_x2;
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;
831
src_h_shift_x2 = src_h_shift*2;
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;
840
long int *line_filtered;
842
line_filtered = (long int*) calloc(S.width, sizeof(*line_filtered));
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;
847
if ( green_mode != WF_GREENMODE_IND)
849
for(row=0; row<S.height; row++)
857
if (row == S.height-1)
862
if ( green_mode == WF_GREENMODE_GX_XG )
865
start_col = ( row+1 ) & 1;
867
if ( start_col == 0 )
874
case WF_IMGMODE_BAYER1PLANE:
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);
884
case WF_IMGMODE_BAYER4PLANE:
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));
895
long int sum_l1, sum_l2;
897
sum_l1 = *src_u1 + *src_d1;
898
sum_l2 = *src_u2 + *src_d2;
904
line_filtered[start_col] = sum_l1 + sum_l2 + (*src_c)*4;
906
src_u2 += src_h_shift;
907
src_d2 += src_h_shift;
909
sum_l2 = *src_u2 + *src_d2;
911
src_c += src_h_shift;
915
int width_m_3 = S.width-3;
919
for (col=start_col; col<width_m_3; col+=2)
921
line_filtered[col] = sum_l1 + sum_l2 + 4*(*src_c);
923
src_u1 += src_h_shift_x2;
924
src_d1 += src_h_shift_x2;
926
sum_l1 = *src_u1 + *src_d1;
928
src_c += src_h_shift;
931
line_filtered[col] = sum_l1 + sum_l2 + 4*(*src_c);
933
src_u2 += src_h_shift_x2;
934
src_d2 += src_h_shift_x2;
936
sum_l2 = *src_u2 + *src_d2;
938
src_c += src_h_shift;
943
if (col == S.width-1)
945
line_filtered[col] = 2*sum_l1 + 4*(*src_c);
947
else if (col == S.width-2)
949
line_filtered[col] = sum_l1 + sum_l2 + 4*(*src_c);
951
else if (col == S.width-3)
953
line_filtered[col] = sum_l1 + sum_l2 + 4*(*src_c);
955
src_c += src_h_shift;
958
line_filtered[col] = 2*sum_l2 + 4*(*src_c);
964
if ( green_mode == WF_GREENMODE_GX_XG )
965
start_col = ( row+1 ) & 1;
972
case WF_IMGMODE_BAYER1PLANE:
973
dst_c = &WF_BAYERDST1(row-1, start_col);
976
case WF_IMGMODE_BAYER4PLANE:
977
dst_c = &WF_BAYERDST4(row-1, start_col, FC(row-1, start_col));
981
for (col=start_col; col<S.width; col+=2)
983
*dst_c=(line_filtered[col])>>3;
987
if (src_image != dst_image)
989
// copy red or blue channel
991
if ( green_mode == WF_GREENMODE_GX_XG )
994
start_col = (row+1) & 1;
998
case WF_IMGMODE_BAYER1PLANE:
999
src = &WF_BAYERSRC1(row-1, start_col);
1002
case WF_IMGMODE_BAYER4PLANE:
1003
src = &WF_BAYERSRC4(row-1, start_col, FC(row-1, start_col));
1007
switch (dst_imgmode)
1009
case WF_IMGMODE_BAYER1PLANE:
1010
dst_rb = &WF_BAYERDST1(row-1, start_col);
1013
case WF_IMGMODE_BAYER4PLANE:
1014
dst_rb = &WF_BAYERDST4(row-1, start_col, FC(row-1, start_col));
1018
for (col=start_col; col<S.width; col+=2)
1022
dst_rb+=dst_h_shift;
1028
if ( green_mode == WF_GREENMODE_GX_XG )
1029
start_col = ( row+1 ) & 1;
1031
start_col = row & 1;
1034
switch (dst_imgmode)
1036
case WF_IMGMODE_BAYER1PLANE:
1037
dst_c = &WF_BAYERDST1(row-1, start_col);
1040
case WF_IMGMODE_BAYER4PLANE:
1041
dst_c = &WF_BAYERDST4(row-1, start_col, FC(row-1, start_col));
1045
for (col=start_col; col<S.width; col+=2)
1047
*dst_c=(line_filtered[col])>>3;
1051
if (src_image != dst_image)
1053
// copy red or blue channel
1055
if ( green_mode == WF_GREENMODE_GX_XG )
1056
start_col = row & 1;
1058
start_col = (row+1) & 1;
1060
switch (src_imgmode)
1062
case WF_IMGMODE_BAYER1PLANE:
1063
src = &WF_BAYERSRC1(row-1, start_col);
1066
case WF_IMGMODE_BAYER4PLANE:
1067
src = &WF_BAYERSRC4(row-1, start_col, FC(row-1, start_col));
1071
switch (dst_imgmode)
1073
case WF_IMGMODE_BAYER1PLANE:
1074
dst_rb = &WF_BAYERDST1(row-1, start_col);
1077
case WF_IMGMODE_BAYER4PLANE:
1078
dst_rb = &WF_BAYERDST4(row-1, start_col, FC(row-1, start_col));
1082
for (col=start_col; col<S.width; col+=2)
1086
dst_rb+=dst_h_shift;
1091
free(line_filtered);
1094
void LibRaw::wf_bayer4_igauss_filter(int radius, void* src_image, int src_imgmode, void* dst_image, int dst_imgmode)
1097
This function filter source bayer4 data with gauss (binominal), 4 channels independently.
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)]
1105
if (radius <= 0 || radius > 8)
1108
long int (*line_filtered)[4];
1110
long int gauss_conv_kernel[9][4];
1112
long int gauss_conv_kernel_c[8][9] =
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},
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]));
1127
int src_h_shift, src_v_shift;
1128
int dst_h_shift, dst_v_shift;
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;
1135
src_v_shift = S.width*src_h_shift;
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;
1142
dst_v_shift = S.width*dst_h_shift;
1144
int width_d2 = S.width / 2;
1145
int height_d2 = S.height / 2;
1149
for (j=0; j<=radius; j++)
1153
gauss_conv_kernel[j][i] = gauss_conv_kernel_c[radius-1][j];
1160
ushort *src [4], *dst[4];
1169
int padding = i<2 && (S.width & 1 == 1) ? 1 : 0;
1170
right_edge[i]=width_d2 + radius + padding;
1173
for(row=0; row<S.height; row+=2)
1175
int row_p1=MIN(row+1, S.height-1);
1177
switch (src_imgmode)
1179
case WF_IMGMODE_BAYER1PLANE:
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);
1187
case WF_IMGMODE_BAYER4PLANE:
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));
1198
for (int j=0; j<line_memory_len; j++)
1201
line_filtered[j][i]=0;
1204
for(col=0; col<S.width-1; col+=2)
1215
line_filtered[colf][i]+=gauss_conv_kernel[0][i]*(src_c[i]);
1217
for(int j=1; j<=radius; j++)
1226
g = gauss_conv_kernel[j][i]*src_c[i];
1228
line_filtered[col1][i]+=g;
1229
line_filtered[col2][i]+=g;
1236
src[i]+=src_h_shift;
1239
// width is odd number
1241
if (col == S.width-1)
1251
line_filtered[colf][i]+=gauss_conv_kernel[0][i]*(src_c[i]);
1253
for(int j=1; j<=radius; j++)
1262
g = gauss_conv_kernel[j][i]*src_c[i];
1264
line_filtered[col1][i]+=g;
1265
line_filtered[col2][i]+=g;
1272
src[i]+=src_h_shift;
1277
for(j=0; j<radius; j++)
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];
1286
switch (dst_imgmode)
1288
case WF_IMGMODE_BAYER1PLANE:
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);
1296
case WF_IMGMODE_BAYER4PLANE:
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));
1307
for(col=0; col<S.width-1; col+=2)
1311
*dst[i]=line_filtered[colf][i]>>16;
1312
dst[i]+=dst_h_shift;
1318
if (col == S.width-1)
1321
*dst[i]=line_filtered[colf][i]>>16;
1332
int padding = i<2 && (S.height & 1 == 1) ? 1 : 0;
1333
lower_edge[i]=height_d2 + radius + padding;
1337
for(col=0; col<S.width; col+=2)
1339
int col_p1=MIN(col+1, S.width-1);
1341
switch (dst_imgmode)
1343
case WF_IMGMODE_BAYER1PLANE:
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);
1351
case WF_IMGMODE_BAYER4PLANE:
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));
1362
for (int j=0; j<line_memory_len; j++)
1365
line_filtered[j][i]=0;
1368
for(row=0; row<S.height-1; row+=2)
1379
line_filtered[rowf][i]+=gauss_conv_kernel[0][i]*(src_c[i]);
1381
for(int j=1; j<=radius; j++)
1391
g[i] = gauss_conv_kernel[j][i]*src_c[i];
1393
line_filtered[row1][i]+=g[i];
1394
line_filtered[row2][i]+=g[i];
1401
src[i]+=dst_v_shift;
1404
// height is odd number
1406
if (row == S.height-1)
1416
line_filtered[rowf][i]+=gauss_conv_kernel[0][i]*(src_c[i]);
1418
for(int j=1; j<=radius; j++)
1428
g[i] = gauss_conv_kernel[j][i]*src_c[i];
1430
line_filtered[row1][i]+=g[i];
1431
line_filtered[row2][i]+=g[i];
1438
src[i]+=dst_v_shift;
1443
for(int j=0; j<radius; j++)
1445
for (int i=0; i<4; i++)
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];
1453
switch (dst_imgmode)
1455
case WF_IMGMODE_BAYER1PLANE:
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);
1463
case WF_IMGMODE_BAYER4PLANE:
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));
1474
for(row=0; row<S.height-1; row+=2)
1478
*dst[i]=line_filtered[rowf][i]>>16;
1479
dst[i]+=dst_v_shift;
1485
if (row == S.height-1)
1488
*dst[i]=line_filtered[rowf][i]>>16;
1492
free(line_filtered);
1495
void LibRaw::wf_bayer4_block_filter(int* radius_list, void* src_image, int src_imgmode, void* dst_image, int dst_imgmode)
1497
#define WF_BLOCKFILTER_MAXF 8
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)]
1504
int filter_itrtns_num = 0;
1506
int block_radius [WF_BLOCKFILTER_MAXF];
1507
int block_radius_x2 [WF_BLOCKFILTER_MAXF];
1508
int block_radius_x2_p1[WF_BLOCKFILTER_MAXF];
1510
int block_radius_max = 0;
1511
int block_radius_max_x2;
1512
int block_radius_max_x2_p1;
1514
for(int i=0; (i<WF_BLOCKFILTER_MAXF) && (radius_list[i]!=0); i++)
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;
1520
if(block_radius_max<block_radius[i])
1521
block_radius_max=block_radius[i];
1523
filter_itrtns_num++;
1526
long int divider[WF_BLOCKFILTER_MAXF];
1527
long int div_multiplication;
1529
div_multiplication=block_radius_x2_p1[0];
1531
for(int i=1; i<filter_itrtns_num; i++)
1533
if (div_multiplication*((long int)block_radius_x2_p1[i])<65535)
1535
div_multiplication*=block_radius_x2_p1[i];
1540
divider[i-1]=block_radius_x2_p1[i];
1544
divider[filter_itrtns_num-1]=div_multiplication;
1546
block_radius_max_x2 = block_radius_max*2;
1547
block_radius_max_x2_p1 = block_radius_max_x2+1;
1549
int line_memory_len;
1551
long int (*source_line)[4];
1552
long int (*line_block_filtered)[4];
1554
line_memory_len = (MAX(S.height, S.width)+1)/2+block_radius_max_x2_p1*2;
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]));
1560
int src_h_shift, dst_h_shift, src_v_shift, dst_v_shift;
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;
1567
src_v_shift = S.width*src_h_shift;
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;
1574
dst_v_shift = S.width*dst_h_shift;
1576
int width_d2 = S.width / 2;
1577
int height_d2 = S.height / 2;
1579
int width_p1_d2 = (S.width+1) / 2;
1580
int height_p1_d2 = (S.height+1) / 2;
1582
ushort *src[4], *dst[4];
1584
long int (*src_plus)[4], (*src_minus)[4];
1585
long int block_sum[4];
1589
int right_edge[4], lower_edge[4];
1591
for(row=0; row<S.height; row+=2)
1593
int row_p1=MIN(row+1, S.height-1);
1595
switch (src_imgmode)
1597
case WF_IMGMODE_BAYER1PLANE:
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);
1605
case WF_IMGMODE_BAYER4PLANE:
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));
1614
for(col=0; col<width_d2; col++)
1616
for (int i=0; i<4; i++)
1618
source_line[col][i]=*src[i];
1619
src[i] += src_h_shift;
1623
if (S.width & 1 == 1)
1625
for (int i=0; i<2; i++)
1627
source_line[width_d2][i]=*src[i];
1630
for (int i=2; i<4; i++)
1632
source_line[width_d2][i]=0;
1636
for(int f=0; f<filter_itrtns_num; f++)
1638
src_minus=src_plus=source_line;
1640
for (int i=0; i<4; i++)
1643
for(col=0; col<block_radius_x2_p1[f]; col++)
1645
for (int i=0; i<4; i++)
1647
block_sum[i]+=(*src_plus)[i];
1648
line_block_filtered[col][i]=block_sum[i];
1654
for(col=block_radius_x2_p1[f]; col<width_p1_d2; col++)
1656
for (int i=0; i<4; i++)
1658
block_sum[i]+=(*src_plus)[i];
1659
block_sum[i]-=(*src_minus)[i];
1660
line_block_filtered[col][i]=block_sum[i];
1667
for(col=width_p1_d2; col<width_p1_d2+block_radius_x2_p1[f]; col++)
1669
for (int i=0; i<4; i++)
1671
block_sum[i]-=(*src_minus)[i];
1672
line_block_filtered[col][i]=block_sum[i];
1680
for (int i=0; i<4; i++)
1682
int padding = i<2 && (S.width & 1 == 1) ? 1 : 0;
1683
right_edge[i]=width_d2 + block_radius[f] + padding;
1686
for(int j=0; j<block_radius[f]; j++)
1688
for (int i=0; i<4; i++)
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];
1697
for(col=0; col<width_d2; col++)
1699
for (int i=0; i<4; i++)
1700
source_line[col][i]=line_block_filtered[col+block_radius[f]][i];
1703
if (S.width & 1 == 1)
1705
for (int i=0; i<2; i++)
1706
source_line[width_d2][i]=line_block_filtered[width_d2+block_radius[f]][i];
1708
for (int i=2; i<4; i++)
1709
source_line[width_d2][i]=0;
1714
for(col=0; col<width_d2; col++)
1716
for (int i=0; i<4; i++)
1717
source_line[col][i]=line_block_filtered[col+block_radius[f]][i]/divider[f];
1720
if (S.width & 1 == 1)
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];
1725
for (int i=2; i<4; i++)
1726
source_line[width_d2][i]=0;
1731
switch (dst_imgmode)
1733
case WF_IMGMODE_BAYER1PLANE:
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);
1741
case WF_IMGMODE_BAYER4PLANE:
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));
1750
for(col=0; col<width_d2; col++)
1752
for (int i=0; i<4; i++)
1754
*dst[i]=source_line[col][i];
1755
dst[i]+=dst_h_shift;
1759
if (S.width & 1 == 1)
1761
for (int i=0; i<2; i++)
1762
*dst[i]=source_line[col][i];
1766
for(col=0; col<S.width; col+=2)
1768
int col_p1=MIN(col+1, S.width-1);
1770
switch (dst_imgmode)
1772
case WF_IMGMODE_BAYER1PLANE:
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);
1780
case WF_IMGMODE_BAYER4PLANE:
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));
1789
for(row=0; row<height_d2; row++)
1791
for (int i=0; i<4; i++)
1793
source_line[row][i]=*src[i];
1794
src[i] += dst_v_shift;
1798
if (S.height & 1 == 1)
1800
for (int i=0; i<2; i++)
1802
source_line[height_d2][i]=*src[i];
1805
for (int i=2; i<4; i++)
1807
source_line[height_d2][i]=0;
1811
for(int f=0; f<filter_itrtns_num; f++)
1813
src_minus=src_plus=source_line;
1815
for (int i=0; i<4; i++)
1818
for(row=0; row<block_radius_x2_p1[f]; row++)
1820
for (int i=0; i<4; i++)
1822
block_sum[i]+=(*src_plus)[i];
1823
line_block_filtered[row][i]=block_sum[i];
1829
for(row=block_radius_x2_p1[f]; row<height_p1_d2; row++)
1831
for (int i=0; i<4; i++)
1833
block_sum[i]+=(*src_plus)[i];
1834
block_sum[i]-=(*src_minus)[i];
1835
line_block_filtered[row][i]=block_sum[i];
1842
for(row=height_p1_d2; row<height_p1_d2+block_radius_x2_p1[f]; row++)
1844
for (int i=0; i<4; i++)
1846
block_sum[i]-=(*src_minus)[i];
1847
line_block_filtered[row][i]=block_sum[i];
1855
for (int i=0; i<4; i++)
1857
int padding = (i<2) && (S.height & 1 == 1) ? 1 : 0;
1858
lower_edge[i]=height_d2 + block_radius[f] + padding;
1861
for(int j=0; j<block_radius[f]; j++)
1863
for (int i=0; i<4; i++)
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];
1872
for(row=0; row<height_d2; row++)
1874
for (int i=0; i<4; i++)
1875
source_line[row][i]=line_block_filtered[row+block_radius[f]][i];
1878
if (S.height & 1 == 1)
1880
for (int i=0; i<2; i++)
1881
source_line[height_d2][i]=line_block_filtered[height_d2+block_radius[f]][i];
1883
for (int i=2; i<4; i++)
1884
source_line[height_d2][i]=0;
1889
for(row=0; row<height_d2; row++)
1891
for (int i=0; i<4; i++)
1892
source_line[row][i]=line_block_filtered[row+block_radius[f]][i]/divider[f];
1895
if (S.height & 1 == 1)
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];
1900
for (int i=2; i<4; i++)
1901
source_line[height_d2][i]=0;
1906
switch (dst_imgmode)
1908
case WF_IMGMODE_BAYER1PLANE:
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);
1916
case WF_IMGMODE_BAYER4PLANE:
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));
1925
for(row=0; row<height_d2; row++)
1927
for (int i=0; i<4; i++)
1929
*dst[i]=source_line[row][i];
1930
dst[i]+=dst_v_shift;
1934
if (S.height & 1 == 1)
1936
for (int i=0; i<2; i++)
1937
*dst[i]=source_line[height_d2][i];
1941
free(line_block_filtered);