#include "../../internal/dcraw_defs.h"
void LibRaw::convert_to_rgb()
{
int i, j, k;
size_t prof_desc_len;
char *prof_desc;
float out_cam[3][4];
double num, inverse[3][3];
static const double(*out_rgb[])[3] = {
LibRaw_constants::rgb_rgb, LibRaw_constants::adobe_rgb,
LibRaw_constants::wide_rgb, LibRaw_constants::prophoto_rgb,
LibRaw_constants::xyz_rgb, LibRaw_constants::aces_rgb};
static const char *name[] = {"sRGB", "Adobe RGB (1998)",
"WideGamut D65", "ProPhoto D65",
"XYZ", "ACES"};
static const unsigned phead[] = {
1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0,
0, 0, 0x61637370, 0, 0, 0x6e6f6e65, 0,
0, 0, 0, 0xf6d6, 0x10000, 0xd32d};
unsigned pbody[] = {10, 0x63707274, 0, 36,
0x64657363, 0, 60,
0x77747074, 0, 20,
0x626b7074, 0, 20,
0x72545243, 0, 14,
0x67545243, 0, 14,
0x62545243, 0, 14,
0x7258595a, 0, 20,
0x6758595a, 0, 20,
0x6258595a, 0, 20};
static const unsigned pwhite[] = {0xf351, 0x10000, 0x116cc};
unsigned pcurve[] = {0x63757276, 0, 1, 0x1000000};
RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB, 0, 2);
prof_desc_len = snprintf(NULL, 0, "%s gamma %g toe slope %g", name[output_color - 1], floorf(1000.f/gamm[0]+.5f)/1000.f, floorf(gamm[1]*1000.0f+.5f)/1000.f) + 1;
prof_desc = (char *)malloc(prof_desc_len);
sprintf(prof_desc, "%s gamma %g toe slope %g", name[output_color - 1], floorf(1000.f/gamm[0]+.5f)/1000.f, floorf(gamm[1]*1000.0f+.5f)/1000.f);
gamma_curve(gamm[0], gamm[1], 0, 0);
memcpy(out_cam, rgb_cam, sizeof out_cam);
raw_color |= colors == 1 || output_color < 1 || output_color > 6;
if (!raw_color)
{
oprof = (unsigned *)calloc(phead[0], 1);
merror(oprof, "convert_to_rgb()");
memcpy(oprof, phead, sizeof phead);
if (output_color == 5)
oprof[4] = oprof[5];
oprof[0] = 132 + 12 * pbody[0];
for (i = 0; i < (int)pbody[0]; i++)
{
oprof[oprof[0] / 4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
pbody[i * 3 + 2] = oprof[0];
oprof[0] += (pbody[i * 3 + 3] + 3) & -4;
}
memcpy(oprof + 32, pbody, sizeof pbody);
oprof[pbody[5] / 4 + 2] = prof_desc_len + 1;
memcpy((char *)oprof + pbody[8] + 8, pwhite, sizeof pwhite);
pcurve[3] = (short)(256 / gamm[5] + 0.5) << 16;
for (i = 4; i < 7; i++)
memcpy((char *)oprof + pbody[i * 3 + 2], pcurve, sizeof pcurve);
pseudoinverse((double(*)[3])out_rgb[output_color - 1], inverse, 3);
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
for (num = k = 0; k < 3; k++)
num += LibRaw_constants::xyzd50_srgb[i][k] * inverse[j][k];
oprof[pbody[j * 3 + 23] / 4 + i + 2] = num * 0x10000 + 0.5;
}
for (i = 0; i < (int)phead[0] / 4; i++)
oprof[i] = htonl(oprof[i]);
strcpy((char *)oprof + pbody[2] + 8, "auto-generated by dcraw");
strcpy((char *)oprof + pbody[5] + 12, prof_desc);
for (i = 0; i < 3; i++)
for (j = 0; j < colors; j++)
for (out_cam[i][j] = k = 0; k < 3; k++)
out_cam[i][j] += out_rgb[output_color - 1][i][k] * rgb_cam[k][j];
}
convert_to_rgb_loop(out_cam);
if (colors == 4 && output_color)
colors = 3;
RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB, 1, 2);
}
void LibRaw::scale_colors()
{
unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8];
int val;
double dsum[8], dmin, dmax;
float scale_mul[4], fr, fc;
ushort *img = 0, *pix;
RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS, 0, 2);
if (user_mul[0])
memcpy(pre_mul, user_mul, sizeof pre_mul);
if (use_auto_wb || (use_camera_wb &&
(cam_mul[0] < -0.5 || (cam_mul[0] <= 0.00001f && !(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_CAMERAWB_FALLBACK_TO_DAYLIGHT))
)))
{
memset(dsum, 0, sizeof dsum);
bottom = MIN(greybox[1] + greybox[3], height);
right = MIN(greybox[0] + greybox[2], width);
for (row = greybox[1]; row < bottom; row += 8)
for (col = greybox[0]; col < right; col += 8)
{
memset(sum, 0, sizeof sum);
for (y = row; y < row + 8 && y < bottom; y++)
for (x = col; x < col + 8 && x < right; x++)
FORC4
{
if (filters)
{
c = fcol(y, x);
val = BAYER2(y, x);
}
else
val = image[y * width + x][c];
if (val > (int)maximum - 25)
goto skip_block;
if ((val -= cblack[c]) < 0)
val = 0;
sum[c] += val;
sum[c + 4]++;
if (filters)
break;
}
FORC(8) dsum[c] += sum[c];
skip_block:;
}
FORC4 if (dsum[c]) pre_mul[c] = dsum[c + 4] / dsum[c];
}
if (use_camera_wb && cam_mul[0] > 0.00001f)
{
memset(sum, 0, sizeof sum);
for (row = 0; row < 8; row++)
for (col = 0; col < 8; col++)
{
c = FC(row, col);
if ((val = white[row][col] - cblack[c]) > 0)
sum[c] += val;
sum[c + 4]++;
}
if (imgdata.color.as_shot_wb_applied)
{
pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = 1.0;
}
else if (sum[0] && sum[1] && sum[2] && sum[3])
FORC4 pre_mul[c] = (float)sum[c + 4] / sum[c];
else if (cam_mul[0] > 0.00001f && cam_mul[2] > 0.00001f)
memcpy(pre_mul, cam_mul, sizeof pre_mul);
else
{
imgdata.process_warnings |= LIBRAW_WARN_BAD_CAMERA_WB;
}
}
if (imgdata.color.as_shot_wb_applied && !use_camera_wb && !use_auto_wb &&
cam_mul[0] > 0.00001f && cam_mul[1] > 0.00001f && cam_mul[2] > 0.00001f)
{
for (c = 0; c < 3; c++)
pre_mul[c] /= cam_mul[c];
}
if (pre_mul[1] == 0)
pre_mul[1] = 1;
if (pre_mul[3] == 0)
pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
if (threshold)
wavelet_denoise();
maximum -= black;
for (dmin = DBL_MAX, dmax = c = 0; c < 4; c++)
{
if (dmin > pre_mul[c])
dmin = pre_mul[c];
if (dmax < pre_mul[c])
dmax = pre_mul[c];
}
if (!highlight)
dmax = dmin;
if (dmax > 0.00001 && maximum > 0)
FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum;
else
FORC4 scale_mul[c] = 1.0;
if (filters > 1000 && (cblack[4] + 1) / 2 == 1 && (cblack[5] + 1) / 2 == 1)
{
FORC4 cblack[FC(c / 2, c % 2)] +=
cblack[6 + c / 2 % cblack[4] * cblack[5] + c % 2 % cblack[5]];
cblack[4] = cblack[5] = 0;
}
size = iheight * iwidth;
scale_colors_loop(scale_mul);
if ((aber[0] != 1 || aber[2] != 1) && colors == 3)
{
for (c = 0; c < 4; c += 2)
{
if (aber[c] == 1)
continue;
img = (ushort *)malloc(size * sizeof *img);
merror(img, "scale_colors()");
for (i = 0; i < size; i++)
img[i] = image[i][c];
for (row = 0; row < iheight; row++)
{
ur = fr = (row - iheight * 0.5) * aber[c] + iheight * 0.5;
if (ur > (unsigned)iheight - 2)
continue;
fr -= ur;
for (col = 0; col < iwidth; col++)
{
uc = fc = (col - iwidth * 0.5) * aber[c] + iwidth * 0.5;
if (uc > (unsigned)iwidth - 2)
continue;
fc -= uc;
pix = img + ur * iwidth + uc;
image[row * iwidth + col][c] =
(pix[0] * (1 - fc) + pix[1] * fc) * (1 - fr) +
(pix[iwidth] * (1 - fc) + pix[iwidth + 1] * fc) * fr;
}
}
free(img);
}
}
RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS, 1, 2);
}
void LibRaw::green_matching()
{
int i, j;
double m1, m2, c1, c2;
int o1_1, o1_2, o1_3, o1_4;
int o2_1, o2_2, o2_3, o2_4;
ushort(*img)[4];
const int margin = 3;
int oj = 2, oi = 2;
float f;
const float thr = 0.01f;
if (half_size || shrink)
return;
if (FC(oj, oi) != 3)
oj++;
if (FC(oj, oi) != 3)
oi++;
if (FC(oj, oi) != 3)
oj--;
img = (ushort(*)[4])calloc(height * width, sizeof *image);
merror(img, "green_matching()");
memcpy(img, image, height * width * sizeof *image);
for (j = oj; j < height - margin; j += 2)
for (i = oi; i < width - margin; i += 2)
{
o1_1 = img[(j - 1) * width + i - 1][1];
o1_2 = img[(j - 1) * width + i + 1][1];
o1_3 = img[(j + 1) * width + i - 1][1];
o1_4 = img[(j + 1) * width + i + 1][1];
o2_1 = img[(j - 2) * width + i][3];
o2_2 = img[(j + 2) * width + i][3];
o2_3 = img[j * width + i - 2][3];
o2_4 = img[j * width + i + 2][3];
m1 = (o1_1 + o1_2 + o1_3 + o1_4) / 4.0;
m2 = (o2_1 + o2_2 + o2_3 + o2_4) / 4.0;
c1 = (abs(o1_1 - o1_2) + abs(o1_1 - o1_3) + abs(o1_1 - o1_4) +
abs(o1_2 - o1_3) + abs(o1_3 - o1_4) + abs(o1_2 - o1_4)) /
6.0;
c2 = (abs(o2_1 - o2_2) + abs(o2_1 - o2_3) + abs(o2_1 - o2_4) +
abs(o2_2 - o2_3) + abs(o2_3 - o2_4) + abs(o2_2 - o2_4)) /
6.0;
if ((img[j * width + i][3] < maximum * 0.95) && (c1 < maximum * thr) &&
(c2 < maximum * thr))
{
f = image[j * width + i][3] * m1 / m2;
image[j * width + i][3] = f > 0xffff ? 0xffff : f;
}
}
free(img);
}