Merge commit '638ecc4cde79b0296f2e04f683ca4cb881c28f36' as 'rtengine/libraw'

This commit is contained in:
Lawrence Lee
2023-11-12 11:49:00 -08:00
213 changed files with 77043 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
/* -*- C++ -*-
* Copyright 2019-2021 LibRaw LLC (info@libraw.org)
*
LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder,
dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net.
LibRaw do not use RESTRICTED code from dcraw.c
LibRaw is free software; you can redistribute it and/or modify
it under the terms of the one of two licenses as you choose:
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
(See file LICENSE.LGPL provided in LibRaw distribution archive for details).
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
(See file LICENSE.CDDL provided in LibRaw distribution archive for details).
*/
#include "../../internal/dcraw_fileio_defs.h"
/*
Search from the current directory up to the root looking for
a ".badpixels" file, and fix those pixels now.
*/
void LibRaw::bad_pixels(const char *cfname)
{
FILE *fp = NULL;
char *cp, line[128];
int time, row, col, r, c, rad, tot, n;
if (!filters)
return;
RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS, 0, 2);
if (cfname)
fp = fopen(cfname, "r");
if (!fp)
{
imgdata.process_warnings |= LIBRAW_WARN_NO_BADPIXELMAP;
return;
}
while (fgets(line, 128, fp))
{
cp = strchr(line, '#');
if (cp)
*cp = 0;
if (sscanf(line, "%d %d %d", &col, &row, &time) != 3)
continue;
if ((unsigned)col >= width || (unsigned)row >= height)
continue;
if (time > timestamp)
continue;
for (tot = n = 0, rad = 1; rad < 3 && n == 0; rad++)
for (r = row - rad; r <= row + rad; r++)
for (c = col - rad; c <= col + rad; c++)
if ((unsigned)r < height && (unsigned)c < width &&
(r != row || c != col) && fcol(r, c) == fcol(row, col))
{
tot += BAYER2(r, c);
n++;
}
if (n > 0)
BAYER2(row, col) = tot / n;
}
fclose(fp);
RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS, 1, 2);
}
void LibRaw::subtract(const char *fname)
{
FILE *fp;
int dim[3] = {0, 0, 0}, comment = 0, number = 0, error = 0, nd = 0, c, row,
col;
RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME, 0, 2);
if (!(fp = fopen(fname, "rb")))
{
imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_FILE;
return;
}
if (fgetc(fp) != 'P' || fgetc(fp) != '5')
error = 1;
while (!error && nd < 3 && (c = fgetc(fp)) != EOF)
{
if (c == '#')
comment = 1;
if (c == '\n')
comment = 0;
if (comment)
continue;
if (isdigit(c))
number = 1;
if (number)
{
if (isdigit(c))
dim[nd] = dim[nd] * 10 + c - '0';
else if (isspace(c))
{
number = 0;
nd++;
}
else
error = 1;
}
}
if (error || nd < 3)
{
fclose(fp);
return;
}
else if (dim[0] != width || dim[1] != height || dim[2] != 65535)
{
imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_DIM;
fclose(fp);
return;
}
std::vector<ushort> pixel(width, 0);
for (row = 0; row < height; row++)
{
fread(pixel.data(), 2, width, fp);
for (col = 0; col < width; col++)
BAYER(row, col) = MAX(BAYER(row, col) - ntohs(pixel[col]), 0);
}
fclose(fp);
memset(cblack, 0, sizeof cblack);
black = 0;
RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME, 1, 2);
}

View File

@@ -0,0 +1,24 @@
/* -*- C++ -*-
* Copyright 2019-2021 LibRaw LLC (info@libraw.org)
*
Placeholder functions to build LibRaw w/o postprocessing
and preprocessing calls
LibRaw is free software; you can redistribute it and/or modify
it under the terms of the one of two licenses as you choose:
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
(See file LICENSE.LGPL provided in LibRaw distribution archive for details).
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
(See file LICENSE.CDDL provided in LibRaw distribution archive for details).
*/
#include "../../internal/libraw_cxx_defs.h"
void LibRaw::copy_fuji_uncropped(unsigned short /*cblack*/[4],
unsigned short * /*dmaxp*/) {}
void LibRaw::copy_bayer(unsigned short /*cblack*/[4], unsigned short * /*dmaxp*/){}
void LibRaw::raw2image_start(){}

View File

@@ -0,0 +1,558 @@
/* -*- C++ -*-
* Copyright 2019-2021 LibRaw LLC (info@libraw.org)
*
LibRaw is free software; you can redistribute it and/or modify
it under the terms of the one of two licenses as you choose:
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
(See file LICENSE.LGPL provided in LibRaw distribution archive for details).
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
(See file LICENSE.CDDL provided in LibRaw distribution archive for details).
*/
#include "../../internal/libraw_cxx_defs.h"
void LibRaw::raw2image_start()
{
// restore color,sizes and internal data into raw_image fields
memmove(&imgdata.color, &imgdata.rawdata.color, sizeof(imgdata.color));
memmove(&imgdata.sizes, &imgdata.rawdata.sizes, sizeof(imgdata.sizes));
memmove(&imgdata.idata, &imgdata.rawdata.iparams, sizeof(imgdata.idata));
memmove(&libraw_internal_data.internal_output_params,
&imgdata.rawdata.ioparams,
sizeof(libraw_internal_data.internal_output_params));
if (O.user_flip >= 0)
S.flip = O.user_flip;
switch ((S.flip + 3600) % 360)
{
case 270:
S.flip = 5;
break;
case 180:
S.flip = 3;
break;
case 90:
S.flip = 6;
break;
}
// adjust for half mode!
IO.shrink =
P1.filters &&
(O.half_size || ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1)));
S.iheight = (S.height + IO.shrink) >> IO.shrink;
S.iwidth = (S.width + IO.shrink) >> IO.shrink;
}
int LibRaw::raw2image(void)
{
CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
try
{
raw2image_start();
if (is_phaseone_compressed() && imgdata.rawdata.raw_alloc)
{
phase_one_allocate_tempbuffer();
int rc = phase_one_subtract_black((ushort *)imgdata.rawdata.raw_alloc,
imgdata.rawdata.raw_image);
if (rc == 0)
rc = phase_one_correct();
if (rc != 0)
{
phase_one_free_tempbuffer();
return rc;
}
}
// free and re-allocate image bitmap
if (imgdata.image)
{
imgdata.image = (ushort(*)[4])realloc(
imgdata.image, S.iheight * S.iwidth * sizeof(*imgdata.image));
memset(imgdata.image, 0, S.iheight * S.iwidth * sizeof(*imgdata.image));
}
else
imgdata.image =
(ushort(*)[4])calloc(S.iheight * S.iwidth, sizeof(*imgdata.image));
libraw_decoder_info_t decoder_info;
get_decoder_info(&decoder_info);
// Copy area size
int copyheight = MAX(0, MIN(int(S.height), int(S.raw_height) - int(S.top_margin)));
int copywidth = MAX(0, MIN(int(S.width), int(S.raw_width) - int(S.left_margin)));
// Move saved bitmap to imgdata.image
if ((imgdata.idata.filters || P1.colors == 1) && imgdata.rawdata.raw_image)
{
if (IO.fuji_width)
{
unsigned r, c;
int row, col;
for (row = 0; row < S.raw_height - S.top_margin * 2; row++)
{
for (col = 0;
col < IO.fuji_width
<< int(!libraw_internal_data.unpacker_data.fuji_layout);
col++)
{
if (libraw_internal_data.unpacker_data.fuji_layout)
{
r = IO.fuji_width - 1 - col + (row >> 1);
c = col + ((row + 1) >> 1);
}
else
{
r = IO.fuji_width - 1 + row - (col >> 1);
c = row + ((col + 1) >> 1);
}
if (r < S.height && c < S.width && col + int(S.left_margin) < int(S.raw_width))
imgdata.image[((r) >> IO.shrink) * S.iwidth + ((c) >> IO.shrink)]
[FC(r, c)] =
imgdata.rawdata
.raw_image[(row + S.top_margin) * S.raw_pitch / 2 +
(col + S.left_margin)];
}
}
}
else
{
int row, col;
for (row = 0; row < copyheight; row++)
for (col = 0; col < copywidth; col++)
imgdata.image[((row) >> IO.shrink) * S.iwidth +
((col) >> IO.shrink)][fcol(row, col)] =
imgdata.rawdata
.raw_image[(row + S.top_margin) * S.raw_pitch / 2 +
(col + S.left_margin)];
}
}
else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY)
{
if (imgdata.rawdata.color4_image)
{
if (S.width * 8u == S.raw_pitch && S.height == S.raw_height)
memmove(imgdata.image, imgdata.rawdata.color4_image,
S.width * S.height * sizeof(*imgdata.image));
else
{
for (int row = 0; row < copyheight; row++)
memmove(&imgdata.image[row * S.width],
&imgdata.rawdata
.color4_image[(row + S.top_margin) * S.raw_pitch / 8 +
S.left_margin],
copywidth * sizeof(*imgdata.image));
}
}
else if (imgdata.rawdata.color3_image)
{
unsigned char *c3image = (unsigned char *)imgdata.rawdata.color3_image;
for (int row = 0; row < copyheight; row++)
{
ushort(*srcrow)[3] =
(ushort(*)[3]) & c3image[(row + S.top_margin) * S.raw_pitch];
ushort(*dstrow)[4] = (ushort(*)[4]) & imgdata.image[row * S.width];
for (int col = 0; col < copywidth; col++)
{
for (int c = 0; c < 3; c++)
dstrow[col][c] = srcrow[S.left_margin + col][c];
dstrow[col][3] = 0;
}
}
}
else
{
// legacy decoder, but no data?
throw LIBRAW_EXCEPTION_DECODE_RAW;
}
}
// Free PhaseOne separate copy allocated at function start
if (is_phaseone_compressed())
{
phase_one_free_tempbuffer();
}
// hack - clear later flags!
if (load_raw == &LibRaw::canon_600_load_raw && S.width < S.raw_width)
{
canon_600_correct();
}
imgdata.progress_flags =
LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN |
LIBRAW_PROGRESS_RAW2_IMAGE | LIBRAW_PROGRESS_IDENTIFY |
LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW;
return 0;
}
catch (const std::bad_alloc&)
{
EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC);
}
catch (const LibRaw_exceptions& err)
{
EXCEPTION_HANDLER(err);
}
}
void LibRaw::copy_fuji_uncropped(unsigned short cblack[4],
unsigned short *dmaxp)
{
#if defined(LIBRAW_USE_OPENMP)
#pragma omp parallel for schedule(dynamic) default(none) firstprivate(cblack) shared(dmaxp)
#endif
for (int row = 0; row < int(S.raw_height) - int(S.top_margin) * 2; row++)
{
int col;
unsigned short ldmax = 0;
for (col = 0;
col < IO.fuji_width << int(!libraw_internal_data.unpacker_data.fuji_layout)
&& col + int(S.left_margin) < int(S.raw_width);
col++)
{
unsigned r, c;
if (libraw_internal_data.unpacker_data.fuji_layout)
{
r = IO.fuji_width - 1 - col + (row >> 1);
c = col + ((row + 1) >> 1);
}
else
{
r = IO.fuji_width - 1 + row - (col >> 1);
c = row + ((col + 1) >> 1);
}
if (r < S.height && c < S.width)
{
unsigned short val =
imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 +
(col + S.left_margin)];
int cc = FC(r, c);
if (val > cblack[cc])
{
val -= cblack[cc];
if (val > ldmax)
ldmax = val;
}
else
val = 0;
imgdata.image[((r) >> IO.shrink) * S.iwidth + ((c) >> IO.shrink)][cc] =
val;
}
}
#if defined(LIBRAW_USE_OPENMP)
#pragma omp critical(dataupdate)
#endif
{
if (*dmaxp < ldmax)
*dmaxp = ldmax;
}
}
}
void LibRaw::copy_bayer(unsigned short cblack[4], unsigned short *dmaxp)
{
// Both cropped and uncropped
int maxHeight = MIN(int(S.height),int(S.raw_height)-int(S.top_margin));
#if defined(LIBRAW_USE_OPENMP)
#pragma omp parallel for schedule(dynamic) default(none) shared(dmaxp) firstprivate(cblack, maxHeight)
#endif
for (int row = 0; row < maxHeight ; row++)
{
int col;
unsigned short ldmax = 0;
for (col = 0; col < S.width && col + S.left_margin < S.raw_width; col++)
{
unsigned short val =
imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 +
(col + S.left_margin)];
int cc = fcol(row, col);
if (val > cblack[cc])
{
val -= cblack[cc];
if (val > ldmax)
ldmax = val;
}
else
val = 0;
imgdata.image[((row) >> IO.shrink) * S.iwidth + ((col) >> IO.shrink)][cc] = val;
}
#if defined(LIBRAW_USE_OPENMP)
#pragma omp critical(dataupdate)
#endif
{
if (*dmaxp < ldmax)
*dmaxp = ldmax;
}
}
}
int LibRaw::raw2image_ex(int do_subtract_black)
{
CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
try
{
raw2image_start();
// Compressed P1 files with bl data!
if (is_phaseone_compressed() && imgdata.rawdata.raw_alloc)
{
phase_one_allocate_tempbuffer();
int rc = phase_one_subtract_black((ushort *)imgdata.rawdata.raw_alloc,
imgdata.rawdata.raw_image);
if (rc == 0)
rc = phase_one_correct();
if (rc != 0)
{
phase_one_free_tempbuffer();
return rc;
}
}
// process cropping
int do_crop = 0;
if (~O.cropbox[2] && ~O.cropbox[3])
{
int crop[4], c, filt;
for (int q = 0; q < 4; q++)
{
crop[q] = O.cropbox[q];
if (crop[q] < 0)
crop[q] = 0;
}
if (IO.fuji_width && imgdata.idata.filters >= 1000)
{
crop[0] = (crop[0] / 4) * 4;
crop[1] = (crop[1] / 4) * 4;
if (!libraw_internal_data.unpacker_data.fuji_layout)
{
crop[2] *= sqrt(2.0);
crop[3] /= sqrt(2.0);
}
crop[2] = (crop[2] / 4 + 1) * 4;
crop[3] = (crop[3] / 4 + 1) * 4;
}
else if (imgdata.idata.filters == 1)
{
crop[0] = (crop[0] / 16) * 16;
crop[1] = (crop[1] / 16) * 16;
}
else if (imgdata.idata.filters == LIBRAW_XTRANS)
{
crop[0] = (crop[0] / 6) * 6;
crop[1] = (crop[1] / 6) * 6;
}
do_crop = 1;
crop[2] = MIN(crop[2], (signed)S.width - crop[0]);
crop[3] = MIN(crop[3], (signed)S.height - crop[1]);
if (crop[2] <= 0 || crop[3] <= 0)
throw LIBRAW_EXCEPTION_BAD_CROP;
// adjust sizes!
S.left_margin += crop[0];
S.top_margin += crop[1];
S.width = crop[2];
S.height = crop[3];
S.iheight = (S.height + IO.shrink) >> IO.shrink;
S.iwidth = (S.width + IO.shrink) >> IO.shrink;
if (!IO.fuji_width && imgdata.idata.filters &&
imgdata.idata.filters >= 1000)
{
for (filt = c = 0; c < 16; c++)
filt |= FC((c >> 1) + (crop[1]), (c & 1) + (crop[0])) << c * 2;
imgdata.idata.filters = filt;
}
}
int alloc_width = S.iwidth;
int alloc_height = S.iheight;
if (IO.fuji_width && do_crop)
{
int IO_fw = S.width >> int(!libraw_internal_data.unpacker_data.fuji_layout);
int t_alloc_width =
(S.height >> libraw_internal_data.unpacker_data.fuji_layout) + IO_fw;
int t_alloc_height = t_alloc_width - 1;
alloc_height = (t_alloc_height + IO.shrink) >> IO.shrink;
alloc_width = (t_alloc_width + IO.shrink) >> IO.shrink;
}
int alloc_sz = alloc_width * alloc_height;
if (imgdata.image)
{
imgdata.image = (ushort(*)[4])realloc(imgdata.image,
alloc_sz * sizeof(*imgdata.image));
memset(imgdata.image, 0, alloc_sz * sizeof(*imgdata.image));
}
else
imgdata.image = (ushort(*)[4])calloc(alloc_sz, sizeof(*imgdata.image));
libraw_decoder_info_t decoder_info;
get_decoder_info(&decoder_info);
// Adjust black levels
unsigned short cblack[4] = {0, 0, 0, 0};
unsigned short dmax = 0;
if (do_subtract_black)
{
adjust_bl();
for (int i = 0; i < 4; i++)
cblack[i] = (unsigned short)C.cblack[i];
}
// Max area size to definitely not overrun in/out buffers
int copyheight = MAX(0, MIN(int(S.height), int(S.raw_height) - int(S.top_margin)));
int copywidth = MAX(0, MIN(int(S.width), int(S.raw_width) - int(S.left_margin)));
// Move saved bitmap to imgdata.image
if ((imgdata.idata.filters || P1.colors == 1) && imgdata.rawdata.raw_image)
{
if (IO.fuji_width)
{
if (do_crop)
{
IO.fuji_width =
S.width >> int(!libraw_internal_data.unpacker_data.fuji_layout);
int IO_fwidth =
(S.height >> int(libraw_internal_data.unpacker_data.fuji_layout)) +
IO.fuji_width;
int IO_fheight = IO_fwidth - 1;
int row, col;
for (row = 0; row < S.height; row++)
{
for (col = 0; col < S.width; col++)
{
int r, c;
if (libraw_internal_data.unpacker_data.fuji_layout)
{
r = IO.fuji_width - 1 - col + (row >> 1);
c = col + ((row + 1) >> 1);
}
else
{
r = IO.fuji_width - 1 + row - (col >> 1);
c = row + ((col + 1) >> 1);
}
unsigned short val =
imgdata.rawdata
.raw_image[(row + S.top_margin) * S.raw_pitch / 2 +
(col + S.left_margin)];
int cc = FCF(row, col);
if (val > cblack[cc])
{
val -= cblack[cc];
if (dmax < val)
dmax = val;
}
else
val = 0;
imgdata.image[((r) >> IO.shrink) * alloc_width +
((c) >> IO.shrink)][cc] = val;
}
}
S.height = IO_fheight;
S.width = IO_fwidth;
S.iheight = (S.height + IO.shrink) >> IO.shrink;
S.iwidth = (S.width + IO.shrink) >> IO.shrink;
S.raw_height -= 2 * S.top_margin;
}
else
{
copy_fuji_uncropped(cblack, &dmax);
}
} // end Fuji
else
{
copy_bayer(cblack, &dmax);
}
}
else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY)
{
if (imgdata.rawdata.color4_image)
{
if (S.raw_pitch != S.width * 8u || S.height != S.raw_height)
{
for (int row = 0; row < copyheight; row++)
memmove(&imgdata.image[row * S.width],
&imgdata.rawdata
.color4_image[(row + S.top_margin) * S.raw_pitch / 8 +
S.left_margin],
copywidth * sizeof(*imgdata.image));
}
else
{
// legacy is always 4channel and not shrinked!
memmove(imgdata.image, imgdata.rawdata.color4_image,
S.width*copyheight * sizeof(*imgdata.image));
}
}
else if (imgdata.rawdata.color3_image)
{
unsigned char *c3image = (unsigned char *)imgdata.rawdata.color3_image;
for (int row = 0; row < copyheight; row++)
{
ushort(*srcrow)[3] =
(ushort(*)[3]) & c3image[(row + S.top_margin) * S.raw_pitch];
ushort(*dstrow)[4] = (ushort(*)[4]) & imgdata.image[row * S.width];
for (int col = 0; col < copywidth; col++)
{
for (int c = 0; c < 3; c++)
dstrow[col][c] = srcrow[S.left_margin + col][c];
dstrow[col][3] = 0;
}
}
}
else
{
// legacy decoder, but no data?
throw LIBRAW_EXCEPTION_DECODE_RAW;
}
}
// Free PhaseOne separate copy allocated at function start
if (is_phaseone_compressed())
{
phase_one_free_tempbuffer();
}
if (load_raw == &LibRaw::canon_600_load_raw && S.width < S.raw_width)
{
canon_600_correct();
}
if (do_subtract_black)
{
C.data_maximum = (int)dmax;
C.maximum -= C.black;
// ZERO(C.cblack);
C.cblack[0] = C.cblack[1] = C.cblack[2] = C.cblack[3] = 0;
C.black = 0;
}
// hack - clear later flags!
imgdata.progress_flags =
LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN |
LIBRAW_PROGRESS_RAW2_IMAGE | LIBRAW_PROGRESS_IDENTIFY |
LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW;
return 0;
}
catch (const LibRaw_exceptions& err)
{
EXCEPTION_HANDLER(err);
}
}

View File

@@ -0,0 +1,91 @@
/* -*- C++ -*-
* Copyright 2019-2021 LibRaw LLC (info@libraw.org)
*
LibRaw is free software; you can redistribute it and/or modify
it under the terms of the one of two licenses as you choose:
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
(See file LICENSE.LGPL provided in LibRaw distribution archive for details).
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
(See file LICENSE.CDDL provided in LibRaw distribution archive for details).
*/
#include "../../internal/libraw_cxx_defs.h"
int LibRaw::subtract_black()
{
adjust_bl();
return subtract_black_internal();
}
int LibRaw::subtract_black_internal()
{
CHECK_ORDER_LOW(LIBRAW_PROGRESS_RAW2_IMAGE);
try
{
if (!is_phaseone_compressed() &&
(C.cblack[0] || C.cblack[1] || C.cblack[2] || C.cblack[3] ||
(C.cblack[4] && C.cblack[5])))
{
int cblk[4], i;
for (i = 0; i < 4; i++)
cblk[i] = C.cblack[i];
int size = S.iheight * S.iwidth;
int dmax = 0;
if (C.cblack[4] && C.cblack[5])
{
for (unsigned q = 0; q < (unsigned)size; q++)
{
for (unsigned c = 0; c < 4; c++)
{
int val = imgdata.image[q][c];
val -= C.cblack[6 + q / S.iwidth % C.cblack[4] * C.cblack[5] +
q % S.iwidth % C.cblack[5]];
val -= cblk[c];
imgdata.image[q][c] = CLIP(val);
if (dmax < val) dmax = val;
}
}
}
else
{
for (unsigned q = 0; q < (unsigned)size; q++)
{
for (unsigned c = 0; c < 4; c++)
{
int val = imgdata.image[q][c];
val -= cblk[c];
imgdata.image[q][c] = CLIP(val);
if (dmax < val) dmax = val;
}
}
}
C.data_maximum = dmax & 0xffff;
C.maximum -= C.black;
ZERO(C.cblack); // Yeah, we used cblack[6+] values too!
C.black = 0;
}
else
{
// Nothing to Do, maximum is already calculated, black level is 0, so no
// change only calculate channel maximum;
int idx;
ushort *p = (ushort *)imgdata.image;
int dmax = 0;
for (idx = 0; idx < S.iheight * S.iwidth * 4; idx++)
if (dmax < p[idx])
dmax = p[idx];
C.data_maximum = dmax;
}
return 0;
}
catch (const LibRaw_exceptions& err)
{
EXCEPTION_HANDLER(err);
}
}