summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Randrianasulu <[email protected]>2023-11-24 17:18:33 +0300
committerAndrew Randrianasulu <[email protected]>2023-11-24 17:18:33 +0300
commit45f8f12863ba59efc902a92a4e8bc1ca33db80ff (patch)
tree985a5c0ac55d0565bf820dc2611cf5bf6ae2730d
parent7469c7de8a78ea6ce541e4460d2ea0460825c240 (diff)
downloadlibkdcraw-45f8f12863ba59efc902a92a4e8bc1ca33db80ff.tar.gz
libkdcraw-45f8f12863ba59efc902a92a4e8bc1ca33db80ff.zip
Update libraw to 0.21.1
Signed-off-by: Andrew Randrianasulu <[email protected]>
-rw-r--r--libkdcraw/dcraw/dcraw.c6757
-rw-r--r--libkdcraw/libkdcraw/kdcraw.cpp10
-rw-r--r--libkdcraw/libkdcraw/kdcrawprivate.cpp2
-rw-r--r--libkdcraw/libraw/CMakeLists.txt3
-rw-r--r--libkdcraw/libraw/internal/dcraw_common.cpp8347
-rw-r--r--libkdcraw/libraw/internal/dcraw_defs.h66
-rw-r--r--libkdcraw/libraw/internal/dcraw_fileio.cpp227
-rw-r--r--libkdcraw/libraw/internal/dcraw_fileio_defs.h25
-rw-r--r--libkdcraw/libraw/internal/defines.h203
-rw-r--r--libkdcraw/libraw/internal/demosaic_packs.cpp35
-rw-r--r--libkdcraw/libraw/internal/dmp_include.h27
-rw-r--r--libkdcraw/libraw/internal/libraw_cameraids.h320
-rw-r--r--libkdcraw/libraw/internal/libraw_cxx_defs.h133
-rw-r--r--libkdcraw/libraw/internal/libraw_internal_funcs.h523
-rw-r--r--libkdcraw/libraw/internal/var_defines.h308
-rw-r--r--libkdcraw/libraw/internal/x3f_tools.h539
-rw-r--r--libkdcraw/libraw/libraw/libraw.h679
-rw-r--r--libkdcraw/libraw/libraw/libraw_alloc.h200
-rw-r--r--libkdcraw/libraw/libraw/libraw_const.h881
-rw-r--r--libkdcraw/libraw/libraw/libraw_datastream.h607
-rw-r--r--libkdcraw/libraw/libraw/libraw_internal.h424
-rw-r--r--libkdcraw/libraw/libraw/libraw_types.h1336
-rw-r--r--libkdcraw/libraw/libraw/libraw_version.h76
-rw-r--r--libkdcraw/libraw/samples/4channels.cpp305
-rw-r--r--libkdcraw/libraw/samples/Makefile2
-rw-r--r--libkdcraw/libraw/samples/dcraw_emu.cpp848
-rw-r--r--libkdcraw/libraw/samples/dcraw_half.c127
-rw-r--r--libkdcraw/libraw/samples/half_mt.c288
-rw-r--r--libkdcraw/libraw/samples/half_mt_win32.c342
-rw-r--r--libkdcraw/libraw/samples/mem_image.cpp376
-rw-r--r--libkdcraw/libraw/samples/mem_image_sample.cpp282
-rw-r--r--libkdcraw/libraw/samples/multirender_test.cpp107
-rw-r--r--libkdcraw/libraw/samples/openbayer_sample.cpp65
-rw-r--r--libkdcraw/libraw/samples/postprocessing_benchmark.cpp223
-rw-r--r--libkdcraw/libraw/samples/raw-identify.cpp739
-rw-r--r--libkdcraw/libraw/samples/rawtextdump.cpp144
-rw-r--r--libkdcraw/libraw/samples/simple_dcraw.cpp376
-rw-r--r--libkdcraw/libraw/samples/unprocessed_raw.cpp429
-rw-r--r--libkdcraw/libraw/src/Makefile2
-rw-r--r--libkdcraw/libraw/src/decoders/canon_600.cpp225
-rw-r--r--libkdcraw/libraw/src/decoders/crx.cpp2781
-rw-r--r--libkdcraw/libraw/src/decoders/decoders_dcraw.cpp1799
-rw-r--r--libkdcraw/libraw/src/decoders/decoders_libraw.cpp861
-rw-r--r--libkdcraw/libraw/src/decoders/decoders_libraw_dcrdefs.cpp411
-rw-r--r--libkdcraw/libraw/src/decoders/dng.cpp278
-rw-r--r--libkdcraw/libraw/src/decoders/fp_dng.cpp689
-rw-r--r--libkdcraw/libraw/src/decoders/fuji_compressed.cpp1210
-rw-r--r--libkdcraw/libraw/src/decoders/generic.cpp101
-rw-r--r--libkdcraw/libraw/src/decoders/kodak_decoders.cpp524
-rw-r--r--libkdcraw/libraw/src/decoders/load_mfbacks.cpp915
-rw-r--r--libkdcraw/libraw/src/decoders/smal.cpp181
-rw-r--r--libkdcraw/libraw/src/decoders/unpack.cpp493
-rw-r--r--libkdcraw/libraw/src/decoders/unpack_thumb.cpp385
-rw-r--r--libkdcraw/libraw/src/demosaic/aahd_demosaic.cpp781
-rw-r--r--libkdcraw/libraw/src/demosaic/ahd_demosaic.cpp355
-rw-r--r--libkdcraw/libraw/src/demosaic/dcb_demosaic.cpp900
-rw-r--r--libkdcraw/libraw/src/demosaic/dht_demosaic.cpp1033
-rw-r--r--libkdcraw/libraw/src/demosaic/misc_demosaic.cpp420
-rw-r--r--libkdcraw/libraw/src/demosaic/xtrans_demosaic.cpp430
-rw-r--r--libkdcraw/libraw/src/integration/dngsdk_glue.cpp414
-rw-r--r--libkdcraw/libraw/src/integration/rawspeed_glue.cpp286
-rw-r--r--libkdcraw/libraw/src/libraw_c_api.cpp534
-rw-r--r--libkdcraw/libraw/src/libraw_cxx.cpp1977
-rw-r--r--libkdcraw/libraw/src/libraw_datastream.cpp1046
-rw-r--r--libkdcraw/libraw/src/metadata/adobepano.cpp154
-rw-r--r--libkdcraw/libraw/src/metadata/canon.cpp1335
-rw-r--r--libkdcraw/libraw/src/metadata/ciff.cpp411
-rw-r--r--libkdcraw/libraw/src/metadata/cr3_parser.cpp896
-rw-r--r--libkdcraw/libraw/src/metadata/epson.cpp96
-rw-r--r--libkdcraw/libraw/src/metadata/exif_gps.cpp430
-rw-r--r--libkdcraw/libraw/src/metadata/fuji.cpp1427
-rw-r--r--libkdcraw/libraw/src/metadata/hasselblad_model.cpp538
-rw-r--r--libkdcraw/libraw/src/metadata/identify.cpp3167
-rw-r--r--libkdcraw/libraw/src/metadata/identify_tools.cpp140
-rw-r--r--libkdcraw/libraw/src/metadata/kodak.cpp363
-rw-r--r--libkdcraw/libraw/src/metadata/leica.cpp375
-rw-r--r--libkdcraw/libraw/src/metadata/makernotes.cpp786
-rw-r--r--libkdcraw/libraw/src/metadata/mediumformat.cpp521
-rw-r--r--libkdcraw/libraw/src/metadata/minolta.cpp110
-rw-r--r--libkdcraw/libraw/src/metadata/misc_parsers.cpp694
-rw-r--r--libkdcraw/libraw/src/metadata/nikon.cpp1051
-rw-r--r--libkdcraw/libraw/src/metadata/normalize_model.cpp1451
-rw-r--r--libkdcraw/libraw/src/metadata/olympus.cpp685
-rw-r--r--libkdcraw/libraw/src/metadata/p1.cpp192
-rw-r--r--libkdcraw/libraw/src/metadata/pentax.cpp675
-rw-r--r--libkdcraw/libraw/src/metadata/samsung.cpp182
-rw-r--r--libkdcraw/libraw/src/metadata/sony.cpp2316
-rw-r--r--libkdcraw/libraw/src/metadata/tiff.cpp2188
-rw-r--r--libkdcraw/libraw/src/postprocessing/aspect_ratio.cpp113
-rw-r--r--libkdcraw/libraw/src/postprocessing/dcraw_process.cpp259
-rw-r--r--libkdcraw/libraw/src/postprocessing/mem_image.cpp292
-rw-r--r--libkdcraw/libraw/src/postprocessing/postprocessing_aux.cpp406
-rw-r--r--libkdcraw/libraw/src/postprocessing/postprocessing_ph.cpp31
-rw-r--r--libkdcraw/libraw/src/postprocessing/postprocessing_utils.cpp190
-rw-r--r--libkdcraw/libraw/src/postprocessing/postprocessing_utils_dcrdefs.cpp308
-rw-r--r--libkdcraw/libraw/src/preprocessing/ext_preprocess.cpp127
-rw-r--r--libkdcraw/libraw/src/preprocessing/preprocessing_ph.cpp24
-rw-r--r--libkdcraw/libraw/src/preprocessing/raw2image.cpp558
-rw-r--r--libkdcraw/libraw/src/preprocessing/subtract_black.cpp91
-rw-r--r--libkdcraw/libraw/src/tables/cameralist.cpp1269
-rw-r--r--libkdcraw/libraw/src/tables/colorconst.cpp57
-rw-r--r--libkdcraw/libraw/src/tables/colordata.cpp1841
-rw-r--r--libkdcraw/libraw/src/tables/wblists.cpp217
-rw-r--r--libkdcraw/libraw/src/utils/curves.cpp151
-rw-r--r--libkdcraw/libraw/src/utils/decoder_info.cpp413
-rw-r--r--libkdcraw/libraw/src/utils/init_close_utils.cpp340
-rw-r--r--libkdcraw/libraw/src/utils/open.cpp1259
-rw-r--r--libkdcraw/libraw/src/utils/phaseone_processing.cpp101
-rw-r--r--libkdcraw/libraw/src/utils/read_utils.cpp176
-rw-r--r--libkdcraw/libraw/src/utils/thumb_utils.cpp328
-rw-r--r--libkdcraw/libraw/src/utils/utils_dcraw.cpp330
-rw-r--r--libkdcraw/libraw/src/utils/utils_libraw.cpp673
-rw-r--r--libkdcraw/libraw/src/write/apply_profile.cpp76
-rw-r--r--libkdcraw/libraw/src/write/file_write.cpp338
-rw-r--r--libkdcraw/libraw/src/write/tiff_writer.cpp73
-rw-r--r--libkdcraw/libraw/src/write/write_ph.cpp39
-rw-r--r--libkdcraw/libraw/src/x3f/x3f_parse_process.cpp708
-rw-r--r--libkdcraw/libraw/src/x3f/x3f_utils_patched.cpp2119
-rw-r--r--libkdcraw/test/CMakeLists.txt6
119 files changed, 62940 insertions, 15568 deletions
diff --git a/libkdcraw/dcraw/dcraw.c b/libkdcraw/dcraw/dcraw.c
index 9781efa..1d0676c 100644
--- a/libkdcraw/dcraw/dcraw.c
+++ b/libkdcraw/dcraw/dcraw.c
@@ -1,6 +1,6 @@
/*
dcraw.c -- Dave Coffin's raw photo decoder
- Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net
+ Copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net
This is a command-line ANSI C program to convert raw photos from
any digital camera on any computer running any operating system.
@@ -19,15 +19,15 @@
*If you have not modified dcraw.c in any way, a link to my
homepage qualifies as "full source code".
- $Revision: 1.399 $
- $Date: 2008/03/05 01:29:34 $
+ $Revision: 1.478 $
+ $Date: 2018/06/01 20:36:25 $
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#define DCRAW_VERSION "8.83"
+#define DCRAW_VERSION "9.28"
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
#define _USE_MATH_DEFINES
#include <ctype.h>
#include <errno.h>
@@ -41,26 +41,8 @@
#include <string.h>
#include <time.h>
#include <sys/types.h>
-#include <locale.h>
-
-/*
- NO_JPEG disables decoding of compressed Kodak DC120 files.
- NO_LCMS disables the "-p" option.
- */
-#ifdef HAVE_JPEG
-#include <jpeglib.h>
-#endif
-#ifndef NO_LCMS
-#include LCMS_HEADER
-#endif
-#ifdef LOCALEDIR
-#include <libintl.h>
-#define _(String) gettext(String)
-#else
-#define _(String) (String)
-#endif
-#ifdef DJGPP
+#if defined(DJGPP) || defined(__MINGW32__)
#define fseeko fseek
#define ftello ftell
#else
@@ -86,51 +68,66 @@ typedef long long INT64;
typedef unsigned long long UINT64;
#endif
-#ifdef LJPEG_DECODE
-#error Please compile dcraw.c by itself.
-#error Do not link it with ljpeg_decode.
+#ifdef NODEPS
+#define NO_JASPER
+#define NO_JPEG
+#define NO_LCMS
#endif
-
-#ifndef LONG_BIT
-#define LONG_BIT (8 * sizeof (long))
+#ifndef NO_JASPER
+#include <jasper/jasper.h> /* Decode Red camera movies */
+#endif
+#ifndef NO_JPEG
+#include <jpeglib.h> /* Decode compressed Kodak DC120 photos */
+#endif /* and Adobe Lossy DNGs */
+#ifndef NO_LCMS
+#include <lcms2.h> /* Support color profiles */
+#endif
+#ifdef LOCALEDIR
+#include <libintl.h>
+#define _(String) gettext(String)
+#else
+#define _(String) (String)
#endif
-#define ushort UshORt
-typedef unsigned char uchar;
-typedef unsigned short ushort;
+#if !defined(uchar)
+#define uchar unsigned char
+#endif
+#if !defined(ushort)
+#define ushort unsigned short
+#endif
/*
All global variables are defined here, and all functions that
- access them are prefixed with "CLASS". Note that a thread-safe
- C++ class cannot have non-const static local variables.
+ access them are prefixed with "CLASS". For thread-safety, all
+ non-const static local variables except cbrt[] must be declared
+ "thread_local".
*/
-
-void swab(const void *restrict from, void *restrict to, ssize_t n);
-void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
-
-FILE *ifp;
+FILE *ifp, *ofp;
short order;
-char *ifname, *meta_data;
+const char *ifname;
+char *meta_data, xtrans[6][6], xtrans_abs[6][6];
char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64];
float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len;
time_t timestamp;
-unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id;
-off_t strip_offset, data_offset;
-off_t thumb_offset, meta_offset, profile_offset;
+off_t strip_offset, data_offset;
+off_t thumb_offset, meta_offset, profile_offset;
+unsigned shot_order, kodak_cbpp, exif_cfa, unique_id;
unsigned thumb_length, meta_length, profile_length;
unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0;
unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress;
-unsigned black, maximum, mix_green, raw_color, use_gamma, zero_is_bad;
+unsigned black, maximum, mix_green, raw_color, zero_is_bad;
unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error;
-unsigned tile_width, tile_length, gpsdata[32];
+unsigned tile_width, tile_length, gpsdata[32], load_flags;
+unsigned flip, tiff_flip, filters, colors;
ushort raw_height, raw_width, height, width, top_margin, left_margin;
ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height;
-int flip, tiff_flip, colors;
-double pixel_aspect, aber[4]={1,1,1,1};
-ushort (*image)[4], white[8][8], curve[0x4001], cr2_slice[3], sraw_mul[4];
+ushort *raw_image, (*image)[4], cblack[4102];
+ushort white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4];
+double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 };
float bright=1, user_mul[4]={0,0,0,0}, threshold=0;
+int mask[8][4];
int half_size=0, four_color_rgb=0, document_mode=0, highlight=0;
-int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1;
+int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=1;
int output_color=1, output_bps=8, output_tiff=0, med_passes=0;
int no_auto_bright=0;
unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX };
@@ -141,7 +138,7 @@ const double xyz_rgb[3][3] = { /* XYZ from RGB */
{ 0.019334, 0.119193, 0.950227 } };
const float d65_white[3] = { 0.950456, 1, 1.088754 };
int histogram[4][0x2000];
-void (*write_thumb)(FILE *), (*write_fun)(FILE *);
+void (*write_thumb)(), (*write_fun)();
void (*load_raw)(), (*thumb_load_raw)();
jmp_buf failure;
@@ -150,12 +147,15 @@ struct decode {
int leaf;
} first_decode[2048], *second_decode, *free_decode;
-struct {
+struct tiff_ifd {
int width, height, bps, comp, phint, offset, flip, samples, bytes;
+ int tile_width, tile_length;
+ float shutter;
} tiff_ifd[10];
-struct {
- int format, key_off, black, black_off, split_col, tag_21a;
+struct ph1 {
+ int format, key_off, tag_21a;
+ int black, split_col, black_col, split_row, black_row;
float tag_210;
} ph1;
@@ -172,8 +172,8 @@ struct {
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define LIM(x,min,max) MAX(min,MIN(x,max))
#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
-#define CLIP(x) LIM(x,0,65535)
-#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+#define CLIP(x) LIM((int)(x),0,65535)
+#define SWAP(a,b) { a=a+b; b=a-b; a=a-b; }
/*
In order to inline this calculation, I make the risky
@@ -214,6 +214,9 @@ struct {
3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B
*/
+#define RAW(row,col) \
+ raw_image[(row)*raw_width+(col)]
+
#define FC(row,col) \
(filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
@@ -221,9 +224,9 @@ struct {
image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
#define BAYER2(row,col) \
- image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)]
+ image[((row) >> shrink)*iwidth + ((col) >> shrink)][fcol(row,col)]
-int CLASS fc (int row, int col)
+int CLASS fcol (int row, int col)
{
static const char filter[16][16] =
{ { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
@@ -243,8 +246,9 @@ int CLASS fc (int row, int col)
{ 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
{ 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
- if (filters != 1) return FC(row,col);
- return filter[(row+top_margin) & 15][(col+left_margin) & 15];
+ if (filters == 1) return filter[(row+top_margin)&15][(col+left_margin)&15];
+ if (filters == 9) return xtrans[(row+6) % 6][(col+6) % 6];
+ return FC(row,col);
}
#ifndef __GLIBC__
@@ -258,9 +262,18 @@ char *my_memmem (char *haystack, size_t haystacklen,
return 0;
}
#define memmem my_memmem
+char *my_strcasestr (char *haystack, const char *needle)
+{
+ char *c;
+ for (c = haystack; *c; c++)
+ if (!strncasecmp(c, needle, strlen(needle)))
+ return c;
+ return 0;
+}
+#define strcasestr my_strcasestr
#endif
-void CLASS merror (void *ptr, char *where)
+void CLASS merror (void *ptr, const char *where)
{
if (ptr) return;
fprintf (stderr,_("%s: Out of memory in %s\n"), ifname, where);
@@ -276,7 +289,7 @@ void CLASS derror()
else
fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp));
}
- data_error = 1;
+ data_error++;
}
ushort CLASS sget2 (uchar *s)
@@ -353,6 +366,61 @@ void CLASS read_shorts (ushort *pixel, int count)
swab (pixel, pixel, count*2);
}
+void CLASS cubic_spline (const int *x_, const int *y_, const int len)
+{
+ float **A, *b, *c, *d, *x, *y;
+ int i, j;
+
+ A = (float **) calloc (((2*len + 4)*sizeof **A + sizeof *A), 2*len);
+ if (!A) return;
+ A[0] = (float *) (A + 2*len);
+ for (i = 1; i < 2*len; i++)
+ A[i] = A[0] + 2*len*i;
+ y = len + (x = i + (d = i + (c = i + (b = A[0] + i*i))));
+ for (i = 0; i < len; i++) {
+ x[i] = x_[i] / 65535.0;
+ y[i] = y_[i] / 65535.0;
+ }
+ for (i = len-1; i > 0; i--) {
+ b[i] = (y[i] - y[i-1]) / (x[i] - x[i-1]);
+ d[i-1] = x[i] - x[i-1];
+ }
+ for (i = 1; i < len-1; i++) {
+ A[i][i] = 2 * (d[i-1] + d[i]);
+ if (i > 1) {
+ A[i][i-1] = d[i-1];
+ A[i-1][i] = d[i-1];
+ }
+ A[i][len-1] = 6 * (b[i+1] - b[i]);
+ }
+ for(i = 1; i < len-2; i++) {
+ float v = A[i+1][i] / A[i][i];
+ for(j = 1; j <= len-1; j++)
+ A[i+1][j] -= v * A[i][j];
+ }
+ for(i = len-2; i > 0; i--) {
+ float acc = 0;
+ for(j = i; j <= len-2; j++)
+ acc += A[i][j]*c[j];
+ c[i] = (A[i][len-1] - acc) / A[i][i];
+ }
+ for (i = 0; i < 0x10000; i++) {
+ float x_out = (float)(i / 65535.0);
+ float y_out = 0;
+ for (j = 0; j < len-1; j++) {
+ if (x[j] <= x_out && x_out <= x[j+1]) {
+ float v = x_out - x[j];
+ y_out = y[j] +
+ ((y[j+1] - y[j]) / d[j] - (2 * d[j] * c[j] + c[j+1] * d[j])/6) * v
+ + (c[j] * 0.5) * v*v + ((c[j+1] - c[j]) / (6 * d[j])) * v*v*v;
+ }
+ }
+ curve[i] = y_out < 0.0 ? 0 : (y_out >= 1.0 ? 65535 :
+ (ushort)(y_out * 65535.0 + 0.5));
+ }
+ free (A);
+}
+
void CLASS canon_600_fixed_wb (int temp)
{
static const short mul[4][5] = {
@@ -472,14 +540,13 @@ void CLASS canon_600_coeff()
void CLASS canon_600_load_raw()
{
uchar data[1120], *dp;
- ushort pixel[896], *pix;
- int irow, row, col, val;
- static const short mul[4][2] =
- { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
+ ushort *pix;
+ int irow, row;
for (irow=row=0; irow < height; irow++) {
- if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror();
- for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) {
+ if (fread (data, 1, 1120, ifp) < 1120) derror();
+ pix = raw_image + row*raw_width;
+ for (dp=data; dp < data+1120; dp+=10, pix+=8) {
pix[0] = (dp[0] << 2) + (dp[1] >> 6 );
pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
@@ -489,14 +556,16 @@ void CLASS canon_600_load_raw()
pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
pix[7] = (dp[8] << 2) + (dp[9] >> 6 );
}
- for (col=0; col < width; col++)
- BAYER(row,col) = pixel[col];
- for (col=width; col < raw_width; col++)
- black += pixel[col];
if ((row+=2) > height) row = 1;
}
- if (raw_width > width)
- black = black / ((raw_width - width) * height) - 4;
+}
+
+void CLASS canon_600_correct()
+{
+ int row, col, val;
+ static const short mul[4][2] =
+ { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
+
for (row=0; row < height; row++)
for (col=0; col < width; col++) {
if ((val = BAYER(row,col) - black) < 0) val = 0;
@@ -510,23 +579,6 @@ void CLASS canon_600_load_raw()
black = 0;
}
-void CLASS remove_zeroes()
-{
- unsigned row, col, tot, n, r, c;
-
- for (row=0; row < height; row++)
- for (col=0; col < width; col++)
- if (BAYER(row,col) == 0) {
- tot = n = 0;
- for (r = row-2; r <= row+2; r++)
- for (c = col-2; c <= col+2; c++)
- if (r < height && c < width &&
- FC(r,c) == FC(row,col) && BAYER(r,c))
- tot += (n++,BAYER(r,c));
- if (n) BAYER(row,col) = tot/n;
- }
-}
-
int CLASS canon_s2is()
{
unsigned row;
@@ -538,57 +590,33 @@ int CLASS canon_s2is()
return 0;
}
-void CLASS canon_a5_load_raw()
-{
- ushort data[2565], *dp, pixel;
- int vbits=0, buf=0, row, col, bc=0;
-
- order = 0x4949;
- for (row=-top_margin; row < raw_height-top_margin; row++) {
- read_shorts (dp=data, raw_width * 10 / 16);
- for (col=-left_margin; col < raw_width-left_margin; col++) {
- if (vbits < 10)
- buf = (vbits += 16, (buf << 16) + *dp++);
- pixel = buf >> (vbits -= 10) & 0x3ff;
- if ((unsigned) row < height && (unsigned) col < width)
- BAYER(row,col) = pixel;
- else if (col > 1-left_margin && col != width)
- black += (bc++,pixel);
- }
- }
- if (bc) black /= bc;
- maximum = 0x3ff;
- if (raw_width > 1600) remove_zeroes();
-}
-
-/*
- getbits(-1) initializes the buffer
- getbits(n) where 0 <= n <= 25 returns an n-bit integer
- */
-unsigned CLASS getbits (int nbits)
+unsigned CLASS getbithuff (int nbits, ushort *huff)
{
static unsigned bitbuf=0;
static int vbits=0, reset=0;
unsigned c;
- if (nbits == -1)
+ if (nbits > 25) return 0;
+ if (nbits < 0)
return bitbuf = vbits = reset = 0;
- if (nbits == 0 || reset) return 0;
- while (vbits < nbits) {
- if ((c = fgetc(ifp)) == EOF) derror();
- if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0;
+ if (nbits == 0 || vbits < 0) return 0;
+ while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF &&
+ !(reset = zero_after_ff && c == 0xff && fgetc(ifp))) {
bitbuf = (bitbuf << 8) + (uchar) c;
vbits += 8;
}
- vbits -= nbits;
- return bitbuf << (32-nbits-vbits) >> (32-nbits);
+ c = bitbuf << (32-vbits) >> (32-nbits);
+ if (huff) {
+ vbits -= huff[c] >> 8;
+ c = (uchar) huff[c];
+ } else
+ vbits -= nbits;
+ if (vbits < 0) derror();
+ return c;
}
-void CLASS init_decoder()
-{
- memset (first_decode, 0, sizeof first_decode);
- free_decode = first_decode;
-}
+#define getbits(n) getbithuff(n,0)
+#define gethuff(h) getbithuff(*h,h+1)
/*
Construct a decode tree according the specification in *source.
@@ -616,33 +644,31 @@ void CLASS init_decoder()
1111110 0x0b
1111111 0xff
*/
-uchar * CLASS make_decoder (const uchar *source, int level)
+ushort * CLASS make_decoder_ref (const uchar **source)
{
- struct decode *cur;
- static int leaf;
- int i, next;
+ int max, len, h, i, j;
+ const uchar *count;
+ ushort *huff;
- if (level==0) leaf=0;
- cur = free_decode++;
- if (free_decode > first_decode+2048) {
- fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
- longjmp (failure, 2);
- }
- for (i=next=0; i <= leaf && next < 16; )
- i += source[next++];
- if (i > leaf) {
- if (level < next) {
- cur->branch[0] = free_decode;
- make_decoder (source, level+1);
- cur->branch[1] = free_decode;
- make_decoder (source, level+1);
- } else
- cur->leaf = source[16 + leaf++];
- }
- return (uchar *) source + 16 + leaf;
+ count = (*source += 16) - 17;
+ for (max=16; max && !count[max]; max--);
+ huff = (ushort *) calloc (1 + (1 << max), sizeof *huff);
+ merror (huff, "make_decoder()");
+ huff[0] = max;
+ for (h=len=1; len <= max; len++)
+ for (i=0; i < count[len]; i++, ++*source)
+ for (j=0; j < 1 << (max-len); j++)
+ if (h <= 1 << max)
+ huff[h++] = len << 8 | **source;
+ return huff;
+}
+
+ushort * CLASS make_decoder (const uchar *source)
+{
+ return make_decoder_ref (&source);
}
-void CLASS crw_init_tables (unsigned table)
+void CLASS crw_init_tables (unsigned table, ushort *huff[2])
{
static const uchar first_tree[3][29] = {
{ 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
@@ -700,10 +726,8 @@ void CLASS crw_init_tables (unsigned table)
0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff }
};
if (table > 2) table = 2;
- init_decoder();
- make_decoder ( first_tree[table], 0);
- second_decode = free_decode;
- make_decoder (second_tree[table], 0);
+ huff[0] = make_decoder ( first_tree[table]);
+ huff[1] = make_decoder (second_tree[table]);
}
/*
@@ -727,33 +751,25 @@ int CLASS canon_has_lowbits()
return ret;
}
-void CLASS canon_compressed_load_raw()
+void CLASS canon_load_raw()
{
- ushort *pixel, *prow;
- int nblocks, lowbits, i, row, r, col, save, val;
- unsigned irow, icol;
- struct decode *decode, *dindex;
+ ushort *pixel, *prow, *huff[2];
+ int nblocks, lowbits, i, c, row, r, save, val;
int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
- uchar c;
- crw_init_tables (tiff_compress);
- pixel = (ushort *) calloc (raw_width*8, sizeof *pixel);
- merror (pixel, "canon_compressed_load_raw()");
+ crw_init_tables (tiff_compress, huff);
lowbits = canon_has_lowbits();
if (!lowbits) maximum = 0x3ff;
fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET);
zero_after_ff = 1;
getbits(-1);
for (row=0; row < raw_height; row+=8) {
+ pixel = raw_image + row*raw_width;
nblocks = MIN (8, raw_height-row) * raw_width >> 6;
for (block=0; block < nblocks; block++) {
memset (diffbuf, 0, sizeof diffbuf);
- decode = first_decode;
for (i=0; i < 64; i++ ) {
- for (dindex=decode; dindex->branch[0]; )
- dindex = dindex->branch[getbits(1)];
- leaf = dindex->leaf;
- decode = second_decode;
+ leaf = gethuff(huff[i > 0]);
if (leaf == 0 && i) break;
if (leaf == 0xff) continue;
i += leaf >> 4;
@@ -786,91 +802,84 @@ void CLASS canon_compressed_load_raw()
}
fseek (ifp, save, SEEK_SET);
}
- for (r=0; r < 8; r++) {
- irow = row - top_margin + r;
- if (irow >= height) continue;
- for (col=0; col < raw_width; col++) {
- icol = col - left_margin;
- if (icol < width)
- BAYER(irow,icol) = pixel[r*raw_width+col];
- else
- black += pixel[r*raw_width+col];
- }
- }
}
- free (pixel);
- if (raw_width > width)
- black /= (raw_width - width) * height;
+ FORC(2) free (huff[c]);
}
-/*
- Not a full implementation of Lossless JPEG, just
- enough to decode Canon, Kodak and Adobe DNG images.
- */
struct jhead {
- int bits, high, wide, clrs, psv, restart, vpred[4];
- struct CLASS decode *huff[4];
- ushort *row;
+ int algo, bits, high, wide, clrs, sraw, psv, restart, vpred[6];
+ ushort quant[64], idct[64], *huff[20], *free[20], *row;
};
int CLASS ljpeg_start (struct jhead *jh, int info_only)
{
- int i, tag, len;
- uchar data[0x10000], *dp;
+ ushort c, tag, len;
+ uchar data[0x10000];
+ const uchar *dp;
- init_decoder();
memset (jh, 0, sizeof *jh);
- for (i=0; i < 4; i++)
- jh->huff[i] = free_decode;
jh->restart = INT_MAX;
- fread (data, 2, 1, ifp);
- if (data[1] != 0xd8) return 0;
+ if ((fgetc(ifp),fgetc(ifp)) != 0xd8) return 0;
do {
- fread (data, 2, 2, ifp);
+ if (!fread (data, 2, 2, ifp)) return 0;
tag = data[0] << 8 | data[1];
len = (data[2] << 8 | data[3]) - 2;
if (tag <= 0xff00) return 0;
fread (data, 1, len, ifp);
switch (tag) {
- case 0xffc0: data[7] = 0;
case 0xffc3:
+ jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
+ case 0xffc1:
+ case 0xffc0:
+ jh->algo = tag & 0xff;
jh->bits = data[0];
jh->high = data[1] << 8 | data[2];
jh->wide = data[3] << 8 | data[4];
- jh->clrs = data[5] + (data[7] == 0x21);
+ jh->clrs = data[5] + jh->sraw;
if (len == 9 && !dng_version) getc(ifp);
break;
case 0xffc4:
if (info_only) break;
- for (dp = data; dp < data+len && *dp < 4; ) {
- jh->huff[*dp] = free_decode;
- dp = make_decoder (++dp, 0);
- }
+ for (dp = data; dp < data+len && !((c = *dp++) & -20); )
+ jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
break;
case 0xffda:
jh->psv = data[1+data[0]*2];
+ jh->bits -= data[3+data[0]*2] & 15;
+ break;
+ case 0xffdb:
+ FORC(64) jh->quant[c] = data[c*2+1] << 8 | data[c*2+2];
break;
case 0xffdd:
jh->restart = data[0] << 8 | data[1];
}
} while (tag != 0xffda);
+ if (jh->bits > 16 || jh->clrs > 6 ||
+ !jh->bits || !jh->high || !jh->wide || !jh->clrs) return 0;
if (info_only) return 1;
- if (jh->clrs == 4) {
- jh->huff[3] = jh->huff[2] = jh->huff[1];
- jh->huff[1] = jh->huff[0];
+ if (!jh->huff[0]) return 0;
+ FORC(19) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
+ if (jh->sraw) {
+ FORC(4) jh->huff[2+c] = jh->huff[1];
+ FORC(jh->sraw) jh->huff[1+c] = jh->huff[0];
}
jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4);
merror (jh->row, "ljpeg_start()");
return zero_after_ff = 1;
}
-int CLASS ljpeg_diff (struct decode *dindex)
+void CLASS ljpeg_end (struct jhead *jh)
+{
+ int c;
+ FORC4 if (jh->free[c]) free (jh->free[c]);
+ free (jh->row);
+}
+
+int CLASS ljpeg_diff (ushort *huff)
{
int len, diff;
- while (dindex->branch[0])
- dindex = dindex->branch[getbits(1)];
- len = dindex->leaf;
+ len = gethuff(huff);
if (len == 16 && (!dng_version || dng_version >= 0x1010000))
return -32768;
diff = getbits(len);
@@ -881,22 +890,24 @@ int CLASS ljpeg_diff (struct decode *dindex)
ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
{
- int col, c, diff, pred;
+ int col, c, diff, pred, spred=0;
ushort mark=0, *row[3];
if (jrow * jh->wide % jh->restart == 0) {
- FORC4 jh->vpred[c] = 1 << (jh->bits-1);
- if (jrow)
+ FORC(6) jh->vpred[c] = 1 << (jh->bits-1);
+ if (jrow) {
+ fseek (ifp, -2, SEEK_CUR);
do mark = (mark << 8) + (c = fgetc(ifp));
while (c != EOF && mark >> 4 != 0xffd);
+ }
getbits(-1);
}
FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
for (col=0; col < jh->wide; col++)
FORC(jh->clrs) {
diff = ljpeg_diff (jh->huff[c]);
- if (jh->clrs == 4 && c < 2 && (col | c))
- pred = row[0][(c << 1)-3];
+ if (jh->sraw && c <= jh->sraw && (col | c))
+ pred = spred;
else if (col) pred = row[0][-jh->clrs];
else pred = (jh->vpred[c] += diff) - diff;
if (jrow && col) switch (jh->psv) {
@@ -910,6 +921,7 @@ ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
default: pred = 0;
}
if ((**row = pred + diff) >> jh->bits) derror();
+ if (c <= jh->sraw) spred = **row;
row[0]++; row[1]++;
}
return row[2];
@@ -919,7 +931,6 @@ void CLASS lossless_jpeg_load_raw()
{
int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0;
struct jhead jh;
- int min=INT_MAX;
ushort *rp;
if (!ljpeg_start (&jh, 0)) return;
@@ -927,109 +938,158 @@ void CLASS lossless_jpeg_load_raw()
for (jrow=0; jrow < jh.high; jrow++) {
rp = ljpeg_row (jrow, &jh);
+ if (load_flags & 1)
+ row = jrow & 1 ? height-1-jrow/2 : jrow/2;
for (jcol=0; jcol < jwide; jcol++) {
- val = *rp++;
- if (jh.bits <= 12)
- val = curve[val];
+ val = curve[*rp++];
if (cr2_slice[0]) {
jidx = jrow*jwide + jcol;
- i = jidx / (cr2_slice[1]*jh.high);
+ i = jidx / (cr2_slice[1]*raw_height);
if ((j = i >= cr2_slice[0]))
i = cr2_slice[0];
- jidx -= i * (cr2_slice[1]*jh.high);
+ jidx -= i * (cr2_slice[1]*raw_height);
row = jidx / cr2_slice[1+j];
col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
}
if (raw_width == 3984 && (col -= 2) < 0)
col += (row--,raw_width);
- if ((unsigned) (row-top_margin) < height) {
- if ((unsigned) (col-left_margin) < width) {
- BAYER(row-top_margin,col-left_margin) = val;
- if (min > val) min = val;
- } else black += val;
- }
+ if ((unsigned) row < raw_height) RAW(row,col) = val;
if (++col >= raw_width)
col = (row++,0);
}
}
- free (jh.row);
- if (raw_width > width)
- black /= (raw_width - width) * height;
- if (!strcasecmp(make,"KODAK"))
- black = min;
+ ljpeg_end (&jh);
}
void CLASS canon_sraw_load_raw()
{
struct jhead jh;
- short *rp=0, *ip;
+ short *rp=0, (*ip)[4];
int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
+ int v[3]={0,0,0}, ver, hue;
+ char *cp;
- if (!ljpeg_start (&jh, 0)) return;
- jwide = (jh.wide >>= 1) * 4;
+ if (!ljpeg_start (&jh, 0) || jh.clrs < 4) return;
+ jwide = (jh.wide >>= 1) * jh.clrs;
for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
scol = ecol;
- ecol += cr2_slice[1] >> 1;
- if (!cr2_slice[0] || ecol > width-1) ecol = width & -2;
- for (row=0; row < height; row++) {
- ip = (short *) image[row*width+scol];
- for (col=scol; col < ecol; col+=2, jcol+=4, ip+=8) {
+ ecol += cr2_slice[1] * 2 / jh.clrs;
+ if (!cr2_slice[0] || ecol > raw_width-1) ecol = raw_width & -2;
+ for (row=0; row < height; row += (jh.clrs >> 1) - 1) {
+ ip = (short (*)[4]) image + row*width;
+ for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
if ((jcol %= jwide) == 0)
rp = (short *) ljpeg_row (jrow++, &jh);
- ip[0] = rp[jcol];
- ip[4] = rp[jcol+1];
- ip[1] = (short) (rp[jcol+2] << 2) >> 2;
- ip[2] = (short) (rp[jcol+3] << 2) >> 2;
+ if (col >= width) continue;
+ FORC (jh.clrs-2)
+ ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c];
+ ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
+ ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
}
}
}
- for (row=0; row < height; row++) {
- ip = (short *) image[row*width+1];
- for (col=1; col < width-1; col+=2, ip+=8) {
- ip[1] = (ip[-3] + ip[5] + 1) >> 1;
- ip[2] = (ip[-2] + ip[6] + 1) >> 1;
- }
- if (col < width) { ip[1] = ip[-3]; ip[2] = ip[-2]; }
- ip = (short *) image[row*width];
- for (col=0; col < width; col++, ip+=4) {
- pix[0] = ip[2] + ip[0];
- pix[2] = ip[1] + ip[0];
- pix[1] = ((ip[0] << 12) - ip[1]*778 - (ip[2] << 11)) >> 12;
- FORC3 ip[c] = CLIP((pix[c] - 512) * sraw_mul[c] >> 10);
+ for (cp=model2; *cp && !isdigit(*cp); cp++);
+ sscanf (cp, "%d.%d.%d", v, v+1, v+2);
+ ver = (v[0]*1000 + v[1])*1000 + v[2];
+ hue = (jh.sraw+1) << 2;
+ if (unique_id >= 0x80000281 || (unique_id == 0x80000218 && ver > 1000006))
+ hue = jh.sraw << 1;
+ ip = (short (*)[4]) image;
+ rp = ip[0];
+ for (row=0; row < height; row++, ip+=width) {
+ if (row & (jh.sraw >> 1))
+ for (col=0; col < width; col+=2)
+ for (c=1; c < 3; c++)
+ if (row == height-1)
+ ip[col][c] = ip[col-width][c];
+ else ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1;
+ for (col=1; col < width; col+=2)
+ for (c=1; c < 3; c++)
+ if (col == width-1)
+ ip[col][c] = ip[col-1][c];
+ else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
+ }
+ for ( ; rp < ip[0]; rp+=4) {
+ if (unique_id == 0x80000218 ||
+ unique_id == 0x80000250 ||
+ unique_id == 0x80000261 ||
+ unique_id == 0x80000281 ||
+ unique_id == 0x80000287) {
+ rp[1] = (rp[1] << 2) + hue;
+ rp[2] = (rp[2] << 2) + hue;
+ pix[0] = rp[0] + (( 50*rp[1] + 22929*rp[2]) >> 14);
+ pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
+ pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 14);
+ } else {
+ if (unique_id < 0x80000218) rp[0] -= 512;
+ pix[0] = rp[0] + rp[2];
+ pix[2] = rp[0] + rp[1];
+ pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12);
}
+ FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
}
- free (jh.row);
+ ljpeg_end (&jh);
maximum = 0x3fff;
}
-void CLASS adobe_copy_pixel (int row, int col, ushort **rp)
+void CLASS adobe_copy_pixel (unsigned row, unsigned col, ushort **rp)
{
- unsigned r, c;
+ int c;
- r = row -= top_margin;
- c = col -= left_margin;
- if (is_raw == 2 && shot_select) (*rp)++;
- if (filters) {
- if (fuji_width) {
- r = row + fuji_width - 1 - (col >> 1);
- c = row + ((col+1) >> 1);
- }
- if (r < height && c < width)
- BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp;
- *rp += is_raw;
+ if (tiff_samples == 2 && shot_select) (*rp)++;
+ if (raw_image) {
+ if (row < raw_height && col < raw_width)
+ RAW(row,col) = curve[**rp];
+ *rp += tiff_samples;
} else {
- if (r < height && c < width)
+ if (row < height && col < width)
FORC(tiff_samples)
- image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c];
+ image[row*width+col][c] = curve[(*rp)[c]];
*rp += tiff_samples;
}
- if (is_raw == 2 && shot_select) (*rp)--;
+ if (tiff_samples == 2 && shot_select) (*rp)--;
+}
+
+void CLASS ljpeg_idct (struct jhead *jh)
+{
+ int c, i, j, len, skip, coef;
+ float work[3][8][8];
+ static float cs[106] = { 0 };
+ static const uchar zigzag[80] =
+ { 0, 1, 8,16, 9, 2, 3,10,17,24,32,25,18,11, 4, 5,12,19,26,33,
+ 40,48,41,34,27,20,13, 6, 7,14,21,28,35,42,49,56,57,50,43,36,
+ 29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,
+ 47,55,62,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63 };
+
+ if (!cs[0])
+ FORC(106) cs[c] = cos((c & 31)*M_PI/16)/2;
+ memset (work, 0, sizeof work);
+ work[0][0][0] = jh->vpred[0] += ljpeg_diff (jh->huff[0]) * jh->quant[0];
+ for (i=1; i < 64; i++ ) {
+ len = gethuff (jh->huff[16]);
+ i += skip = len >> 4;
+ if (!(len &= 15) && skip < 15) break;
+ coef = getbits(len);
+ if ((coef & (1 << (len-1))) == 0)
+ coef -= (1 << len) - 1;
+ ((float *)work)[zigzag[i]] = coef * jh->quant[i];
+ }
+ FORC(8) work[0][0][c] *= M_SQRT1_2;
+ FORC(8) work[0][c][0] *= M_SQRT1_2;
+ for (i=0; i < 8; i++)
+ for (j=0; j < 8; j++)
+ FORC(8) work[1][i][j] += work[0][i][c] * cs[(j*2+1)*c];
+ for (i=0; i < 8; i++)
+ for (j=0; j < 8; j++)
+ FORC(8) work[2][i][j] += work[1][c][j] * cs[(i*2+1)*c];
+
+ FORC(64) jh->idct[c] = CLIP(((float *)work[2])[c]+0.5);
}
-void CLASS adobe_dng_load_raw_lj()
+void CLASS lossless_dng_load_raw()
{
- unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
+ unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col, i, j;
struct jhead jh;
ushort *rp;
@@ -1040,29 +1100,47 @@ void CLASS adobe_dng_load_raw_lj()
if (!ljpeg_start (&jh, 0)) break;
jwide = jh.wide;
if (filters) jwide *= jh.clrs;
- jwide /= is_raw;
- for (row=col=jrow=0; jrow < jh.high; jrow++) {
- rp = ljpeg_row (jrow, &jh);
- for (jcol=0; jcol < jwide; jcol++) {
- adobe_copy_pixel (trow+row, tcol+col, &rp);
- if (++col >= tile_width || col >= raw_width)
- row += 1 + (col = 0);
- }
+ jwide /= MIN (is_raw, tiff_samples);
+ switch (jh.algo) {
+ case 0xc1:
+ jh.vpred[0] = 16384;
+ getbits(-1);
+ for (jrow=0; jrow+7 < jh.high; jrow += 8) {
+ for (jcol=0; jcol+7 < jh.wide; jcol += 8) {
+ ljpeg_idct (&jh);
+ rp = jh.idct;
+ row = trow + jcol/tile_width + jrow*2;
+ col = tcol + jcol%tile_width;
+ for (i=0; i < 16; i+=2)
+ for (j=0; j < 8; j++)
+ adobe_copy_pixel (row+i, col+j, &rp);
+ }
+ }
+ break;
+ case 0xc3:
+ for (row=col=jrow=0; jrow < jh.high; jrow++) {
+ rp = ljpeg_row (jrow, &jh);
+ for (jcol=0; jcol < jwide; jcol++) {
+ adobe_copy_pixel (trow+row, tcol+col, &rp);
+ if (++col >= tile_width || col >= raw_width)
+ row += 1 + (col = 0);
+ }
+ }
}
fseek (ifp, save+4, SEEK_SET);
if ((tcol += tile_width) >= raw_width)
trow += tile_length + (tcol = 0);
- free (jh.row);
+ ljpeg_end (&jh);
}
}
-void CLASS adobe_dng_load_raw_nc()
+void CLASS packed_dng_load_raw()
{
ushort *pixel, *rp;
int row, col;
- pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel);
- merror (pixel, "adobe_dng_load_raw_nc()");
+ pixel = (ushort *) calloc (raw_width, tiff_samples*sizeof *pixel);
+ merror (pixel, "packed_dng_load_raw()");
for (row=0; row < raw_height; row++) {
if (tiff_bps == 16)
read_shorts (pixel, raw_width * tiff_samples);
@@ -1077,29 +1155,34 @@ void CLASS adobe_dng_load_raw_nc()
free (pixel);
}
-void CLASS pentax_k10_load_raw()
+void CLASS pentax_load_raw()
{
- static const uchar pentax_tree[] =
- { 0,2,3,1,1,1,1,1,1,2,0,0,0,0,0,0,
- 3,4,2,5,1,6,0,7,8,9,10,11,12 };
- int row, col, diff;
+ ushort bit[2][15], huff[4097];
+ int dep, row, col, diff, c, i;
ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
- init_decoder();
- make_decoder (pentax_tree, 0);
+ fseek (ifp, meta_offset, SEEK_SET);
+ dep = (get2() + 12) & 15;
+ fseek (ifp, 12, SEEK_CUR);
+ FORC(dep) bit[0][c] = get2();
+ FORC(dep) bit[1][c] = fgetc(ifp);
+ FORC(dep)
+ for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); )
+ huff[++i] = bit[1][c] << 8 | c;
+ huff[0] = 12;
+ fseek (ifp, data_offset, SEEK_SET);
getbits(-1);
- for (row=0; row < height; row++)
+ for (row=0; row < raw_height; row++)
for (col=0; col < raw_width; col++) {
- diff = ljpeg_diff (first_decode);
+ diff = ljpeg_diff (huff);
if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
else hpred[col & 1] += diff;
- if (col < width)
- BAYER(row,col) = hpred[col & 1];
- if (hpred[col & 1] >> 12) derror();
+ RAW(row,col) = hpred[col & 1];
+ if (hpred[col & 1] >> tiff_bps) derror();
}
}
-void CLASS nikon_compressed_load_raw()
+void CLASS nikon_load_raw()
{
static const uchar nikon_tree[][32] = {
{ 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */
@@ -1114,17 +1197,16 @@ void CLASS nikon_compressed_load_raw()
8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
{ 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */
7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
- struct decode *dindex;
- ushort ver0, ver1, vpred[2][2], hpred[2], csize;
- int i, max, step=0, huff=0, split=0, row, col, len, shl, diff;
+ ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize;
+ int i, min, max, step=0, tree=0, split=0, row, col, len, shl, diff;
fseek (ifp, meta_offset, SEEK_SET);
ver0 = fgetc(ifp);
ver1 = fgetc(ifp);
if (ver0 == 0x49 || ver1 == 0x58)
fseek (ifp, 2110, SEEK_CUR);
- if (ver0 == 0x46) huff = 2;
- if (tiff_bps == 14) huff += 3;
+ if (ver0 == 0x46) tree = 2;
+ if (tiff_bps == 14) tree += 3;
read_shorts (vpred[0], 4);
max = 1 << tiff_bps & 0x7fff;
if ((csize = get2()) > 1)
@@ -1139,72 +1221,49 @@ void CLASS nikon_compressed_load_raw()
split = get2();
} else if (ver0 != 0x46 && csize <= 0x4001)
read_shorts (curve, max=csize);
- init_decoder();
- make_decoder (nikon_tree[huff], 0);
+ while (curve[max-2] == curve[max-1]) max--;
+ huff = make_decoder (nikon_tree[tree]);
fseek (ifp, data_offset, SEEK_SET);
getbits(-1);
- for (row=0; row < height; row++) {
+ for (min=row=0; row < height; row++) {
if (split && row == split) {
- init_decoder();
- make_decoder (nikon_tree[huff+1], 0);
+ free (huff);
+ huff = make_decoder (nikon_tree[tree+1]);
+ max += (min = 16) << 1;
}
for (col=0; col < raw_width; col++) {
- for (dindex=first_decode; dindex->branch[0]; )
- dindex = dindex->branch[getbits(1)];
- len = dindex->leaf & 15;
- shl = dindex->leaf >> 4;
+ i = gethuff(huff);
+ len = i & 15;
+ shl = i >> 4;
diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - !shl;
if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
else hpred[col & 1] += diff;
- if (hpred[col & 1] >= max) derror();
- if ((unsigned) (col-left_margin) < width)
- BAYER(row,col-left_margin) = curve[hpred[col & 1] & 0x3fff];
+ if ((ushort)(hpred[col & 1] + min) >= max) derror();
+ RAW(row,col) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
}
}
+ free (huff);
}
-void CLASS nikon_load_raw()
+void CLASS nikon_yuv_load_raw()
{
- int irow, row, col, i;
+ int row, col, yuv[4], rgb[3], b, c;
+ UINT64 bitbuf=0;
- getbits(-1);
- for (irow=0; irow < height; irow++) {
- row = irow;
- if (make[0] == 'O' || model[0] == 'E') {
- row = irow * 2 % height + irow / (height/2);
- if (row == 1 && data_offset == 0) {
- fseek (ifp, 0, SEEK_END);
- fseek (ifp, ftell(ifp)/2, SEEK_SET);
- getbits(-1);
- }
- }
+ for (row=0; row < raw_height; row++)
for (col=0; col < raw_width; col++) {
- i = getbits(12);
- if ((unsigned) (col-left_margin) < width)
- BAYER(row,col-left_margin) = i;
- if (tiff_compress > 32768 && (col % 10) == 9)
- if (getbits(8)) derror();
+ if (!(b = col & 1)) {
+ bitbuf = 0;
+ FORC(6) bitbuf |= (UINT64) fgetc(ifp) << c*8;
+ FORC(4) yuv[c] = (bitbuf >> c*12 & 0xfff) - (c >> 1 << 11);
+ }
+ rgb[0] = yuv[b] + 1.370705*yuv[3];
+ rgb[1] = yuv[b] - 0.337633*yuv[2] - 0.698001*yuv[3];
+ rgb[2] = yuv[b] + 1.732446*yuv[2];
+ FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,0xfff)] / cam_mul[c];
}
- }
-}
-
-/*
- Figure out if a NEF file is compressed. These fancy heuristics
- are only needed for the D100, thanks to a bug in some cameras
- that tags all images as "compressed".
- */
-int CLASS nikon_is_compressed()
-{
- uchar test[256];
- int i;
-
- fseek (ifp, data_offset, SEEK_SET);
- fread (test, 1, 256, ifp);
- for (i=15; i < 256; i+=16)
- if (test[i]) return 1;
- return 0;
}
/*
@@ -1251,10 +1310,10 @@ void CLASS nikon_3700()
int bits;
char make[12], model[15];
} table[] = {
- { 0x00, "PENTAX", "Optio 33WR" },
- { 0x03, "NIKON", "E3200" },
- { 0x32, "NIKON", "E3700" },
- { 0x33, "OLYMPUS", "C740UZ" } };
+ { 0x00, "Pentax", "Optio 33WR" },
+ { 0x03, "Nikon", "E3200" },
+ { 0x32, "Nikon", "E3700" },
+ { 0x33, "Olympus", "C740UZ" } };
fseek (ifp, 3072, SEEK_SET);
fread (dp, 1, 24, ifp);
@@ -1271,105 +1330,46 @@ void CLASS nikon_3700()
*/
int CLASS minolta_z2()
{
- int i;
+ int i, nz;
char tail[424];
fseek (ifp, -sizeof tail, SEEK_END);
fread (tail, 1, sizeof tail, ifp);
- for (i=0; i < sizeof tail; i++)
- if (tail[i]) return 1;
- return 0;
+ for (nz=i=0; i < sizeof tail; i++)
+ if (tail[i]) nz++;
+ return nz > 20;
}
-/* Here raw_width is in bytes, not pixels. */
-void CLASS nikon_e900_load_raw()
-{
- int offset=0, irow, row, col;
+void CLASS jpeg_thumb();
- for (irow=0; irow < height; irow++) {
- row = irow * 2 % height;
- if (row == 1)
- offset = - (-offset & -4096);
- fseek (ifp, offset, SEEK_SET);
- offset += raw_width;
- getbits(-1);
- for (col=0; col < width; col++)
- BAYER(row,col) = getbits(10);
- }
-}
-
-void CLASS nikon_e2100_load_raw()
-{
- uchar data[4608], *dp;
- ushort pixel[3072], *pix;
- int row, col;
-
- for (row=0; row <= height; row+=2) {
- if (row == height) {
- fseek (ifp, 0, SEEK_END);
- fseek (ifp, ftell(ifp)/2, SEEK_SET);
- row = 1;
- }
- fread (data, 1, width*3/2, ifp);
- for (dp=data, pix=pixel; pix < pixel+width; dp+=12, pix+=8) {
- pix[0] = (dp[2] >> 4) + (dp[ 3] << 4);
- pix[1] = (dp[2] << 8) + dp[ 1];
- pix[2] = (dp[7] >> 4) + (dp[ 0] << 4);
- pix[3] = (dp[7] << 8) + dp[ 6];
- pix[4] = (dp[4] >> 4) + (dp[ 5] << 4);
- pix[5] = (dp[4] << 8) + dp[11];
- pix[6] = (dp[9] >> 4) + (dp[10] << 4);
- pix[7] = (dp[9] << 8) + dp[ 8];
- }
- for (col=0; col < width; col++)
- BAYER(row,col) = (pixel[col] & 0xfff);
- }
-}
-
-/*
- The Fuji Super CCD is just a Bayer grid rotated 45 degrees.
- */
-void CLASS fuji_load_raw()
-{
- ushort *pixel;
- int wide, row, col, r, c;
-
- fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
- wide = fuji_width << !fuji_layout;
- pixel = (ushort *) calloc (wide, sizeof *pixel);
- merror (pixel, "fuji_load_raw()");
- for (row=0; row < raw_height; row++) {
- read_shorts (pixel, wide);
- fseek (ifp, 2*(raw_width - wide), SEEK_CUR);
- for (col=0; col < wide; col++) {
- if (fuji_layout) {
- r = fuji_width - 1 - col + (row >> 1);
- c = col + ((row+1) >> 1);
- } else {
- r = fuji_width - 1 + row - (col >> 1);
- c = row + ((col+1) >> 1);
- }
- BAYER(r,c) = pixel[col];
- }
- }
- free (pixel);
-}
-
-void CLASS jpeg_thumb (FILE *tfp);
-
-void CLASS ppm_thumb (FILE *tfp)
+void CLASS ppm_thumb()
{
char *thumb;
thumb_length = thumb_width*thumb_height*3;
thumb = (char *) malloc (thumb_length);
merror (thumb, "ppm_thumb()");
- fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
fread (thumb, 1, thumb_length, ifp);
- fwrite (thumb, 1, thumb_length, tfp);
+ fwrite (thumb, 1, thumb_length, ofp);
+ free (thumb);
+}
+
+void CLASS ppm16_thumb()
+{
+ int i;
+ char *thumb;
+ thumb_length = thumb_width*thumb_height*3;
+ thumb = (char *) calloc (thumb_length, 2);
+ merror (thumb, "ppm16_thumb()");
+ read_shorts ((ushort *) thumb, thumb_length);
+ for (i=0; i < thumb_length; i++)
+ thumb[i] = ((ushort *) thumb)[i] >> 8;
+ fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ fwrite (thumb, 1, thumb_length, ofp);
free (thumb);
}
-void CLASS layer_thumb (FILE *tfp)
+void CLASS layer_thumb()
{
int i, c;
char *thumb, map[][4] = { "012","102" };
@@ -1378,15 +1378,15 @@ void CLASS layer_thumb (FILE *tfp)
thumb_length = thumb_width*thumb_height;
thumb = (char *) calloc (colors, thumb_length);
merror (thumb, "layer_thumb()");
- fprintf (tfp, "P%d\n%d %d\n255\n",
+ fprintf (ofp, "P%d\n%d %d\n255\n",
5 + (colors >> 1), thumb_width, thumb_height);
fread (thumb, thumb_length, colors, ifp);
for (i=0; i < thumb_length; i++)
- FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], tfp);
+ FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], ofp);
free (thumb);
}
-void CLASS rollei_thumb (FILE *tfp)
+void CLASS rollei_thumb()
{
unsigned i;
ushort *thumb;
@@ -1394,12 +1394,12 @@ void CLASS rollei_thumb (FILE *tfp)
thumb_length = thumb_width * thumb_height;
thumb = (ushort *) calloc (thumb_length, 2);
merror (thumb, "rollei_thumb()");
- fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
read_shorts (thumb, thumb_length);
for (i=0; i < thumb_length; i++) {
- putc (thumb[i] << 3, tfp);
- putc (thumb[i] >> 5 << 2, tfp);
- putc (thumb[i] >> 11 << 3, tfp);
+ putc (thumb[i] << 3, ofp);
+ putc (thumb[i] >> 5 << 2, ofp);
+ putc (thumb[i] >> 11 << 3, ofp);
}
free (thumb);
}
@@ -1407,7 +1407,7 @@ void CLASS rollei_thumb (FILE *tfp)
void CLASS rollei_load_raw()
{
uchar pixel[10];
- unsigned iten=0, isix, i, buffer=0, row, col, todo[16];
+ unsigned iten=0, isix, i, buffer=0, todo[16];
isix = raw_width * raw_height * 5 / 8;
while (fread (pixel, 1, 10, ifp) == 10) {
@@ -1420,32 +1420,30 @@ void CLASS rollei_load_raw()
todo[i] = isix++;
todo[i+1] = buffer >> (14-i)*5;
}
- for (i=0; i < 16; i+=2) {
- row = todo[i] / raw_width - top_margin;
- col = todo[i] % raw_width - left_margin;
- if (row < height && col < width)
- BAYER(row,col) = (todo[i+1] & 0x3ff);
- }
+ for (i=0; i < 16; i+=2)
+ raw_image[todo[i]] = (todo[i+1] & 0x3ff);
}
maximum = 0x3ff;
}
-int CLASS bayer (unsigned row, unsigned col)
+int CLASS raw (unsigned row, unsigned col)
{
- return (row < height && col < width) ? BAYER(row,col) : 0;
+ return (row < raw_height && col < raw_width) ? RAW(row,col) : 0;
}
void CLASS phase_one_flat_field (int is_float, int nc)
{
ushort head[8];
- unsigned wide, y, x, c, rend, cend, row, col;
+ unsigned wide, high, y, x, c, rend, cend, row, col;
float *mrow, num, mult[4];
read_shorts (head, 8);
- wide = head[2] / head[4];
+ if (head[2] * head[3] * head[4] * head[5] == 0) return;
+ wide = head[2] / head[4] + (head[2] % head[4] != 0);
+ high = head[3] / head[5] + (head[3] % head[5] != 0);
mrow = (float *) calloc (nc*wide, sizeof *mrow);
merror (mrow, "phase_one_flat_field()");
- for (y=0; y < head[3] / head[5]; y++) {
+ for (y=0; y < high; y++) {
for (x=0; x < wide; x++)
for (c=0; c < nc; c+=2) {
num = is_float ? getreal(11) : get2()/32768.0;
@@ -1453,19 +1451,23 @@ void CLASS phase_one_flat_field (int is_float, int nc)
else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
}
if (y==0) continue;
- rend = head[1]-top_margin + y*head[5];
- for (row = rend-head[5]; row < height && row < rend; row++) {
+ rend = head[1] + y*head[5];
+ for (row = rend-head[5];
+ row < raw_height && row < rend &&
+ row < head[1]+head[3]-head[5]; row++) {
for (x=1; x < wide; x++) {
for (c=0; c < nc; c+=2) {
mult[c] = mrow[c*wide+x-1];
mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
}
- cend = head[0]-left_margin + x*head[4];
- for (col = cend-head[4]; col < width && col < cend; col++) {
- c = nc > 2 ? FC(row,col) : 0;
+ cend = head[0] + x*head[4];
+ for (col = cend-head[4];
+ col < raw_width &&
+ col < cend && col < head[0]+head[2]-head[4]; col++) {
+ c = nc > 2 ? FC(row-top_margin,col-left_margin) : 0;
if (!(c & 1)) {
- c = BAYER(row,col) * mult[c];
- BAYER(row,col) = LIM(c,0,65535);
+ c = RAW(row,col) * mult[c];
+ RAW(row,col) = LIM(c,0,65535);
}
for (c=0; c < nc; c+=2)
mult[c] += mult[c+1];
@@ -1488,7 +1490,8 @@ void CLASS phase_one_correct()
{ {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
{-2,-2}, {-2,2}, {2,-2}, {2,2} };
float poly[8], num, cfrac, frac, mult[2], *yval[2];
- ushort curve[0x10000], *xval[2];
+ ushort *xval[2];
+ int qmult_applied = 0, qlin_applied = 0;
if (half_size || !meta_length) return;
if (verbose) fprintf (stderr,_("Phase One correction...\n"));
@@ -1519,37 +1522,37 @@ void CLASS phase_one_correct()
num = num * i + poly[j];
curve[i] = LIM(num+i,0,65535);
} apply: /* apply to whole image */
- for (row=0; row < height; row++)
- for (col = (tag & 1)*ph1.split_col; col < width; col++)
- BAYER(row,col) = curve[BAYER(row,col)];
+ for (row=0; row < raw_height; row++)
+ for (col = (tag & 1)*ph1.split_col; col < raw_width; col++)
+ RAW(row,col) = curve[RAW(row,col)];
} else if (tag == 0x400) { /* Sensor defects */
while ((len -= 8) >= 0) {
- col = get2() - left_margin;
- row = get2() - top_margin;
+ col = get2();
+ row = get2();
type = get2(); get2();
- if (col >= width) continue;
- if (type == 131) /* Bad column */
- for (row=0; row < height; row++)
- if (FC(row,col) == 1) {
+ if (col >= raw_width) continue;
+ if (type == 131 || type == 137) /* Bad column */
+ for (row=0; row < raw_height; row++)
+ if (FC(row-top_margin,col-left_margin) == 1) {
for (sum=i=0; i < 4; i++)
- sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]);
+ sum += val[i] = raw (row+dir[i][0], col+dir[i][1]);
for (max=i=0; i < 4; i++) {
dev[i] = abs((val[i] << 2) - sum);
if (dev[max] < dev[i]) max = i;
}
- BAYER(row,col) = (sum - val[max])/3.0 + 0.5;
+ RAW(row,col) = (sum - val[max])/3.0 + 0.5;
} else {
for (sum=0, i=8; i < 12; i++)
- sum += bayer (row+dir[i][0], col+dir[i][1]);
- BAYER(row,col) = 0.5 + sum * 0.0732233 +
- (bayer(row,col-2) + bayer(row,col+2)) * 0.3535534;
+ sum += raw (row+dir[i][0], col+dir[i][1]);
+ RAW(row,col) = 0.5 + sum * 0.0732233 +
+ (raw(row,col-2) + raw(row,col+2)) * 0.3535534;
}
else if (type == 129) { /* Bad pixel */
- if (row >= height) continue;
- j = (FC(row,col) != 1) * 4;
+ if (row >= raw_height) continue;
+ j = (FC(row-top_margin,col-left_margin) != 1) * 4;
for (sum=0, i=j; i < j+8; i++)
- sum += bayer (row+dir[i][0], col+dir[i][1]);
- BAYER(row,col) = (sum + 4) >> 3;
+ sum += raw (row+dir[i][0], col+dir[i][1]);
+ RAW(row,col) = (sum + 4) >> 3;
}
}
} else if (tag == 0x401) { /* All-color flat fields */
@@ -1565,6 +1568,83 @@ void CLASS phase_one_correct()
mindiff = diff;
off_412 = ftell(ifp) - 38;
}
+ } else if (tag == 0x41f && !qlin_applied) { /* Quadrant linearization */
+ ushort lc[2][2][16], ref[16];
+ int qr, qc;
+ for (qr = 0; qr < 2; qr++)
+ for (qc = 0; qc < 2; qc++)
+ for (i = 0; i < 16; i++)
+ lc[qr][qc][i] = get4();
+ for (i = 0; i < 16; i++) {
+ int v = 0;
+ for (qr = 0; qr < 2; qr++)
+ for (qc = 0; qc < 2; qc++)
+ v += lc[qr][qc][i];
+ ref[i] = (v + 2) >> 2;
+ }
+ for (qr = 0; qr < 2; qr++) {
+ for (qc = 0; qc < 2; qc++) {
+ int cx[19], cf[19];
+ for (i = 0; i < 16; i++) {
+ cx[1+i] = lc[qr][qc][i];
+ cf[1+i] = ref[i];
+ }
+ cx[0] = cf[0] = 0;
+ cx[17] = cf[17] = ((unsigned) ref[15] * 65535) / lc[qr][qc][15];
+ cx[18] = cf[18] = 65535;
+ cubic_spline(cx, cf, 19);
+ for (row = (qr ? ph1.split_row : 0);
+ row < (qr ? raw_height : ph1.split_row); row++)
+ for (col = (qc ? ph1.split_col : 0);
+ col < (qc ? raw_width : ph1.split_col); col++)
+ RAW(row,col) = curve[RAW(row,col)];
+ }
+ }
+ qlin_applied = 1;
+ } else if (tag == 0x41e && !qmult_applied) { /* Quadrant multipliers */
+ float qmult[2][2] = { { 1, 1 }, { 1, 1 } };
+ get4(); get4(); get4(); get4();
+ qmult[0][0] = 1.0 + getreal(11);
+ get4(); get4(); get4(); get4(); get4();
+ qmult[0][1] = 1.0 + getreal(11);
+ get4(); get4(); get4();
+ qmult[1][0] = 1.0 + getreal(11);
+ get4(); get4(); get4();
+ qmult[1][1] = 1.0 + getreal(11);
+ for (row=0; row < raw_height; row++)
+ for (col=0; col < raw_width; col++) {
+ i = qmult[row >= ph1.split_row][col >= ph1.split_col] * RAW(row,col);
+ RAW(row,col) = LIM(i,0,65535);
+ }
+ qmult_applied = 1;
+ } else if (tag == 0x431 && !qmult_applied) { /* Quadrant combined */
+ ushort lc[2][2][7], ref[7];
+ int qr, qc;
+ for (i = 0; i < 7; i++)
+ ref[i] = get4();
+ for (qr = 0; qr < 2; qr++)
+ for (qc = 0; qc < 2; qc++)
+ for (i = 0; i < 7; i++)
+ lc[qr][qc][i] = get4();
+ for (qr = 0; qr < 2; qr++) {
+ for (qc = 0; qc < 2; qc++) {
+ int cx[9], cf[9];
+ for (i = 0; i < 7; i++) {
+ cx[1+i] = ref[i];
+ cf[1+i] = ((unsigned) ref[i] * lc[qr][qc][i]) / 10000;
+ }
+ cx[0] = cf[0] = 0;
+ cx[8] = cf[8] = 65535;
+ cubic_spline(cx, cf, 9);
+ for (row = (qr ? ph1.split_row : 0);
+ row < (qr ? raw_height : ph1.split_row); row++)
+ for (col = (qc ? ph1.split_col : 0);
+ col < (qc ? raw_width : ph1.split_col); col++)
+ RAW(row,col) = curve[RAW(row,col)];
+ }
+ }
+ qmult_applied = 1;
+ qlin_applied = 1;
}
fseek (ifp, save, SEEK_SET);
}
@@ -1583,11 +1663,11 @@ void CLASS phase_one_correct()
for (i=0; i < 2; i++)
for (j=0; j < head[i+1]*head[i+3]; j++)
xval[i][j] = get2();
- for (row=0; row < height; row++)
- for (col=0; col < width; col++) {
+ for (row=0; row < raw_height; row++)
+ for (col=0; col < raw_width; col++) {
cfrac = (float) col * head[3] / raw_width;
cfrac -= cip = cfrac;
- num = BAYER(row,col) * 0.5;
+ num = RAW(row,col) * 0.5;
for (i=cip; i < cip+2; i++) {
for (k=j=0; j < head[1]; j++)
if (num < xval[0][k = head[1]*i+j]) break;
@@ -1595,9 +1675,8 @@ void CLASS phase_one_correct()
(xval[0][k] - num) / (xval[0][k] - xval[0][k-1]);
mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac);
}
- i = ((mult[0] * (1-cfrac) + mult[1] * cfrac)
- * (row + top_margin) + num) * 2;
- BAYER(row,col) = LIM(i,0,65535);
+ i = ((mult[0] * (1-cfrac) + mult[1] * cfrac) * row + num) * 2;
+ RAW(row,col) = LIM(i,0,65535);
}
free (yval[0]);
}
@@ -1605,35 +1684,29 @@ void CLASS phase_one_correct()
void CLASS phase_one_load_raw()
{
- int row, col, a, b;
- ushort *pixel, akey, bkey, mask;
+ int a, b, i;
+ ushort akey, bkey, mask;
fseek (ifp, ph1.key_off, SEEK_SET);
akey = get2();
bkey = get2();
mask = ph1.format == 1 ? 0x5555:0x1354;
- fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET);
- pixel = (ushort *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "phase_one_load_raw()");
- for (row=0; row < height; row++) {
- read_shorts (pixel, raw_width);
- for (col=0; col < raw_width; col+=2) {
- a = pixel[col+0] ^ akey;
- b = pixel[col+1] ^ bkey;
- pixel[col+0] = (a & mask) | (b & ~mask);
- pixel[col+1] = (b & mask) | (a & ~mask);
+ fseek (ifp, data_offset, SEEK_SET);
+ read_shorts (raw_image, raw_width*raw_height);
+ if (ph1.format)
+ for (i=0; i < raw_width*raw_height; i+=2) {
+ a = raw_image[i+0] ^ akey;
+ b = raw_image[i+1] ^ bkey;
+ raw_image[i+0] = (a & mask) | (b & ~mask);
+ raw_image[i+1] = (b & mask) | (a & ~mask);
}
- for (col=0; col < width; col++)
- BAYER(row,col) = pixel[col+left_margin];
- }
- free (pixel);
- phase_one_correct();
}
-unsigned CLASS ph1_bits (int nbits)
+unsigned CLASS ph1_bithuff (int nbits, ushort *huff)
{
static UINT64 bitbuf=0;
static int vbits=0;
+ unsigned c;
if (nbits == -1)
return bitbuf = vbits = 0;
@@ -1642,27 +1715,38 @@ unsigned CLASS ph1_bits (int nbits)
bitbuf = bitbuf << 32 | get4();
vbits += 32;
}
+ c = bitbuf << (64-vbits) >> (64-nbits);
+ if (huff) {
+ vbits -= huff[c] >> 8;
+ return (uchar) huff[c];
+ }
vbits -= nbits;
- return bitbuf << (64-nbits-vbits) >> (64-nbits);
+ return c;
}
+#define ph1_bits(n) ph1_bithuff(n,0)
+#define ph1_huff(h) ph1_bithuff(*h,h+1)
void CLASS phase_one_load_raw_c()
{
static const int length[] = { 8,7,6,9,11,10,5,12,14,13 };
int *offset, len[2], pred[2], row, col, i, j;
ushort *pixel;
- short (*black)[2];
+ short (*cblack)[2], (*rblack)[2];
- pixel = (ushort *) calloc (raw_width + raw_height*4, 2);
+ pixel = (ushort *) calloc (raw_width*3 + raw_height*4, 2);
merror (pixel, "phase_one_load_raw_c()");
offset = (int *) (pixel + raw_width);
fseek (ifp, strip_offset, SEEK_SET);
for (row=0; row < raw_height; row++)
offset[row] = get4();
- black = (short (*)[2]) offset + raw_height;
- fseek (ifp, ph1.black_off, SEEK_SET);
- if (ph1.black_off)
- read_shorts ((ushort *) black[0], raw_height*2);
+ cblack = (short (*)[2]) (offset + raw_height);
+ fseek (ifp, ph1.black_col, SEEK_SET);
+ if (ph1.black_col)
+ read_shorts ((ushort *) cblack[0], raw_height*2);
+ rblack = cblack + raw_height;
+ fseek (ifp, ph1.black_row, SEEK_SET);
+ if (ph1.black_row)
+ read_shorts ((ushort *) rblack[0], raw_width*2);
for (i=0; i < 256; i++)
curve[i] = i*i / 3.969 + 0.5;
for (row=0; row < raw_height; row++) {
@@ -1685,94 +1769,127 @@ void CLASS phase_one_load_raw_c()
if (ph1.format == 5 && pixel[col] < 256)
pixel[col] = curve[pixel[col]];
}
- if ((unsigned) (row-top_margin) < height)
- for (col=0; col < width; col++) {
- i = (pixel[col+left_margin] << 2)
- - ph1.black + black[row][col >= ph1.split_col];
- if (i > 0) BAYER(row-top_margin,col) = i;
- }
+ for (col=0; col < raw_width; col++) {
+ i = (pixel[col] << 2*(ph1.format != 8)) - ph1.black
+ + cblack[row][col >= ph1.split_col]
+ + rblack[col][row >= ph1.split_row];
+ if (i > 0) RAW(row,col) = i;
+ }
}
free (pixel);
- phase_one_correct();
maximum = 0xfffc - ph1.black;
}
void CLASS hasselblad_load_raw()
{
struct jhead jh;
- struct decode *dindex;
- int row, col, pred[2], len[2], diff, i;
+ int shot, row, col, *back[5], len[2], diff[12], pred, sh, f, s, c;
+ unsigned upix, urow, ucol;
+ ushort *ip;
if (!ljpeg_start (&jh, 0)) return;
- free (jh.row);
+ order = 0x4949;
ph1_bits(-1);
- for (row=-top_margin; row < height; row++) {
- pred[0] = pred[1] = 0x8000;
- for (col=-left_margin; col < raw_width-left_margin; col+=2) {
- for (i=0; i < 2; i++) {
- for (dindex=jh.huff[0]; dindex->branch[0]; )
- dindex = dindex->branch[ph1_bits(1)];
- len[i] = dindex->leaf;
+ back[4] = (int *) calloc (raw_width, 3*sizeof **back);
+ merror (back[4], "hasselblad_load_raw()");
+ FORC3 back[c] = back[4] + c*raw_width;
+ cblack[6] >>= sh = tiff_samples > 1;
+ shot = LIM(shot_select, 1, tiff_samples) - 1;
+ for (row=0; row < raw_height; row++) {
+ FORC4 back[(c+3) & 3] = back[c];
+ for (col=0; col < raw_width; col+=2) {
+ for (s=0; s < tiff_samples*2; s+=2) {
+ FORC(2) len[c] = ph1_huff(jh.huff[0]);
+ FORC(2) {
+ diff[s+c] = ph1_bits(len[c]);
+ if ((diff[s+c] & (1 << (len[c]-1))) == 0)
+ diff[s+c] -= (1 << len[c]) - 1;
+ if (diff[s+c] == 65535) diff[s+c] = -32768;
+ }
}
- for (i=0; i < 2; i++) {
- diff = ph1_bits(len[i]);
- if ((diff & (1 << (len[i]-1))) == 0)
- diff -= (1 << len[i]) - 1;
- pred[i] += diff;
- if (row >= 0 && (unsigned)(col+i) < width)
- BAYER(row,col+i) = pred[i];
+ for (s=col; s < col+2; s++) {
+ pred = 0x8000 + load_flags;
+ if (col) pred = back[2][s-2];
+ if (col && row > 1) switch (jh.psv) {
+ case 11: pred += back[0][s]/2 - back[0][s-2]/2; break;
+ }
+ f = (row & 1)*3 ^ ((col+s) & 1);
+ FORC (tiff_samples) {
+ pred += diff[(s & 1)*tiff_samples+c];
+ upix = pred >> sh & 0xffff;
+ if (raw_image && c == shot)
+ RAW(row,s) = upix;
+ if (image) {
+ urow = row-top_margin + (c & 1);
+ ucol = col-left_margin - ((c >> 1) & 1);
+ ip = &image[urow*width+ucol][f];
+ if (urow < height && ucol < width)
+ *ip = c < 4 ? upix : (*ip + upix) >> 1;
+ }
+ }
+ back[2][s] = pred;
}
}
}
- maximum = 0xffff;
+ free (back[4]);
+ ljpeg_end (&jh);
+ if (image) mix_green = 1;
}
void CLASS leaf_hdr_load_raw()
{
- ushort *pixel;
+ ushort *pixel=0;
unsigned tile=0, r, c, row, col;
- pixel = (ushort *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "leaf_hdr_load_raw()");
+ if (!filters) {
+ pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "leaf_hdr_load_raw()");
+ }
FORC(tiff_samples)
for (r=0; r < raw_height; r++) {
if (r % tile_length == 0) {
fseek (ifp, data_offset + 4*tile++, SEEK_SET);
- fseek (ifp, get4() + 2*left_margin, SEEK_SET);
+ fseek (ifp, get4(), SEEK_SET);
}
if (filters && c != shot_select) continue;
+ if (filters) pixel = raw_image + r*raw_width;
read_shorts (pixel, raw_width);
- if ((row = r - top_margin) >= height) continue;
- for (col=0; col < width; col++)
- if (filters) BAYER(row,col) = pixel[col];
- else image[row*width+col][c] = pixel[col];
+ if (!filters && (row = r - top_margin) < height)
+ for (col=0; col < width; col++)
+ image[row*width+col][c] = pixel[col+left_margin];
}
- free (pixel);
if (!filters) {
maximum = 0xffff;
raw_color = 1;
+ free (pixel);
}
}
-void CLASS unpacked_load_raw();
+void CLASS unpacked_load_raw()
+{
+ int row, col, bits=0;
+
+ while (1 << ++bits < maximum);
+ read_shorts (raw_image, raw_width*raw_height);
+ for (row=0; row < raw_height; row++)
+ for (col=0; col < raw_width; col++)
+ if ((RAW(row,col) >>= load_flags) >> bits
+ && (unsigned) (row-top_margin) < height
+ && (unsigned) (col-left_margin) < width) derror();
+}
void CLASS sinar_4shot_load_raw()
{
ushort *pixel;
unsigned shot, row, col, r, c;
- if ((shot = shot_select) || half_size) {
- if (shot) shot--;
- if (shot > 3) shot = 3;
+ if (raw_image) {
+ shot = LIM (shot_select, 1, 4) - 1;
fseek (ifp, data_offset + shot*4, SEEK_SET);
fseek (ifp, get4(), SEEK_SET);
unpacked_load_raw();
return;
}
- free (image);
- image = (ushort (*)[4])
- calloc ((iheight=height)*(iwidth=width), sizeof *image);
- merror (image, "sinar_4shot_load_raw()");
pixel = (ushort *) calloc (raw_width, sizeof *pixel);
merror (pixel, "sinar_4shot_load_raw()");
for (shot=0; shot < 4; shot++) {
@@ -1783,199 +1900,197 @@ void CLASS sinar_4shot_load_raw()
if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue;
for (col=0; col < raw_width; col++) {
if ((c = col-left_margin - (shot & 1)) >= width) continue;
- image[r*width+c][FC(row,col)] = pixel[col];
+ image[r*width+c][(row & 1)*3 ^ (~col & 1)] = pixel[col];
}
}
}
free (pixel);
- shrink = filters = 0;
+ mix_green = 1;
}
void CLASS imacon_full_load_raw()
{
int row, col;
+ if (!image) return;
for (row=0; row < height; row++)
for (col=0; col < width; col++)
read_shorts (image[row*width+col], 3);
}
-void CLASS packed_12_load_raw()
+void CLASS packed_load_raw()
{
- int row, col;
-
- if (raw_width * 2 < width * 3)
- raw_width = raw_width * 3 / 2; /* Convert raw_width to bytes */
- getbits(-1);
- for (row=0; row < height; row++) {
- for (col=0; col < left_margin; col++)
- getbits(12);
- for (col=0; col < width; col++)
- BAYER(row,col) = getbits(12);
- for (col = (width+left_margin)*3/2; col < raw_width; col++)
- if (getbits(8) && raw_width-col < 35 && width != 3896) derror();
- }
-}
+ int vbits=0, bwide, rbits, bite, half, irow, row, col, val, i;
+ UINT64 bitbuf=0;
-void CLASS unpacked_load_raw()
-{
- ushort *pixel;
- int row, col, bits=0;
-
- while (1 << ++bits < maximum);
- fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
- pixel = (ushort *) calloc (width, sizeof *pixel);
- merror (pixel, "unpacked_load_raw()");
- for (row=0; row < height; row++) {
- read_shorts (pixel, width);
- fseek (ifp, 2*(raw_width - width), SEEK_CUR);
- for (col=0; col < width; col++)
- if ((BAYER2(row,col) = pixel[col]) >> bits) derror();
+ bwide = raw_width * tiff_bps / 8;
+ bwide += bwide & load_flags >> 9;
+ rbits = bwide * 8 - raw_width * tiff_bps;
+ if (load_flags & 1) bwide = bwide * 16 / 15;
+ bite = 8 + (load_flags & 56);
+ half = (raw_height+1) >> 1;
+ for (irow=0; irow < raw_height; irow++) {
+ row = irow;
+ if (load_flags & 2 &&
+ (row = irow % half * 2 + irow / half) == 1 &&
+ load_flags & 4) {
+ if (vbits=0, tiff_compress)
+ fseek (ifp, data_offset - (-half*bwide & -2048), SEEK_SET);
+ else {
+ fseek (ifp, 0, SEEK_END);
+ fseek (ifp, ftell(ifp) >> 3 << 2, SEEK_SET);
+ }
+ }
+ for (col=0; col < raw_width; col++) {
+ for (vbits -= tiff_bps; vbits < 0; vbits += bite) {
+ bitbuf <<= bite;
+ for (i=0; i < bite; i+=8)
+ bitbuf |= ((UINT64) fgetc(ifp) << i);
+ }
+ val = bitbuf << (64-tiff_bps-vbits) >> (64-tiff_bps);
+ RAW(row,col ^ (load_flags >> 6 & 3)) = val;
+ if (load_flags & 1 && (col % 10) == 9 && fgetc(ifp) &&
+ row < height+top_margin && col < width+left_margin) derror();
+ }
+ vbits -= rbits;
}
- free (pixel);
}
void CLASS nokia_load_raw()
{
uchar *data, *dp;
- ushort *pixel, *pix;
- int dwide, row, c;
+ int rev, dwide, row, col, c;
+ double sum[]={0,0};
- dwide = raw_width * 5 / 4;
- data = (uchar *) malloc (dwide + raw_width*2);
+ rev = 3 * (order == 0x4949);
+ dwide = (raw_width * 5 + 1) / 4;
+ data = (uchar *) malloc (dwide*2);
merror (data, "nokia_load_raw()");
- pixel = (ushort *) (data + dwide);
for (row=0; row < raw_height; row++) {
- if (fread (data, 1, dwide, ifp) < dwide) derror();
- for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=5, pix+=4)
- FORC4 pix[c] = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
- if (row < top_margin)
- FORC(width) black += pixel[c];
- else
- FORC(width) BAYER(row-top_margin,c) = pixel[c];
+ if (fread (data+dwide, 1, dwide, ifp) < dwide) derror();
+ FORC(dwide) data[c] = data[dwide+(c ^ rev)];
+ for (dp=data, col=0; col < raw_width; dp+=5, col+=4)
+ FORC4 RAW(row,col+c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
}
free (data);
- if (top_margin) black /= top_margin * width;
maximum = 0x3ff;
+ if (strcmp(make,"OmniVision")) return;
+ row = raw_height/2;
+ FORC(width-1) {
+ sum[ c & 1] += SQR(RAW(row,c)-RAW(row+1,c+1));
+ sum[~c & 1] += SQR(RAW(row+1,c)-RAW(row,c+1));
+ }
+ if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
+}
+
+void CLASS canon_rmf_load_raw()
+{
+ int row, col, bits, orow, ocol, c;
+
+ for (row=0; row < raw_height; row++)
+ for (col=0; col < raw_width-2; col+=3) {
+ bits = get4();
+ FORC3 {
+ orow = row;
+ if ((ocol = col+c-4) < 0) {
+ ocol += raw_width;
+ if ((orow -= 2) < 0)
+ orow += raw_height;
+ }
+ RAW(orow,ocol) = curve[bits >> (10*c+2) & 0x3ff];
+ }
+ }
+ maximum = curve[0x3ff];
}
unsigned CLASS pana_bits (int nbits)
{
- static uchar buf[16], vbits=0;
+ static uchar buf[0x4000];
+ static int vbits;
+ int byte;
- if (!vbits && fread (buf, 1, 16, ifp) < 16) derror();
- vbits = (vbits - nbits) & 127;
- return (buf[(vbits >> 3)+1] << 8 | buf[vbits >> 3])
- >> (vbits & 7) & ~(-1 << nbits);
+ if (!nbits) return vbits=0;
+ if (!vbits) {
+ fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
+ fread (buf, 1, load_flags, ifp);
+ }
+ vbits = (vbits - nbits) & 0x1ffff;
+ byte = vbits >> 3 ^ 0x3ff0;
+ return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
}
void CLASS panasonic_load_raw()
{
int row, col, i, j, sh=0, pred[2], nonz[2];
- raw_width = (raw_width+13)/14*14;
+ pana_bits(0);
for (row=0; row < height; row++)
for (col=0; col < raw_width; col++) {
- if ((i = col % 14) < 2)
- nonz[i] = pred[i] = pana_bits(12);
- else {
- if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
+ if ((i = col % 14) == 0)
+ pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
+ if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
+ if (nonz[i & 1]) {
if ((j = pana_bits(8))) {
if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
pred[i & 1] &= ~(-1 << sh);
- pred[i & 1] += nonz[i & 1] ? j << sh : j;
- nonz[i & 1] = 1;
+ pred[i & 1] += j << sh;
}
- }
- if (col < width)
- if ((BAYER(row,col) = pred[col & 1]) >> 12) derror();
+ } else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
+ pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
+ if ((RAW(row,col) = pred[col & 1]) > 4098 && col < width) derror();
}
- maximum = 0xf96;
- black = 15;
}
-void CLASS olympus_e300_load_raw()
+void CLASS olympus_load_raw()
{
- uchar *data, *dp;
- ushort *pixel, *pix;
- int dwide, row, col;
-
- dwide = raw_width * 16 / 10;
- fseek (ifp, dwide*top_margin, SEEK_CUR);
- data = (uchar *) malloc (dwide + raw_width*2);
- merror (data, "olympus_e300_load_raw()");
- pixel = (ushort *) (data + dwide);
- for (row=0; row < height; row++) {
- if (fread (data, 1, dwide, ifp) < dwide) derror();
- for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) {
- if (((dp-data) & 15) == 15)
- if (*dp++ && pix < pixel+width+left_margin) derror();
- pix[0] = dp[1] << 8 | dp[0];
- pix[1] = dp[2] << 4 | dp[1] >> 4;
- }
- for (col=0; col < width; col++)
- BAYER(row,col) = (pixel[col+left_margin] & 0xfff);
- }
- free (data);
- maximum >>= 4;
- black >>= 4;
-}
-
-void CLASS olympus_e410_load_raw()
-{
- int row, col, nbits, sign, low, high, i, w, n, nw;
+ ushort huff[4096];
+ int row, col, nbits, sign, low, high, i, c, w, n, nw;
int acarry[2][3], *carry, pred, diff;
+ huff[n=0] = 0xc0c;
+ for (i=12; i--; )
+ FORC(2048 >> i) huff[++n] = (i+1) << 8 | i;
fseek (ifp, 7, SEEK_CUR);
getbits(-1);
for (row=0; row < height; row++) {
memset (acarry, 0, sizeof acarry);
- for (col=0; col < width; col++) {
+ for (col=0; col < raw_width; col++) {
carry = acarry[col & 1];
i = 2 * (carry[2] < 3);
for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++);
- sign = getbits(1) * -1;
- low = getbits(2);
- for (high=0; high < 12; high++)
- if (getbits(1)) break;
- if (high == 12)
+ low = (sign = getbits(3)) & 3;
+ sign = sign << 29 >> 31;
+ if ((high = getbithuff(12,huff)) == 12)
high = getbits(16-nbits) >> 1;
carry[0] = (high << nbits) | getbits(nbits);
diff = (carry[0] ^ sign) + carry[1];
carry[1] = (diff*3 + carry[1]) >> 5;
carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
+ if (col >= width) continue;
if (row < 2 && col < 2) pred = 0;
- else if (row < 2) pred = BAYER(row,col-2);
- else if (col < 2) pred = BAYER(row-2,col);
+ else if (row < 2) pred = RAW(row,col-2);
+ else if (col < 2) pred = RAW(row-2,col);
else {
- w = BAYER(row,col-2);
- n = BAYER(row-2,col);
- nw = BAYER(row-2,col-2);
+ w = RAW(row,col-2);
+ n = RAW(row-2,col);
+ nw = RAW(row-2,col-2);
if ((w < nw && nw < n) || (n < nw && nw < w)) {
if (ABS(w-nw) > 32 || ABS(n-nw) > 32)
pred = w + n - nw;
else pred = (w + n) >> 1;
} else pred = ABS(w-nw) > ABS(n-nw) ? w : n;
}
- if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
+ if ((RAW(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
}
}
}
-void CLASS olympus_cseries_load_raw()
+void CLASS canon_crx_load_raw()
{
- int irow, row, col;
+}
- for (irow=0; irow < height; irow++) {
- row = irow * 2 % height + irow / (height/2);
- if (row < 2) {
- fseek (ifp, data_offset - row*(-width*height*3/4 & -2048), SEEK_SET);
- getbits(-1);
- }
- for (col=0; col < width; col++)
- BAYER(row,col) = getbits(12);
- }
- black >>= 4;
+void CLASS fuji_xtrans_load_raw()
+{
}
void CLASS minolta_rd175_load_raw()
@@ -1995,37 +2110,17 @@ void CLASS minolta_rd175_load_raw()
}
if ((box < 12) && (box & 1)) {
for (col=0; col < 1533; col++, row ^= 1)
- if (col != 1) BAYER(row,col) = (col+1) & 2 ?
+ if (col != 1) RAW(row,col) = (col+1) & 2 ?
pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
- BAYER(row,1) = pixel[1] << 1;
- BAYER(row,1533) = pixel[765] << 1;
+ RAW(row,1) = pixel[1] << 1;
+ RAW(row,1533) = pixel[765] << 1;
} else
for (col=row & 1; col < 1534; col+=2)
- BAYER(row,col) = pixel[col/2] << 1;
+ RAW(row,col) = pixel[col/2] << 1;
}
maximum = 0xff << 1;
}
-void CLASS casio_qv5700_load_raw()
-{
- uchar data[3232], *dp;
- ushort pixel[2576], *pix;
- int row, col;
-
- for (row=0; row < height; row++) {
- fread (data, 1, 3232, ifp);
- for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) {
- pix[0] = (dp[0] << 2) + (dp[1] >> 6);
- pix[1] = (dp[1] << 4) + (dp[2] >> 4);
- pix[2] = (dp[2] << 6) + (dp[3] >> 2);
- pix[3] = (dp[3] << 8) + (dp[4] );
- }
- for (col=0; col < width; col++)
- BAYER(row,col) = (pixel[col] & 0x3ff);
- }
- maximum = 0x3fc;
-}
-
void CLASS quicktake_100_load_raw()
{
uchar pixel[484][644];
@@ -2089,32 +2184,20 @@ void CLASS quicktake_100_load_raw()
}
for (row=0; row < height; row++)
for (col=0; col < width; col++)
- BAYER(row,col) = curve[pixel[row+2][col+2]];
+ RAW(row,col) = curve[pixel[row+2][col+2]];
maximum = 0x3ff;
}
-const int * CLASS make_decoder_int (const int *source, int level)
-{
- struct decode *cur;
+#define radc_token(tree) ((signed char) getbithuff(8,huff[tree]))
- cur = free_decode++;
- if (level < source[0]) {
- cur->branch[0] = free_decode;
- source = make_decoder_int (source, level+1);
- cur->branch[1] = free_decode;
- source = make_decoder_int (source, level+1);
- } else {
- cur->leaf = source[1];
- source += 2;
- }
- return source;
-}
+#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
-int CLASS radc_token (int tree)
+#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
+: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
+
+void CLASS kodak_radc_load_raw()
{
- int t;
- static struct decode *dstart[18], *dindex;
- static const int *s, source[] = {
+ static const char src[] = {
1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8,
1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8,
2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8,
@@ -2134,37 +2217,24 @@ int CLASS radc_token (int tree)
2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76,
2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37
};
-
- if (free_decode == first_decode)
- for (s=source, t=0; t < 18; t++) {
- dstart[t] = free_decode;
- s = make_decoder_int (s, 0);
- }
- if (tree == 18) {
- if (kodak_cbpp == 243)
- return (getbits(6) << 2) + 2; /* most DC50 photos */
- else
- return (getbits(5) << 3) + 4; /* DC40, Fotoman Pixtura */
- }
- for (dindex = dstart[tree]; dindex->branch[0]; )
- dindex = dindex->branch[getbits(1)];
- return dindex->leaf;
-}
-
-#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
-
-#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
-: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
-
-void CLASS kodak_radc_load_raw()
-{
+ ushort huff[19][256];
int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];
-
- init_decoder();
+ static const ushort pt[] =
+ { 0,0, 1280,1344, 2320,3616, 3328,8000, 4095,16383, 65535,16383 };
+
+ for (i=2; i < 12; i+=2)
+ for (c=pt[i-2]; c <= pt[i]; c++)
+ curve[c] = (float)
+ (c-pt[i-2]) / (pt[i]-pt[i-2]) * (pt[i+1]-pt[i-1]) + pt[i-1] + 0.5;
+ for (s=i=0; i < sizeof src; i+=2)
+ FORC(256 >> src[i])
+ ((ushort *)huff)[s++] = src[i] << 8 | (uchar) src[i+1];
+ s = kodak_cbpp == 243 ? 2 : 3;
+ FORC(256) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1);
getbits(-1);
for (i=0; i < sizeof(buf)/sizeof(short); i++)
- buf[0][0][i] = 2048;
+ ((short *)buf)[i] = 2048;
for (row=0; row < height; row+=4) {
FORC3 mul[c] = getbits(6);
FORC3 {
@@ -2173,7 +2243,7 @@ void CLASS kodak_radc_load_raw()
x = ~(-1 << (s-1));
val <<= 12-s;
for (i=0; i < sizeof(buf[0])/sizeof(short); i++)
- buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
+ ((short *)buf[c])[i] = (((short *)buf[c])[i] * val + x) >> s;
last[c] = mul[c];
for (r=0; r <= !c; r++) {
buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
@@ -2181,7 +2251,7 @@ void CLASS kodak_radc_load_raw()
if ((tree = radc_token(tree))) {
col -= 2;
if (tree == 8)
- FORYX buf[c][y][x] = radc_token(tree+10) * mul[c];
+ FORYX buf[c][y][x] = (uchar) radc_token(18) * mul[c];
else
FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
} else
@@ -2201,8 +2271,8 @@ void CLASS kodak_radc_load_raw()
for (x=0; x < width/2; x++) {
val = (buf[c][y+1][x] << 4) / mul[c];
if (val < 0) val = 0;
- if (c) BAYER(row+y*2+c-1,x*2+2-c) = val;
- else BAYER(row+r*2+y,x*2+y) = val;
+ if (c) RAW(row+y*2+c-1,x*2+2-c) = val;
+ else RAW(row+r*2+y,x*2+y) = val;
}
memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
}
@@ -2212,20 +2282,22 @@ void CLASS kodak_radc_load_raw()
if ((x+y) & 1) {
r = x ? x-1 : x+1;
s = x+1 < width ? x+1 : x-1;
- val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2;
+ val = (RAW(y,x)-2048)*2 + (RAW(y,r)+RAW(y,s))/2;
if (val < 0) val = 0;
- BAYER(y,x) = val;
+ RAW(y,x) = val;
}
}
- maximum = 0xfff;
- use_gamma = 0;
+ for (i=0; i < height*width; i++)
+ raw_image[i] = curve[raw_image[i]];
+ maximum = 0x3fff;
}
#undef FORYX
#undef PREDICTOR
-#ifdef HAVE_JPEG
+#ifdef NO_JPEG
void CLASS kodak_jpeg_load_raw() {}
+void CLASS lossy_dng_load_raw() {}
#else
METHODDEF(boolean)
@@ -2270,16 +2342,81 @@ void CLASS kodak_jpeg_load_raw()
jpeg_read_scanlines (&cinfo, buf, 1);
pixel = (JSAMPLE (*)[3]) buf[0];
for (col=0; col < width; col+=2) {
- BAYER(row+0,col+0) = pixel[col+0][1] << 1;
- BAYER(row+1,col+1) = pixel[col+1][1] << 1;
- BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
- BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
+ RAW(row+0,col+0) = pixel[col+0][1] << 1;
+ RAW(row+1,col+1) = pixel[col+1][1] << 1;
+ RAW(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
+ RAW(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
}
}
jpeg_finish_decompress (&cinfo);
jpeg_destroy_decompress (&cinfo);
maximum = 0xff << 1;
}
+
+void CLASS gamma_curve (double pwr, double ts, int mode, int imax);
+
+void CLASS lossy_dng_load_raw()
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPARRAY buf;
+ JSAMPLE (*pixel)[3];
+ unsigned sorder=order, ntags, opcode, deg, i, j, c;
+ unsigned save=data_offset-4, trow=0, tcol=0, row, col;
+ ushort cur[3][256];
+ double coeff[9], tot;
+
+ if (meta_offset) {
+ fseek (ifp, meta_offset, SEEK_SET);
+ order = 0x4d4d;
+ ntags = get4();
+ while (ntags--) {
+ opcode = get4(); get4(); get4();
+ if (opcode != 8)
+ { fseek (ifp, get4(), SEEK_CUR); continue; }
+ fseek (ifp, 20, SEEK_CUR);
+ if ((c = get4()) > 2) break;
+ fseek (ifp, 12, SEEK_CUR);
+ if ((deg = get4()) > 8) break;
+ for (i=0; i <= deg && i < 9; i++)
+ coeff[i] = getreal(12);
+ for (i=0; i < 256; i++) {
+ for (tot=j=0; j <= deg; j++)
+ tot += coeff[j] * pow(i/255.0, j);
+ cur[c][i] = tot*0xffff;
+ }
+ }
+ order = sorder;
+ } else {
+ gamma_curve (1/2.4, 12.92, 1, 255);
+ FORC3 memcpy (cur[c], curve, sizeof cur[0]);
+ }
+ cinfo.err = jpeg_std_error (&jerr);
+ jpeg_create_decompress (&cinfo);
+ while (trow < raw_height) {
+ fseek (ifp, save+=4, SEEK_SET);
+ if (tile_length < INT_MAX)
+ fseek (ifp, get4(), SEEK_SET);
+ jpeg_stdio_src (&cinfo, ifp);
+ jpeg_read_header (&cinfo, TRUE);
+ jpeg_start_decompress (&cinfo);
+ buf = (*cinfo.mem->alloc_sarray)
+ ((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width*3, 1);
+ while (cinfo.output_scanline < cinfo.output_height &&
+ (row = trow + cinfo.output_scanline) < height) {
+ jpeg_read_scanlines (&cinfo, buf, 1);
+ pixel = (JSAMPLE (*)[3]) buf[0];
+ for (col=0; col < cinfo.output_width && tcol+col < width; col++) {
+ FORC3 image[row*width+tcol+col][c] = cur[c][pixel[col][c]];
+ }
+ }
+ jpeg_abort_decompress (&cinfo);
+ if ((tcol += tile_width) >= raw_width)
+ trow += tile_length + (tcol = 0);
+ }
+ jpeg_destroy_decompress (&cinfo);
+ maximum = 0xffff;
+}
#endif
void CLASS kodak_dc120_load_raw()
@@ -2293,7 +2430,7 @@ void CLASS kodak_dc120_load_raw()
if (fread (pixel, 1, 848, ifp) < 848) derror();
shift = row * mul[row & 3] + add[row & 3];
for (col=0; col < width; col++)
- BAYER(row,col) = (ushort) pixel[(col + shift) % 848];
+ RAW(row,col) = (ushort) pixel[(col + shift) % 848];
}
maximum = 0xff;
}
@@ -2301,25 +2438,65 @@ void CLASS kodak_dc120_load_raw()
void CLASS eight_bit_load_raw()
{
uchar *pixel;
- unsigned row, col, val, lblack=0;
+ unsigned row, col;
pixel = (uchar *) calloc (raw_width, sizeof *pixel);
merror (pixel, "eight_bit_load_raw()");
- fseek (ifp, top_margin*raw_width, SEEK_CUR);
- for (row=0; row < height; row++) {
+ for (row=0; row < raw_height; row++) {
if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
- for (col=0; col < raw_width; col++) {
- val = curve[pixel[col]];
- if ((unsigned) (col-left_margin) < width)
- BAYER(row,col-left_margin) = val;
- else lblack += val;
+ for (col=0; col < raw_width; col++)
+ RAW(row,col) = curve[pixel[col]];
+ }
+ free (pixel);
+ maximum = curve[0xff];
+}
+
+void CLASS kodak_c330_load_raw()
+{
+ uchar *pixel;
+ int row, col, y, cb, cr, rgb[3], c;
+
+ pixel = (uchar *) calloc (raw_width, 2*sizeof *pixel);
+ merror (pixel, "kodak_c330_load_raw()");
+ for (row=0; row < height; row++) {
+ if (fread (pixel, raw_width, 2, ifp) < 2) derror();
+ if (load_flags && (row & 31) == 31)
+ fseek (ifp, raw_width*32, SEEK_CUR);
+ for (col=0; col < width; col++) {
+ y = pixel[col*2];
+ cb = pixel[(col*2 & -4) | 1] - 128;
+ cr = pixel[(col*2 & -4) | 3] - 128;
+ rgb[1] = y - ((cb + cr + 2) >> 2);
+ rgb[2] = rgb[1] + cb;
+ rgb[0] = rgb[1] + cr;
+ FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,255)];
+ }
+ }
+ free (pixel);
+ maximum = curve[0xff];
+}
+
+void CLASS kodak_c603_load_raw()
+{
+ uchar *pixel;
+ int row, col, y, cb, cr, rgb[3], c;
+
+ pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
+ merror (pixel, "kodak_c603_load_raw()");
+ for (row=0; row < height; row++) {
+ if (~row & 1)
+ if (fread (pixel, raw_width, 3, ifp) < 3) derror();
+ for (col=0; col < width; col++) {
+ y = pixel[width*2*(row & 1) + col];
+ cb = pixel[width + (col & -2)] - 128;
+ cr = pixel[width + (col & -2)+1] - 128;
+ rgb[1] = y - ((cb + cr + 2) >> 2);
+ rgb[2] = rgb[1] + cb;
+ rgb[0] = rgb[1] + cr;
+ FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,255)];
}
}
free (pixel);
- if (raw_width > width+1)
- black = lblack / ((raw_width - width) * height);
- if (!strncmp(model,"DC2",3))
- black = 0;
maximum = curve[0xff];
}
@@ -2328,22 +2505,17 @@ void CLASS kodak_262_load_raw()
static const uchar kodak_tree[2][26] =
{ { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 },
{ 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } };
- struct decode *decode[2];
+ ushort *huff[2];
uchar *pixel;
- int *strip, ns, i, row, col, chess, pi=0, pi1, pi2, pred, val;
+ int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val;
- init_decoder();
- for (i=0; i < 2; i++) {
- decode[i] = free_decode;
- make_decoder (kodak_tree[i], 0);
- }
+ FORC(2) huff[c] = make_decoder (kodak_tree[c]);
ns = (raw_height+63) >> 5;
pixel = (uchar *) malloc (raw_width*32 + ns*4);
merror (pixel, "kodak_262_load_raw()");
strip = (int *) (pixel + raw_width*32);
order = 0x4d4d;
- for (i=0; i < ns; i++)
- strip[i] = get4();
+ FORC(ns) strip[c] = get4();
for (row=0; row < raw_height; row++) {
if ((row & 31) == 0) {
fseek (ifp, strip[row >> 5], SEEK_SET);
@@ -2359,17 +2531,14 @@ void CLASS kodak_262_load_raw()
if (pi2 < 0) pi2 = pi1;
if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
- pixel[pi] = val = pred + ljpeg_diff (decode[chess]);
+ pixel[pi] = val = pred + ljpeg_diff (huff[chess]);
if (val >> 8) derror();
val = curve[pixel[pi++]];
- if ((unsigned) (col-left_margin) < width)
- BAYER(row,col-left_margin) = val;
- else black += val;
+ RAW(row,col) = val;
}
}
free (pixel);
- if (raw_width > width)
- black /= (raw_width - width) * height;
+ FORC(2) free (huff[c]);
}
int CLASS kodak_65000_decode (short *out, int bsize)
@@ -2429,7 +2598,7 @@ void CLASS kodak_65000_load_raw()
len = MIN (256, width-col);
ret = kodak_65000_decode (buf, len);
for (i=0; i < len; i++)
- if ((BAYER(row,col+i) = curve[ret ? buf[i] :
+ if ((RAW(row,col+i) = curve[ret ? buf[i] :
(pred[i & 1] += buf[i])]) >> 12) derror();
}
}
@@ -2440,6 +2609,7 @@ void CLASS kodak_ycbcr_load_raw()
int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
ushort *ip;
+ if (!image) return;
for (row=0; row < height; row+=2)
for (col=0; col < width; col+=128) {
len = MIN (128, width-col);
@@ -2500,8 +2670,8 @@ void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
for (p=0; p < 127; p++)
pad[p] = htonl(pad[p]);
}
- while (len--)
- *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
+ while (len-- && p++)
+ *data++ ^= pad[(p-1) & 127] = pad[p & 127] ^ pad[(p+64) & 127];
}
void CLASS sony_load_raw()
@@ -2516,44 +2686,37 @@ void CLASS sony_load_raw()
key = get4();
fseek (ifp, 164600, SEEK_SET);
fread (head, 1, 40, ifp);
- sony_decrypt ((unsigned int *) head, 10, 1, key);
+ sony_decrypt ((unsigned *) head, 10, 1, key);
for (i=26; i-- > 22; )
key = key << 8 | head[i];
fseek (ifp, data_offset, SEEK_SET);
- pixel = (ushort *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "sony_load_raw()");
- for (row=0; row < height; row++) {
+ for (row=0; row < raw_height; row++) {
+ pixel = raw_image + row*raw_width;
if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
- sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
- for (col=9; col < left_margin; col++)
- black += ntohs(pixel[col]);
- for (col=0; col < width; col++)
- if ((BAYER(row,col) = ntohs(pixel[col+left_margin])) >> 14)
- derror();
+ sony_decrypt ((unsigned *) pixel, raw_width/2, !row, key);
+ for (col=0; col < raw_width; col++)
+ if ((pixel[col] = ntohs(pixel[col])) >> 14) derror();
}
- free (pixel);
- if (left_margin > 9)
- black /= (left_margin-9) * height;
maximum = 0x3ff0;
}
void CLASS sony_arw_load_raw()
{
- int col, row, len, diff, sum=0;
+ ushort huff[32770];
+ static const ushort tab[18] =
+ { 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809,
+ 0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 };
+ int i, c, n, col, row, sum=0;
+ huff[0] = 15;
+ for (n=i=0; i < 18; i++)
+ FORC(32768 >> (tab[i] >> 8)) huff[++n] = tab[i];
getbits(-1);
for (col = raw_width; col--; )
for (row=0; row < raw_height+1; row+=2) {
if (row == raw_height) row = 1;
- len = 4 - getbits(2);
- if (len == 3 && getbits(1)) len = 0;
- if (len == 4)
- while (len < 17 && !getbits(1)) len++;
- diff = getbits(len);
- if ((diff & (1 << (len-1))) == 0)
- diff -= (1 << len) - 1;
- if ((sum += diff) >> 12) derror();
- if (row < height) BAYER(row,col) = sum;
+ if ((sum += ljpeg_diff(huff)) >> 12) derror();
+ if (row < height) RAW(row,col) = sum;
}
}
@@ -2563,37 +2726,132 @@ void CLASS sony_arw2_load_raw()
ushort pix[16];
int row, col, val, max, min, imax, imin, sh, bit, i;
- data = (uchar *) malloc (raw_width*tiff_bps >> 3);
+ data = (uchar *) malloc (raw_width+1);
merror (data, "sony_arw2_load_raw()");
for (row=0; row < height; row++) {
- fread (data, 1, raw_width*tiff_bps >> 3, ifp);
- if (tiff_bps == 8) {
- for (dp=data, col=0; col < width-30; dp+=16) {
- max = 0x7ff & (val = sget4(dp));
- min = 0x7ff & val >> 11;
- imax = 0x0f & val >> 22;
- imin = 0x0f & val >> 26;
- for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++);
- for (bit=30, i=0; i < 16; i++)
- if (i == imax) pix[i] = max;
- else if (i == imin) pix[i] = min;
- else {
- pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
- if (pix[i] > 0x7ff) pix[i] = 0x7ff;
- bit += 7;
- }
- for (i=0; i < 16; i++, col+=2)
- BAYER(row,col) = curve[pix[i] << 1] >> 1;
- col -= col & 1 ? 1:31;
+ fread (data, 1, raw_width, ifp);
+ for (dp=data, col=0; col < raw_width-30; dp+=16) {
+ max = 0x7ff & (val = sget4(dp));
+ min = 0x7ff & val >> 11;
+ imax = 0x0f & val >> 22;
+ imin = 0x0f & val >> 26;
+ for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++);
+ for (bit=30, i=0; i < 16; i++)
+ if (i == imax) pix[i] = max;
+ else if (i == imin) pix[i] = min;
+ else {
+ pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
+ if (pix[i] > 0x7ff) pix[i] = 0x7ff;
+ bit += 7;
+ }
+ for (i=0; i < 16; i++, col+=2)
+ RAW(row,col) = curve[pix[i] << 1] >> 2;
+ col -= col & 1 ? 1:31;
+ }
+ }
+ free (data);
+}
+
+void CLASS samsung_load_raw()
+{
+ int row, col, c, i, dir, op[4], len[4];
+
+ order = 0x4949;
+ for (row=0; row < raw_height; row++) {
+ fseek (ifp, strip_offset+row*4, SEEK_SET);
+ fseek (ifp, data_offset+get4(), SEEK_SET);
+ ph1_bits(-1);
+ FORC4 len[c] = row < 2 ? 7:4;
+ for (col=0; col < raw_width; col+=16) {
+ dir = ph1_bits(1);
+ FORC4 op[c] = ph1_bits(2);
+ FORC4 switch (op[c]) {
+ case 3: len[c] = ph1_bits(4); break;
+ case 2: len[c]--; break;
+ case 1: len[c]++;
}
- } else if (tiff_bps == 12)
- for (dp=data, col=0; col < width; dp+=3, col+=2) {
- BAYER(row,col) = ((dp[1] << 8 | dp[0]) & 0xfff) << 1;
- BAYER(row,col+1) = (dp[2] << 4 | dp[1] >> 4) << 1;
+ for (c=0; c < 16; c+=2) {
+ i = len[((c & 1) << 1) | (c >> 3)];
+ RAW(row,col+c) = ((signed) ph1_bits(i) << (32-i) >> (32-i)) +
+ (dir ? RAW(row+(~c | -2),col+c) : col ? RAW(row,col+(c | -2)) : 128);
+ if (c == 14) c = -1;
}
+ }
+ }
+ for (row=0; row < raw_height-1; row+=2)
+ for (col=0; col < raw_width-1; col+=2)
+ SWAP (RAW(row,col+1), RAW(row+1,col));
+}
+
+void CLASS samsung2_load_raw()
+{
+ static const ushort tab[14] =
+ { 0x304,0x307,0x206,0x205,0x403,0x600,0x709,
+ 0x80a,0x90b,0xa0c,0xa0d,0x501,0x408,0x402 };
+ ushort huff[1026], vpred[2][2] = {{0,0},{0,0}}, hpred[2];
+ int i, c, n, row, col, diff;
+
+ huff[0] = 10;
+ for (n=i=0; i < 14; i++)
+ FORC(1024 >> (tab[i] >> 8)) huff[++n] = tab[i];
+ getbits(-1);
+ for (row=0; row < raw_height; row++)
+ for (col=0; col < raw_width; col++) {
+ diff = ljpeg_diff (huff);
+ if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+ else hpred[col & 1] += diff;
+ RAW(row,col) = hpred[col & 1];
+ if (hpred[col & 1] >> tiff_bps) derror();
+ }
+}
+
+void CLASS samsung3_load_raw()
+{
+ int opt, init, mag, pmode, row, tab, col, pred, diff, i, c;
+ ushort lent[3][2], len[4], *prow[2];
+
+ order = 0x4949;
+ fseek (ifp, 9, SEEK_CUR);
+ opt = fgetc(ifp);
+ init = (get2(),get2());
+ for (row=0; row < raw_height; row++) {
+ fseek (ifp, (data_offset-ftell(ifp)) & 15, SEEK_CUR);
+ ph1_bits(-1);
+ mag = 0; pmode = 7;
+ FORC(6) ((ushort *)lent)[c] = row < 2 ? 7:4;
+ prow[ row & 1] = &RAW(row-1,1-((row & 1) << 1)); // green
+ prow[~row & 1] = &RAW(row-2,0); // red and blue
+ for (tab=0; tab+15 < raw_width; tab+=16) {
+ if (~opt & 4 && !(tab & 63)) {
+ i = ph1_bits(2);
+ mag = i < 3 ? mag-'2'+"204"[i] : ph1_bits(12);
+ }
+ if (opt & 2)
+ pmode = 7 - 4*ph1_bits(1);
+ else if (!ph1_bits(1))
+ pmode = ph1_bits(3);
+ if (opt & 1 || !ph1_bits(1)) {
+ FORC4 len[c] = ph1_bits(2);
+ FORC4 {
+ i = ((row & 1) << 1 | (c & 1)) % 3;
+ len[c] = len[c] < 3 ? lent[i][0]-'1'+"120"[len[c]] : ph1_bits(4);
+ lent[i][0] = lent[i][1];
+ lent[i][1] = len[c];
+ }
+ }
+ FORC(16) {
+ col = tab + (((c & 7) << 1)^(c >> 3)^(row & 1));
+ pred = (pmode == 7 || row < 2)
+ ? (tab ? RAW(row,tab-2+(col & 1)) : init)
+ : (prow[col & 1][col-'4'+"0224468"[pmode]] +
+ prow[col & 1][col-'4'+"0244668"[pmode]] + 1) >> 1;
+ diff = ph1_bits (i = len[c >> 2]);
+ if (diff >> (i-1)) diff -= 1 << i;
+ diff = diff * (mag*2+1) + mag;
+ RAW(row,col) = pred + diff;
+ }
+ }
}
- free (data);
- maximum = 0x1fff;
}
#define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1)
@@ -2606,13 +2864,14 @@ void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
{ 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
{ 3, 3, 0, 0, 63, 47, 31, 15, 0 } };
int low, high=0xff, carry=0, nbits=8;
- int s, count, bin, next, i, sym[3];
+ int pix, s, count, bin, next, i, sym[3];
uchar diff, pred[]={0,0};
ushort data=0, range=0;
- unsigned pix, row, col;
fseek (ifp, seg[0][1]+1, SEEK_SET);
getbits(-1);
+ if (seg[1][0] > raw_width*raw_height)
+ seg[1][0] = raw_width*raw_height;
for (pix=seg[0][0]; pix < seg[1][0]; pix++) {
for (s=0; s < 3; s++) {
data = data << nbits | getbits(nbits);
@@ -2655,12 +2914,8 @@ void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
diff = diff ? -diff : 0x80;
if (ftell(ifp) + 12 >= seg[1][1])
diff = 0;
- pred[pix & 1] += diff;
- row = pix / raw_width - top_margin;
- col = pix % raw_width - left_margin;
- if (row < height && col < width)
- BAYER(row,col) = pred[pix & 1];
- if (!(pix & 1) && HOLE(row)) pix += 2;
+ raw_image[pix] = pred[pix & 1] += diff;
+ if (!(pix & 1) && HOLE(pix / raw_width)) pix += 2;
}
maximum = 0xff;
}
@@ -2675,7 +2930,6 @@ void CLASS smal_v6_load_raw()
seg[1][0] = raw_width * raw_height;
seg[1][1] = INT_MAX;
smal_decode_segment (seg, 0);
- use_gamma = 0;
}
int CLASS median4 (int *p)
@@ -2698,21 +2952,21 @@ void CLASS fill_holes (int holes)
for (row=2; row < height-2; row++) {
if (!HOLE(row)) continue;
for (col=1; col < width-1; col+=4) {
- val[0] = BAYER(row-1,col-1);
- val[1] = BAYER(row-1,col+1);
- val[2] = BAYER(row+1,col-1);
- val[3] = BAYER(row+1,col+1);
- BAYER(row,col) = median4(val);
+ val[0] = RAW(row-1,col-1);
+ val[1] = RAW(row-1,col+1);
+ val[2] = RAW(row+1,col-1);
+ val[3] = RAW(row+1,col+1);
+ RAW(row,col) = median4(val);
}
for (col=2; col < width-2; col+=4)
if (HOLE(row-2) || HOLE(row+2))
- BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1;
+ RAW(row,col) = (RAW(row,col-2) + RAW(row,col+2)) >> 1;
else {
- val[0] = BAYER(row,col-2);
- val[1] = BAYER(row,col+2);
- val[2] = BAYER(row-2,col);
- val[3] = BAYER(row+2,col);
- BAYER(row,col) = median4(val);
+ val[0] = RAW(row,col-2);
+ val[1] = RAW(row,col+2);
+ val[2] = RAW(row-2,col);
+ val[3] = RAW(row+2,col);
+ RAW(row,col) = median4(val);
}
}
}
@@ -2723,10 +2977,10 @@ void CLASS smal_v9_load_raw()
fseek (ifp, 67, SEEK_SET);
offset = get4();
- nseg = fgetc(ifp);
+ nseg = (uchar) fgetc(ifp);
fseek (ifp, offset, SEEK_SET);
for (i=0; i < nseg*2; i++)
- seg[0][i] = get4() + data_offset*(i & 1);
+ ((unsigned *)seg)[i] = get4() + data_offset*(i & 1);
fseek (ifp, 78, SEEK_SET);
holes = fgetc(ifp);
fseek (ifp, 88, SEEK_SET);
@@ -2737,6 +2991,58 @@ void CLASS smal_v9_load_raw()
if (holes) fill_holes (holes);
}
+void CLASS redcine_load_raw()
+{
+#ifndef NO_JASPER
+ int c, row, col;
+ jas_stream_t *in;
+ jas_image_t *jimg;
+ jas_matrix_t *jmat;
+ jas_seqent_t *data;
+ ushort *img, *pix;
+
+ jas_init();
+ in = jas_stream_fopen (ifname, "rb");
+ jas_stream_seek (in, data_offset+20, SEEK_SET);
+ jimg = jas_image_decode (in, -1, 0);
+ if (!jimg) longjmp (failure, 3);
+ jmat = jas_matrix_create (height/2, width/2);
+ merror (jmat, "redcine_load_raw()");
+ img = (ushort *) calloc ((height+2), (width+2)*2);
+ merror (img, "redcine_load_raw()");
+ FORC4 {
+ jas_image_readcmpt (jimg, c, 0, 0, width/2, height/2, jmat);
+ data = jas_matrix_getref (jmat, 0, 0);
+ for (row = c >> 1; row < height; row+=2)
+ for (col = c & 1; col < width; col+=2)
+ img[(row+1)*(width+2)+col+1] = data[(row/2)*(width/2)+col/2];
+ }
+ for (col=1; col <= width; col++) {
+ img[col] = img[2*(width+2)+col];
+ img[(height+1)*(width+2)+col] = img[(height-1)*(width+2)+col];
+ }
+ for (row=0; row < height+2; row++) {
+ img[row*(width+2)] = img[row*(width+2)+2];
+ img[(row+1)*(width+2)-1] = img[(row+1)*(width+2)-3];
+ }
+ for (row=1; row <= height; row++) {
+ pix = img + row*(width+2) + (col = 1 + (FC(row,1) & 1));
+ for ( ; col <= width; col+=2, pix+=2) {
+ c = (((pix[0] - 0x800) << 3) +
+ pix[-(width+2)] + pix[width+2] + pix[-1] + pix[1]) >> 2;
+ pix[0] = LIM(c,0,4095);
+ }
+ }
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ RAW(row,col) = curve[img[(row+1)*(width+2)+col+1]];
+ free (img);
+ jas_matrix_destroy (jmat);
+ jas_image_destroy (jimg);
+ jas_stream_close (in);
+#endif
+}
+
/* RESTRICTED code starts here */
void CLASS foveon_decoder (unsigned size, unsigned code)
@@ -2748,7 +3054,8 @@ void CLASS foveon_decoder (unsigned size, unsigned code)
if (!code) {
for (i=0; i < size; i++)
huff[i] = get4();
- init_decoder();
+ memset (first_decode, 0, sizeof first_decode);
+ free_decode = first_decode;
}
cur = free_decode++;
if (free_decode > first_decode+2048) {
@@ -2770,7 +3077,7 @@ void CLASS foveon_decoder (unsigned size, unsigned code)
foveon_decoder (size, code+1);
}
-void CLASS foveon_thumb (FILE *tfp)
+void CLASS foveon_thumb()
{
unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
char *buf;
@@ -2778,14 +3085,14 @@ void CLASS foveon_thumb (FILE *tfp)
short pred[3];
bwide = get4();
- fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
if (bwide > 0) {
if (bwide < thumb_width*3) return;
buf = (char *) malloc (bwide);
merror (buf, "foveon_thumb()");
for (row=0; row < thumb_height; row++) {
fread (buf, 1, bwide, ifp);
- fwrite (buf, 3, thumb_width, tfp);
+ fwrite (buf, 3, thumb_width, ofp);
}
free (buf);
return;
@@ -2804,41 +3111,26 @@ void CLASS foveon_thumb (FILE *tfp)
dindex = dindex->branch[bitbuf >> bit & 1];
}
pred[c] += dindex->leaf;
- fputc (pred[c], tfp);
+ fputc (pred[c], ofp);
}
}
}
-void CLASS foveon_load_camf()
-{
- unsigned key, i, val;
-
- fseek (ifp, meta_offset, SEEK_SET);
- key = get4();
- fread (meta_data, 1, meta_length, ifp);
- for (i=0; i < meta_length; i++) {
- key = (key * 1597 + 51749) % 244944;
- val = key * (INT64) 301593171 >> 24;
- meta_data[i] ^= ((((key << 8) - val) >> 1) + val) >> 17;
- }
-}
-
-void CLASS foveon_load_raw()
+void CLASS foveon_sd_load_raw()
{
struct decode *dindex;
short diff[1024];
unsigned bitbuf=0;
- int pred[3], fixed, row, col, bit=-1, c, i;
+ int pred[3], row, col, bit=-1, c, i;
- fixed = get4();
read_shorts ((ushort *) diff, 1024);
- if (!fixed) foveon_decoder (1024, 0);
+ if (!load_flags) foveon_decoder (1024, 0);
for (row=0; row < height; row++) {
memset (pred, 0, sizeof pred);
- if (!bit && !fixed && atoi(model+2) < 14) get4();
+ if (!bit && !load_flags && atoi(model+2) < 14) get4();
for (col=bit=0; col < width; col++) {
- if (fixed) {
+ if (load_flags) {
bitbuf = get4();
FORC3 pred[2-c] += diff[bitbuf >> c*10 & 0x3ff];
}
@@ -2855,10 +3147,83 @@ void CLASS foveon_load_raw()
FORC3 image[row*width+col][c] = pred[c];
}
}
- if (document_mode)
- for (i=0; i < height*width*4; i++)
- if ((short) image[0][i] < 0) image[0][i] = 0;
- foveon_load_camf();
+}
+
+void CLASS foveon_huff (ushort *huff)
+{
+ int i, j, clen, code;
+
+ huff[0] = 8;
+ for (i=0; i < 13; i++) {
+ clen = getc(ifp);
+ code = getc(ifp);
+ for (j=0; j < 256 >> clen; )
+ huff[code+ ++j] = clen << 8 | i;
+ }
+ get2();
+}
+
+void CLASS foveon_dp_load_raw()
+{
+ unsigned c, roff[4], row, col, diff;
+ ushort huff[512], vpred[2][2], hpred[2];
+
+ fseek (ifp, 8, SEEK_CUR);
+ foveon_huff (huff);
+ roff[0] = 48;
+ FORC3 roff[c+1] = -(-(roff[c] + get4()) & -16);
+ FORC3 {
+ fseek (ifp, data_offset+roff[c], SEEK_SET);
+ getbits(-1);
+ vpred[0][0] = vpred[0][1] = vpred[1][0] = vpred[1][1] = 512;
+ for (row=0; row < height; row++) {
+ for (col=0; col < width; col++) {
+ diff = ljpeg_diff(huff);
+ if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+ else hpred[col & 1] += diff;
+ image[row*width+col][c] = hpred[col & 1];
+ }
+ }
+ }
+}
+
+void CLASS foveon_load_camf()
+{
+ unsigned type, wide, high, i, j, row, col, diff;
+ ushort huff[258], vpred[2][2] = {{512,512},{512,512}}, hpred[2];
+
+ fseek (ifp, meta_offset, SEEK_SET);
+ type = get4(); get4(); get4();
+ wide = get4();
+ high = get4();
+ if (type == 2) {
+ fread (meta_data, 1, meta_length, ifp);
+ for (i=0; i < meta_length; i++) {
+ high = (high * 1597 + 51749) % 244944;
+ wide = high * (INT64) 301593171 >> 24;
+ meta_data[i] ^= ((((high << 8) - wide) >> 1) + wide) >> 17;
+ }
+ } else if (type == 4) {
+ free (meta_data);
+ meta_data = (char *) malloc (meta_length = wide*high*3/2);
+ merror (meta_data, "foveon_load_camf()");
+ foveon_huff (huff);
+ get4();
+ getbits(-1);
+ for (j=row=0; row < high; row++) {
+ for (col=0; col < wide; col++) {
+ diff = ljpeg_diff(huff);
+ if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+ else hpred[col & 1] += diff;
+ if (col & 1) {
+ meta_data[j++] = hpred[0] >> 4;
+ meta_data[j++] = hpred[0] << 4 | hpred[1] >> 8;
+ meta_data[j++] = hpred[1];
+ }
+ }
+ }
+ } else
+ fprintf (stderr,_("%s has unknown CAMF type %d.\n"), ifname, type);
}
const char * CLASS foveon_camf_param (const char *block, const char *param)
@@ -2922,6 +3287,7 @@ int CLASS foveon_fixed (void *ptr, int size, const char *name)
void *dp;
unsigned dim[3];
+ if (!name) return 0;
dp = foveon_camf_matrix (dim, name);
if (!dp) return 0;
memcpy (ptr, dp, size*4);
@@ -3002,6 +3368,7 @@ void CLASS foveon_interpolate()
if (verbose)
fprintf (stderr,_("Foveon interpolation...\n"));
+ foveon_load_camf();
foveon_fixed (dscr, 4, "DarkShieldColRange");
foveon_fixed (ppm[0][0], 27, "PostPolyMatrix");
foveon_fixed (satlev, 3, "SaturationLevel");
@@ -3010,9 +3377,9 @@ void CLASS foveon_interpolate()
foveon_fixed (chroma_dq, 3, "ChromaDQ");
foveon_fixed (color_dq, 3,
foveon_camf_param ("IncludeBlocks", "ColorDQ") ?
- "ColorDQ" : "ColorDTQCamRGB");
+ "ColorDQ" : "ColorDQCamRGB");
if (foveon_camf_param ("IncludeBlocks", "ColumnFilter"))
- foveon_fixed (&cfilt, 1, "ColumnFilter");
+ foveon_fixed (&cfilt, 1, "ColumnFilter");
memset (ddft, 0, sizeof ddft);
if (!foveon_camf_param ("IncludeBlocks", "DarkDrift")
@@ -3076,10 +3443,10 @@ void CLASS foveon_interpolate()
black = (float (*)[3]) calloc (height, sizeof *black);
for (row=0; row < height; row++) {
for (i=0; i < 6; i++)
- ddft[0][0][i] = ddft[1][0][i] +
- row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
+ ((float *)ddft[0])[i] = ((float *)ddft[1])[i] +
+ row / (height-1.0) * (((float *)ddft[2])[i] - ((float *)ddft[1])[i]);
FORC3 black[row][c] =
- ( foveon_avg (image[row*width]+c, dscr[0], cfilt) +
+ ( foveon_avg (image[row*width]+c, dscr[0], cfilt) +
foveon_avg (image[row*width]+c, dscr[1], cfilt) * 3
- ddft[0][c][0] ) / 4 - ddft[0][c][1];
}
@@ -3122,8 +3489,8 @@ void CLASS foveon_interpolate()
for (row=0; row < height; row++) {
for (i=0; i < 6; i++)
- ddft[0][0][i] = ddft[1][0][i] +
- row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
+ ((float *)ddft[0])[i] = ((float *)ddft[1])[i] +
+ row / (height-1.0) * (((float *)ddft[2])[i] - ((float *)ddft[1])[i]);
pix = image[row*width];
memcpy (prev, pix, sizeof prev);
frow = row / (height-1.0) * (dim[2]-1);
@@ -3162,7 +3529,7 @@ void CLASS foveon_interpolate()
free (sgrow);
free (sgain);
- if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) {
+ if ((badpix = (unsigned *) foveon_camf_matrix (dim, "BadPixels"))) {
for (i=0; i < dim[0]; i++) {
col = (badpix[i] >> 8 & 0xfff) - keep[0];
row = (badpix[i] >> 20 ) - keep[1];
@@ -3304,7 +3671,7 @@ void CLASS foveon_interpolate()
}
/* Smooth the image bottom-to-top and save at 1/4 scale */
- shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *shrink);
+ shrink = (short (*)[3]) calloc ((height/4), (width/4)*sizeof *shrink);
merror (shrink, "foveon_interpolate()");
for (row = height/4; row--; )
for (col=0; col < width/4; col++) {
@@ -3380,19 +3747,106 @@ void CLASS foveon_interpolate()
/* RESTRICTED code ends here */
+void CLASS crop_masked_pixels()
+{
+ int row, col;
+ unsigned r, c, m, mblack[8], zero, val;
+
+ if (load_raw == &CLASS phase_one_load_raw ||
+ load_raw == &CLASS phase_one_load_raw_c)
+ phase_one_correct();
+ if (fuji_width) {
+ for (row=0; row < raw_height-top_margin*2; row++) {
+ for (col=0; col < fuji_width << !fuji_layout; col++) {
+ if (fuji_layout) {
+ r = fuji_width - 1 - col + (row >> 1);
+ c = col + ((row+1) >> 1);
+ } else {
+ r = fuji_width - 1 + row - (col >> 1);
+ c = row + ((col+1) >> 1);
+ }
+ if (r < height && c < width)
+ BAYER(r,c) = RAW(row+top_margin,col+left_margin);
+ }
+ }
+ } else {
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ BAYER2(row,col) = RAW(row+top_margin,col+left_margin);
+ }
+ if (mask[0][3] > 0) goto mask_set;
+ if (load_raw == &CLASS canon_load_raw ||
+ load_raw == &CLASS lossless_jpeg_load_raw) {
+ mask[0][1] = mask[1][1] += 2;
+ mask[0][3] -= 2;
+ goto sides;
+ }
+ if (load_raw == &CLASS canon_600_load_raw ||
+ load_raw == &CLASS sony_load_raw ||
+ (load_raw == &CLASS eight_bit_load_raw && strncmp(model,"DC2",3)) ||
+ load_raw == &CLASS kodak_262_load_raw ||
+ (load_raw == &CLASS packed_load_raw && (load_flags & 256))) {
+sides:
+ mask[0][0] = mask[1][0] = top_margin;
+ mask[0][2] = mask[1][2] = top_margin+height;
+ mask[0][3] += left_margin;
+ mask[1][1] += left_margin+width;
+ mask[1][3] += raw_width;
+ }
+ if (load_raw == &CLASS nokia_load_raw) {
+ mask[0][2] = top_margin;
+ mask[0][3] = width;
+ }
+mask_set:
+ memset (mblack, 0, sizeof mblack);
+ for (zero=m=0; m < 8; m++)
+ for (row=MAX(mask[m][0],0); row < MIN(mask[m][2],raw_height); row++)
+ for (col=MAX(mask[m][1],0); col < MIN(mask[m][3],raw_width); col++) {
+ c = FC(row-top_margin,col-left_margin);
+ mblack[c] += val = RAW(row,col);
+ mblack[4+c]++;
+ zero += !val;
+ }
+ if (load_raw == &CLASS canon_600_load_raw && width < raw_width) {
+ black = (mblack[0]+mblack[1]+mblack[2]+mblack[3]) /
+ (mblack[4]+mblack[5]+mblack[6]+mblack[7]) - 4;
+ canon_600_correct();
+ } else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7]) {
+ FORC4 cblack[c] = mblack[c] / mblack[4+c];
+ cblack[4] = cblack[5] = cblack[6] = 0;
+ }
+}
+
+void CLASS remove_zeroes()
+{
+ unsigned row, col, tot, n, r, c;
+
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ if (BAYER(row,col) == 0) {
+ tot = n = 0;
+ for (r = row-2; r <= row+2; r++)
+ for (c = col-2; c <= col+2; c++)
+ if (r < height && c < width &&
+ FC(r,c) == FC(row,col) && BAYER(r,c))
+ tot += (n++,BAYER(r,c));
+ if (n) BAYER(row,col) = tot/n;
+ }
+}
+
/*
Seach from the current directory up to the root looking for
a ".badpixels" file, and fix those pixels now.
*/
-void CLASS bad_pixels (char *fname)
+void CLASS bad_pixels (const char *cfname)
{
FILE *fp=0;
- char *cp, line[128];
+ char *fname, *cp, line[128];
int len, time, row, col, r, c, rad, tot, n, fixed=0;
if (!filters) return;
- if (fname)
- fp = fopen (fname, "r");
+ if (cfname)
+ fp = fopen (cfname, "r");
else {
for (len=32 ; ; len *= 2) {
fname = (char *) malloc (len);
@@ -3428,7 +3882,7 @@ void CLASS bad_pixels (char *fname)
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) && fc(r,c) == fc(row,col)) {
+ (r != row || c != col) && fcol(r,c) == fcol(row,col)) {
tot += BAYER2(r,c);
n++;
}
@@ -3443,7 +3897,7 @@ void CLASS bad_pixels (char *fname)
fclose (fp);
}
-void CLASS subtract (char *fname)
+void CLASS subtract (const char *fname)
{
FILE *fp;
int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col;
@@ -3480,9 +3934,46 @@ void CLASS subtract (char *fname)
BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0);
}
free (pixel);
+ fclose (fp);
+ memset (cblack, 0, sizeof cblack);
black = 0;
}
+void CLASS gamma_curve (double pwr, double ts, int mode, int imax)
+{
+ int i;
+ double g[6], bnd[2]={0,0}, r;
+
+ g[0] = pwr;
+ g[1] = ts;
+ g[2] = g[3] = g[4] = 0;
+ bnd[g[1] >= 1] = 1;
+ if (g[1] && (g[1]-1)*(g[0]-1) <= 0) {
+ for (i=0; i < 48; i++) {
+ g[2] = (bnd[0] + bnd[1])/2;
+ if (g[0]) bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2];
+ else bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2];
+ }
+ g[3] = g[2] / g[1];
+ if (g[0]) g[4] = g[2] * (1/g[0] - 1);
+ }
+ if (g[0]) g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) +
+ (1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1;
+ else g[5] = 1 / (g[1]*SQR(g[3])/2 + 1
+ - g[2] - g[3] - g[2]*g[3]*(log(g[3]) - 1)) - 1;
+ if (!mode--) {
+ memcpy (gamm, g, sizeof gamm);
+ return;
+ }
+ for (i=0; i < 0x10000; i++) {
+ curve[i] = 0xffff;
+ if ((r = (double) i / imax) < 1)
+ curve[i] = 0x10000 * ( mode
+ ? (r < g[3] ? r*g[1] : (g[0] ? pow( r,g[0])*(1+g[4])-g[4] : log(r)*g[2]+1))
+ : (r < g[2] ? r/g[1] : (g[0] ? pow((r+g[4])/(1+g[4]),1/g[0]) : exp((r-1)/g[2]))));
+ }
+}
+
void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
{
double work[3][6], num;
@@ -3512,7 +4003,7 @@ void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
out[i][j] += work[j][k+3] * in[i][k];
}
-void CLASS cam_xyz_coeff (double cam_xyz[4][3])
+void CLASS cam_xyz_coeff (float rgb_cam[3][4], double cam_xyz[4][3])
{
double cam_rgb[4][3], inverse[4][3], num;
int i, j, k;
@@ -3530,7 +4021,7 @@ void CLASS cam_xyz_coeff (double cam_xyz[4][3])
pre_mul[i] = 1 / num;
}
pseudoinverse (cam_rgb, inverse, colors);
- for (raw_color = i=0; i < 3; i++)
+ for (i=0; i < 3; i++)
for (j=0; j < colors; j++)
rgb_cam[i][j] = inverse[j][i];
}
@@ -3541,31 +4032,7 @@ void CLASS colorcheck()
#define NSQ 24
// Coordinates of the GretagMacbeth ColorChecker squares
// width, height, 1st_column, 1st_row
- static const int cut[NSQ][4] = {
- { 241, 231, 234, 274 },
- { 251, 235, 534, 274 },
- { 255, 239, 838, 272 },
- { 255, 240, 1146, 274 },
- { 251, 237, 1452, 278 },
- { 243, 238, 1758, 288 },
- { 253, 253, 218, 558 },
- { 255, 249, 524, 562 },
- { 261, 253, 830, 562 },
- { 260, 255, 1144, 564 },
- { 261, 255, 1450, 566 },
- { 247, 247, 1764, 576 },
- { 255, 251, 212, 862 },
- { 259, 259, 518, 862 },
- { 263, 261, 826, 864 },
- { 265, 263, 1138, 866 },
- { 265, 257, 1450, 872 },
- { 257, 255, 1762, 874 },
- { 257, 253, 212, 1164 },
- { 262, 251, 516, 1172 },
- { 263, 257, 826, 1172 },
- { 263, 255, 1136, 1176 },
- { 255, 252, 1452, 1182 },
- { 257, 253, 1760, 1180 } };
+ int cut[NSQ][4]; // you must set these
// ColorChecker Chart under 6500-kelvin illumination
static const double gmb_xyY[NSQ][3] = {
{ 0.400, 0.350, 10.1 }, // Dark Skin
@@ -3593,8 +4060,8 @@ void CLASS colorcheck()
{ 0.310, 0.316, 9.0 }, // Neutral 3.5
{ 0.310, 0.316, 3.1 } }; // Black
double gmb_cam[NSQ][4], gmb_xyz[NSQ][3];
- double inverse[NSQ][3], cam_xyz[4][3], num;
- int c, i, j, k, sq, row, col, count[4];
+ double inverse[NSQ][3], cam_xyz[4][3], balance[4], num;
+ int c, i, j, k, sq, row, col, pass, count[4];
memset (gmb_cam, 0, sizeof gmb_cam);
for (sq=0; sq < NSQ; sq++) {
@@ -3603,7 +4070,8 @@ void CLASS colorcheck()
for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) {
c = FC(row,col);
if (c >= colors) c -= 2;
- gmb_cam[sq][c] += BAYER(row,col);
+ gmb_cam[sq][c] += BAYER2(row,col);
+ BAYER2(row,col) = black + (BAYER2(row,col)-black)/2;
count[c]++;
}
FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black;
@@ -3613,11 +4081,16 @@ void CLASS colorcheck()
(1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1];
}
pseudoinverse (gmb_xyz, inverse, NSQ);
- for (i=0; i < colors; i++)
- for (j=0; j < 3; j++)
- for (cam_xyz[i][j] = k=0; k < NSQ; k++)
- cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j];
- cam_xyz_coeff (cam_xyz);
+ for (pass=0; pass < 2; pass++) {
+ for (raw_color = i=0; i < colors; i++)
+ for (j=0; j < 3; j++)
+ for (cam_xyz[i][j] = k=0; k < NSQ; k++)
+ cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j];
+ cam_xyz_coeff (rgb_cam, cam_xyz);
+ FORCC balance[c] = pre_mul[c] * gmb_cam[20][c];
+ for (sq=0; sq < NSQ; sq++)
+ FORCC gmb_cam[sq][c] *= balance[c];
+ }
if (verbose) {
printf (" { \"%s %s\", %d,\n\t{", make, model, black);
num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]);
@@ -3643,7 +4116,7 @@ void CLASS hat_transform (float *temp, float *base, int st, int size, int sc)
void CLASS wavelet_denoise()
{
float *fimg=0, *temp, thold, mul[2], avg, diff;
- int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
+ int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast, blk[2];
ushort *window[4];
static const float noise[] =
{ 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
@@ -3653,6 +4126,7 @@ void CLASS wavelet_denoise()
while (maximum << scale < 0x10000) scale++;
maximum <<= --scale;
black <<= scale;
+ FORC4 cblack[c] <<= scale;
if ((size = iheight*iwidth) < 0x15550000)
fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
merror (fimg, "wavelet_denoise()");
@@ -3660,12 +4134,12 @@ void CLASS wavelet_denoise()
if ((nc = colors) == 3 && filters) nc++;
FORC(nc) { /* denoise R,G1,B,G3 individually */
for (i=0; i < size; i++)
- fimg[i] = sqrt((unsigned) (image[i][c] << (scale+16)));
+ fimg[i] = 256 * sqrt(image[i][c] << scale);
for (hpass=lev=0; lev < 5; lev++) {
lpass = size*((lev & 1)+1);
for (row=0; row < iheight; row++) {
hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
- for (col=0; col < iwidth; col++)
+ for (col=0; col < iwidth; col++)
fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
}
for (col=0; col < iwidth; col++) {
@@ -3687,8 +4161,10 @@ void CLASS wavelet_denoise()
image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
}
if (filters && colors == 3) { /* pull G1 and G3 closer together */
- for (row=0; row < 2; row++)
+ for (row=0; row < 2; row++) {
mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
+ blk[row] = cblack[FC(row,0) | 1];
+ }
for (i=0; i < 4; i++)
window[i] = (ushort *) fimg + width*i;
for (wlast=-1, row=1; row < height-1; row++) {
@@ -3701,8 +4177,8 @@ void CLASS wavelet_denoise()
thold = threshold/512;
for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
avg = ( window[0][col-1] + window[0][col+1] +
- window[2][col-1] + window[2][col+1] - black*4 )
- * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
+ window[2][col-1] + window[2][col+1] - blk[~row & 1]*4 )
+ * mul[row & 1] + (window[1][col] + blk[row & 1]) * 0.5;
avg = avg < 0 ? 0 : sqrt(avg);
diff = sqrt(BAYER(row,col)) - avg;
if (diff < -thold) diff += thold;
@@ -3736,12 +4212,12 @@ void CLASS scale_colors()
for (x=col; x < col+8 && x < right; x++)
FORC4 {
if (filters) {
- c = FC(y,x);
- val = BAYER(y,x);
+ c = fcol(y,x);
+ val = BAYER2(y,x);
} else
val = image[y*width+x][c];
if (val > maximum-25) goto skip_block;
- if ((val -= black) < 0) val = 0;
+ if ((val -= cblack[c]) < 0) val = 0;
sum[c] += val;
sum[c+4]++;
if (filters) break;
@@ -3756,7 +4232,7 @@ skip_block: ;
for (row=0; row < 8; row++)
for (col=0; col < 8; col++) {
c = FC(row,col);
- if ((val = white[row][col] - black) > 0)
+ if ((val = white[row][col] - cblack[c]) > 0)
sum[c] += val;
sum[c+4]++;
}
@@ -3767,6 +4243,7 @@ skip_block: ;
else
fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname);
}
+ if (pre_mul[1] == 0) pre_mul[1] = 1;
if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
dark = black;
sat = maximum;
@@ -3786,13 +4263,20 @@ skip_block: ;
FORC4 fprintf (stderr, " %f", pre_mul[c]);
fputc ('\n', stderr);
}
+ 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;
for (i=0; i < size*4; i++) {
- val = image[0][i];
- if (!val) continue;
- val -= black;
+ if (!(val = ((ushort *)image)[i])) continue;
+ if (cblack[4] && cblack[5])
+ val -= cblack[6 + i/4 / iwidth % cblack[4] * cblack[5] +
+ i/4 % iwidth % cblack[5]];
+ val -= cblack[i & 3];
val *= scale_mul[i & 3];
- image[0][i] = CLIP(val);
+ ((ushort *)image)[i] = CLIP(val);
}
if ((aber[0] != 1 || aber[2] != 1) && colors == 3) {
if (verbose)
@@ -3831,12 +4315,24 @@ void CLASS pre_interpolate()
if (half_size) {
height = iheight;
width = iwidth;
+ if (filters == 9) {
+ for (row=0; row < 3; row++)
+ for (col=1; col < 4; col++)
+ if (!(image[row*width+col][0] | image[row*width+col][2]))
+ goto break2; break2:
+ for ( ; row < height; row+=3)
+ for (col=(col-1)%3+1; col < width-1; col+=3) {
+ img = image + row*width+col;
+ for (c=0; c < 3; c+=2)
+ img[0][c] = (img[-1][c] + img[1][c]) >> 1;
+ }
+ }
} else {
- img = (ushort (*)[4]) calloc (height*width, sizeof *img);
- merror (img, "unshrink()");
+ img = (ushort (*)[4]) calloc (height, width*sizeof *img);
+ merror (img, "pre_interpolate()");
for (row=0; row < height; row++)
for (col=0; col < width; col++) {
- c = fc(row,col);
+ c = fcol(row,col);
img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c];
}
free (image);
@@ -3844,8 +4340,9 @@ void CLASS pre_interpolate()
shrink = 0;
}
}
- if (filters && colors == 3) {
- if ((mix_green = four_color_rgb)) colors++;
+ if (filters > 1000 && colors == 3) {
+ mix_green = four_color_rgb ^ half_size;
+ if (four_color_rgb | half_size) colors++;
else {
for (row = FC(1,0) >> 1; row < height; row+=2)
for (col = FC(row,1) & 1; col < width; col+=2)
@@ -3868,11 +4365,11 @@ void CLASS border_interpolate (int border)
for (y=row-1; y != row+2; y++)
for (x=col-1; x != col+2; x++)
if (y < height && x < width) {
- f = fc(y,x);
+ f = fcol(y,x);
sum[f] += image[y*width+x][f];
sum[f+4]++;
}
- f = fc(row,col);
+ f = fcol(row,col);
FORCC if (c != f && sum[c+4])
image[row*width+col][c] = sum[c] / sum[c+4];
}
@@ -3880,29 +4377,31 @@ void CLASS border_interpolate (int border)
void CLASS lin_interpolate()
{
- int code[16][16][32], *ip, sum[4];
- int c, i, x, y, row, col, shift, color;
+ int code[16][16][32], size=16, *ip, sum[4];
+ int f, c, i, x, y, row, col, shift, color;
ushort *pix;
if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
-
+ if (filters == 9) size = 6;
border_interpolate(1);
- for (row=0; row < 16; row++)
- for (col=0; col < 16; col++) {
- ip = code[row][col];
+ for (row=0; row < size; row++)
+ for (col=0; col < size; col++) {
+ ip = code[row][col]+1;
+ f = fcol(row,col);
memset (sum, 0, sizeof sum);
for (y=-1; y <= 1; y++)
for (x=-1; x <= 1; x++) {
shift = (y==0) + (x==0);
- if (shift == 2) continue;
- color = fc(row+y,col+x);
+ color = fcol(row+y,col+x);
+ if (color == f) continue;
*ip++ = (width*y + x)*4 + color;
*ip++ = shift;
*ip++ = color;
sum[color] += 1 << shift;
}
+ code[row][col][0] = (ip - code[row][col]) / 3;
FORCC
- if (c != fc(row,col)) {
+ if (c != f) {
*ip++ = c;
*ip++ = 256 / sum[c];
}
@@ -3910,9 +4409,9 @@ void CLASS lin_interpolate()
for (row=1; row < height-1; row++)
for (col=1; col < width-1; col++) {
pix = image[row*width+col];
- ip = code[row & 15][col & 15];
+ ip = code[row % size][col % size];
memset (sum, 0, sizeof sum);
- for (i=8; i--; ip+=3)
+ for (i=*ip++; i--; ip+=3)
sum[ip[2]] += pix[ip[0]] << ip[1];
for (i=colors; --i; ip+=2)
pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
@@ -3924,66 +4423,60 @@ void CLASS lin_interpolate()
"Interpolation using a Threshold-based variable number of gradients"
- described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html
+ described in http://scien.stanford.edu/pages/labsite/1999/psych221/projects/99/tingchen/algodep/vargra.html
I've extended the basic idea to work with non-Bayer filter arrays.
Gradients are numbered clockwise from NW=0 to W=7.
*/
void CLASS vng_interpolate()
{
- struct interpolate_terms {
- signed char y1, x1, y2, x2, weight;
- unsigned char grads;
- };
- static const struct interpolate_terms terms[] = {
- {-2,-2,+0,-1,0,0x01}, {-2,-2,+0,+0,1,0x01}, {-2,-1,-1,+0,0,0x01},
- {-2,-1,+0,-1,0,0x02}, {-2,-1,+0,+0,0,0x03}, {-2,-1,+0,+1,1,0x01},
- {-2,+0,+0,-1,0,0x06}, {-2,+0,+0,+0,1,0x02}, {-2,+0,+0,+1,0,0x03},
- {-2,+1,-1,+0,0,0x04}, {-2,+1,+0,-1,1,0x04}, {-2,+1,+0,+0,0,0x06},
- {-2,+1,+0,+1,0,0x02}, {-2,+2,+0,+0,1,0x04}, {-2,+2,+0,+1,0,0x04},
- {-1,-2,-1,+0,0,0x80}, {-1,-2,+0,-1,0,0x01}, {-1,-2,+1,-1,0,0x01},
- {-1,-2,+1,+0,1,0x01}, {-1,-1,-1,+1,0,0x88}, {-1,-1,+1,-2,0,0x40},
- {-1,-1,+1,-1,0,0x22}, {-1,-1,+1,+0,0,0x33}, {-1,-1,+1,+1,1,0x11},
- {-1,+0,-1,+2,0,0x08}, {-1,+0,+0,-1,0,0x44}, {-1,+0,+0,+1,0,0x11},
- {-1,+0,+1,-2,1,0x40}, {-1,+0,+1,-1,0,0x66}, {-1,+0,+1,+0,1,0x22},
- {-1,+0,+1,+1,0,0x33}, {-1,+0,+1,+2,1,0x10}, {-1,+1,+1,-1,1,0x44},
- {-1,+1,+1,+0,0,0x66}, {-1,+1,+1,+1,0,0x22}, {-1,+1,+1,+2,0,0x10},
- {-1,+2,+0,+1,0,0x04}, {-1,+2,+1,+0,1,0x04}, {-1,+2,+1,+1,0,0x04},
- {+0,-2,+0,+0,1,0x80}, {+0,-1,+0,+1,1,0x88}, {+0,-1,+1,-2,0,0x40},
- {+0,-1,+1,+0,0,0x11}, {+0,-1,+2,-2,0,0x40}, {+0,-1,+2,-1,0,0x20},
- {+0,-1,+2,+0,0,0x30}, {+0,-1,+2,+1,1,0x10}, {+0,+0,+0,+2,1,0x08},
- {+0,+0,+2,-2,1,0x40}, {+0,+0,+2,-1,0,0x60}, {+0,+0,+2,+0,1,0x20},
- {+0,+0,+2,+1,0,0x30}, {+0,+0,+2,+2,1,0x10}, {+0,+1,+1,+0,0,0x44},
- {+0,+1,+1,+2,0,0x10}, {+0,+1,+2,-1,1,0x40}, {+0,+1,+2,+0,0,0x60},
- {+0,+1,+2,+1,0,0x20}, {+0,+1,+2,+2,0,0x10}, {+1,-2,+1,+0,0,0x80},
- {+1,-1,+1,+1,0,0x88}, {+1,+0,+1,+2,0,0x08}, {+1,+0,+2,-1,0,0x40},
- {+1,+0,+2,+1,0,0x10}
- };
- const struct interpolate_terms *cpt;
- signed char *cp;
- signed char chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
+ static const signed char *cp, terms[] = {
+ -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
+ -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
+ -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
+ -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
+ -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
+ -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
+ -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
+ -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
+ -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
+ -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
+ -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
+ -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
+ -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
+ +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
+ +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
+ +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
+ +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
+ +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
+ +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
+ +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
+ +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
+ +1,+0,+2,+1,0,0x10
+ }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
ushort (*brow[5])[4], *pix;
- int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
+ int prow=8, pcol=2, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
int g, diff, thold, num, c;
lin_interpolate();
if (verbose) fprintf (stderr,_("VNG interpolation...\n"));
- if (filters == 1) prow = pcol = 15;
- ip = (int *) calloc ((prow+1)*(pcol+1), 1280);
+ if (filters == 1) prow = pcol = 16;
+ if (filters == 9) prow = pcol = 6;
+ ip = (int *) calloc (prow*pcol, 1280);
merror (ip, "vng_interpolate()");
- for (row=0; row <= prow; row++) /* Precalculate for VNG */
- for (col=0; col <= pcol; col++) {
+ for (row=0; row < prow; row++) /* Precalculate for VNG */
+ for (col=0; col < pcol; col++) {
code[row][col] = ip;
- for (cpt=&terms[0], t=0; t < 64, cpt = &terms[t]; t++) {
- y1 = cpt->y1; x1 = cpt->x1;
- y2 = cpt->y2; x2 = cpt->x2;
- weight = cpt->weight;
- grads = cpt->grads;
- color = fc(row+y1,col+x1);
- if (fc(row+y2,col+x2) != color) continue;
- diag = (fc(row,col+1) == color && fc(row+1,col) == color) ? 2:1;
+ for (cp=terms, t=0; t < 64; t++) {
+ y1 = *cp++; x1 = *cp++;
+ y2 = *cp++; x2 = *cp++;
+ weight = *cp++;
+ grads = *cp++;
+ color = fcol(row+y1,col+x1);
+ if (fcol(row+y2,col+x2) != color) continue;
+ diag = (fcol(row,col+1) == color && fcol(row+1,col) == color) ? 2:1;
if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
*ip++ = (y1*width + x1)*4 + color;
*ip++ = (y2*width + x2)*4 + color;
@@ -3996,8 +4489,8 @@ void CLASS vng_interpolate()
for (cp=chood, g=0; g < 8; g++) {
y = *cp++; x = *cp++;
*ip++ = (y*width + x) * 4;
- color = fc(row,col);
- if (fc(row+y,col+x) != color && fc(row+y*2,col+x*2) == color)
+ color = fcol(row,col);
+ if (fcol(row+y,col+x) != color && fcol(row+y*2,col+x*2) == color)
*ip++ = (y*width + x) * 8 + color;
else
*ip++ = 0;
@@ -4010,7 +4503,7 @@ void CLASS vng_interpolate()
for (row=2; row < height-2; row++) { /* Do VNG interpolation */
for (col=2; col < width-2; col++) {
pix = image[row*width+col];
- ip = code[row & prow][col & pcol];
+ ip = code[row % prow][col % pcol];
memset (gval, 0, sizeof gval);
while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */
diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
@@ -4033,7 +4526,7 @@ void CLASS vng_interpolate()
}
thold = gmin + (gmax >> 1);
memset (sum, 0, sizeof sum);
- color = fc(row,col);
+ color = fcol(row,col);
for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */
if (gval[g] <= thold) {
FORCC
@@ -4067,9 +4560,8 @@ void CLASS vng_interpolate()
*/
void CLASS ppg_interpolate()
{
- int gr[4], dir[5] = { 1, width, -1, -width, 1 };
- int row, col, avg, diff[2], guess[2], c, d, i;
- static const short sort[] = { 0,2,1,3,0,1,2,3 };
+ int dir[5] = { 1, width, -1, -width, 1 };
+ int row, col, diff[2], guess[2], c, d, i;
ushort (*pix)[4];
border_interpolate(3);
@@ -4079,20 +4571,6 @@ void CLASS ppg_interpolate()
for (row=3; row < height-3; row++)
for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) {
pix = image + row*width+col;
- for (avg=i=0; i < 4; i++)
- avg += gr[i] = pix[dir[i]][1] << 2;
- avg >>= 2;
- for (i=0; i < 8; i+=2)
- if (gr[sort[i]] > gr[sort[i+1]])
- SWAP(gr[sort[i]],gr[sort[i+1]])
- for (d=0; d < 4; d++) {
- for (i=-2; i < 2; i++)
- if (pix[i*dir[d] + (i+1)*dir[d+1]][1] <= avg) break;
- if (i == 2) {
- pix[0][1] = (gr[1]+gr[2]) >> 3;
- goto next_pixel;
- }
- }
for (i=0; (d=dir[i]) > 0; i++) {
guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
- pix[-2*d][c] - pix[2*d][c];
@@ -4104,7 +4582,6 @@ void CLASS ppg_interpolate()
}
d = dir[i = diff[0] > diff[1]];
pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
-next_pixel: ;
}
/* Calculate red and blue for each green pixel: */
for (row=1; row < height-1; row++)
@@ -4132,36 +4609,288 @@ next_pixel: ;
}
}
+void CLASS cielab (ushort rgb[3], short lab[3])
+{
+ int c, i, j, k;
+ float r, xyz[3];
+ static float cbrt[0x10000], xyz_cam[3][4];
+
+ if (!rgb) {
+ for (i=0; i < 0x10000; i++) {
+ r = i / 65535.0;
+ cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0;
+ }
+ for (i=0; i < 3; i++)
+ for (j=0; j < colors; j++)
+ for (xyz_cam[i][j] = k=0; k < 3; k++)
+ xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
+ return;
+ }
+ xyz[0] = xyz[1] = xyz[2] = 0.5;
+ FORCC {
+ xyz[0] += xyz_cam[0][c] * rgb[c];
+ xyz[1] += xyz_cam[1][c] * rgb[c];
+ xyz[2] += xyz_cam[2][c] * rgb[c];
+ }
+ xyz[0] = cbrt[CLIP((int) xyz[0])];
+ xyz[1] = cbrt[CLIP((int) xyz[1])];
+ xyz[2] = cbrt[CLIP((int) xyz[2])];
+ lab[0] = 64 * (116 * xyz[1] - 16);
+ lab[1] = 64 * 500 * (xyz[0] - xyz[1]);
+ lab[2] = 64 * 200 * (xyz[1] - xyz[2]);
+}
+
+#define TS 512 /* Tile Size */
+#define fcol(row,col) xtrans[(row+6) % 6][(col+6) % 6]
+
+/*
+ Frank Markesteijn's algorithm for Fuji X-Trans sensors
+ */
+void CLASS xtrans_interpolate (int passes)
+{
+ int c, d, f, g, h, i, v, ng, row, col, top, left, mrow, mcol;
+ int val, ndir, pass, hm[8], avg[4], color[3][8];
+ static const short orth[12] = { 1,0,0,1,-1,0,0,-1,1,0,0,1 },
+ patt[2][16] = { { 0,1,0,-1,2,0,-1,0,1,1,1,-1,0,0,0,0 },
+ { 0,1,0,-2,1,0,-2,0,1,1,-2,-2,1,-1,-1,1 } },
+ dir[4] = { 1,TS,TS+1,TS-1 };
+ short allhex[3][3][2][8], *hex;
+ ushort min, max, sgrow, sgcol;
+ ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4];
+ short (*lab) [TS][3], (*lix)[3];
+ float (*drv)[TS][TS], diff[6], tr;
+ char (*homo)[TS][TS], *buffer;
+
+ if (verbose)
+ fprintf (stderr,_("%d-pass X-Trans interpolation...\n"), passes);
+
+ cielab (0,0);
+ ndir = 4 << (passes > 1);
+ buffer = (char *) malloc (TS*TS*(ndir*11+6));
+ merror (buffer, "xtrans_interpolate()");
+ rgb = (ushort(*)[TS][TS][3]) buffer;
+ lab = (short (*) [TS][3])(buffer + TS*TS*(ndir*6));
+ drv = (float (*)[TS][TS]) (buffer + TS*TS*(ndir*6+6));
+ homo = (char (*)[TS][TS]) (buffer + TS*TS*(ndir*10+6));
+
+/* Map a green hexagon around each non-green pixel and vice versa: */
+ for (row=0; row < 3; row++)
+ for (col=0; col < 3; col++)
+ for (ng=d=0; d < 10; d+=2) {
+ g = fcol(row,col) == 1;
+ if (fcol(row+orth[d],col+orth[d+2]) == 1) ng=0; else ng++;
+ if (ng == 4) { sgrow = row; sgcol = col; }
+ if (ng == g+1) FORC(8) {
+ v = orth[d ]*patt[g][c*2] + orth[d+1]*patt[g][c*2+1];
+ h = orth[d+2]*patt[g][c*2] + orth[d+3]*patt[g][c*2+1];
+ allhex[row][col][0][c^(g*2 & d)] = h + v*width;
+ allhex[row][col][1][c^(g*2 & d)] = h + v*TS;
+ }
+ }
+
+/* Set green1 and green3 to the minimum and maximum allowed values: */
+ for (row=2; row < height-2; row++)
+ for (min=~(max=0), col=2; col < width-2; col++) {
+ if (fcol(row,col) == 1 && (min=~(max=0))) continue;
+ pix = image + row*width + col;
+ hex = allhex[row % 3][col % 3][0];
+ if (!max) FORC(6) {
+ val = pix[hex[c]][1];
+ if (min > val) min = val;
+ if (max < val) max = val;
+ }
+ pix[0][1] = min;
+ pix[0][3] = max;
+ switch ((row-sgrow) % 3) {
+ case 1: if (row < height-3) { row++; col--; } break;
+ case 2: if ((min=~(max=0)) && (col+=2) < width-3 && row > 2) row--;
+ }
+ }
+
+ for (top=3; top < height-19; top += TS-16)
+ for (left=3; left < width-19; left += TS-16) {
+ mrow = MIN (top+TS, height-3);
+ mcol = MIN (left+TS, width-3);
+ for (row=top; row < mrow; row++)
+ for (col=left; col < mcol; col++)
+ memcpy (rgb[0][row-top][col-left], image[row*width+col], 6);
+ FORC3 memcpy (rgb[c+1], rgb[0], sizeof *rgb);
+
+/* Interpolate green horizontally, vertically, and along both diagonals: */
+ for (row=top; row < mrow; row++)
+ for (col=left; col < mcol; col++) {
+ if ((f = fcol(row,col)) == 1) continue;
+ pix = image + row*width + col;
+ hex = allhex[row % 3][col % 3][0];
+ color[1][0] = 174 * (pix[ hex[1]][1] + pix[ hex[0]][1]) -
+ 46 * (pix[2*hex[1]][1] + pix[2*hex[0]][1]);
+ color[1][1] = 223 * pix[ hex[3]][1] + pix[ hex[2]][1] * 33 +
+ 92 * (pix[ 0 ][f] - pix[ -hex[2]][f]);
+ FORC(2) color[1][2+c] =
+ 164 * pix[hex[4+c]][1] + 92 * pix[-2*hex[4+c]][1] + 33 *
+ (2*pix[0][f] - pix[3*hex[4+c]][f] - pix[-3*hex[4+c]][f]);
+ FORC4 rgb[c^!((row-sgrow) % 3)][row-top][col-left][1] =
+ LIM(color[1][c] >> 8,pix[0][1],pix[0][3]);
+ }
+
+ for (pass=0; pass < passes; pass++) {
+ if (pass == 1)
+ memcpy (rgb+=4, buffer, 4*sizeof *rgb);
+
+/* Recalculate green from interpolated values of closer pixels: */
+ if (pass) {
+ for (row=top+2; row < mrow-2; row++)
+ for (col=left+2; col < mcol-2; col++) {
+ if ((f = fcol(row,col)) == 1) continue;
+ pix = image + row*width + col;
+ hex = allhex[row % 3][col % 3][1];
+ for (d=3; d < 6; d++) {
+ rix = &rgb[(d-2)^!((row-sgrow) % 3)][row-top][col-left];
+ val = rix[-2*hex[d]][1] + 2*rix[hex[d]][1]
+ - rix[-2*hex[d]][f] - 2*rix[hex[d]][f] + 3*rix[0][f];
+ rix[0][1] = LIM(val/3,pix[0][1],pix[0][3]);
+ }
+ }
+ }
+
+/* Interpolate red and blue values for solitary green pixels: */
+ for (row=(top-sgrow+4)/3*3+sgrow; row < mrow-2; row+=3)
+ for (col=(left-sgcol+4)/3*3+sgcol; col < mcol-2; col+=3) {
+ rix = &rgb[0][row-top][col-left];
+ h = fcol(row,col+1);
+ memset (diff, 0, sizeof diff);
+ for (i=1, d=0; d < 6; d++, i^=TS^1, h^=2) {
+ for (c=0; c < 2; c++, h^=2) {
+ g = 2*rix[0][1] - rix[i<<c][1] - rix[-i<<c][1];
+ color[h][d] = g + rix[i<<c][h] + rix[-i<<c][h];
+ if (d > 1)
+ diff[d] += SQR (rix[i<<c][1] - rix[-i<<c][1]
+ - rix[i<<c][h] + rix[-i<<c][h]) + SQR(g);
+ }
+ if (d > 1 && (d & 1))
+ if (diff[d-1] < diff[d])
+ FORC(2) color[c*2][d] = color[c*2][d-1];
+ if (d < 2 || (d & 1)) {
+ FORC(2) rix[0][c*2] = CLIP(color[c*2][d]/2);
+ rix += TS*TS;
+ }
+ }
+ }
+
+/* Interpolate red for blue pixels and vice versa: */
+ for (row=top+3; row < mrow-3; row++)
+ for (col=left+3; col < mcol-3; col++) {
+ if ((f = 2-fcol(row,col)) == 1) continue;
+ rix = &rgb[0][row-top][col-left];
+ c = (row-sgrow) % 3 ? TS:1;
+ h = 3 * (c ^ TS ^ 1);
+ for (d=0; d < 4; d++, rix += TS*TS) {
+ i = d > 1 || ((d ^ c) & 1) ||
+ ((ABS(rix[0][1]-rix[c][1])+ABS(rix[0][1]-rix[-c][1])) <
+ 2*(ABS(rix[0][1]-rix[h][1])+ABS(rix[0][1]-rix[-h][1]))) ? c:h;
+ rix[0][f] = CLIP((rix[i][f] + rix[-i][f] +
+ 2*rix[0][1] - rix[i][1] - rix[-i][1])/2);
+ }
+ }
+
+/* Fill in red and blue for 2x2 blocks of green: */
+ for (row=top+2; row < mrow-2; row++) if ((row-sgrow) % 3)
+ for (col=left+2; col < mcol-2; col++) if ((col-sgcol) % 3) {
+ rix = &rgb[0][row-top][col-left];
+ hex = allhex[row % 3][col % 3][1];
+ for (d=0; d < ndir; d+=2, rix += TS*TS)
+ if (hex[d] + hex[d+1]) {
+ g = 3*rix[0][1] - 2*rix[hex[d]][1] - rix[hex[d+1]][1];
+ for (c=0; c < 4; c+=2) rix[0][c] =
+ CLIP((g + 2*rix[hex[d]][c] + rix[hex[d+1]][c])/3);
+ } else {
+ g = 2*rix[0][1] - rix[hex[d]][1] - rix[hex[d+1]][1];
+ for (c=0; c < 4; c+=2) rix[0][c] =
+ CLIP((g + rix[hex[d]][c] + rix[hex[d+1]][c])/2);
+ }
+ }
+ }
+ rgb = (ushort(*)[TS][TS][3]) buffer;
+ mrow -= top;
+ mcol -= left;
+
+/* Convert to CIELab and differentiate in all directions: */
+ for (d=0; d < ndir; d++) {
+ for (row=2; row < mrow-2; row++)
+ for (col=2; col < mcol-2; col++)
+ cielab (rgb[d][row][col], lab[row][col]);
+ for (f=dir[d & 3],row=3; row < mrow-3; row++)
+ for (col=3; col < mcol-3; col++) {
+ lix = &lab[row][col];
+ g = 2*lix[0][0] - lix[f][0] - lix[-f][0];
+ drv[d][row][col] = SQR(g)
+ + SQR((2*lix[0][1] - lix[f][1] - lix[-f][1] + g*500/232))
+ + SQR((2*lix[0][2] - lix[f][2] - lix[-f][2] - g*500/580));
+ }
+ }
+
+/* Build homogeneity maps from the derivatives: */
+ memset(homo, 0, ndir*TS*TS);
+ for (row=4; row < mrow-4; row++)
+ for (col=4; col < mcol-4; col++) {
+ for (tr=FLT_MAX, d=0; d < ndir; d++)
+ if (tr > drv[d][row][col])
+ tr = drv[d][row][col];
+ tr *= 8;
+ for (d=0; d < ndir; d++)
+ for (v=-1; v <= 1; v++)
+ for (h=-1; h <= 1; h++)
+ if (drv[d][row+v][col+h] <= tr)
+ homo[d][row][col]++;
+ }
+
+/* Average the most homogenous pixels for the final result: */
+ if (height-top < TS+4) mrow = height-top+2;
+ if (width-left < TS+4) mcol = width-left+2;
+ for (row = MIN(top,8); row < mrow-8; row++)
+ for (col = MIN(left,8); col < mcol-8; col++) {
+ for (d=0; d < ndir; d++)
+ for (hm[d]=0, v=-2; v <= 2; v++)
+ for (h=-2; h <= 2; h++)
+ hm[d] += homo[d][row+v][col+h];
+ for (d=0; d < ndir-4; d++)
+ if (hm[d] < hm[d+4]) hm[d ] = 0; else
+ if (hm[d] > hm[d+4]) hm[d+4] = 0;
+ for (max=hm[0],d=1; d < ndir; d++)
+ if (max < hm[d]) max = hm[d];
+ max -= max >> 3;
+ memset (avg, 0, sizeof avg);
+ for (d=0; d < ndir; d++)
+ if (hm[d] >= max) {
+ FORC3 avg[c] += rgb[d][row][col][c];
+ avg[3]++;
+ }
+ FORC3 image[(row+top)*width+col+left][c] = avg[c]/avg[3];
+ }
+ }
+ free(buffer);
+ border_interpolate(8);
+}
+#undef fcol
+
/*
Adaptive Homogeneity-Directed interpolation is based on
the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
*/
-#define TS 256 /* Tile Size */
-
void CLASS ahd_interpolate()
{
- int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
- ushort (*pix)[4], (*rix)[3];
+ int i, j, top, left, row, col, tr, tc, c, d, val, hm[2];
static const int dir[4] = { -1, 1, -TS, TS };
unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
- float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
- ushort (*rgb)[TS][TS][3];
+ ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4];
short (*lab)[TS][TS][3], (*lix)[3];
char (*homo)[TS][TS], *buffer;
if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
- for (i=0; i < 0x10000; i++) {
- r = i / 65535.0;
- cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0;
- }
- for (i=0; i < 3; i++)
- for (j=0; j < colors; j++)
- for (xyz_cam[i][j] = k=0; k < 3; k++)
- xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
-
+ cielab (0,0);
border_interpolate(5);
- buffer = (char *) malloc (26*TS*TS); /* 1664 kB */
+ buffer = (char *) malloc (26*TS*TS);
merror (buffer, "ahd_interpolate()");
rgb = (ushort(*)[TS][TS][3]) buffer;
lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
@@ -4171,7 +4900,7 @@ void CLASS ahd_interpolate()
for (left=2; left < width-5; left += TS-6) {
/* Interpolate green horizontally and vertically: */
- for (row = top; row < top+TS && row < height-2; row++) {
+ for (row=top; row < top+TS && row < height-2; row++) {
col = left + (FC(row,left) & 1);
for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
pix = image + row*width+col;
@@ -4205,18 +4934,7 @@ void CLASS ahd_interpolate()
rix[0][c] = CLIP(val);
c = FC(row,col);
rix[0][c] = pix[0][c];
- xyz[0] = xyz[1] = xyz[2] = 0.5;
- FORCC {
- xyz[0] += xyz_cam[0][c] * rix[0][c];
- xyz[1] += xyz_cam[1][c] * rix[0][c];
- xyz[2] += xyz_cam[2][c] * rix[0][c];
- }
- xyz[0] = cbrt[CLIP((int) xyz[0])];
- xyz[1] = cbrt[CLIP((int) xyz[1])];
- xyz[2] = cbrt[CLIP((int) xyz[2])];
- lix[0][0] = 64 * (116 * xyz[1] - 16);
- lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
- lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
+ cielab (rix[0],lix[0]);
}
/* Build homogeneity maps from the CIELab images: */
memset (homo, 0, 2*TS*TS);
@@ -4263,7 +4981,7 @@ void CLASS ahd_interpolate()
}
#undef TS
-void CLASS median_filter ()
+void CLASS median_filter()
{
ushort (*pix)[4];
int pass, c, i, j, k, med[9];
@@ -4346,7 +5064,7 @@ void CLASS recover_highlights()
if (pre_mul[kc] < pre_mul[c]) kc = c;
high = height / SCALE;
wide = width / SCALE;
- map = (float *) calloc (high*wide, sizeof *map);
+ map = (float *) calloc (high, wide*sizeof *map);
merror (map, "recover_highlights()");
FORCC if (c != kc) {
memset (map, 0, high*wide*sizeof *map);
@@ -4413,7 +5131,7 @@ void CLASS tiff_get (unsigned base,
*type = get2();
*len = get4();
*save = ftell(ifp) + 4;
- if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4)
+ if (*len * ("11124811248484"[*type < 14 ? *type:0]-'0') > 4)
fseek (ifp, get4()+base, SEEK_SET);
}
@@ -4470,12 +5188,13 @@ void CLASS parse_makernote (int base, int uptag)
unsigned offset=0, entries, tag, type, len, save, c;
unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
uchar buf97[324], ci, cj, ck;
- short sorder=order;
+ short morder, sorder=order;
char buf[10];
/*
The MakerNote might have its own TIFF header (possibly with
its own byte-order!), or it might just be a table.
*/
+ if (!strcmp(make,"Nokia")) return;
fread (buf, 1, 10, ifp);
if (!strncmp (buf,"KDK" ,3) || /* these aren't TIFF tables */
!strncmp (buf,"VER" ,3) ||
@@ -4499,14 +5218,18 @@ void CLASS parse_makernote (int base, int uptag)
if (get2() != 42) goto quit;
offset = get4();
fseek (ifp, offset-8, SEEK_CUR);
- } else if (!strcmp (buf,"OLYMPUS")) {
+ } else if (!strcmp (buf,"OLYMPUS") ||
+ !strcmp (buf,"PENTAX ")) {
base = ftell(ifp)-10;
fseek (ifp, -2, SEEK_CUR);
- order = get2(); get2();
- } else if (!strncmp (buf,"FUJIFILM",8) ||
- !strncmp (buf,"SONY",4) ||
+ order = get2();
+ if (buf[0] == 'O') get2();
+ } else if (!strncmp (buf,"SONY",4) ||
!strcmp (buf,"Panasonic")) {
- order = 0x4949;
+ goto nf;
+ } else if (!strncmp (buf,"FUJIFILM",8)) {
+ base = ftell(ifp)-10;
+nf: order = 0x4949;
fseek (ifp, 2, SEEK_CUR);
} else if (!strcmp (buf,"OLYMP") ||
!strcmp (buf,"LEICA") ||
@@ -4516,31 +5239,52 @@ void CLASS parse_makernote (int base, int uptag)
else if (!strcmp (buf,"AOC") ||
!strcmp (buf,"QVC"))
fseek (ifp, -4, SEEK_CUR);
- else fseek (ifp, -10, SEEK_CUR);
-
+ else {
+ fseek (ifp, -10, SEEK_CUR);
+ if (!strncmp(make,"SAMSUNG",7))
+ base = ftell(ifp);
+ }
entries = get2();
if (entries > 1000) return;
+ morder = order;
while (entries--) {
+ order = morder;
tiff_get (base, &tag, &type, &len, &save);
tag |= uptag << 16;
- if (tag == 2 && strstr(make,"NIKON"))
+ if (tag == 2 && strstr(make,"NIKON") && !iso_speed)
iso_speed = (get2(),get2());
if (tag == 4 && len > 26 && len < 35) {
- iso_speed = 50 * pow (2, (get4(),get2())/32.0 - 4);
- if ((i=(get2(),get2())) != 0x7fff)
+ if ((i=(get4(),get2())) != 0x7fff && !iso_speed)
+ iso_speed = 50 * pow (2, i/32.0 - 4);
+ if ((i=(get2(),get2())) != 0x7fff && !aperture)
aperture = pow (2, i/64.0);
- if ((i=get2()) != 0xffff)
+ if ((i=get2()) != 0xffff && !shutter)
shutter = pow (2, (short) i/-32.0);
wbi = (get2(),get2());
shot_order = (get2(),get2());
}
+ if ((tag == 4 || tag == 0x114) && !strncmp(make,"KONICA",6)) {
+ fseek (ifp, tag == 4 ? 140:160, SEEK_CUR);
+ switch (get2()) {
+ case 72: flip = 0; break;
+ case 76: flip = 6; break;
+ case 82: flip = 5; break;
+ }
+ }
+ if (tag == 7 && type == 2 && len > 20)
+ fgets (model2, 64, ifp);
if (tag == 8 && type == 4)
shot_order = get4();
if (tag == 9 && !strcmp(make,"Canon"))
fread (artist, 64, 1, ifp);
- if (tag == 0xc && len == 4) {
- cam_mul[0] = getreal(type);
- cam_mul[2] = getreal(type);
+ if (tag == 0xc && len == 4)
+ FORC3 cam_mul[(c << 1 | c >> 1) & 3] = getreal(type);
+ if (tag == 0xd && type == 7 && get2() == 0xaaaa) {
+ for (c=i=2; (ushort) c != 0xbbbb && i < len; i++)
+ c = c << 8 | fgetc(ifp);
+ while ((i+=4) < len-5)
+ if (get4() == 257 && (i=len) && (c = (get4(),fgetc(ifp))) < 3)
+ flip = "065"[c]-'0';
}
if (tag == 0x10 && type == 4)
unique_id = get4();
@@ -4548,9 +5292,18 @@ void CLASS parse_makernote (int base, int uptag)
fseek (ifp, get4()+base, SEEK_SET);
parse_tiff_ifd (base);
}
- if (tag == 0x14 && len == 2560 && type == 7) {
- fseek (ifp, 1248, SEEK_CUR);
- goto get2_256;
+ if (tag == 0x14 && type == 7) {
+ if (len == 2560) {
+ fseek (ifp, 1248, SEEK_CUR);
+ goto get2_256;
+ }
+ fread (buf, 1, 10, ifp);
+ if (!strncmp(buf,"NRW ",4)) {
+ fseek (ifp, strcmp(buf+4,"0100") ? 46:1546, SEEK_CUR);
+ cam_mul[0] = get4() << 2;
+ cam_mul[1] = get4() + get4();
+ cam_mul[2] = get4() << 2;
+ }
}
if (tag == 0x15 && type == 2 && is_raw)
fread (model, 64, 1, ifp);
@@ -4561,6 +5314,13 @@ void CLASS parse_makernote (int base, int uptag)
if (tag == 0x1d)
while ((c = fgetc(ifp)) && c != EOF)
serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
+ if (tag == 0x29 && type == 1) {
+ c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
+ fseek (ifp, 8 + c*32, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4();
+ }
+ if (tag == 0x3d && type == 3 && len == 4)
+ FORC4 cblack[c ^ c >> 1] = get2() >> (14-tiff_bps);
if (tag == 0x81 && type == 4) {
data_offset = get4();
fseek (ifp, data_offset + 41, SEEK_SET);
@@ -4568,11 +5328,6 @@ void CLASS parse_makernote (int base, int uptag)
raw_width = get2();
filters = 0x61616161;
}
- if (tag == 0x29 && type == 1) {
- c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
- fseek (ifp, 8 + c*32, SEEK_CUR);
- FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4();
- }
if ((tag == 0x81 && type == 7) ||
(tag == 0x100 && type == 7) ||
(tag == 0x280 && type == 1)) {
@@ -4587,51 +5342,55 @@ void CLASS parse_makernote (int base, int uptag)
meta_offset = ftell(ifp);
if (tag == 0x97) {
for (i=0; i < 4; i++)
- ver97 = (ver97 << 4) + fgetc(ifp)-'0';
+ ver97 = ver97 * 10 + fgetc(ifp)-'0';
switch (ver97) {
- case 0x100:
+ case 100:
fseek (ifp, 68, SEEK_CUR);
FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
break;
- case 0x102:
+ case 102:
fseek (ifp, 6, SEEK_CUR);
- goto get2_rggb;
- case 0x103:
+ FORC4 cam_mul[c ^ (c >> 1)] = get2();
+ break;
+ case 103:
fseek (ifp, 16, SEEK_CUR);
FORC4 cam_mul[c] = get2();
}
- if (ver97 >> 8 == 2) {
- if (ver97 != 0x205) fseek (ifp, 280, SEEK_CUR);
+ if (ver97 >= 200) {
+ if (ver97 != 205) fseek (ifp, 280, SEEK_CUR);
fread (buf97, 324, 1, ifp);
}
}
+ if (tag == 0xa1 && type == 7) {
+ order = 0x4949;
+ fseek (ifp, 140, SEEK_CUR);
+ FORC3 cam_mul[c] = get4();
+ }
if (tag == 0xa4 && type == 3) {
fseek (ifp, wbi*48, SEEK_CUR);
FORC3 cam_mul[c] = get2();
}
- if (tag == 0xa7 && ver97 >> 8 == 2) {
+ if (tag == 0xa7 && (unsigned) (ver97-200) < 17) {
ci = xlat[0][serial & 0xff];
cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)];
ck = 0x60;
for (i=0; i < 324; i++)
buf97[i] ^= (cj += ci * ck++);
- FORC4 cam_mul[c ^ (c >> 1)] =
- sget2 (buf97 + (ver97 == 0x205 ? 14:6) + c*2);
- if (ver97 == 0x209)
- FORC4 cam_mul[c ^ (c >> 1) ^ 1] =
- sget2 (buf97 + 10 + c*2);
+ i = "66666>666;6A;:;55"[ver97-200] - '0';
+ FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
+ sget2 (buf97 + (i & -2) + c*2);
}
if (tag == 0x200 && len == 3)
shot_order = (get4(),get4());
if (tag == 0x200 && len == 4)
- black = (get2()+get2()+get2()+get2())/4;
+ FORC4 cblack[c ^ c >> 1] = get2();
if (tag == 0x201 && len == 4)
- goto get2_rggb;
- if (tag == 0x401 && len == 4) {
- black = (get4()+get4()+get4()+get4())/4;
- }
+ FORC4 cam_mul[c ^ (c >> 1)] = get2();
+ if (tag == 0x220 && type == 7)
+ meta_offset = ftell(ifp);
+ if (tag == 0x401 && type == 4 && len == 4)
+ FORC4 cblack[c ^ c >> 1] = get4();
if (tag == 0xe01) { /* Nikon Capture Note */
- type = order;
order = 0x4949;
fseek (ifp, 22, SEEK_CUR);
for (offset=22; offset+22 < len; offset += 22+i) {
@@ -4641,7 +5400,6 @@ void CLASS parse_makernote (int base, int uptag)
if (tag == 0x76a43207) flip = get2();
else fseek (ifp, i, SEEK_CUR);
}
- order = type;
}
if (tag == 0xe80 && len == 256 && type == 7) {
fseek (ifp, 48, SEEK_CUR);
@@ -4660,8 +5418,7 @@ void CLASS parse_makernote (int base, int uptag)
for (i=0; i < 3; i++)
FORC3 cmatrix[i][c] = ((short) get2()) / 256.0;
if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
- for (black = i=0; i < 4; i++)
- black += get2() << 2;
+ FORC4 cblack[c ^ c >> 1] = get2();
if (tag == 0x1017 || tag == 0x20400100)
cam_mul[0] = get2() / 256.0;
if (tag == 0x1018 || tag == 0x20400100)
@@ -4672,22 +5429,34 @@ get2_256:
cam_mul[0] = get2() / 256.0;
cam_mul[2] = get2() / 256.0;
}
- if (tag == 0x2020)
+ if ((tag | 0x70) == 0x2070 && (type == 4 || type == 13))
+ fseek (ifp, get4()+base, SEEK_SET);
+ if (tag == 0x2020 && !strncmp(buf,"OLYMP",5))
parse_thumb_note (base, 257, 258);
if (tag == 0x2040)
parse_makernote (base, 0x2040);
if (tag == 0xb028) {
- fseek (ifp, get4(), SEEK_SET);
+ fseek (ifp, get4()+base, SEEK_SET);
parse_thumb_note (base, 136, 137);
}
- if (tag == 0x4001 && type == 3) {
- i = len == 582 ? 50 : len == 653 ? 68 : 126;
+ if (tag == 0x4001 && len > 500) {
+ i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
fseek (ifp, i, SEEK_CUR);
-get2_rggb:
FORC4 cam_mul[c ^ (c >> 1)] = get2();
- fseek (ifp, 22, SEEK_CUR);
- FORC4 sraw_mul[c ^ (c >> 1)] = get2();
+ for (i+=18; i <= len; i+=10) {
+ get2();
+ FORC4 sraw_mul[c ^ (c >> 1)] = get2();
+ if (sraw_mul[1] == 1170) break;
+ }
}
+ if (tag == 0x4021 && get4() && get4())
+ FORC4 cam_mul[c] = 1024;
+ if (tag == 0xa021)
+ FORC4 cam_mul[c ^ (c >> 1)] = get4();
+ if (tag == 0xa028)
+ FORC4 cam_mul[c ^ (c >> 1)] -= get4();
+ if (tag == 0xb001)
+ unique_id = get2();
next:
fseek (ifp, save, SEEK_SET);
}
@@ -4716,6 +5485,7 @@ void CLASS get_timestamp (int reversed)
return;
t.tm_year -= 1900;
t.tm_mon -= 1;
+ t.tm_isdst = -1;
if (mktime(&t) > 0)
timestamp = mktime(&t);
}
@@ -4725,17 +5495,19 @@ void CLASS parse_exif (int base)
unsigned kodak, entries, tag, type, len, save, c;
double expo;
- kodak = !strncmp(make,"EASTMAN",7);
+ kodak = !strncmp(make,"EASTMAN",7) && tiff_nifds < 3;
entries = get2();
while (entries--) {
tiff_get (base, &tag, &type, &len, &save);
switch (tag) {
- case 33434: shutter = getreal(type); break;
+ case 33434: tiff_ifd[tiff_nifds-1].shutter =
+ shutter = getreal(type); break;
case 33437: aperture = getreal(type); break;
case 34855: iso_speed = get2(); break;
case 36867:
case 36868: get_timestamp(0); break;
case 37377: if ((expo = -getreal(type)) < 128)
+ tiff_ifd[tiff_nifds-1].shutter =
shutter = pow (2, expo); break;
case 37378: aperture = pow (2, getreal(type)/2); break;
case 37386: focal_len = getreal(type); break;
@@ -4793,7 +5565,9 @@ void CLASS parse_mos (int offset)
static const char *mod[] =
{ "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22",
"Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65",
- "Aptus 54S","Aptus 65S","Aptus 75S" };
+ "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7",
+ "AFi-II 7","Aptus-II 7","","Aptus-II 6","","","Aptus-II 10","Aptus-II 5",
+ "","","","","Aptus-II 10R","Aptus-II 8","","Aptus-II 12","","AFi-II 12" };
float romm_cam[3][3];
fseek (ifp, offset, SEEK_SET);
@@ -4818,12 +5592,12 @@ void CLASS parse_mos (int offset)
}
if (!strcmp(data,"icc_camera_to_tone_matrix")) {
for (i=0; i < 9; i++)
- romm_cam[0][i] = int_to_float(get4());
+ ((float *)romm_cam)[i] = int_to_float(get4());
romm_coeff (romm_cam);
}
if (!strcmp(data,"CaptProf_color_matrix")) {
for (i=0; i < 9; i++)
- fscanf (ifp, "%f", &romm_cam[0][i]);
+ fscanf (ifp, "%f", (float *)romm_cam + i);
romm_coeff (romm_cam);
}
if (!strcmp(data,"CaptProf_number_of_planes"))
@@ -4843,6 +5617,8 @@ void CLASS parse_mos (int offset)
FORC4 fscanf (ifp, "%d", neut+c);
FORC3 cam_mul[c] = (float) neut[0] / neut[c+1];
}
+ if (!strcmp(data,"Rows_data"))
+ load_flags = get4();
parse_mos (from);
fseek (ifp, skip+from, SEEK_SET);
}
@@ -4865,7 +5641,8 @@ void CLASS parse_kodak_ifd (int base)
{
unsigned entries, tag, type, len, save;
int i, c, wbi=-2, wbtemp=6500;
- float mul[3], num;
+ float mul[3]={1,1,1}, num;
+ static const int wbtag[] = { 64037,64040,64039,64041,-1,-1,64042 };
entries = get2();
if (entries > 1024) return;
@@ -4878,6 +5655,8 @@ void CLASS parse_kodak_ifd (int base)
wbi = -2;
}
if (tag == 2118) wbtemp = getint(type);
+ if (tag == 2120 + wbi && wbi >= 0)
+ FORC3 cam_mul[c] = 2048.0 / getreal(type);
if (tag == 2130 + wbi)
FORC3 mul[c] = getreal(type);
if (tag == 2140 + wbi && wbi >= 0)
@@ -4888,11 +5667,17 @@ void CLASS parse_kodak_ifd (int base)
}
if (tag == 2317) linear_table (len);
if (tag == 6020) iso_speed = getint(type);
+ if (tag == 64013) wbi = fgetc(ifp);
+ if ((unsigned) wbi < 7 && tag == wbtag[wbi])
+ FORC3 cam_mul[c] = get4();
+ if (tag == 64019) width = getint(type);
+ if (tag == 64020) height = (getint(type)+1) & -2;
fseek (ifp, save, SEEK_SET);
}
}
void CLASS parse_minolta (int base);
+int CLASS parse_tiff (int base);
int CLASS parse_tiff_ifd (int base)
{
@@ -4900,7 +5685,7 @@ int CLASS parse_tiff_ifd (int base)
int ifd, use_cm=0, cfa, i, j, c, ima_len=0;
char software[64], *cbuf, *cp;
uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256];
- double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num;
+ double cc[4][4], cm[4][3], cam_xyz[4][3], num;
double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 };
unsigned sony_curve[] = { 0,0,0,0,0,4095 };
unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
@@ -4918,6 +5703,10 @@ int CLASS parse_tiff_ifd (int base)
while (entries--) {
tiff_get (base, &tag, &type, &len, &save);
switch (tag) {
+ case 5: width = get2(); break;
+ case 6: height = get2(); break;
+ case 7: width += get2(); break;
+ case 9: if ((i = get2())) filters = i; break;
case 17: case 18:
if (type == 3 && len == 1)
cam_mul[(tag-17)*2] = get2() / 256.0;
@@ -4925,8 +5714,12 @@ int CLASS parse_tiff_ifd (int base)
case 23:
if (type == 3) iso_speed = get2();
break;
+ case 28: case 29: case 30:
+ cblack[tag-28] = get2();
+ cblack[3] = cblack[1];
+ break;
case 36: case 37: case 38:
- cam_mul[tag-0x24] = get2();
+ cam_mul[tag-36] = get2();
break;
case 39:
if (len < 50 || cam_mul[0]) break;
@@ -4938,18 +5731,30 @@ int CLASS parse_tiff_ifd (int base)
thumb_offset = ftell(ifp) - 2;
thumb_length = len;
break;
- case 2: case 256: /* ImageWidth */
+ case 61440: /* Fuji HS10 table */
+ fseek (ifp, get4()+base, SEEK_SET);
+ parse_tiff_ifd (base);
+ break;
+ case 2: case 256: case 61441: /* ImageWidth */
tiff_ifd[ifd].width = getint(type);
break;
- case 3: case 257: /* ImageHeight */
+ case 3: case 257: case 61442: /* ImageHeight */
tiff_ifd[ifd].height = getint(type);
break;
case 258: /* BitsPerSample */
+ case 61443:
tiff_ifd[ifd].samples = len & 7;
- tiff_ifd[ifd].bps = get2();
+ if ((tiff_ifd[ifd].bps = getint(type)) > 32)
+ tiff_ifd[ifd].bps = 8;
+ if (tiff_bps < tiff_ifd[ifd].bps)
+ tiff_bps = tiff_ifd[ifd].bps;
+ break;
+ case 61446:
+ raw_height = 0;
+ load_flags = get4() ? 24:80;
break;
case 259: /* Compression */
- tiff_ifd[ifd].comp = get2();
+ tiff_ifd[ifd].comp = getint(type);
break;
case 262: /* PhotometricInterpretation */
tiff_ifd[ifd].phint = get2();
@@ -4963,17 +5768,31 @@ int CLASS parse_tiff_ifd (int base)
case 272: /* Model */
fgets (model, 64, ifp);
break;
+ case 280: /* Panasonic RW2 offset */
+ if (type != 4) break;
+ load_raw = &CLASS panasonic_load_raw;
+ load_flags = 0x2008;
case 273: /* StripOffset */
- case 513:
+ case 513: /* JpegIFOffset */
+ case 61447:
tiff_ifd[ifd].offset = get4()+base;
- if (!tiff_ifd[ifd].bps) {
+ if (!tiff_ifd[ifd].bps && tiff_ifd[ifd].offset > 0) {
fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
if (ljpeg_start (&jh, 1)) {
tiff_ifd[ifd].comp = 6;
- tiff_ifd[ifd].width = jh.wide << (jh.clrs == 2);
+ tiff_ifd[ifd].width = jh.wide;
tiff_ifd[ifd].height = jh.high;
tiff_ifd[ifd].bps = jh.bits;
tiff_ifd[ifd].samples = jh.clrs;
+ if (!(jh.sraw || (jh.clrs & 1)))
+ tiff_ifd[ifd].width *= jh.clrs;
+ if ((tiff_ifd[ifd].width > 4*tiff_ifd[ifd].height) & ~jh.clrs) {
+ tiff_ifd[ifd].width /= 2;
+ tiff_ifd[ifd].height *= 2;
+ }
+ i = order;
+ parse_tiff (tiff_ifd[ifd].offset + 12);
+ order = i;
}
}
break;
@@ -4985,12 +5804,17 @@ int CLASS parse_tiff_ifd (int base)
break;
case 279: /* StripByteCounts */
case 514:
+ case 61448:
tiff_ifd[ifd].bytes = get4();
break;
- case 305: /* Software */
+ case 61454:
+ FORC3 cam_mul[(4-c) % 3] = getint(type);
+ break;
+ case 305: case 11: /* Software */
fgets (software, 64, ifp);
if (!strncmp(software,"Adobe",5) ||
!strncmp(software,"dcraw",5) ||
+ !strncmp(software,"UFRaw",5) ||
!strncmp(software,"Bibble",6) ||
!strncmp(software,"Nikon Scan",10) ||
!strcmp (software,"Digital Photo Professional"))
@@ -5003,13 +5827,15 @@ int CLASS parse_tiff_ifd (int base)
fread (artist, 64, 1, ifp);
break;
case 322: /* TileWidth */
- tile_width = getint(type);
+ tiff_ifd[ifd].tile_width = getint(type);
break;
case 323: /* TileLength */
- tile_length = getint(type);
+ tiff_ifd[ifd].tile_length = getint(type);
break;
case 324: /* TileOffsets */
tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
+ if (len == 1)
+ tiff_ifd[ifd].tile_width = tiff_ifd[ifd].tile_length = 0;
if (len == 4) {
load_raw = &CLASS sinar_4shot_load_raw;
is_raw = 5;
@@ -5017,6 +5843,7 @@ int CLASS parse_tiff_ifd (int base)
break;
case 330: /* SubIFDs */
if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].width == 3872) {
+ load_raw = &CLASS sony_arw_load_raw;
data_offset = get4()+base;
ifd++; break;
}
@@ -5047,14 +5874,27 @@ int CLASS parse_tiff_ifd (int base)
case 29443:
FORC4 cam_mul[c ^ (c < 2)] = get2();
break;
+ case 29459:
+ FORC4 cam_mul[c] = get2();
+ i = (cam_mul[1] == 1024 && cam_mul[2] == 1024) << 1;
+ SWAP (cam_mul[i],cam_mul[i+1])
+ break;
case 33405: /* Model2 */
fgets (model2, 64, ifp);
break;
+ case 33421: /* CFARepeatPatternDim */
+ if (get2() == 6 && get2() == 6)
+ filters = 9;
+ break;
case 33422: /* CFAPattern */
+ if (filters == 9) {
+ FORC(36) ((char *)xtrans)[c] = fgetc(ifp) & 3;
+ break;
+ }
case 64777: /* Kodak P-series */
if ((plen=len) > 16) plen = 16;
fread (cfa_pat, 1, plen, ifp);
- for (colors=cfa=i=0; i < plen; i++) {
+ for (colors=cfa=i=0; i < plen && colors < 4; i++) {
colors += !(cfa & (1 << cfa_pat[i]));
cfa |= 1 << cfa_pat[i];
}
@@ -5062,11 +5902,12 @@ int CLASS parse_tiff_ifd (int base)
if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4); /* GMCY */
goto guess_cfa_pc;
case 33424:
+ case 65024:
fseek (ifp, get4()+base, SEEK_SET);
parse_kodak_ifd (base);
break;
case 33434: /* ExposureTime */
- shutter = getreal(type);
+ tiff_ifd[ifd].shutter = shutter = getreal(type);
break;
case 33437: /* FNumber */
aperture = getreal(type);
@@ -5119,13 +5960,24 @@ int CLASS parse_tiff_ifd (int base)
FORC3 rgb_cam[i][c] = getreal(type);
}
break;
+ case 40976:
+ strip_offset = get4();
+ switch (tiff_ifd[ifd].comp) {
+ case 32770: load_raw = &CLASS samsung_load_raw; break;
+ case 32772: load_raw = &CLASS samsung2_load_raw; break;
+ case 32773: load_raw = &CLASS samsung3_load_raw; break;
+ }
+ break;
case 46275: /* Imacon tags */
strcpy (make, "Imacon");
data_offset = ftell(ifp);
ima_len = len;
break;
case 46279:
- fseek (ifp, 78, SEEK_CUR);
+ if (!ima_len) break;
+ fseek (ifp, 38, SEEK_CUR);
+ case 46274:
+ fseek (ifp, 40, SEEK_CUR);
raw_width = get4();
raw_height = get4();
left_margin = get4() & 7;
@@ -5143,7 +5995,9 @@ int CLASS parse_tiff_ifd (int base)
flip = (get2() >> 7) * 90;
if (width * height * 6 == ima_len) {
if (flip % 180 == 90) SWAP(width,height);
- filters = flip = 0;
+ raw_width = width;
+ raw_height = height;
+ left_margin = top_margin = filters = flip = 0;
}
sprintf (model, "Ixpress %d-Mp", height*width/1000000);
load_raw = &CLASS imacon_full_load_raw;
@@ -5162,6 +6016,9 @@ int CLASS parse_tiff_ifd (int base)
sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2);
free (cbuf);
break;
+ case 50458:
+ if (!make[0]) strcpy (make, "Hasselblad");
+ break;
case 50459: /* Hasselblad tag */
i = order;
j = ftell(ifp);
@@ -5175,8 +6032,19 @@ int CLASS parse_tiff_ifd (int base)
break;
case 50706: /* DNGVersion */
FORC4 dng_version = (dng_version << 8) + fgetc(ifp);
+ if (!make[0]) strcpy (make, "DNG");
+ is_raw = 1;
+ break;
+ case 50708: /* UniqueCameraModel */
+ if (model[0]) break;
+ fgets (make, 64, ifp);
+ if ((cp = strchr(make,' '))) {
+ strcpy(model,cp+1);
+ *cp = 0;
+ }
break;
case 50710: /* CFAPlaneColor */
+ if (filters == 9) break;
if (len > 4) len = 4;
colors = len;
fread (cfa_pc, 1, colors, ifp);
@@ -5185,23 +6053,35 @@ guess_cfa_pc:
cdesc[c] = 0;
for (i=16; i--; )
filters = filters << 2 | tab[cfa_pat[i % plen]];
+ filters -= !filters;
break;
case 50711: /* CFALayout */
- if (get2() == 2) {
- fuji_width = 1;
- filters = 0x49494949;
- }
+ if (get2() == 2) fuji_width = 1;
break;
case 291:
case 50712: /* LinearizationTable */
linear_table (len);
break;
+ case 50713: /* BlackLevelRepeatDim */
+ cblack[4] = get2();
+ cblack[5] = get2();
+ if (cblack[4] * cblack[5] > sizeof cblack / sizeof *cblack - 6)
+ cblack[4] = cblack[5] = 1;
+ break;
+ case 61450:
+ cblack[4] = cblack[5] = MIN(sqrt(len),64);
case 50714: /* BlackLevel */
+ if (!(cblack[4] * cblack[5]))
+ cblack[4] = cblack[5] = 1;
+ FORC (cblack[4] * cblack[5])
+ cblack[6+c] = getreal(type);
+ black = 0;
+ break;
case 50715: /* BlackLevelDeltaH */
case 50716: /* BlackLevelDeltaV */
- for (dblack=i=0; i < len; i++)
- dblack += getreal(type);
- black += dblack/len + 0.5;
+ for (num=i=0; i < (len & 0xffff); i++)
+ num += getreal(type);
+ black += num/len + 0.5;
break;
case 50717: /* WhiteLevel */
maximum = getint(type);
@@ -5220,6 +6100,7 @@ guess_cfa_pc:
case 50724: /* CameraCalibration2 */
for (i=0; i < colors; i++)
FORCC cc[i][c] = getreal(type);
+ break;
case 50727: /* AnalogBalance */
FORCC ab[c] = getreal(type);
break;
@@ -5247,12 +6128,24 @@ guess_cfa_pc:
height = getint(type) - top_margin;
width = getint(type) - left_margin;
break;
+ case 50830: /* MaskedAreas */
+ for (i=0; i < len && i < 32; i++)
+ ((int *)mask)[i] = getint(type);
+ black = 0;
+ break;
+ case 51009: /* OpcodeList2 */
+ meta_offset = ftell(ifp);
+ break;
case 64772: /* Kodak P-series */
+ if (len < 13) break;
fseek (ifp, 16, SEEK_CUR);
data_offset = get4();
fseek (ifp, 28, SEEK_CUR);
data_offset += get4();
- load_raw = &CLASS packed_12_load_raw;
+ load_raw = &CLASS packed_load_raw;
+ break;
+ case 65026:
+ if (type == 2) fgets (model2, 64, ifp);
}
fseek (ifp, save, SEEK_SET);
}
@@ -5276,7 +6169,7 @@ guess_cfa_pc:
FORCC for (i=0; i < 3; i++)
for (cam_xyz[c][i]=j=0; j < colors; j++)
cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i];
- cam_xyz_coeff (cam_xyz);
+ cam_xyz_coeff (cmatrix, cam_xyz);
}
if (asn[0]) {
cam_mul[3] = 0;
@@ -5287,21 +6180,26 @@ guess_cfa_pc:
return 0;
}
-void CLASS parse_tiff (int base)
+int CLASS parse_tiff (int base)
{
- int doff, max_samp=0, raw=-1, thm=-1, i;
- struct jhead jh;
+ int doff;
fseek (ifp, base, SEEK_SET);
order = get2();
- if (order != 0x4949 && order != 0x4d4d) return;
+ if (order != 0x4949 && order != 0x4d4d) return 0;
get2();
- memset (tiff_ifd, 0, sizeof tiff_ifd);
- tiff_nifds = 0;
while ((doff = get4())) {
fseek (ifp, doff+base, SEEK_SET);
if (parse_tiff_ifd (base)) break;
}
+ return 1;
+}
+
+void CLASS apply_tiff()
+{
+ int max_samp=0, ties=0, os, ns, raw=-1, thm=-1, i;
+ struct jhead jh;
+
thumb_misc = 16;
if (thumb_offset) {
fseek (ifp, thumb_offset, SEEK_SET);
@@ -5311,12 +6209,25 @@ void CLASS parse_tiff (int base)
thumb_height = jh.high;
}
}
+ for (i=tiff_nifds; i--; ) {
+ if (tiff_ifd[i].shutter)
+ shutter = tiff_ifd[i].shutter;
+ tiff_ifd[i].shutter = shutter;
+ }
for (i=0; i < tiff_nifds; i++) {
if (max_samp < tiff_ifd[i].samples)
max_samp = tiff_ifd[i].samples;
if (max_samp > 3) max_samp = 3;
+ os = raw_width*raw_height;
+ ns = tiff_ifd[i].width*tiff_ifd[i].height;
+ if (tiff_bps) {
+ os *= tiff_bps;
+ ns *= tiff_ifd[i].bps;
+ }
if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) &&
- tiff_ifd[i].width*tiff_ifd[i].height > raw_width*raw_height) {
+ (tiff_ifd[i].width | tiff_ifd[i].height) < 0x10000 &&
+ ns && ((ns > os && (ties = 1)) ||
+ (ns == os && shot_select == ties++))) {
raw_width = tiff_ifd[i].width;
raw_height = tiff_ifd[i].height;
tiff_bps = tiff_ifd[i].bps;
@@ -5324,60 +6235,105 @@ void CLASS parse_tiff (int base)
data_offset = tiff_ifd[i].offset;
tiff_flip = tiff_ifd[i].flip;
tiff_samples = tiff_ifd[i].samples;
+ tile_width = tiff_ifd[i].tile_width;
+ tile_length = tiff_ifd[i].tile_length;
+ shutter = tiff_ifd[i].shutter;
raw = i;
}
}
- fuji_width *= (raw_width+1)/2;
- if (tiff_ifd[0].flip) tiff_flip = tiff_ifd[0].flip;
+ if (is_raw == 1 && ties) is_raw = ties;
+ if (!tile_width ) tile_width = INT_MAX;
+ if (!tile_length) tile_length = INT_MAX;
+ for (i=tiff_nifds; i--; )
+ if (tiff_ifd[i].flip) tiff_flip = tiff_ifd[i].flip;
if (raw >= 0 && !load_raw)
switch (tiff_compress) {
+ case 32767:
+ if (tiff_ifd[raw].bytes == raw_width*raw_height) {
+ tiff_bps = 12;
+ maximum = 4095;
+ load_raw = &CLASS sony_arw2_load_raw; break;
+ }
+ if (tiff_ifd[raw].bytes*8 != raw_width*raw_height*tiff_bps) {
+ raw_height += 8;
+ load_raw = &CLASS sony_arw_load_raw; break;
+ }
+ load_flags = 79;
+ case 32769:
+ load_flags++;
+ case 32770:
+ case 32773: goto slr;
case 0: case 1:
+ if (!strncmp(make,"OLYMPUS",7) &&
+ tiff_ifd[raw].bytes*2 == raw_width*raw_height*3)
+ load_flags = 24;
+ if (!strcmp(make,"SONY") && tiff_bps < 14 &&
+ tiff_ifd[raw].bytes == raw_width*raw_height*2)
+ tiff_bps = 14;
+ if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) {
+ load_flags = 81;
+ tiff_bps = 12;
+ } slr:
switch (tiff_bps) {
case 8: load_raw = &CLASS eight_bit_load_raw; break;
- case 12: load_raw = &CLASS packed_12_load_raw;
- if (!strncmp(make,"NIKON",5))
- load_raw = &CLASS nikon_load_raw;
- if (strncmp(make,"PENTAX",6)) break;
- case 14:
- case 16: load_raw = &CLASS unpacked_load_raw; break;
+ case 12: if (tiff_ifd[raw].phint == 2)
+ load_flags = 6;
+ load_raw = &CLASS packed_load_raw; break;
+ case 14: load_raw = &CLASS packed_load_raw;
+ if (tiff_ifd[raw].bytes*4 == raw_width*raw_height*7) break;
+ load_flags = 0;
+ case 16: load_raw = &CLASS unpacked_load_raw;
+ if (!strncmp(make,"OLYMPUS",7) &&
+ tiff_ifd[raw].bytes*7 > raw_width*raw_height)
+ load_raw = &CLASS olympus_load_raw;
}
- if (tiff_ifd[raw].bytes * 5 == raw_width * raw_height * 8)
- load_raw = &CLASS olympus_e300_load_raw;
- if (tiff_bps == 12 && tiff_ifd[raw].phint == 2)
- load_raw = &CLASS olympus_cseries_load_raw;
+ if (filters == 9 && tiff_ifd[raw].bytes*8 < raw_width*raw_height*tiff_bps)
+ load_raw = &CLASS fuji_xtrans_load_raw;
break;
case 6: case 7: case 99:
load_raw = &CLASS lossless_jpeg_load_raw; break;
case 262:
load_raw = &CLASS kodak_262_load_raw; break;
- case 32767:
- load_raw = &CLASS sony_arw2_load_raw; break;
- case 32769:
- load_raw = &CLASS nikon_load_raw; break;
- case 32773:
- load_raw = &CLASS packed_12_load_raw; break;
case 34713:
- load_raw = &CLASS nikon_compressed_load_raw; break;
+ if ((raw_width+9)/10*16*raw_height == tiff_ifd[raw].bytes) {
+ load_raw = &CLASS packed_load_raw;
+ load_flags = 1;
+ } else if (raw_width*raw_height*3 == tiff_ifd[raw].bytes*2) {
+ load_raw = &CLASS packed_load_raw;
+ if (model[0] == 'N') load_flags = 80;
+ } else if (raw_width*raw_height*3 == tiff_ifd[raw].bytes) {
+ load_raw = &CLASS nikon_yuv_load_raw;
+ gamma_curve (1/2.4, 12.92, 1, 4095);
+ memset (cblack, 0, sizeof cblack);
+ filters = 0;
+ } else if (raw_width*raw_height*2 == tiff_ifd[raw].bytes) {
+ load_raw = &CLASS unpacked_load_raw;
+ load_flags = 4;
+ order = 0x4d4d;
+ } else
+ load_raw = &CLASS nikon_load_raw; break;
case 65535:
- load_raw = &CLASS pentax_k10_load_raw; break;
+ load_raw = &CLASS pentax_load_raw; break;
case 65000:
switch (tiff_ifd[raw].phint) {
case 2: load_raw = &CLASS kodak_rgb_load_raw; filters = 0; break;
case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0; break;
case 32803: load_raw = &CLASS kodak_65000_load_raw;
}
- case 32867: break;
+ case 32867: case 34892: break;
default: is_raw = 0;
}
- if (!dng_version && tiff_samples == 3)
- if (tiff_ifd[raw].bytes && tiff_bps != 14 && tiff_bps != 2048)
+ if (!dng_version)
+ if ( (tiff_samples == 3 && tiff_ifd[raw].bytes && tiff_bps != 14 &&
+ (tiff_compress & -16) != 32768)
+ || (tiff_bps == 8 && strncmp(make,"Phase",5) &&
+ !strcasestr(make,"Kodak") && !strstr(model2,"DEBUG RAW")))
is_raw = 0;
- if (!dng_version && tiff_bps == 8 && tiff_compress == 1 &&
- tiff_ifd[raw].phint == 1) is_raw = 0;
for (i=0; i < tiff_nifds; i++)
if (i != raw && tiff_ifd[i].samples == max_samp &&
- tiff_ifd[i].width * tiff_ifd[i].height / SQR(tiff_ifd[i].bps+1) >
- thumb_width * thumb_height / SQR(thumb_misc+1)) {
+ tiff_ifd[i].width * tiff_ifd[i].height / (SQR(tiff_ifd[i].bps)+1) >
+ thumb_width * thumb_height / (SQR(thumb_misc)+1)
+ && tiff_ifd[i].comp != 34892) {
thumb_width = tiff_ifd[i].width;
thumb_height = tiff_ifd[i].height;
thumb_offset = tiff_ifd[i].offset;
@@ -5392,10 +6348,12 @@ void CLASS parse_tiff (int base)
write_thumb = &CLASS layer_thumb;
break;
case 1:
- if (tiff_ifd[thm].bps > 8)
- thumb_load_raw = &CLASS kodak_thumb_load_raw;
- else
+ if (tiff_ifd[thm].bps <= 8)
write_thumb = &CLASS ppm_thumb;
+ else if (!strcmp(make,"Imacon"))
+ write_thumb = &CLASS ppm16_thumb;
+ else
+ thumb_load_raw = &CLASS kodak_thumb_load_raw;
break;
case 65000:
thumb_load_raw = tiff_ifd[thm].phint == 6 ?
@@ -5425,7 +6383,7 @@ void CLASS parse_minolta (int base)
break;
case 0x574247: /* WBG */
get4();
- i = strstr(model,"A200") ? 3:0;
+ i = strcmp(model,"DiMAGE A200") ? 0:3;
FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2();
break;
case 0x545457: /* TTW */
@@ -5446,7 +6404,8 @@ void CLASS parse_minolta (int base)
*/
void CLASS parse_external_jpeg()
{
- char *file, *ext, *jname, *jfile, *jext;
+ const char *file, *ext;
+ char *jname, *jfile, *jext;
FILE *save=ifp;
ext = strrchr (ifname, '.');
@@ -5456,18 +6415,20 @@ void CLASS parse_external_jpeg()
file++;
if (!ext || strlen(ext) != 4 || ext-file != 8) return;
jname = (char *) malloc (strlen(ifname) + 1);
- merror (jname, "parse_external()");
+ merror (jname, "parse_external_jpeg()");
strcpy (jname, ifname);
jfile = file - ifname + jname;
jext = ext - ifname + jname;
if (strcasecmp (ext, ".jpg")) {
strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
- memcpy (jfile, file+4, 4);
- memcpy (jfile+4, file, 4);
+ if (isdigit(*file)) {
+ memcpy (jfile, file+4, 4);
+ memcpy (jfile+4, file, 4);
+ }
} else
while (isdigit(*--jext)) {
if (*jext != '9') {
- (*jext)++;
+ (*jext)++;
break;
}
*jext = '0';
@@ -5507,16 +6468,14 @@ void CLASS ciff_block_1030()
bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
vbits += 16;
}
- white[row][col] =
- bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
- vbits -= bpp;
+ white[row][col] = bitbuf >> (vbits -= bpp) & ~(-1 << bpp);
}
}
/*
Parse a CIFF file, better known as Canon CRW format.
*/
-void CLASS parse_ciff (int offset, int length)
+void CLASS parse_ciff (int offset, int length, int depth)
{
int tboff, nrecs, c, type, len, save, wbi=-1;
ushort key[] = { 0x410, 0x45f3 };
@@ -5525,15 +6484,14 @@ void CLASS parse_ciff (int offset, int length)
tboff = get4() + offset;
fseek (ifp, tboff, SEEK_SET);
nrecs = get2();
- if (nrecs > 100) return;
+ if ((nrecs | depth) > 127) return;
while (nrecs--) {
type = get2();
len = get4();
save = ftell(ifp) + 4;
fseek (ifp, offset+get4(), SEEK_SET);
if ((((type >> 8) + 8) | 8) == 0x38)
- parse_ciff (ftell(ifp), len); /* Parse a sub-table */
-
+ parse_ciff (ftell(ifp), len, depth+1); /* Parse a sub-table */
if (type == 0x0810)
fread (artist, 64, 1, ifp);
if (type == 0x080a) {
@@ -5542,7 +6500,9 @@ void CLASS parse_ciff (int offset, int length)
fread (model, 64, 1, ifp);
}
if (type == 0x1810) {
- fseek (ifp, 12, SEEK_CUR);
+ width = get4();
+ height = get4();
+ pixel_aspect = int_to_float(get4());
flip = get4();
}
if (type == 0x1835) /* Get the decoder table */
@@ -5700,7 +6660,7 @@ void CLASS parse_phase_one (int base)
fseek (ifp, base, SEEK_SET);
order = get4() & 0xffff;
if (get4() >> 8 != 0x526177) return; /* "Raw" */
- fseek (ifp, base+get4(), SEEK_SET);
+ fseek (ifp, get4()+base, SEEK_SET);
entries = get4();
get4();
while (entries--) {
@@ -5714,7 +6674,7 @@ void CLASS parse_phase_one (int base)
case 0x100: flip = "0653"[data & 3]-'0'; break;
case 0x106:
for (i=0; i < 9; i++)
- romm_cam[0][i] = getreal(11);
+ ((float *)romm_cam)[i] = getreal(11);
romm_coeff (romm_cam);
break;
case 0x107:
@@ -5735,8 +6695,10 @@ void CLASS parse_phase_one (int base)
case 0x21a: ph1.tag_21a = data; break;
case 0x21c: strip_offset = data+base; break;
case 0x21d: ph1.black = data; break;
- case 0x222: ph1.split_col = data - left_margin; break;
- case 0x223: ph1.black_off = data+base; break;
+ case 0x222: ph1.split_col = data; break;
+ case 0x223: ph1.black_col = data+base; break;
+ case 0x224: ph1.split_row = data; break;
+ case 0x225: ph1.black_row = data+base; break;
case 0x301:
model[63] = 0;
fread (model, 1, 63, ifp);
@@ -5774,10 +6736,22 @@ void CLASS parse_fuji (int offset)
} else if (tag == 0x121) {
height = get2();
if ((width = get2()) == 4284) width += 3;
- } else if (tag == 0x130)
+ } else if (tag == 0x130) {
fuji_layout = fgetc(ifp) >> 7;
- if (tag == 0x2ff0)
+ fuji_width = !(fgetc(ifp) & 8);
+ } else if (tag == 0x131) {
+ filters = 9;
+ FORC(36) xtrans_abs[0][35-c] = fgetc(ifp) & 3;
+ } else if (tag == 0x2ff0) {
FORC4 cam_mul[c ^ 1] = get2();
+ } else if (tag == 0xc000 && len > 20000) {
+ c = order;
+ order = 0x4949;
+ while ((tag = get4()) > raw_width);
+ width = tag;
+ height = get4();
+ order = c;
+ }
fseek (ifp, save+len, SEEK_SET);
}
height <<= fuji_layout;
@@ -5795,7 +6769,7 @@ int CLASS parse_jpeg (int offset)
order = 0x4d4d;
len = get2() - 2;
save = ftell(ifp);
- if (mark == 0xc0 || mark == 0xc3) {
+ if (mark == 0xc0 || mark == 0xc3 || mark == 0xc9) {
fgetc(ifp);
raw_height = get2();
raw_width = get2();
@@ -5803,8 +6777,8 @@ int CLASS parse_jpeg (int offset)
order = get2();
hlen = get4();
if (get4() == 0x48454150) /* "HEAP" */
- parse_ciff (save+hlen, len-hlen);
- parse_tiff (save+6);
+ parse_ciff (save+hlen, len-hlen, 0);
+ if (parse_tiff (save+6)) apply_tiff();
fseek (ifp, save+len, SEEK_SET);
}
return 1;
@@ -5821,18 +6795,26 @@ void CLASS parse_riff()
order = 0x4949;
fread (tag, 4, 1, ifp);
size = get4();
+ end = ftell(ifp) + size;
if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) {
- end = ftell(ifp) + size;
get4();
- while (ftell(ifp) < end)
+ while (ftell(ifp)+7 < end && !feof(ifp))
parse_riff();
+ } else if (!memcmp(tag,"nctg",4)) {
+ while (ftell(ifp)+7 < end) {
+ i = get2();
+ size = get2();
+ if ((i+1) >> 1 == 10 && size == 20)
+ get_timestamp(0);
+ else fseek (ifp, size, SEEK_CUR);
+ }
} else if (!memcmp(tag,"IDIT",4) && size < 64) {
fread (date, 64, 1, ifp);
date[size] = 0;
memset (&t, 0, sizeof t);
if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday,
&t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) {
- for (i=0; i < 12 && strcmp(mon[i],month); i++);
+ for (i=0; i < 12 && strcasecmp(mon[i],month); i++);
t.tm_mon = i;
t.tm_year -= 1900;
if (mktime(&t) > 0)
@@ -5842,6 +6824,92 @@ void CLASS parse_riff()
fseek (ifp, size, SEEK_CUR);
}
+void CLASS parse_crx (int end)
+{
+ unsigned i, save, size, tag, base;
+ static int index=0, wide, high, off, len;
+
+ order = 0x4d4d;
+ while (ftell(ifp)+7 < end) {
+ save = ftell(ifp);
+ if ((size = get4()) < 8) break;
+ switch (tag = get4()) {
+ case 0x6d6f6f76: /* moov */
+ case 0x7472616b: /* trak */
+ case 0x6d646961: /* mdia */
+ case 0x6d696e66: /* minf */
+ case 0x7374626c: /* stbl */
+ parse_crx (save+size);
+ break;
+ case 0x75756964: /* uuid */
+ switch (i=get4()) {
+ case 0xeaf42b5e: fseek (ifp, 8, SEEK_CUR);
+ case 0x85c0b687: fseek (ifp, 12, SEEK_CUR);
+ parse_crx (save+size);
+ }
+ break;
+ case 0x434d5431: /* CMT1 */
+ case 0x434d5432: /* CMT2 */
+ base = ftell(ifp);
+ order = get2();
+ fseek (ifp, 6, SEEK_CUR);
+ tag & 1 ? parse_tiff_ifd (base) : parse_exif (base);
+ order = 0x4d4d;
+ break;
+ case 0x746b6864: /* tkhd */
+ fseek (ifp, 12, SEEK_CUR);
+ index = get4();
+ fseek (ifp, 58, SEEK_CUR);
+ wide = get4();
+ high = get4();
+ break;
+ case 0x7374737a: /* stsz */
+ len = (get4(),get4());
+ break;
+ case 0x636f3634: /* co64 */
+ fseek (ifp, 12, SEEK_CUR);
+ off = get4();
+ switch (index) {
+ case 1: /* 1 = full size, 2 = 27% size */
+ thumb_width = wide;
+ thumb_height = high;
+ thumb_length = len;
+ thumb_offset = off;
+ break;
+ case 3:
+ raw_width = wide;
+ raw_height = high;
+ data_offset = off;
+ load_raw = &CLASS canon_crx_load_raw;
+ }
+ break;
+ case 0x50525657: /* PRVW */
+ fseek (ifp, 6, SEEK_CUR);
+ }
+ fseek (ifp, save+size, SEEK_SET);
+ }
+}
+
+void CLASS parse_qt (int end)
+{
+ unsigned save, size;
+ char tag[4];
+
+ order = 0x4d4d;
+ while (ftell(ifp)+7 < end) {
+ save = ftell(ifp);
+ if ((size = get4()) < 8) return;
+ fread (tag, 4, 1, ifp);
+ if (!memcmp(tag,"moov",4) ||
+ !memcmp(tag,"udta",4) ||
+ !memcmp(tag,"CNTH",4))
+ parse_qt (save+size);
+ if (!memcmp(tag,"CNDA",4))
+ parse_jpeg (ftell(ifp));
+ fseek (ifp, save+size, SEEK_SET);
+ }
+}
+
void CLASS parse_smal (int offset, int fsize)
{
int ver;
@@ -5910,6 +6978,35 @@ void CLASS parse_cine()
data_offset += (INT64) get4() << 32;
}
+void CLASS parse_redcine()
+{
+ unsigned i, len, rdvo;
+
+ order = 0x4d4d;
+ is_raw = 0;
+ fseek (ifp, 52, SEEK_SET);
+ width = get4();
+ height = get4();
+ fseek (ifp, 0, SEEK_END);
+ fseek (ifp, -(i = ftello(ifp) & 511), SEEK_CUR);
+ if (get4() != i || get4() != 0x52454f42) {
+ fprintf (stderr,_("%s: Tail is missing, parsing from head...\n"), ifname);
+ fseek (ifp, 0, SEEK_SET);
+ while ((len = get4()) != EOF) {
+ if (get4() == 0x52454456)
+ if (is_raw++ == shot_select)
+ data_offset = ftello(ifp) - 8;
+ fseek (ifp, len-8, SEEK_CUR);
+ }
+ } else {
+ rdvo = get4();
+ fseek (ifp, 12, SEEK_CUR);
+ is_raw = get4();
+ fseeko (ifp, rdvo+8 + shot_select*4, SEEK_SET);
+ data_offset = get4();
+ }
+}
+
char * CLASS foveon_gets (int offset, char *str, int len)
{
int i;
@@ -5942,16 +7039,25 @@ void CLASS parse_foveon()
switch (tag) {
case 0x47414d49: /* IMAG */
case 0x32414d49: /* IMA2 */
- fseek (ifp, 12, SEEK_CUR);
+ fseek (ifp, 8, SEEK_CUR);
+ pent = get4();
wide = get4();
high = get4();
if (wide > raw_width && high > raw_height) {
+ switch (pent) {
+ case 5: load_flags = 1;
+ case 6: load_raw = &CLASS foveon_sd_load_raw; break;
+ case 30: load_raw = &CLASS foveon_dp_load_raw; break;
+ default: load_raw = 0;
+ }
raw_width = wide;
raw_height = high;
- data_offset = off+24;
+ data_offset = off+28;
+ is_foveon = 1;
}
fseek (ifp, off+28, SEEK_SET);
- if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8) {
+ if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8
+ && thumb_length < len-28) {
thumb_offset = off+28;
thumb_length = len-28;
write_thumb = &CLASS jpeg_thumb;
@@ -5964,10 +7070,8 @@ void CLASS parse_foveon()
}
break;
case 0x464d4143: /* CAMF */
- meta_offset = off+24;
+ meta_offset = off+8;
meta_length = len-28;
- if (meta_length > 0x20000)
- meta_length = 0x20000;
break;
case 0x504f5250: /* PROP */
pent = (get4(),get4());
@@ -5975,7 +7079,7 @@ void CLASS parse_foveon()
off += pent*8 + 24;
if ((unsigned) pent > 256) pent=256;
for (i=0; i < pent*2; i++)
- poff[0][i] = off + get4()*2;
+ ((int *)poff)[i] = off + get4()*2;
for (i=0; i < pent; i++) {
foveon_gets (poff[i][0], name, 64);
foveon_gets (poff[i][1], value, 64);
@@ -6002,384 +7106,1159 @@ void CLASS parse_foveon()
}
fseek (ifp, save, SEEK_SET);
}
- is_foveon = 1;
}
/*
- Thanks to Adobe for providing these excellent CAM -> XYZ matrices!
+ All matrices are from Adobe DNG Converter unless otherwise noted.
*/
-void CLASS adobe_coeff (char *make, char *model)
+void CLASS adobe_coeff (const char *make, const char *model)
{
static const struct {
const char *prefix;
- short black, trans[12];
+ short black, maximum, trans[12];
} table[] = {
- { "Apple QuickTake", 0, /* DJC */
- { 17576,-3191,-3318,5210,6733,-1942,9031,1280,-124 } },
- { "Canon EOS D2000", 0,
+ { "AgfaPhoto DC-833m", 0, 0, /* DJC */
+ { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } },
+ { "Apple QuickTake", 0, 0, /* DJC */
+ { 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } },
+ { "Canon EOS D2000", 0, 0,
{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
- { "Canon EOS D6000", 0,
+ { "Canon EOS D6000", 0, 0,
{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
- { "Canon EOS D30", 0,
+ { "Canon EOS D30", 0, 0,
{ 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } },
- { "Canon EOS D60", 0,
+ { "Canon EOS D60", 0, 0xfa0,
{ 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } },
- { "Canon EOS 5D", 0,
+ { "Canon EOS 5DS", 0, 0x3c96,
+ { 6250,-711,-808,-5153,12794,2636,-1249,2198,5610 } },
+ { "Canon EOS 5D Mark IV", 0, 0,
+ { 6446,-366,-864,-4436,12204,2513,-952,2496,6348 } },
+ { "Canon EOS 5D Mark III", 0, 0x3c80,
+ { 6722,-635,-963,-4287,12460,2028,-908,2162,5668 } },
+ { "Canon EOS 5D Mark II", 0, 0x3cf0,
+ { 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } },
+ { "Canon EOS 5D", 0, 0xe6c,
{ 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } },
- { "Canon EOS 20Da", 0,
+ { "Canon EOS 6D Mark II", 0, 0,
+ { 6875,-970,-932,-4691,12459,2501,-874,1953,5809 } },
+ { "Canon EOS 6D", 0, 0x3c82,
+ { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } },
+ { "Canon EOS 7D Mark II", 0, 0x3510,
+ { 7268,-1082,-969,-4186,11839,2663,-825,2029,5839 } },
+ { "Canon EOS 7D", 0, 0x3510,
+ { 6844,-996,-856,-3876,11761,2396,-593,1772,6198 } },
+ { "Canon EOS 10D", 0, 0xfa0,
+ { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+ { "Canon EOS 20Da", 0, 0,
{ 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } },
- { "Canon EOS 20D", 0,
+ { "Canon EOS 20D", 0, 0xfff,
{ 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } },
- { "Canon EOS 30D", 0,
+ { "Canon EOS 30D", 0, 0,
{ 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } },
- { "Canon EOS 40D", 0,
+ { "Canon EOS 40D", 0, 0x3f60,
{ 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } },
- { "Canon EOS 350D", 0,
+ { "Canon EOS 50D", 0, 0x3d93,
+ { 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } },
+ { "Canon EOS 60D", 0, 0x2ff7,
+ { 6719,-994,-925,-4408,12426,2211,-887,2129,6051 } },
+ { "Canon EOS 70D", 0, 0x3bc7,
+ { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } },
+ { "Canon EOS 77D", 0, 0,
+ { 7377,-742,-998,-4235,11981,2549,-673,1918,5538 } },
+ { "Canon EOS 80D", 0, 0,
+ { 7457,-671,-937,-4849,12495,2643,-1213,2354,5492 } },
+ { "Canon EOS 100D", 0, 0x350f,
+ { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
+ { "Canon EOS 200D", 0, 0,
+ { 7377,-742,-998,-4235,11981,2549,-673,1918,5538 } },
+ { "Canon EOS 300D", 0, 0xfa0,
+ { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+ { "Canon EOS 350D", 0, 0xfff,
{ 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
- { "Canon EOS 400D", 0,
+ { "Canon EOS 400D", 0, 0xe8e,
{ 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
- { "Canon EOS-1Ds Mark III", 0,
+ { "Canon EOS 450D", 0, 0x390d,
+ { 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } },
+ { "Canon EOS 500D", 0, 0x3479,
+ { 4763,712,-646,-6821,14399,2640,-1921,3276,6561 } },
+ { "Canon EOS 550D", 0, 0x3dd7,
+ { 6941,-1164,-857,-3825,11597,2534,-416,1540,6039 } },
+ { "Canon EOS 600D", 0, 0x3510,
+ { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } },
+ { "Canon EOS 650D", 0, 0x354d,
+ { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
+ { "Canon EOS 700D", 0, 0x3c00,
+ { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
+ { "Canon EOS 750D", 0, 0x368e,
+ { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } },
+ { "Canon EOS 760D", 0, 0x350f,
+ { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } },
+ { "Canon EOS 800D", 0, 0,
+ { 6970,-512,-968,-4425,12161,2553,-739,1982,5601 } },
+ { "Canon EOS 1000D", 0, 0xe43,
+ { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } },
+ { "Canon EOS 1100D", 0, 0x3510,
+ { 6444,-904,-893,-4563,12308,2535,-903,2016,6728 } },
+ { "Canon EOS 1200D", 0, 0x37c2,
+ { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } },
+ { "Canon EOS 1300D", 0, 0x3510,
+ { 6939,-1016,-866,-4428,12473,2177,-1175,2178,6162 } },
+ { "Canon EOS 1500D", 0, 0,
+ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } },
+ { "Canon EOS 3000D", 0, 0,
+ { 6939,-1016,-866,-4428,12473,2177,-1175,2178,6162 } },
+ { "Canon EOS M6", 0, 0,
+ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } },
+ { "Canon EOS M5", 0, 0, /* also M50 */
+ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } },
+ { "Canon EOS M3", 0, 0,
+ { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } },
+ { "Canon EOS M100", 0, 0,
+ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } },
+ { "Canon EOS M10", 0, 0,
+ { 6400,-480,-888,-5294,13416,2047,-1296,2203,6137 } },
+ { "Canon EOS M", 0, 0,
+ { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
+ { "Canon EOS-1Ds Mark III", 0, 0x3bb0,
{ 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } },
- { "Canon EOS-1Ds Mark II", 0,
+ { "Canon EOS-1Ds Mark II", 0, 0xe80,
{ 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } },
- { "Canon EOS-1D Mark II N", 0,
- { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
- { "Canon EOS-1D Mark III", 0,
+ { "Canon EOS-1D Mark IV", 0, 0x3bb0,
+ { 6014,-220,-795,-4109,12014,2361,-561,1824,5787 } },
+ { "Canon EOS-1D Mark III", 0, 0x3bb0,
{ 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } },
- { "Canon EOS-1D Mark II", 0,
+ { "Canon EOS-1D Mark II N", 0, 0xe80,
+ { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
+ { "Canon EOS-1D Mark II", 0, 0xe80,
{ 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } },
- { "Canon EOS-1DS", 0,
+ { "Canon EOS-1DS", 0, 0xe20,
{ 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } },
- { "Canon EOS-1D", 0,
+ { "Canon EOS-1D C", 0, 0x3c4e,
+ { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } },
+ { "Canon EOS-1D X Mark II", 0, 0,
+ { 7596,-978,-967,-4808,12571,2503,-1398,2567,5752 } },
+ { "Canon EOS-1D X", 0, 0x3c4e,
+ { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } },
+ { "Canon EOS-1D", 0, 0xe20,
{ 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
- { "Canon EOS", 0,
- { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
- { "Canon PowerShot A50", 0,
+ { "Canon EOS C500", 853, 0, /* DJC */
+ { 17851,-10604,922,-7425,16662,763,-3660,3636,22278 } },
+ { "Canon PowerShot A530", 0, 0,
+ { 0 } }, /* don't want the A5 matrix */
+ { "Canon PowerShot A50", 0, 0,
{ -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } },
- { "Canon PowerShot A5", 0,
+ { "Canon PowerShot A5", 0, 0,
{ -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } },
- { "Canon PowerShot G1", 0,
+ { "Canon PowerShot G10", 0, 0,
+ { 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } },
+ { "Canon PowerShot G11", 0, 0,
+ { 12177,-4817,-1069,-1612,9864,2049,-98,850,4471 } },
+ { "Canon PowerShot G12", 0, 0,
+ { 13244,-5501,-1248,-1508,9858,1935,-270,1083,4366 } },
+ { "Canon PowerShot G15", 0, 0,
+ { 7474,-2301,-567,-4056,11456,2975,-222,716,4181 } },
+ { "Canon PowerShot G16", 0, 0,
+ { 8020,-2687,-682,-3704,11879,2052,-965,1921,5556 } },
+ { "Canon PowerShot G1 X Mark III", 0, 0,
+ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } },
+ { "Canon PowerShot G1 X", 0, 0,
+ { 7378,-1255,-1043,-4088,12251,2048,-876,1946,5805 } },
+ { "Canon PowerShot G1", 0, 0,
{ -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } },
- { "Canon PowerShot G2", 0,
+ { "Canon PowerShot G2", 0, 0,
{ 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } },
- { "Canon PowerShot G3", 0,
+ { "Canon PowerShot G3 X", 0, 0,
+ { 9701,-3857,-921,-3149,11537,1817,-786,1817,5147 } },
+ { "Canon PowerShot G3", 0, 0,
{ 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } },
- { "Canon PowerShot G5", 0,
+ { "Canon PowerShot G5 X", 0, 0,
+ { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } },
+ { "Canon PowerShot G5", 0, 0,
{ 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } },
- { "Canon PowerShot G6", 0,
+ { "Canon PowerShot G6", 0, 0,
{ 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } },
- { "Canon PowerShot G9", 0,
+ { "Canon PowerShot G7 X", 0, 0,
+ { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } },
+ { "Canon PowerShot G9 X Mark II", 0, 0,
+ { 10056,-4131,-944,-2576,11143,1625,-238,1294,5179 } },
+ { "Canon PowerShot G9 X", 0, 0,
+ { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } },
+ { "Canon PowerShot G9", 0, 0,
{ 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } },
- { "Canon PowerShot Pro1", 0,
+ { "Canon PowerShot Pro1", 0, 0,
{ 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } },
- { "Canon PowerShot Pro70", 34,
+ { "Canon PowerShot Pro70", 34, 0,
{ -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } },
- { "Canon PowerShot Pro90", 0,
+ { "Canon PowerShot Pro90", 0, 0,
{ -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } },
- { "Canon PowerShot S30", 0,
+ { "Canon PowerShot S30", 0, 0,
{ 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } },
- { "Canon PowerShot S40", 0,
+ { "Canon PowerShot S40", 0, 0,
{ 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } },
- { "Canon PowerShot S45", 0,
+ { "Canon PowerShot S45", 0, 0,
{ 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } },
- { "Canon PowerShot S50", 0,
+ { "Canon PowerShot S50", 0, 0,
{ 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } },
- { "Canon PowerShot S60", 0,
+ { "Canon PowerShot S60", 0, 0,
{ 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } },
- { "Canon PowerShot S70", 0,
+ { "Canon PowerShot S70", 0, 0,
{ 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } },
- { "Canon PowerShot A610", 0, /* DJC */
+ { "Canon PowerShot S90", 0, 0,
+ { 12374,-5016,-1049,-1677,9902,2078,-83,852,4683 } },
+ { "Canon PowerShot S95", 0, 0,
+ { 13440,-5896,-1279,-1236,9598,1931,-180,1001,4651 } },
+ { "Canon PowerShot S100", 0, 0,
+ { 7968,-2565,-636,-2873,10697,2513,180,667,4211 } },
+ { "Canon PowerShot S110", 0, 0,
+ { 8039,-2643,-654,-3783,11230,2930,-206,690,4194 } },
+ { "Canon PowerShot S120", 0, 0,
+ { 6961,-1685,-695,-4625,12945,1836,-1114,2152,5518 } },
+ { "Canon PowerShot SX1 IS", 0, 0,
+ { 6578,-259,-502,-5974,13030,3309,-308,1058,4970 } },
+ { "Canon PowerShot SX50 HS", 0, 0,
+ { 12432,-4753,-1247,-2110,10691,1629,-412,1623,4926 } },
+ { "Canon PowerShot SX60 HS", 0, 0,
+ { 13161,-5451,-1344,-1989,10654,1531,-47,1271,4955 } },
+ { "Canon PowerShot A3300", 0, 0, /* DJC */
+ { 10826,-3654,-1023,-3215,11310,1906,0,999,4960 } },
+ { "Canon PowerShot A470", 0, 0, /* DJC */
+ { 12513,-4407,-1242,-2680,10276,2405,-878,2215,4734 } },
+ { "Canon PowerShot A610", 0, 0, /* DJC */
{ 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } },
- { "Canon PowerShot A620", 0, /* DJC */
+ { "Canon PowerShot A620", 0, 0, /* DJC */
{ 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } },
- { "Canon PowerShot A640", 0, /* DJC */
+ { "Canon PowerShot A630", 0, 0, /* DJC */
+ { 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } },
+ { "Canon PowerShot A640", 0, 0, /* DJC */
{ 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } },
- { "Canon PowerShot A650", 0, /* DJC */
+ { "Canon PowerShot A650", 0, 0, /* DJC */
{ 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } },
- { "Canon PowerShot S3 IS", 0, /* DJC */
+ { "Canon PowerShot A720", 0, 0, /* DJC */
+ { 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } },
+ { "Canon PowerShot S3 IS", 0, 0, /* DJC */
{ 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } },
- { "CINE 650", 0,
+ { "Canon PowerShot SX110 IS", 0, 0, /* DJC */
+ { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } },
+ { "Canon PowerShot SX220", 0, 0, /* DJC */
+ { 13898,-5076,-1447,-1405,10109,1297,-244,1860,3687 } },
+ { "Canon IXUS 160", 0, 0, /* DJC */
+ { 11657,-3781,-1136,-3544,11262,2283,-160,1219,4700 } },
+ { "Casio EX-S20", 0, 0, /* DJC */
+ { 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } },
+ { "Casio EX-Z750", 0, 0, /* DJC */
+ { 10819,-3873,-1099,-4903,13730,1175,-1755,3751,4632 } },
+ { "Casio EX-Z10", 128, 0xfff, /* DJC */
+ { 9790,-3338,-603,-2321,10222,2099,-344,1273,4799 } },
+ { "CINE 650", 0, 0,
{ 3390,480,-500,-800,3610,340,-550,2336,1192 } },
- { "CINE 660", 0,
+ { "CINE 660", 0, 0,
{ 3390,480,-500,-800,3610,340,-550,2336,1192 } },
- { "CINE", 0,
+ { "CINE", 0, 0,
{ 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } },
- { "Contax N Digital", 0,
+ { "Contax N Digital", 0, 0xf1e,
{ 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } },
- { "EPSON R-D1", 0,
+ { "DXO ONE", 0, 0,
+ { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } },
+ { "Epson R-D1", 0, 0,
{ 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } },
- { "FUJIFILM FinePix E550", 0,
+ { "Fujifilm E550", 0, 0,
{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
- { "FUJIFILM FinePix E900", 0,
+ { "Fujifilm E900", 0, 0,
{ 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
- { "FUJIFILM FinePix F8", 0,
- { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
- { "FUJIFILM FinePix F7", 0,
+ { "Fujifilm F5", 0, 0,
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { "Fujifilm F6", 0, 0,
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { "Fujifilm F77", 0, 0xfe9,
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { "Fujifilm F7", 0, 0,
{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
- { "FUJIFILM FinePix S20Pro", 0,
+ { "Fujifilm F8", 0, 0,
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { "Fujifilm GFX 50S", 0, 0,
+ { 11756,-4754,-874,-3056,11045,2305,-381,1457,6006 } },
+ { "Fujifilm S100FS", 514, 0,
+ { 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } },
+ { "Fujifilm S1", 0, 0,
+ { 12297,-4882,-1202,-2106,10691,1623,-88,1312,4790 } },
+ { "Fujifilm S20Pro", 0, 0,
{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
- { "FUJIFILM FinePix S2Pro", 128,
+ { "Fujifilm S20", 512, 0x3fff,
+ { 11401,-4498,-1312,-5088,12751,2613,-838,1568,5941 } },
+ { "Fujifilm S2Pro", 128, 0xf15,
{ 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } },
- { "FUJIFILM FinePix S3Pro", 0,
+ { "Fujifilm S3Pro", 0, 0x3dff,
{ 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
- { "FUJIFILM FinePix S5Pro", 0,
+ { "Fujifilm S5Pro", 0, 0,
{ 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
- { "FUJIFILM FinePix S5000", 0,
+ { "Fujifilm S5000", 0, 0,
{ 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
- { "FUJIFILM FinePix S5100", 0,
+ { "Fujifilm S5100", 0, 0,
{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
- { "FUJIFILM FinePix S5500", 0,
+ { "Fujifilm S5500", 0, 0,
{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
- { "FUJIFILM FinePix S5200", 0,
+ { "Fujifilm S5200", 0, 0,
{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
- { "FUJIFILM FinePix S5600", 0,
+ { "Fujifilm S5600", 0, 0,
{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
- { "FUJIFILM FinePix S6", 0,
+ { "Fujifilm S6", 0, 0,
{ 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
- { "FUJIFILM FinePix S7000", 0,
+ { "Fujifilm S7000", 0, 0,
{ 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
- { "FUJIFILM FinePix S9000", 0,
+ { "Fujifilm S9000", 0, 0,
{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
- { "FUJIFILM FinePix S9500", 0,
+ { "Fujifilm S9500", 0, 0,
{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
- { "FUJIFILM FinePix S9100", 0,
+ { "Fujifilm S9100", 0, 0,
{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
- { "FUJIFILM FinePix S9600", 0,
+ { "Fujifilm S9600", 0, 0,
{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
- { "FUJIFILM IS-1", 0,
+ { "Fujifilm SL1000", 0, 0,
+ { 11705,-4262,-1107,-2282,10791,1709,-555,1713,4945 } },
+ { "Fujifilm IS-1", 0, 0,
{ 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } },
- { "Imacon Ixpress", 0, /* DJC */
+ { "Fujifilm IS Pro", 0, 0,
+ { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+ { "Fujifilm HS10 HS11", 0, 0xf68,
+ { 12440,-3954,-1183,-1123,9674,1708,-83,1614,4086 } },
+ { "Fujifilm HS2", 0, 0xfef,
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { "Fujifilm HS3", 0, 0,
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { "Fujifilm HS50EXR", 0, 0,
+ { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } },
+ { "Fujifilm F900EXR", 0, 0,
+ { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } },
+ { "Fujifilm X100F", 0, 0,
+ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } },
+ { "Fujifilm X100S", 0, 0,
+ { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } },
+ { "Fujifilm X100T", 0, 0,
+ { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } },
+ { "Fujifilm X100", 0, 0,
+ { 12161,-4457,-1069,-5034,12874,2400,-795,1724,6904 } },
+ { "Fujifilm X10", 0, 0,
+ { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } },
+ { "Fujifilm X20", 0, 0,
+ { 11768,-4971,-1133,-4904,12927,2183,-480,1723,4605 } },
+ { "Fujifilm X30", 0, 0,
+ { 12328,-5256,-1144,-4469,12927,1675,-87,1291,4351 } },
+ { "Fujifilm X70", 0, 0,
+ { 10450,-4329,-878,-3217,11105,2421,-752,1758,6519 } },
+ { "Fujifilm X-Pro1", 0, 0,
+ { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } },
+ { "Fujifilm X-Pro2", 0, 0,
+ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } },
+ { "Fujifilm X-A10", 0, 0,
+ { 11540,-4999,-991,-2949,10963,2278,-382,1049,5605 } },
+ { "Fujifilm X-A20", 0, 0,
+ { 11540,-4999,-991,-2949,10963,2278,-382,1049,5605 } },
+ { "Fujifilm X-A1", 0, 0,
+ { 11086,-4555,-839,-3512,11310,2517,-815,1341,5940 } },
+ { "Fujifilm X-A2", 0, 0,
+ { 10763,-4560,-917,-3346,11311,2322,-475,1135,5843 } },
+ { "Fujifilm X-A3", 0, 0,
+ { 12407,-5222,-1086,-2971,11116,2120,-294,1029,5284 } },
+ { "Fujifilm X-A5", 0, 0,
+ { 11673,-4760,-1041,-3988,12058,2166,-771,1417,5569 } },
+ { "Fujifilm X-E1", 0, 0,
+ { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } },
+ { "Fujifilm X-E2S", 0, 0,
+ { 11562,-5118,-961,-3022,11007,2311,-525,1569,6097 } },
+ { "Fujifilm X-E2", 0, 0,
+ { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } },
+ { "Fujifilm X-E3", 0, 0,
+ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } },
+ { "Fujifilm X-H1", 0, 0,
+ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } },
+ { "Fujifilm X-M1", 0, 0,
+ { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } },
+ { "Fujifilm X-S1", 0, 0,
+ { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } },
+ { "Fujifilm X-T1", 0, 0, /* also X-T10 */
+ { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } },
+ { "Fujifilm X-T2", 0, 0, /* also X-T20 */
+ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } },
+ { "Fujifilm XF1", 0, 0,
+ { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } },
+ { "Fujifilm XQ", 0, 0, /* XQ1 and XQ2 */
+ { 9252,-2704,-1064,-5893,14265,1717,-1101,2341,4349 } },
+ { "GoPro HERO5 Black", 0, 0,
+ { 10344,-4210,-620,-2315,10625,1948,93,1058,5541 } },
+ { "Imacon Ixpress", 0, 0, /* DJC */
{ 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } },
- { "KODAK NC2000", 0,
+ { "Kodak NC2000", 0, 0,
{ 13891,-6055,-803,-465,9919,642,2121,82,1291 } },
- { "Kodak DCS315C", 8,
+ { "Kodak DCS315C", 8, 0,
{ 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } },
- { "Kodak DCS330C", 8,
+ { "Kodak DCS330C", 8, 0,
{ 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } },
- { "KODAK DCS420", 0,
+ { "Kodak DCS420", 0, 0,
{ 10868,-1852,-644,-1537,11083,484,2343,628,2216 } },
- { "KODAK DCS460", 0,
+ { "Kodak DCS460", 0, 0,
{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
- { "KODAK EOSDCS1", 0,
+ { "Kodak EOSDCS1", 0, 0,
{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
- { "KODAK EOSDCS3B", 0,
+ { "Kodak EOSDCS3B", 0, 0,
{ 9898,-2700,-940,-2478,12219,206,1985,634,1031 } },
- { "Kodak DCS520C", 180,
+ { "Kodak DCS520C", 178, 0,
{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
- { "Kodak DCS560C", 188,
+ { "Kodak DCS560C", 177, 0,
{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
- { "Kodak DCS620C", 180,
+ { "Kodak DCS620C", 177, 0,
{ 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
- { "Kodak DCS620X", 185,
+ { "Kodak DCS620X", 176, 0,
{ 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
- { "Kodak DCS660C", 214,
+ { "Kodak DCS660C", 173, 0,
{ 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } },
- { "Kodak DCS720X", 0,
+ { "Kodak DCS720X", 0, 0,
{ 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } },
- { "Kodak DCS760C", 0,
+ { "Kodak DCS760C", 0, 0,
{ 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } },
- { "Kodak DCS Pro SLR", 0,
+ { "Kodak DCS Pro SLR", 0, 0,
{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
- { "Kodak DCS Pro 14nx", 0,
+ { "Kodak DCS Pro 14nx", 0, 0,
{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
- { "Kodak DCS Pro 14", 0,
+ { "Kodak DCS Pro 14", 0, 0,
{ 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } },
- { "Kodak ProBack645", 0,
+ { "Kodak ProBack645", 0, 0,
{ 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } },
- { "Kodak ProBack", 0,
+ { "Kodak ProBack", 0, 0,
{ 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } },
- { "KODAK P712", 0,
+ { "Kodak P712", 0, 0,
{ 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } },
- { "KODAK P850", 0,
+ { "Kodak P850", 0, 0xf7c,
{ 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } },
- { "KODAK P880", 0,
+ { "Kodak P880", 0, 0xfff,
{ 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } },
- { "Leaf CMost", 0,
+ { "Kodak EasyShare Z980", 0, 0,
+ { 11313,-3559,-1101,-3893,11891,2257,-1214,2398,4908 } },
+ { "Kodak EasyShare Z981", 0, 0,
+ { 12729,-4717,-1188,-1367,9187,2582,274,860,4411 } },
+ { "Kodak EasyShare Z990", 0, 0xfed,
+ { 11749,-4048,-1309,-1867,10572,1489,-138,1449,4522 } },
+ { "Kodak EASYSHARE Z1015", 0, 0xef1,
+ { 11265,-4286,-992,-4694,12343,2647,-1090,1523,5447 } },
+ { "Leaf CMost", 0, 0,
{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
- { "Leaf Valeo 6", 0,
+ { "Leaf Valeo 6", 0, 0,
{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
- { "Leaf Aptus 54S", 0,
+ { "Leaf Aptus 54S", 0, 0,
{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
- { "Leaf Aptus 65", 0,
+ { "Leaf Aptus 65", 0, 0,
{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
- { "Leaf Aptus 75", 0,
+ { "Leaf Aptus 75", 0, 0,
{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
- { "Leaf", 0,
+ { "Leaf", 0, 0,
{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
- { "Mamiya ZD", 0,
+ { "Mamiya ZD", 0, 0,
{ 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } },
- { "Micron 2010", 110, /* DJC */
+ { "Micron 2010", 110, 0, /* DJC */
{ 16695,-3761,-2151,155,9682,163,3433,951,4904 } },
- { "Minolta DiMAGE 5", 0,
+ { "Minolta DiMAGE 5", 0, 0xf7d,
{ 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } },
- { "Minolta DiMAGE 7Hi", 0,
+ { "Minolta DiMAGE 7Hi", 0, 0xf7d,
{ 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } },
- { "Minolta DiMAGE 7", 0,
+ { "Minolta DiMAGE 7", 0, 0xf7d,
{ 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } },
- { "Minolta DiMAGE A1", 0,
+ { "Minolta DiMAGE A1", 0, 0xf8b,
{ 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } },
- { "MINOLTA DiMAGE A200", 0,
+ { "Minolta DiMAGE A200", 0, 0,
{ 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } },
- { "Minolta DiMAGE A2", 0,
+ { "Minolta DiMAGE A2", 0, 0xf8f,
{ 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } },
- { "Minolta DiMAGE Z2", 0, /* DJC */
+ { "Minolta DiMAGE Z2", 0, 0, /* DJC */
{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
- { "MINOLTA DYNAX 5", 0,
+ { "Minolta DYNAX 5", 0, 0xffb,
{ 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } },
- { "MINOLTA DYNAX 7", 0,
+ { "Minolta DYNAX 7", 0, 0xffb,
{ 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } },
- { "NIKON D100", 0,
+ { "Motorola PIXL", 0, 0, /* DJC */
+ { 8898,-989,-1033,-3292,11619,1674,-661,3178,5216 } },
+ { "Nikon D100", 0, 0,
{ 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } },
- { "NIKON D1H", 0,
+ { "Nikon D1H", 0, 0,
{ 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } },
- { "NIKON D1X", 0,
+ { "Nikon D1X", 0, 0,
{ 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } },
- { "NIKON D1", 0, /* multiplied by 2.218750, 1.0, 1.148438 */
+ { "Nikon D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */
{ 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } },
- { "NIKON D2H", 0,
+ { "Nikon D200", 0, 0xfbc,
+ { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
+ { "Nikon D2H", 0, 0,
{ 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } },
- { "NIKON D2X", 0,
+ { "Nikon D2X", 0, 0,
{ 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } },
- { "NIKON D40X", 0,
+ { "Nikon D3000", 0, 0,
+ { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+ { "Nikon D3100", 0, 0,
+ { 7911,-2167,-813,-5327,13150,2408,-1288,2483,7968 } },
+ { "Nikon D3200", 0, 0xfb9,
+ { 7013,-1408,-635,-5268,12902,2640,-1470,2801,7379 } },
+ { "Nikon D3300", 0, 0,
+ { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } },
+ { "Nikon D3400", 0, 0,
+ { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } },
+ { "Nikon D300", 0, 0,
+ { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } },
+ { "Nikon D3X", 0, 0,
+ { 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } },
+ { "Nikon D3S", 0, 0,
+ { 8828,-2406,-694,-4874,12603,2541,-660,1509,7587 } },
+ { "Nikon D3", 0, 0,
+ { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+ { "Nikon D40X", 0, 0,
{ 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } },
- { "NIKON D40", 0,
+ { "Nikon D40", 0, 0,
{ 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } },
- { "NIKON D50", 0,
+ { "Nikon D4S", 0, 0,
+ { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } },
+ { "Nikon D4", 0, 0,
+ { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } },
+ { "Nikon Df", 0, 0,
+ { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } },
+ { "Nikon D5000", 0, 0xf00,
+ { 7309,-1403,-519,-8474,16008,2622,-2433,2826,8064 } },
+ { "Nikon D5100", 0, 0x3de6,
+ { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } },
+ { "Nikon D5200", 0, 0,
+ { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } },
+ { "Nikon D5300", 0, 0,
+ { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } },
+ { "Nikon D5500", 0, 0,
+ { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } },
+ { "Nikon D5600", 0, 0,
+ { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } },
+ { "Nikon D500", 0, 0,
+ { 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 } },
+ { "Nikon D50", 0, 0,
{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
- { "NIKON D70", 0,
+ { "Nikon D5", 0, 0,
+ { 9200,-3522,-992,-5755,13803,2117,-753,1486,6338 } },
+ { "Nikon D600", 0, 0x3e07,
+ { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } },
+ { "Nikon D610", 0, 0,
+ { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } },
+ { "Nikon D60", 0, 0,
+ { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+ { "Nikon D7000", 0, 0,
+ { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } },
+ { "Nikon D7100", 0, 0,
+ { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } },
+ { "Nikon D7200", 0, 0,
+ { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } },
+ { "Nikon D7500", 0, 0,
+ { 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 } },
+ { "Nikon D750", 0, 0,
+ { 9020,-2890,-715,-4535,12436,2348,-934,1919,7086 } },
+ { "Nikon D700", 0, 0,
+ { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+ { "Nikon D70", 0, 0,
{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
- { "NIKON D80", 0,
+ { "Nikon D850", 0, 0,
+ { 10405,-3755,-1270,-5461,13787,1793,-1040,2015,6785 } },
+ { "Nikon D810", 0, 0,
+ { 9369,-3195,-791,-4488,12430,2301,-893,1796,6872 } },
+ { "Nikon D800", 0, 0,
+ { 7866,-2108,-555,-4869,12483,2681,-1176,2069,7501 } },
+ { "Nikon D80", 0, 0,
{ 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } },
- { "NIKON D200", 0,
- { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
- { "NIKON D300", 0,
- { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } },
- { "NIKON D3", 0,
- { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
- { "NIKON E950", 0, /* DJC */
+ { "Nikon D90", 0, 0xf00,
+ { 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } },
+ { "Nikon E700", 0, 0x3dd, /* DJC */
+ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
+ { "Nikon E800", 0, 0x3dd, /* DJC */
+ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
+ { "Nikon E950", 0, 0x3dd, /* DJC */
{ -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
- { "NIKON E995", 0, /* copied from E5000 */
+ { "Nikon E995", 0, 0, /* copied from E5000 */
{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
- { "NIKON E2100", 0, /* copied from Z2, new white balance */
+ { "Nikon E2100", 0, 0, /* copied from Z2, new white balance */
{ 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} },
- { "NIKON E2500", 0,
+ { "Nikon E2500", 0, 0,
{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
- { "NIKON E4300", 0, /* copied from Minolta DiMAGE Z2 */
+ { "Nikon E3200", 0, 0, /* DJC */
+ { 9846,-2085,-1019,-3278,11109,2170,-774,2134,5745 } },
+ { "Nikon E4300", 0, 0, /* copied from Minolta DiMAGE Z2 */
{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
- { "NIKON E4500", 0,
+ { "Nikon E4500", 0, 0,
{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
- { "NIKON E5000", 0,
+ { "Nikon E5000", 0, 0,
{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
- { "NIKON E5400", 0,
+ { "Nikon E5400", 0, 0,
{ 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } },
- { "NIKON E5700", 0,
+ { "Nikon E5700", 0, 0,
{ -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } },
- { "NIKON E8400", 0,
+ { "Nikon E8400", 0, 0,
{ 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } },
- { "NIKON E8700", 0,
+ { "Nikon E8700", 0, 0,
{ 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
- { "NIKON E8800", 0,
+ { "Nikon E8800", 0, 0,
{ 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } },
- { "OLYMPUS C5050", 0,
+ { "Nikon COOLPIX A", 0, 0,
+ { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } },
+ { "Nikon COOLPIX B700", 200, 0,
+ { 14387,-6014,-1299,-1357,9975,1616,467,1047,4744 } },
+ { "Nikon COOLPIX P330", 200, 0,
+ { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
+ { "Nikon COOLPIX P340", 200, 0,
+ { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
+ { "Nikon COOLPIX P6000", 0, 0,
+ { 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } },
+ { "Nikon COOLPIX P7000", 0, 0,
+ { 11432,-3679,-1111,-3169,11239,2202,-791,1380,4455 } },
+ { "Nikon COOLPIX P7100", 0, 0,
+ { 11053,-4269,-1024,-1976,10182,2088,-526,1263,4469 } },
+ { "Nikon COOLPIX P7700", 200, 0,
+ { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
+ { "Nikon COOLPIX P7800", 200, 0,
+ { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
+ { "Nikon 1 V3", 0, 0,
+ { 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 } },
+ { "Nikon 1 J4", 0, 0,
+ { 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 } },
+ { "Nikon 1 J5", 0, 0,
+ { 7520,-2518,-645,-3844,12102,1945,-913,2249,6835 } },
+ { "Nikon 1 S2", 200, 0,
+ { 6612,-1342,-618,-3338,11055,2623,-174,1792,5075 } },
+ { "Nikon 1 V2", 0, 0,
+ { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } },
+ { "Nikon 1 J3", 0, 0,
+ { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } },
+ { "Nikon 1 AW1", 0, 0,
+ { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } },
+ { "Nikon 1 ", 0, 0, /* J1, J2, S1, V1 */
+ { 8994,-2667,-865,-4594,12324,2552,-699,1786,6260 } },
+ { "Olympus AIR A01", 0, 0,
+ { 8992,-3093,-639,-2563,10721,2122,-437,1270,5473 } },
+ { "Olympus C5050", 0, 0,
{ 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } },
- { "OLYMPUS C5060", 0,
+ { "Olympus C5060", 0, 0,
{ 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } },
- { "OLYMPUS C7070", 0,
+ { "Olympus C7070", 0, 0,
{ 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } },
- { "OLYMPUS C70", 0,
+ { "Olympus C70", 0, 0,
{ 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } },
- { "OLYMPUS C80", 0,
+ { "Olympus C80", 0, 0,
{ 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } },
- { "OLYMPUS E-10", 0,
+ { "Olympus E-10", 0, 0xffc,
{ 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
- { "OLYMPUS E-1", 0,
+ { "Olympus E-1", 0, 0,
{ 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
- { "OLYMPUS E-20", 0,
+ { "Olympus E-20", 0, 0xffc,
{ 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } },
- { "OLYMPUS E-300", 0,
+ { "Olympus E-300", 0, 0,
{ 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
- { "OLYMPUS E-330", 0,
+ { "Olympus E-330", 0, 0,
{ 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
- { "OLYMPUS E-3", 0,
+ { "Olympus E-30", 0, 0xfbc,
+ { 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } },
+ { "Olympus E-3", 0, 0xf99,
{ 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } },
- { "OLYMPUS E-400", 0,
+ { "Olympus E-400", 0, 0,
{ 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
- { "OLYMPUS E-410", 0,
+ { "Olympus E-410", 0, 0xf6a,
{ 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
- { "OLYMPUS E-500", 0,
+ { "Olympus E-420", 0, 0xfd7,
+ { 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } },
+ { "Olympus E-450", 0, 0xfd2,
+ { 8745,-2425,-1095,-7594,15613,2073,-1780,2309,7416 } },
+ { "Olympus E-500", 0, 0,
{ 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
- { "OLYMPUS E-510", 0,
+ { "Olympus E-510", 0, 0xf6a,
{ 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } },
- { "OLYMPUS SP350", 0,
+ { "Olympus E-520", 0, 0xfd2,
+ { 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } },
+ { "Olympus E-5", 0, 0xeec,
+ { 11200,-3783,-1325,-4576,12593,2206,-695,1742,7504 } },
+ { "Olympus E-600", 0, 0xfaf,
+ { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } },
+ { "Olympus E-620", 0, 0xfaf,
+ { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } },
+ { "Olympus E-P1", 0, 0xffd,
+ { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } },
+ { "Olympus E-P2", 0, 0xffd,
+ { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } },
+ { "Olympus E-P3", 0, 0,
+ { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
+ { "Olympus E-P5", 0, 0,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { "Olympus E-PL1s", 0, 0,
+ { 11409,-3872,-1393,-4572,12757,2003,-709,1810,7415 } },
+ { "Olympus E-PL1", 0, 0,
+ { 11408,-4289,-1215,-4286,12385,2118,-387,1467,7787 } },
+ { "Olympus E-PL2", 0, 0xcf3,
+ { 15030,-5552,-1806,-3987,12387,1767,-592,1670,7023 } },
+ { "Olympus E-PL3", 0, 0,
+ { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
+ { "Olympus E-PL5", 0, 0xfcb,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { "Olympus E-PL6", 0, 0,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { "Olympus E-PL7", 0, 0,
+ { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } },
+ { "Olympus E-PL8", 0, 0,
+ { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } },
+ { "Olympus E-PL9", 0, 0,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { "Olympus E-PM1", 0, 0,
+ { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
+ { "Olympus E-PM2", 0, 0,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { "Olympus E-M10", 0, 0, /* also E-M10 Mark II & III */
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { "Olympus E-M1Mark II", 0, 0,
+ { 9383,-3170,-763,-2457,10702,2020,-384,1236,5552 } },
+ { "Olympus E-M1", 0, 0,
+ { 7687,-1984,-606,-4327,11928,2721,-1381,2339,6452 } },
+ { "Olympus E-M5MarkII", 0, 0,
+ { 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 } },
+ { "Olympus E-M5", 0, 0xfe1,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { "Olympus PEN-F", 0, 0,
+ { 9476,-3182,-765,-2613,10958,1893,-449,1315,5268 } },
+ { "Olympus SH-2", 0, 0,
+ { 10156,-3425,-1077,-2611,11177,1624,-385,1592,5080 } },
+ { "Olympus SP350", 0, 0,
{ 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
- { "OLYMPUS SP3", 0,
+ { "Olympus SP3", 0, 0,
{ 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } },
- { "OLYMPUS SP500UZ", 0,
+ { "Olympus SP500UZ", 0, 0xfff,
{ 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
- { "OLYMPUS SP510UZ", 0,
+ { "Olympus SP510UZ", 0, 0xffe,
{ 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
- { "OLYMPUS SP550UZ", 0,
+ { "Olympus SP550UZ", 0, 0xffe,
{ 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } },
- { "OLYMPUS SP560UZ", 0,
+ { "Olympus SP560UZ", 0, 0xff9,
{ 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } },
- { "PENTAX *ist DL2", 0,
+ { "Olympus SP570UZ", 0, 0,
+ { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } },
+ { "Olympus STYLUS1", 0, 0,
+ { 8360,-2420,-880,-3928,12353,1739,-1381,2416,5173 } },
+ { "Olympus TG-4", 0, 0,
+ { 11426,-4159,-1126,-2066,10678,1593,-120,1327,4998 } },
+ { "Olympus TG-5", 0, 0,
+ { 10899,-3833,-1082,-2112,10736,1575,-267,1452,5269 } },
+ { "Olympus XZ-10", 0, 0,
+ { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } },
+ { "Olympus XZ-1", 0, 0,
+ { 10901,-4095,-1074,-1141,9208,2293,-62,1417,5158 } },
+ { "Olympus XZ-2", 0, 0,
+ { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } },
+ { "OmniVision", 0, 0, /* DJC */
+ { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } },
+ { "Pentax *ist DL2", 0, 0,
{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
- { "PENTAX *ist DL", 0,
+ { "Pentax *ist DL", 0, 0,
{ 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } },
- { "PENTAX *ist DS2", 0,
+ { "Pentax *ist DS2", 0, 0,
{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
- { "PENTAX *ist DS", 0,
+ { "Pentax *ist DS", 0, 0,
{ 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } },
- { "PENTAX *ist D", 0,
+ { "Pentax *ist D", 0, 0,
{ 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } },
- { "PENTAX K10D", 0,
+ { "Pentax K10D", 0, 0,
{ 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } },
- { "PENTAX K1", 0,
+ { "Pentax K1", 0, 0,
{ 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } },
- { "Panasonic DMC-FZ8", 0,
+ { "Pentax K20D", 0, 0,
+ { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
+ { "Pentax K200D", 0, 0,
+ { 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } },
+ { "Pentax K2000", 0, 0,
+ { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+ { "Pentax K-m", 0, 0,
+ { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+ { "Pentax K-x", 0, 0,
+ { 8843,-2837,-625,-5025,12644,2668,-411,1234,7410 } },
+ { "Pentax K-r", 0, 0,
+ { 9895,-3077,-850,-5304,13035,2521,-883,1768,6936 } },
+ { "Pentax K-1", 0, 0,
+ { 8596,-2981,-639,-4202,12046,2431,-685,1424,6122 } },
+ { "Pentax K-30", 0, 0,
+ { 8710,-2632,-1167,-3995,12301,1881,-981,1719,6535 } },
+ { "Pentax K-3 II", 0, 0,
+ { 8626,-2607,-1155,-3995,12301,1881,-1039,1822,6925 } },
+ { "Pentax K-3", 0, 0,
+ { 7415,-2052,-721,-5186,12788,2682,-1446,2157,6773 } },
+ { "Pentax K-5 II", 0, 0,
+ { 8170,-2725,-639,-4440,12017,2744,-771,1465,6599 } },
+ { "Pentax K-5", 0, 0,
+ { 8713,-2833,-743,-4342,11900,2772,-722,1543,6247 } },
+ { "Pentax K-70", 0, 0,
+ { 8270,-2117,-1299,-4359,12953,1515,-1078,1933,5975 } },
+ { "Pentax K-7", 0, 0,
+ { 9142,-2947,-678,-8648,16967,1663,-2224,2898,8615 } },
+ { "Pentax K-S1", 0, 0,
+ { 8512,-3211,-787,-4167,11966,2487,-638,1288,6054 } },
+ { "Pentax K-S2", 0, 0,
+ { 8662,-3280,-798,-3928,11771,2444,-586,1232,6054 } },
+ { "Pentax KP", 0, 0,
+ { 8617,-3228,-1034,-4674,12821,2044,-803,1577,5728 } },
+ { "Pentax Q-S1", 0, 0,
+ { 12995,-5593,-1107,-1879,10139,2027,-64,1233,4919 } },
+ { "Pentax 645D", 0, 0x3e00,
+ { 10646,-3593,-1158,-3329,11699,1831,-667,2874,6287 } },
+ { "Panasonic DMC-CM1", 15, 0,
+ { 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 } },
+ { "Panasonic DC-FZ80", 0, 0,
+ { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } },
+ { "Panasonic DMC-FZ8", 0, 0xf7f,
{ 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } },
- { "Panasonic DMC-FZ18", 0,
+ { "Panasonic DMC-FZ18", 0, 0,
{ 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } },
- { "Panasonic DMC-FZ30", 0,
+ { "Panasonic DMC-FZ28", 15, 0xf96,
+ { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
+ { "Panasonic DMC-FZ2500", 15, 0,
+ { 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 } },
+ { "Panasonic DMC-FZ330", 15, 0,
+ { 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 } },
+ { "Panasonic DMC-FZ300", 15, 0,
+ { 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 } },
+ { "Panasonic DMC-FZ30", 0, 0xf94,
{ 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
- { "Panasonic DMC-FZ50", 0, /* aka "LEICA V-LUX1" */
+ { "Panasonic DMC-FZ3", 15, 0, /* FZ35, FZ38 */
+ { 9938,-2780,-890,-4604,12393,2480,-1117,2304,4620 } },
+ { "Panasonic DMC-FZ4", 15, 0, /* FZ40, FZ45 */
+ { 13639,-5535,-1371,-1698,9633,2430,316,1152,4108 } },
+ { "Panasonic DMC-FZ50", 0, 0,
{ 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
- { "Panasonic DMC-L10", 0,
+ { "Panasonic DMC-FZ7", 15, 0, /* FZ70, FZ72 */
+ { 11532,-4324,-1066,-2375,10847,1749,-564,1699,4351 } },
+ { "Leica V-LUX1", 0, 0,
+ { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
+ { "Panasonic DMC-L10", 15, 0xf96,
{ 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } },
- { "Panasonic DMC-L1", 0, /* aka "LEICA DIGILUX 3" */
+ { "Panasonic DMC-L1", 0, 0xf7f,
+ { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
+ { "Leica DIGILUX 3", 0, 0xf7f,
{ 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
- { "Panasonic DMC-LC1", 0, /* aka "LEICA DIGILUX 2" */
+ { "Panasonic DMC-LC1", 0, 0,
{ 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
- { "Panasonic DMC-LX1", 0, /* aka "LEICA D-LUX2" */
+ { "Leica DIGILUX 2", 0, 0,
+ { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
+ { "Panasonic DMC-LX100", 15, 0,
+ { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } },
+ { "Leica D-LUX (Typ 109)", 15, 0,
+ { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } },
+ { "Panasonic DMC-LF1", 15, 0,
+ { 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 } },
+ { "Leica C (Typ 112)", 15, 0,
+ { 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 } },
+ { "Panasonic DMC-LX1", 0, 0xf7f,
+ { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
+ { "Leica D-LUX2", 0, 0xf7f,
{ 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
- { "Panasonic DMC-LX2", 0, /* aka "LEICA D-LUX3" */
+ { "Panasonic DMC-LX2", 0, 0,
{ 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
- { "Phase One H 20", 0, /* DJC */
+ { "Leica D-LUX3", 0, 0,
+ { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
+ { "Panasonic DMC-LX3", 15, 0,
+ { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
+ { "Leica D-LUX 4", 15, 0,
+ { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
+ { "Panasonic DMC-LX5", 15, 0,
+ { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } },
+ { "Leica D-LUX 5", 15, 0,
+ { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } },
+ { "Panasonic DMC-LX7", 15, 0,
+ { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } },
+ { "Leica D-LUX 6", 15, 0,
+ { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } },
+ { "Panasonic DMC-LX9", 15, 0,
+ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } },
+ { "Panasonic DMC-FZ1000", 15, 0,
+ { 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 } },
+ { "Leica V-LUX (Typ 114)", 15, 0,
+ { 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 } },
+ { "Panasonic DMC-FZ100", 15, 0xfff,
+ { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } },
+ { "Leica V-LUX 2", 15, 0xfff,
+ { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } },
+ { "Panasonic DMC-FZ150", 15, 0xfff,
+ { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } },
+ { "Leica V-LUX 3", 15, 0xfff,
+ { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } },
+ { "Panasonic DMC-FZ200", 15, 0xfff,
+ { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } },
+ { "Leica V-LUX 4", 15, 0xfff,
+ { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } },
+ { "Panasonic DMC-FX150", 15, 0xfff,
+ { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } },
+ { "Panasonic DMC-G10", 0, 0,
+ { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } },
+ { "Panasonic DMC-G1", 15, 0xf94,
+ { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
+ { "Panasonic DMC-G2", 15, 0xf3c,
+ { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } },
+ { "Panasonic DMC-G3", 15, 0xfff,
+ { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } },
+ { "Panasonic DMC-G5", 15, 0xfff,
+ { 7798,-2562,-740,-3879,11584,2613,-1055,2248,5434 } },
+ { "Panasonic DMC-G6", 15, 0xfff,
+ { 8294,-2891,-651,-3869,11590,2595,-1183,2267,5352 } },
+ { "Panasonic DMC-G7", 15, 0xfff,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { "Panasonic DMC-G8", 15, 0xfff, /* G8, G80, G81, G85 */
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { "Panasonic DC-G9", 15, 0xfff,
+ { 7685,-2375,-634,-3687,11700,2249,-748,1546,5111 } },
+ { "Panasonic DMC-GF1", 15, 0xf92,
+ { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } },
+ { "Panasonic DMC-GF2", 15, 0xfff,
+ { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } },
+ { "Panasonic DMC-GF3", 15, 0xfff,
+ { 9051,-2468,-1204,-5212,13276,2121,-1197,2510,6890 } },
+ { "Panasonic DMC-GF5", 15, 0xfff,
+ { 8228,-2945,-660,-3938,11792,2430,-1094,2278,5793 } },
+ { "Panasonic DMC-GF6", 15, 0,
+ { 8130,-2801,-946,-3520,11289,2552,-1314,2511,5791 } },
+ { "Panasonic DMC-GF7", 15, 0,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { "Panasonic DMC-GF8", 15, 0,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { "Panasonic DC-GF9", 15, 0,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { "Panasonic DMC-GH1", 15, 0xf92,
+ { 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } },
+ { "Panasonic DMC-GH2", 15, 0xf95,
+ { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } },
+ { "Panasonic DMC-GH3", 15, 0,
+ { 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 } },
+ { "Panasonic DMC-GH4", 15, 0,
+ { 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 } },
+ { "Panasonic DC-GH5S", 15, 0,
+ { 6929,-2355,-708,-4192,12534,1828,-1097,1989,5195 } },
+ { "Panasonic DC-GH5", 15, 0,
+ { 7641,-2336,-605,-3218,11299,2187,-485,1338,5121 } },
+ { "Panasonic DMC-GM1", 15, 0,
+ { 6770,-1895,-744,-5232,13145,2303,-1664,2691,5703 } },
+ { "Panasonic DMC-GM5", 15, 0,
+ { 8238,-3244,-679,-3921,11814,2384,-836,2022,5852 } },
+ { "Panasonic DMC-GX1", 15, 0,
+ { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } },
+ { "Panasonic DMC-GX7", 15, 0,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { "Panasonic DMC-GX85", 15, 0,
+ { 7771,-3020,-629,-4029,11950,2345,-821,1977,6119 } },
+ { "Panasonic DMC-GX8", 15, 0,
+ { 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 } },
+ { "Panasonic DC-GX9", 15, 0,
+ { 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 } },
+ { "Panasonic DMC-ZS100", 15, 0,
+ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } },
+ { "Panasonic DC-ZS200", 15, 0,
+ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } },
+ { "Panasonic DMC-ZS40", 15, 0,
+ { 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 } },
+ { "Panasonic DMC-ZS50", 15, 0,
+ { 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 } },
+ { "Panasonic DMC-TZ82", 15, 0,
+ { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } },
+ { "Panasonic DMC-ZS6", 15, 0,
+ { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } },
+ { "Panasonic DMC-ZS70", 15, 0,
+ { 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 } },
+ { "Leica S (Typ 007)", 0, 0,
+ { 6063,-2234,-231,-5210,13787,1500,-1043,2866,6997 } },
+ { "Leica X", 0, 0, /* X and X-U, both (Typ 113) */
+ { 7712,-2059,-653,-3882,11494,2726,-710,1332,5958 } },
+ { "Leica Q (Typ 116)", 0, 0,
+ { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830 } },
+ { "Leica M (Typ 262)", 0, 0,
+ { 6653,-1486,-611,-4221,13303,929,-881,2416,7226 } },
+ { "Leica SL (Typ 601)", 0, 0,
+ { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830 } },
+ { "Leica TL2", 0, 0,
+ { 5836,-1626,-647,-5384,13326,2261,-1207,2129,5861 } },
+ { "Leica TL", 0, 0,
+ { 5463,-988,-364,-4634,12036,2946,-766,1389,6522 } },
+ { "Leica CL", 0, 0,
+ { 7414,-2393,-840,-5127,13180,2138,-1585,2468,5064 } },
+ { "Leica M10", 0, 0,
+ { 8249,-2849,-620,-5415,14756,565,-957,3074,6517 } },
+ { "Phase One H 20", 0, 0, /* DJC */
{ 1313,1855,-109,-6715,15908,808,-327,1840,6020 } },
- { "Phase One P 2", 0,
+ { "Phase One H 25", 0, 0,
+ { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
+ { "Phase One P 2", 0, 0,
{ 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
- { "Phase One P 30", 0,
+ { "Phase One P 30", 0, 0,
{ 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } },
- { "Phase One P 45", 0,
+ { "Phase One P 45", 0, 0,
{ 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } },
- { "SAMSUNG GX-1", 0,
+ { "Phase One P40", 0, 0,
+ { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } },
+ { "Phase One P65", 0, 0,
+ { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } },
+ { "Photron BC2-HD", 0, 0, /* DJC */
+ { 14603,-4122,-528,-1810,9794,2017,-297,2763,5936 } },
+ { "Red One", 704, 0xffff, /* DJC */
+ { 21014,-7891,-2613,-3056,12201,856,-2203,5125,8042 } },
+ { "Ricoh GR II", 0, 0,
+ { 4630,-834,-423,-4977,12805,2417,-638,1467,6115 } },
+ { "Ricoh GR", 0, 0,
+ { 3708,-543,-160,-5381,12254,3556,-1471,1929,8234 } },
+ { "Samsung EX1", 0, 0x3e00,
+ { 8898,-2498,-994,-3144,11328,2066,-760,1381,4576 } },
+ { "Samsung EX2F", 0, 0x7ff,
+ { 10648,-3897,-1055,-2022,10573,1668,-492,1611,4742 } },
+ { "Samsung EK-GN120", 0, 0,
+ { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } },
+ { "Samsung NX mini", 0, 0,
+ { 5222,-1196,-550,-6540,14649,2009,-1666,2819,5657 } },
+ { "Samsung NX3300", 0, 0,
+ { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } },
+ { "Samsung NX3000", 0, 0,
+ { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } },
+ { "Samsung NX30", 0, 0, /* NX30, NX300, NX300M */
+ { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } },
+ { "Samsung NX2000", 0, 0,
+ { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } },
+ { "Samsung NX2", 0, 0xfff, /* NX20, NX200, NX210 */
+ { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } },
+ { "Samsung NX1000", 0, 0,
+ { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } },
+ { "Samsung NX1100", 0, 0,
+ { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } },
+ { "Samsung NX11", 0, 0,
+ { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } },
+ { "Samsung NX10", 0, 0, /* also NX100 */
+ { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } },
+ { "Samsung NX500", 0, 0,
+ { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } },
+ { "Samsung NX5", 0, 0,
+ { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } },
+ { "Samsung NX1", 0, 0,
+ { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } },
+ { "Samsung WB2000", 0, 0xfff,
+ { 12093,-3557,-1155,-1000,9534,1733,-22,1787,4576 } },
+ { "Samsung GX-1", 0, 0,
{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
- { "Sinar", 0, /* DJC */
+ { "Samsung GX20", 0, 0, /* copied from Pentax K20D */
+ { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
+ { "Samsung S85", 0, 0, /* DJC */
+ { 11885,-3968,-1473,-4214,12299,1916,-835,1655,5549 } },
+ { "Sinar", 0, 0, /* DJC */
{ 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } },
- { "SONY DSC-F828", 491,
+ { "Sony DSC-F828", 0, 0,
{ 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } },
- { "SONY DSC-R1", 512,
+ { "Sony DSC-R1", 0, 0,
{ 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } },
- { "SONY DSC-V3", 0,
+ { "Sony DSC-V3", 0, 0,
{ 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } },
- { "SONY DSLR-A100", 0,
+ { "Sony DSC-RX100M", 0, 0, /* M2, M3, M4, and M5 */
+ { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } },
+ { "Sony DSC-RX100", 0, 0,
+ { 8651,-2754,-1057,-3464,12207,1373,-568,1398,4434 } },
+ { "Sony DSC-RX10M4", 0, 0,
+ { 7699,-2566,-629,-2967,11270,1928,-378,1286,4807 } },
+ { "Sony DSC-RX10", 0, 0, /* also RX10M2, RX10M3 */
+ { 6679,-1825,-745,-5047,13256,1953,-1580,2422,5183 } },
+ { "Sony DSC-RX1RM2", 0, 0,
+ { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } },
+ { "Sony DSC-RX1", 0, 0,
+ { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } },
+ { "Sony DSC-RX0", 200, 0,
+ { 9396,-3507,-843,-2497,11111,1572,-343,1355,5089 } },
+ { "Sony DSLR-A100", 0, 0xfeb,
{ 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } },
- { "SONY DSLR-A200", 0,
+ { "Sony DSLR-A290", 0, 0,
+ { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } },
+ { "Sony DSLR-A2", 0, 0,
{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
- { "SONY DSLR-A350", 0, /* copied from above */
+ { "Sony DSLR-A300", 0, 0,
{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
- { "SONY DSLR-A700", 254,
- { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } }
+ { "Sony DSLR-A330", 0, 0,
+ { 9847,-3091,-929,-8485,16346,2225,-714,595,7103 } },
+ { "Sony DSLR-A350", 0, 0xffc,
+ { 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } },
+ { "Sony DSLR-A380", 0, 0,
+ { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } },
+ { "Sony DSLR-A390", 0, 0,
+ { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } },
+ { "Sony DSLR-A450", 0, 0xfeb,
+ { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } },
+ { "Sony DSLR-A580", 0, 0xfeb,
+ { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } },
+ { "Sony DSLR-A500", 0, 0xfeb,
+ { 6046,-1127,-278,-5574,13076,2786,-691,1419,7625 } },
+ { "Sony DSLR-A5", 0, 0xfeb,
+ { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } },
+ { "Sony DSLR-A700", 0, 0,
+ { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } },
+ { "Sony DSLR-A850", 0, 0,
+ { 5413,-1162,-365,-5665,13098,2866,-608,1179,8440 } },
+ { "Sony DSLR-A900", 0, 0,
+ { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } },
+ { "Sony ILCA-68", 0, 0,
+ { 6435,-1903,-536,-4722,12449,2550,-663,1363,6517 } },
+ { "Sony ILCA-77M2", 0, 0,
+ { 5991,-1732,-443,-4100,11989,2381,-704,1467,5992 } },
+ { "Sony ILCA-99M2", 0, 0,
+ { 6660,-1918,-471,-4613,12398,2485,-649,1433,6447 } },
+ { "Sony ILCE-6", 0, 0, /* 6300, 6500 */
+ { 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 } },
+ { "Sony ILCE-7M2", 0, 0,
+ { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } },
+ { "Sony ILCE-7M3", 0, 0,
+ { 7374,-2389,-551,-5435,13162,2519,-1006,1795,6552 } },
+ { "Sony ILCE-7S", 0, 0, /* also ILCE-7SM2 */
+ { 5838,-1430,-246,-3497,11477,2297,-748,1885,5778 } },
+ { "Sony ILCE-7RM3", 0, 0,
+ { 6640,-1847,-503,-5238,13010,2474,-993,1673,6527 } },
+ { "Sony ILCE-7RM2", 0, 0,
+ { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } },
+ { "Sony ILCE-7R", 0, 0,
+ { 4913,-541,-202,-6130,13513,2906,-1564,2151,7183 } },
+ { "Sony ILCE-7", 0, 0,
+ { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } },
+ { "Sony ILCE-9", 0, 0,
+ { 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 } },
+ { "Sony ILCE", 0, 0, /* 3000, 5000, 5100, 6000, and QX1 */
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+ { "Sony NEX-5N", 0, 0,
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+ { "Sony NEX-5R", 0, 0,
+ { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
+ { "Sony NEX-5T", 0, 0,
+ { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
+ { "Sony NEX-3N", 0, 0,
+ { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
+ { "Sony NEX-3", 138, 0, /* DJC */
+ { 6907,-1256,-645,-4940,12621,2320,-1710,2581,6230 } },
+ { "Sony NEX-5", 116, 0, /* DJC */
+ { 6807,-1350,-342,-4216,11649,2567,-1089,2001,6420 } },
+ { "Sony NEX-3", 0, 0, /* Adobe */
+ { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } },
+ { "Sony NEX-5", 0, 0, /* Adobe */
+ { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } },
+ { "Sony NEX-6", 0, 0,
+ { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
+ { "Sony NEX-7", 0, 0,
+ { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } },
+ { "Sony NEX", 0, 0, /* NEX-C3, NEX-F3 */
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+ { "Sony SLT-A33", 0, 0,
+ { 6069,-1221,-366,-5221,12779,2734,-1024,2066,6834 } },
+ { "Sony SLT-A35", 0, 0,
+ { 5986,-1618,-415,-4557,11820,3120,-681,1404,6971 } },
+ { "Sony SLT-A37", 0, 0,
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+ { "Sony SLT-A55", 0, 0,
+ { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } },
+ { "Sony SLT-A57", 0, 0,
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+ { "Sony SLT-A58", 0, 0,
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+ { "Sony SLT-A65", 0, 0,
+ { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } },
+ { "Sony SLT-A77", 0, 0,
+ { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } },
+ { "Sony SLT-A99", 0, 0,
+ { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } },
+ { "YI M1", 0, 0,
+ { 7712,-2059,-653,-3882,11494,2726,-710,1332,5958 } },
};
double cam_xyz[4][3];
char name[130];
@@ -6388,11 +8267,13 @@ void CLASS adobe_coeff (char *make, char *model)
sprintf (name, "%s %s", make, model);
for (i=0; i < sizeof table / sizeof *table; i++)
if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) {
- if (table[i].black)
- black = table[i].black;
- for (j=0; j < 12; j++)
- cam_xyz[0][j] = table[i].trans[j] / 10000.0;
- cam_xyz_coeff (cam_xyz);
+ if (table[i].black) black = (ushort) table[i].black;
+ if (table[i].maximum) maximum = (ushort) table[i].maximum;
+ if (table[i].trans[0]) {
+ for (raw_color = j=0; j < 12; j++)
+ ((double *)cam_xyz)[j] = table[i].trans[j] / 10000.0;
+ cam_xyz_coeff (rgb_cam, cam_xyz);
+ }
break;
}
}
@@ -6436,100 +8317,336 @@ short CLASS guess_byte_order (int words)
return sum[0] < sum[1] ? 0x4d4d : 0x4949;
}
+float CLASS find_green (int bps, int bite, int off0, int off1)
+{
+ UINT64 bitbuf=0;
+ int vbits, col, i, c;
+ ushort img[2][2064];
+ double sum[]={0,0};
+
+ FORC(2) {
+ fseek (ifp, c ? off1:off0, SEEK_SET);
+ for (vbits=col=0; col < width; col++) {
+ for (vbits -= bps; vbits < 0; vbits += bite) {
+ bitbuf <<= bite;
+ for (i=0; i < bite; i+=8)
+ bitbuf |= (unsigned) (fgetc(ifp) << i);
+ }
+ img[c][col] = bitbuf << (64-bps-vbits) >> (64-bps);
+ }
+ }
+ FORC(width-1) {
+ sum[ c & 1] += ABS(img[0][c]-img[1][c+1]);
+ sum[~c & 1] += ABS(img[1][c]-img[0][c+1]);
+ }
+ return 100 * log(sum[0]/sum[1]);
+}
+
/*
Identify which camera created this file, and set global variables
accordingly.
*/
void CLASS identify()
{
- char head[32], *cp;
- unsigned hlen, fsize, i, c, is_canon;
- struct jhead jh;
+ static const short pana[][6] = {
+ { 3130, 1743, 4, 0, -6, 0 },
+ { 3130, 2055, 4, 0, -6, 0 },
+ { 3130, 2319, 4, 0, -6, 0 },
+ { 3170, 2103, 18, 0,-42, 20 },
+ { 3170, 2367, 18, 13,-42,-21 },
+ { 3177, 2367, 0, 0, -1, 0 },
+ { 3304, 2458, 0, 0, -1, 0 },
+ { 3330, 2463, 9, 0, -5, 0 },
+ { 3330, 2479, 9, 0,-17, 4 },
+ { 3370, 1899, 15, 0,-44, 20 },
+ { 3370, 2235, 15, 0,-44, 20 },
+ { 3370, 2511, 15, 10,-44,-21 },
+ { 3690, 2751, 3, 0, -8, -3 },
+ { 3710, 2751, 0, 0, -3, 0 },
+ { 3724, 2450, 0, 0, 0, -2 },
+ { 3770, 2487, 17, 0,-44, 19 },
+ { 3770, 2799, 17, 15,-44,-19 },
+ { 3880, 2170, 6, 0, -6, 0 },
+ { 4060, 3018, 0, 0, 0, -2 },
+ { 4290, 2391, 3, 0, -8, -1 },
+ { 4330, 2439, 17, 15,-44,-19 },
+ { 4508, 2962, 0, 0, -3, -4 },
+ { 4508, 3330, 0, 0, -3, -6 },
+ };
+ static const ushort canon[][11] = {
+ { 1944, 1416, 0, 0, 48, 0 },
+ { 2144, 1560, 4, 8, 52, 2, 0, 0, 0, 25 },
+ { 2224, 1456, 48, 6, 0, 2 },
+ { 2376, 1728, 12, 6, 52, 2 },
+ { 2672, 1968, 12, 6, 44, 2 },
+ { 3152, 2068, 64, 12, 0, 0, 16 },
+ { 3160, 2344, 44, 12, 4, 4 },
+ { 3344, 2484, 4, 6, 52, 6 },
+ { 3516, 2328, 42, 14, 0, 0 },
+ { 3596, 2360, 74, 12, 0, 0 },
+ { 3744, 2784, 52, 12, 8, 12 },
+ { 3944, 2622, 30, 18, 6, 2 },
+ { 3948, 2622, 42, 18, 0, 2 },
+ { 3984, 2622, 76, 20, 0, 2, 14 },
+ { 4104, 3048, 48, 12, 24, 12 },
+ { 4116, 2178, 4, 2, 0, 0 },
+ { 4152, 2772, 192, 12, 0, 0 },
+ { 4160, 3124, 104, 11, 8, 65 },
+ { 4176, 3062, 96, 17, 8, 0, 0, 16, 0, 7, 0x49 },
+ { 4192, 3062, 96, 17, 24, 0, 0, 16, 0, 0, 0x49 },
+ { 4312, 2876, 22, 18, 0, 2 },
+ { 4352, 2874, 62, 18, 0, 0 },
+ { 4476, 2954, 90, 34, 0, 0 },
+ { 4480, 3348, 12, 10, 36, 12, 0, 0, 0, 18, 0x49 },
+ { 4480, 3366, 80, 50, 0, 0 },
+ { 4496, 3366, 80, 50, 12, 0 },
+ { 4768, 3516, 96, 16, 0, 0, 0, 16 },
+ { 4832, 3204, 62, 26, 0, 0 },
+ { 4832, 3228, 62, 51, 0, 0 },
+ { 5108, 3349, 98, 13, 0, 0 },
+ { 5120, 3318, 142, 45, 62, 0 },
+ { 5280, 3528, 72, 52, 0, 0 },
+ { 5344, 3516, 142, 51, 0, 0 },
+ { 5344, 3584, 126,100, 0, 2 },
+ { 5360, 3516, 158, 51, 0, 0 },
+ { 5568, 3708, 72, 38, 0, 0 },
+ { 5632, 3710, 96, 17, 0, 0, 0, 16, 0, 0, 0x49 },
+ { 5712, 3774, 62, 20, 10, 2 },
+ { 5792, 3804, 158, 51, 0, 0 },
+ { 5920, 3950, 122, 80, 2, 0 },
+ { 6096, 4051, 76, 35, 0, 0 },
+ { 6096, 4056, 72, 34, 0, 0 },
+ { 6288, 4056, 264, 36, 0, 0 },
+ { 6384, 4224, 120, 44, 0, 0 },
+ { 6880, 4544, 136, 42, 0, 0 },
+ { 8896, 5920, 160, 64, 0, 0 },
+ };
+ static const struct {
+ ushort id;
+ char model[20];
+ } unique[] = {
+ { 0x168, "EOS 10D" }, { 0x001, "EOS-1D" },
+ { 0x175, "EOS 20D" }, { 0x174, "EOS-1D Mark II" },
+ { 0x234, "EOS 30D" }, { 0x232, "EOS-1D Mark II N" },
+ { 0x190, "EOS 40D" }, { 0x169, "EOS-1D Mark III" },
+ { 0x261, "EOS 50D" }, { 0x281, "EOS-1D Mark IV" },
+ { 0x287, "EOS 60D" }, { 0x167, "EOS-1DS" },
+ { 0x325, "EOS 70D" },
+ { 0x408, "EOS 77D" }, { 0x331, "EOS M" },
+ { 0x350, "EOS 80D" }, { 0x328, "EOS-1D X Mark II" },
+ { 0x346, "EOS 100D" },
+ { 0x417, "EOS 200D" },
+ { 0x170, "EOS 300D" }, { 0x188, "EOS-1Ds Mark II" },
+ { 0x176, "EOS 450D" }, { 0x215, "EOS-1Ds Mark III" },
+ { 0x189, "EOS 350D" }, { 0x324, "EOS-1D C" },
+ { 0x236, "EOS 400D" }, { 0x269, "EOS-1D X" },
+ { 0x252, "EOS 500D" }, { 0x213, "EOS 5D" },
+ { 0x270, "EOS 550D" }, { 0x218, "EOS 5D Mark II" },
+ { 0x286, "EOS 600D" }, { 0x285, "EOS 5D Mark III" },
+ { 0x301, "EOS 650D" }, { 0x302, "EOS 6D" },
+ { 0x326, "EOS 700D" }, { 0x250, "EOS 7D" },
+ { 0x393, "EOS 750D" }, { 0x289, "EOS 7D Mark II" },
+ { 0x347, "EOS 760D" }, { 0x406, "EOS 6D Mark II" },
+ { 0x405, "EOS 800D" }, { 0x349, "EOS 5D Mark IV" },
+ { 0x254, "EOS 1000D" },
+ { 0x288, "EOS 1100D" },
+ { 0x327, "EOS 1200D" }, { 0x382, "EOS 5DS" },
+ { 0x404, "EOS 1300D" }, { 0x401, "EOS 5DS R" },
+ { 0x422, "EOS 1500D" },
+ { 0x432, "EOS 3000D" },
+ }, sonique[] = {
+ { 0x002, "DSC-R1" }, { 0x100, "DSLR-A100" },
+ { 0x101, "DSLR-A900" }, { 0x102, "DSLR-A700" },
+ { 0x103, "DSLR-A200" }, { 0x104, "DSLR-A350" },
+ { 0x105, "DSLR-A300" }, { 0x108, "DSLR-A330" },
+ { 0x109, "DSLR-A230" }, { 0x10a, "DSLR-A290" },
+ { 0x10d, "DSLR-A850" }, { 0x111, "DSLR-A550" },
+ { 0x112, "DSLR-A500" }, { 0x113, "DSLR-A450" },
+ { 0x116, "NEX-5" }, { 0x117, "NEX-3" },
+ { 0x118, "SLT-A33" }, { 0x119, "SLT-A55V" },
+ { 0x11a, "DSLR-A560" }, { 0x11b, "DSLR-A580" },
+ { 0x11c, "NEX-C3" }, { 0x11d, "SLT-A35" },
+ { 0x11e, "SLT-A65V" }, { 0x11f, "SLT-A77V" },
+ { 0x120, "NEX-5N" }, { 0x121, "NEX-7" },
+ { 0x123, "SLT-A37" }, { 0x124, "SLT-A57" },
+ { 0x125, "NEX-F3" }, { 0x126, "SLT-A99V" },
+ { 0x127, "NEX-6" }, { 0x128, "NEX-5R" },
+ { 0x129, "DSC-RX100" }, { 0x12a, "DSC-RX1" },
+ { 0x12e, "ILCE-3000" }, { 0x12f, "SLT-A58" },
+ { 0x131, "NEX-3N" }, { 0x132, "ILCE-7" },
+ { 0x133, "NEX-5T" }, { 0x134, "DSC-RX100M2" },
+ { 0x135, "DSC-RX10" }, { 0x136, "DSC-RX1R" },
+ { 0x137, "ILCE-7R" }, { 0x138, "ILCE-6000" },
+ { 0x139, "ILCE-5000" }, { 0x13d, "DSC-RX100M3" },
+ { 0x13e, "ILCE-7S" }, { 0x13f, "ILCA-77M2" },
+ { 0x153, "ILCE-5100" }, { 0x154, "ILCE-7M2" },
+ { 0x155, "DSC-RX100M4" },{ 0x156, "DSC-RX10M2" },
+ { 0x158, "DSC-RX1RM2" }, { 0x15a, "ILCE-QX1" },
+ { 0x15b, "ILCE-7RM2" }, { 0x15e, "ILCE-7SM2" },
+ { 0x161, "ILCA-68" }, { 0x162, "ILCA-99M2" },
+ { 0x163, "DSC-RX10M3" }, { 0x164, "DSC-RX100M5" },
+ { 0x165, "ILCE-6300" }, { 0x166, "ILCE-9" },
+ { 0x168, "ILCE-6500" }, { 0x16a, "ILCE-7RM3" },
+ { 0x16b, "ILCE-7M3" }, { 0x16c, "DSC-RX0" },
+ { 0x16d, "DSC-RX10M4" },
+ };
+ static const char *orig, panalias[][12] = {
+ "@DC-FZ80", "DC-FZ82", "DC-FZ85",
+ "@DC-FZ81", "DC-FZ83",
+ "@DC-GF9", "DC-GX800", "DC-GX850",
+ "@DC-GF10", "DC-GF90",
+ "@DC-GX9", "DC-GX7MK3",
+ "@DC-ZS70", "DC-TZ90", "DC-TZ91", "DC-TZ92", "DC-TZ93",
+ "@DMC-FZ40", "DMC-FZ45",
+ "@DMC-FZ2500", "DMC-FZ2000", "DMC-FZH1",
+ "@DMC-G8", "DMC-G80", "DMC-G81", "DMC-G85",
+ "@DMC-GX85", "DMC-GX80", "DMC-GX7MK2",
+ "@DMC-LX9", "DMC-LX10", "DMC-LX15",
+ "@DMC-ZS40", "DMC-TZ60", "DMC-TZ61",
+ "@DMC-ZS50", "DMC-TZ70", "DMC-TZ71",
+ "@DMC-ZS60", "DMC-TZ80", "DMC-TZ81", "DMC-TZ85",
+ "@DMC-ZS100", "DMC-ZS110", "DMC-TZ100", "DMC-TZ101", "DMC-TZ110", "DMC-TX1",
+ "@DC-ZS200", "DC-TX2", "DC-TZ200", "DC-TZ202", "DC-TZ220", "DC-ZS220",
+ };
static const struct {
- int fsize;
- char make[12], model[19], withjpeg;
+ unsigned fsize;
+ ushort rw, rh;
+ uchar lm, tm, rm, bm, lf, cf, max, flags;
+ char make[10], model[20];
+ ushort offset;
} table[] = {
- { 62464, "Kodak", "DC20" ,0 },
- { 124928, "Kodak", "DC20" ,0 },
- { 1652736, "Kodak", "DCS200" ,0 },
- { 4159302, "Kodak", "C330" ,0 },
- { 4162462, "Kodak", "C330" ,0 },
- { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */
- { 614400, "Kodak", "KAI-0340" ,0 },
- { 787456, "Creative", "PC-CAM 600" ,0 },
- { 1138688, "Minolta", "RD175" ,0 },
- { 3840000, "Foculus", "531C" ,0 },
- { 786432, "AVT", "F-080C" ,0 },
- { 1447680, "AVT", "F-145C" ,0 },
- { 1920000, "AVT", "F-201C" ,0 },
- { 5067304, "AVT", "F-510C" ,0 },
- { 10134608, "AVT", "F-510C" ,0 },
- { 16157136, "AVT", "F-810C" ,0 },
- { 1409024, "Sony", "XCD-SX910CR",0 },
- { 2818048, "Sony", "XCD-SX910CR",0 },
- { 3884928, "Micron", "2010" ,0 },
- { 6624000, "Pixelink", "A782" ,0 },
- { 13248000, "Pixelink", "A782" ,0 },
- { 6291456, "RoverShot","3320AF" ,0 },
- { 6553440, "Canon", "PowerShot A460",0 },
- { 6653280, "Canon", "PowerShot A530",0 },
- { 6573120, "Canon", "PowerShot A610",0 },
- { 9219600, "Canon", "PowerShot A620",0 },
- { 10341600, "Canon", "PowerShot A720",0 },
- { 10383120, "Canon", "PowerShot A630",0 },
- { 12945240, "Canon", "PowerShot A640",0 },
- { 15636240, "Canon", "PowerShot A650",0 },
- { 7710960, "Canon", "PowerShot S3 IS",0 },
- { 5939200, "OLYMPUS", "C770UZ" ,0 },
- { 1581060, "NIKON", "E900" ,1 }, /* or E900s,E910 */
- { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */
- { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */
- { 4771840, "NIKON", "E990" ,1 }, /* or E995, Oly C3030Z */
- { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */
- { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */
- { 5865472, "NIKON", "E4500" ,1 },
- { 7438336, "NIKON", "E5000" ,1 }, /* or E5700 */
- { 8998912, "NIKON", "COOLPIX S6" ,1 },
- { 1976352, "CASIO", "QV-2000UX" ,1 },
- { 3217760, "CASIO", "QV-3*00EX" ,1 },
- { 6218368, "CASIO", "QV-5700" ,1 },
- { 6054400, "CASIO", "QV-R41" ,1 },
- { 7530816, "CASIO", "QV-R51" ,1 },
- { 7684000, "CASIO", "QV-4000" ,1 },
- { 4948608, "CASIO", "EX-S100" ,1 },
- { 7542528, "CASIO", "EX-Z50" ,1 },
- { 7753344, "CASIO", "EX-Z55" ,1 },
- { 7426656, "CASIO", "EX-P505" ,1 },
- { 9313536, "CASIO", "EX-P600" ,1 },
- { 10979200, "CASIO", "EX-P700" ,1 },
- { 3178560, "PENTAX", "Optio S" ,1 },
- { 4841984, "PENTAX", "Optio S" ,1 },
- { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i, CASIO EX-Z4 */
- { 10702848, "PENTAX", "Optio 750Z" ,1 },
- { 12582980, "Sinar", "" ,0 },
- { 33292868, "Sinar", "" ,0 },
- { 44390468, "Sinar", "" ,0 } };
+ { 786432,1024, 768, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-080C" },
+ { 1447680,1392,1040, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-145C" },
+ { 1920000,1600,1200, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-201C" },
+ { 5067304,2588,1958, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-510C" },
+ { 5067316,2588,1958, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-510C",12 },
+ { 10134608,2588,1958, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-510C" },
+ { 10134620,2588,1958, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-510C",12 },
+ { 16157136,3272,2469, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-810C" },
+ { 15980544,3264,2448, 0, 0, 0, 0, 8,0x61,0,1,"AgfaPhoto","DC-833m" },
+ { 9631728,2532,1902, 0, 0, 0, 0,96,0x61,0,0,"Alcatel","5035D" },
+ { 2868726,1384,1036, 0, 0, 0, 0,64,0x49,0,8,"Baumer","TXG14",1078 },
+ { 5298000,2400,1766,12,12,44, 2, 8,0x94,0,2,"Canon","PowerShot SD300" },
+ { 6553440,2664,1968, 4, 4,44, 4, 8,0x94,0,2,"Canon","PowerShot A460" },
+ { 6573120,2672,1968,12, 8,44, 0, 8,0x94,0,2,"Canon","PowerShot A610" },
+ { 6653280,2672,1992,10, 6,42, 2, 8,0x94,0,2,"Canon","PowerShot A530" },
+ { 7710960,2888,2136,44, 8, 4, 0, 8,0x94,0,2,"Canon","PowerShot S3 IS" },
+ { 9219600,3152,2340,36,12, 4, 0, 8,0x94,0,2,"Canon","PowerShot A620" },
+ { 9243240,3152,2346,12, 7,44,13, 8,0x49,0,2,"Canon","PowerShot A470" },
+ { 10341600,3336,2480, 6, 5,32, 3, 8,0x94,0,2,"Canon","PowerShot A720 IS" },
+ { 10383120,3344,2484,12, 6,44, 6, 8,0x94,0,2,"Canon","PowerShot A630" },
+ { 12945240,3736,2772,12, 6,52, 6, 8,0x94,0,2,"Canon","PowerShot A640" },
+ { 15636240,4104,3048,48,12,24,12, 8,0x94,0,2,"Canon","PowerShot A650" },
+ { 15467760,3720,2772, 6,12,30, 0, 8,0x94,0,2,"Canon","PowerShot SX110 IS" },
+ { 15534576,3728,2778,12, 9,44, 9, 8,0x94,0,2,"Canon","PowerShot SX120 IS" },
+ { 18653760,4080,3048,24,12,24,12, 8,0x94,0,2,"Canon","PowerShot SX20 IS" },
+ { 19131120,4168,3060,92,16, 4, 1, 8,0x94,0,2,"Canon","PowerShot SX220 HS" },
+ { 21936096,4464,3276,25,10,73,12, 8,0x16,0,2,"Canon","PowerShot SX30 IS" },
+ { 24724224,4704,3504, 8,16,56, 8, 8,0x94,0,2,"Canon","PowerShot A3300 IS" },
+ { 30858240,5248,3920, 8,16,56,16, 8,0x94,0,2,"Canon","IXUS 160" },
+ { 1976352,1632,1211, 0, 2, 0, 1, 0,0x94,0,1,"Casio","QV-2000UX" },
+ { 3217760,2080,1547, 0, 0,10, 1, 0,0x94,0,1,"Casio","QV-3*00EX" },
+ { 6218368,2585,1924, 0, 0, 9, 0, 0,0x94,0,1,"Casio","QV-5700" },
+ { 7816704,2867,2181, 0, 0,34,36, 0,0x16,0,1,"Casio","EX-Z60" },
+ { 2937856,1621,1208, 0, 0, 1, 0, 0,0x94,7,13,"Casio","EX-S20" },
+ { 4948608,2090,1578, 0, 0,32,34, 0,0x94,7,1,"Casio","EX-S100" },
+ { 6054400,2346,1720, 2, 0,32, 0, 0,0x94,7,1,"Casio","QV-R41" },
+ { 7426656,2568,1928, 0, 0, 0, 0, 0,0x94,0,1,"Casio","EX-P505" },
+ { 7530816,2602,1929, 0, 0,22, 0, 0,0x94,7,1,"Casio","QV-R51" },
+ { 7542528,2602,1932, 0, 0,32, 0, 0,0x94,7,1,"Casio","EX-Z50" },
+ { 7562048,2602,1937, 0, 0,25, 0, 0,0x16,7,1,"Casio","EX-Z500" },
+ { 7753344,2602,1986, 0, 0,32,26, 0,0x94,7,1,"Casio","EX-Z55" },
+ { 9313536,2858,2172, 0, 0,14,30, 0,0x94,7,1,"Casio","EX-P600" },
+ { 10834368,3114,2319, 0, 0,27, 0, 0,0x94,0,1,"Casio","EX-Z750" },
+ { 10843712,3114,2321, 0, 0,25, 0, 0,0x94,0,1,"Casio","EX-Z75" },
+ { 10979200,3114,2350, 0, 0,32,32, 0,0x94,7,1,"Casio","EX-P700" },
+ { 12310144,3285,2498, 0, 0, 6,30, 0,0x94,0,1,"Casio","EX-Z850" },
+ { 12489984,3328,2502, 0, 0,47,35, 0,0x94,0,1,"Casio","EX-Z8" },
+ { 15499264,3754,2752, 0, 0,82, 0, 0,0x94,0,1,"Casio","EX-Z1050" },
+ { 18702336,4096,3044, 0, 0,24, 0,80,0x94,7,1,"Casio","EX-ZR100" },
+ { 7684000,2260,1700, 0, 0, 0, 0,13,0x94,0,1,"Casio","QV-4000" },
+ { 787456,1024, 769, 0, 1, 0, 0, 0,0x49,0,0,"Creative","PC-CAM 600" },
+ { 28829184,4384,3288, 0, 0, 0, 0,36,0x61,0,0,"DJI" },
+ { 15151104,4608,3288, 0, 0, 0, 0, 0,0x94,0,0,"Matrix" },
+ { 3840000,1600,1200, 0, 0, 0, 0,65,0x49,0,0,"Foculus","531C" },
+ { 307200, 640, 480, 0, 0, 0, 0, 0,0x94,0,0,"Generic" },
+ { 62464, 256, 244, 1, 1, 6, 1, 0,0x8d,0,0,"Kodak","DC20" },
+ { 124928, 512, 244, 1, 1,10, 1, 0,0x8d,0,0,"Kodak","DC20" },
+ { 1652736,1536,1076, 0,52, 0, 0, 0,0x61,0,0,"Kodak","DCS200" },
+ { 4159302,2338,1779, 1,33, 1, 2, 0,0x94,0,0,"Kodak","C330" },
+ { 4162462,2338,1779, 1,33, 1, 2, 0,0x94,0,0,"Kodak","C330",3160 },
+ { 2247168,1232, 912, 0, 0,16, 0, 0,0x00,0,0,"Kodak","C330" },
+ { 3370752,1232, 912, 0, 0,16, 0, 0,0x00,0,0,"Kodak","C330" },
+ { 6163328,2864,2152, 0, 0, 0, 0, 0,0x94,0,0,"Kodak","C603" },
+ { 6166488,2864,2152, 0, 0, 0, 0, 0,0x94,0,0,"Kodak","C603",3160 },
+ { 460800, 640, 480, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","C603" },
+ { 9116448,2848,2134, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","C603" },
+ { 12241200,4040,3030, 2, 0, 0,13, 0,0x49,0,0,"Kodak","12MP" },
+ { 12272756,4040,3030, 2, 0, 0,13, 0,0x49,0,0,"Kodak","12MP",31556 },
+ { 18000000,4000,3000, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","12MP" },
+ { 614400, 640, 480, 0, 3, 0, 0,64,0x94,0,0,"Kodak","KAI-0340" },
+ { 15360000,3200,2400, 0, 0, 0, 0,96,0x16,0,0,"Lenovo","A820" },
+ { 3884928,1608,1207, 0, 0, 0, 0,96,0x16,0,0,"Micron","2010",3212 },
+ { 1138688,1534, 986, 0, 0, 0, 0, 0,0x61,0,0,"Minolta","RD175",513 },
+ { 1581060,1305, 969, 0, 0,18, 6, 6,0x1e,4,1,"Nikon","E900" },
+ { 2465792,1638,1204, 0, 0,22, 1, 6,0x4b,5,1,"Nikon","E950" },
+ { 2940928,1616,1213, 0, 0, 0, 7,30,0x94,0,1,"Nikon","E2100" },
+ { 4771840,2064,1541, 0, 0, 0, 1, 6,0xe1,0,1,"Nikon","E990" },
+ { 4775936,2064,1542, 0, 0, 0, 0,30,0x94,0,1,"Nikon","E3700" },
+ { 5865472,2288,1709, 0, 0, 0, 1, 6,0xb4,0,1,"Nikon","E4500" },
+ { 5869568,2288,1710, 0, 0, 0, 0, 6,0x16,0,1,"Nikon","E4300" },
+ { 7438336,2576,1925, 0, 0, 0, 1, 6,0xb4,0,1,"Nikon","E5000" },
+ { 8998912,2832,2118, 0, 0, 0, 0,30,0x94,7,1,"Nikon","COOLPIX S6" },
+ { 5939200,2304,1718, 0, 0, 0, 0,30,0x16,0,0,"Olympus","C770UZ" },
+ { 3178560,2064,1540, 0, 0, 0, 0, 0,0x94,0,1,"Pentax","Optio S" },
+ { 4841984,2090,1544, 0, 0,22, 0, 0,0x94,7,1,"Pentax","Optio S" },
+ { 6114240,2346,1737, 0, 0,22, 0, 0,0x94,7,1,"Pentax","Optio S4" },
+ { 10702848,3072,2322, 0, 0, 0,21,30,0x94,0,1,"Pentax","Optio 750Z" },
+ { 4147200,1920,1080, 0, 0, 0, 0, 0,0x49,0,0,"Photron","BC2-HD" },
+ { 4151666,1920,1080, 0, 0, 0, 0, 0,0x49,0,0,"Photron","BC2-HD",8 },
+ { 13248000,2208,3000, 0, 0, 0, 0,13,0x61,0,0,"Pixelink","A782" },
+ { 6291456,2048,1536, 0, 0, 0, 0,96,0x61,0,0,"RoverShot","3320AF" },
+ { 311696, 644, 484, 0, 0, 0, 0, 0,0x16,0,8,"ST Micro","STV680 VGA" },
+ { 16098048,3288,2448, 0, 0,24, 0, 9,0x94,0,1,"Samsung","S85" },
+ { 16215552,3312,2448, 0, 0,48, 0, 9,0x94,0,1,"Samsung","S85" },
+ { 20487168,3648,2808, 0, 0, 0, 0,13,0x94,5,1,"Samsung","WB550" },
+ { 24000000,4000,3000, 0, 0, 0, 0,13,0x94,5,1,"Samsung","WB550" },
+ { 12582980,3072,2048, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 },
+ { 33292868,4080,4080, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 },
+ { 44390468,4080,5440, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 },
+ { 1409024,1376,1024, 0, 0, 1, 0, 0,0x49,0,0,"Sony","XCD-SX910CR" },
+ { 2818048,1376,1024, 0, 0, 1, 0,97,0x49,0,0,"Sony","XCD-SX910CR" },
+ { 17496000,4320,3240, 0, 0, 0,0,224,0x94,0,0,"Xiro","Xplorer V" },
+ };
static const char *corp[] =
- { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX",
- "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One",
- "SAMSUNG", "Mamiya" };
+ { "AgfaPhoto", "Canon", "Casio", "Epson", "Fujifilm",
+ "Mamiya", "Minolta", "Motorola", "Kodak", "Konica", "Leica",
+ "Nikon", "Nokia", "Olympus", "Ricoh", "Pentax", "Phase One",
+ "Samsung", "Sigma", "Sinar", "Sony", "YI" };
+ char head[32], *cp;
+ int hlen, flen, fsize, zero_fsize=1, i, c;
+ struct jhead jh;
- tiff_flip = flip = filters = -1; /* 0 is valid, so -1 is unknown */
+ tiff_flip = flip = filters = UINT_MAX; /* unknown */
raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
maximum = height = width = top_margin = left_margin = 0;
cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
iso_speed = shutter = aperture = focal_len = unique_id = 0;
+ tiff_nifds = 0;
+ memset (tiff_ifd, 0, sizeof tiff_ifd);
memset (gpsdata, 0, sizeof gpsdata);
+ memset (cblack, 0, sizeof cblack);
memset (white, 0, sizeof white);
+ memset (mask, 0, sizeof mask);
thumb_offset = thumb_length = thumb_width = thumb_height = 0;
load_raw = thumb_load_raw = 0;
write_thumb = &CLASS jpeg_thumb;
- data_offset = meta_length = tiff_bps = tiff_compress = 0;
- kodak_cbpp = zero_after_ff = dng_version = 0;
+ data_offset = meta_offset = meta_length = tiff_bps = tiff_compress = 0;
+ kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
timestamp = shot_order = tiff_samples = black = is_foveon = 0;
mix_green = profile_length = data_error = zero_is_bad = 0;
- pixel_aspect = is_raw = raw_color = use_gamma = 1;
- tile_width = tile_length = INT_MAX;
+ pixel_aspect = is_raw = raw_color = 1;
+ tile_width = tile_length = 0;
for (i=0; i < 4; i++) {
cam_mul[i] = i == 1;
pre_mul[i] = i < 3;
@@ -6537,26 +8654,24 @@ void CLASS identify()
FORC3 rgb_cam[c][i] = c == i;
}
colors = 3;
- tiff_bps = 12;
- for (i=0; i < 0x4000; i++) curve[i] = i;
+ for (i=0; i < 0x10000; i++) curve[i] = i;
order = get2();
hlen = get4();
fseek (ifp, 0, SEEK_SET);
fread (head, 1, 32, ifp);
fseek (ifp, 0, SEEK_END);
- fsize = ftell(ifp);
+ flen = fsize = ftell(ifp);
if ((cp = (char *) memmem (head, 32, "MMMM", 4)) ||
(cp = (char *) memmem (head, 32, "IIII", 4))) {
parse_phase_one (cp-head);
- if (cp-head) parse_tiff(0);
+ if (cp-head && parse_tiff(0)) apply_tiff();
} else if (order == 0x4949 || order == 0x4d4d) {
if (!memcmp (head+6,"HEAPCCDR",8)) {
data_offset = hlen;
- parse_ciff (hlen, fsize - hlen);
- } else {
- parse_tiff(0);
- }
+ parse_ciff (hlen, flen-hlen, 0);
+ load_raw = &CLASS canon_load_raw;
+ } else if (parse_tiff(0)) apply_tiff();
} else if (!memcmp (head,"\xff\xd8\xff\xe1",4) &&
!memcmp (head+6,"Exif",4)) {
fseek (ifp, 4, SEEK_SET);
@@ -6578,9 +8693,11 @@ void CLASS identify()
} else if (!strcmp (head, "qktk")) {
strcpy (make, "Apple");
strcpy (model,"QuickTake 100");
+ load_raw = &CLASS quicktake_100_load_raw;
} else if (!strcmp (head, "qktn")) {
strcpy (make, "Apple");
strcpy (model,"QuickTake 150");
+ load_raw = &CLASS kodak_radc_load_raw;
} else if (!memcmp (head,"FUJIFILM",8)) {
fseek (ifp, 84, SEEK_SET);
thumb_offset = get4();
@@ -6593,12 +8710,24 @@ void CLASS identify()
if (is_raw == 2 && shot_select)
parse_fuji (i);
}
- fseek (ifp, 100, SEEK_SET);
- data_offset = get4();
+ fseek (ifp, 100+28*(shot_select > 0), SEEK_SET);
+ parse_tiff (data_offset = get4());
parse_tiff (thumb_offset+12);
+ apply_tiff();
+ if (!load_raw) {
+ load_raw = &CLASS unpacked_load_raw;
+ tiff_bps = 14;
+ }
} else if (!memcmp (head,"RIFF",4)) {
fseek (ifp, 0, SEEK_SET);
parse_riff();
+ } else if (!memcmp (head+4,"ftypcrx ",8)) {
+ fseek (ifp, 0, SEEK_SET);
+ parse_crx (fsize);
+ } else if (!memcmp (head+4,"ftypqt ",9)) {
+ fseek (ifp, 0, SEEK_SET);
+ parse_qt (fsize);
+ is_raw = 0;
} else if (!memcmp (head,"\0\001\0\001\0@",6)) {
fseek (ifp, 6, SEEK_SET);
fread (make, 1, 8, ifp);
@@ -6608,8 +8737,53 @@ void CLASS identify()
get2();
raw_width = get2();
raw_height = get2();
- load_raw = nokia_load_raw;
+ load_raw = &CLASS nokia_load_raw;
filters = 0x61616161;
+ } else if (!memcmp (head,"NOKIARAW",8)) {
+ strcpy (make, "NOKIA");
+ order = 0x4949;
+ fseek (ifp, 300, SEEK_SET);
+ data_offset = get4();
+ i = get4();
+ width = get2();
+ height = get2();
+ switch (tiff_bps = i*8 / (width * height)) {
+ case 8: load_raw = &CLASS eight_bit_load_raw; break;
+ case 10: load_raw = &CLASS nokia_load_raw;
+ }
+ raw_height = height + (top_margin = i / (width * tiff_bps/8) - height);
+ mask[0][3] = 1;
+ filters = 0x61616161;
+ } else if (!memcmp (head,"ARRI",4)) {
+ order = 0x4949;
+ fseek (ifp, 20, SEEK_SET);
+ width = get4();
+ height = get4();
+ strcpy (make, "ARRI");
+ fseek (ifp, 668, SEEK_SET);
+ fread (model, 1, 64, ifp);
+ data_offset = 4096;
+ load_raw = &CLASS packed_load_raw;
+ load_flags = 88;
+ filters = 0x61616161;
+ } else if (!memcmp (head,"XPDS",4)) {
+ order = 0x4949;
+ fseek (ifp, 0x800, SEEK_SET);
+ fread (make, 1, 41, ifp);
+ raw_height = get2();
+ raw_width = get2();
+ fseek (ifp, 56, SEEK_CUR);
+ fread (model, 1, 30, ifp);
+ data_offset = 0x10000;
+ load_raw = &CLASS canon_rmf_load_raw;
+ gamma_curve (0, 12.25, 1, 1023);
+ } else if (!memcmp (head+4,"RED1",4)) {
+ strcpy (make, "Red");
+ strcpy (model,"One");
+ parse_redcine();
+ load_raw = &CLASS redcine_load_raw;
+ gamma_curve (1/2.4, 12.92, 1, 4095);
+ filters = 0x49494949;
} else if (!memcmp (head,"DSC-Image",9))
parse_rollei();
else if (!memcmp (head,"PWAD",4))
@@ -6620,22 +8794,67 @@ void CLASS identify()
parse_foveon();
else if (!memcmp (head,"CI",2))
parse_cine();
- else
- for (i=0; i < sizeof table / sizeof *table; i++)
+ if (make[0] == 0)
+ for (zero_fsize=i=0; i < sizeof table / sizeof *table; i++)
if (fsize == table[i].fsize) {
strcpy (make, table[i].make );
strcpy (model, table[i].model);
- if (table[i].withjpeg)
+ flip = table[i].flags >> 2;
+ zero_is_bad = table[i].flags & 2;
+ if (table[i].flags & 1)
parse_external_jpeg();
+ data_offset = table[i].offset;
+ raw_width = table[i].rw;
+ raw_height = table[i].rh;
+ left_margin = table[i].lm;
+ top_margin = table[i].tm;
+ width = raw_width - left_margin - table[i].rm;
+ height = raw_height - top_margin - table[i].bm;
+ filters = 0x1010101 * table[i].cf;
+ colors = 4 - !((filters & filters >> 1) & 0x5555);
+ load_flags = table[i].lf;
+ switch (tiff_bps = (fsize-data_offset)*8 / (raw_width*raw_height)) {
+ case 6:
+ load_raw = &CLASS minolta_rd175_load_raw; break;
+ case 8:
+ load_raw = &CLASS eight_bit_load_raw; break;
+ case 10: case 12:
+ load_flags |= 512;
+ if (!strcmp(make,"Canon")) load_flags |= 256;
+ load_raw = &CLASS packed_load_raw; break;
+ case 16:
+ order = 0x4949 | 0x404 * (load_flags & 1);
+ tiff_bps -= load_flags >> 4;
+ tiff_bps -= load_flags = load_flags >> 1 & 7;
+ load_raw = &CLASS unpacked_load_raw;
+ }
+ maximum = (1 << tiff_bps) - (1 << table[i].max);
}
- if (make[0] == 0) parse_smal (0, fsize);
- if (make[0] == 0) parse_jpeg (is_raw = 0);
+ if (zero_fsize) fsize = 0;
+ if (make[0] == 0) parse_smal (0, flen);
+ if (make[0] == 0) {
+ parse_jpeg(0);
+ if (!(strncmp(model,"ov",2) && strncmp(model,"RP_OV",5)) &&
+ !fseek (ifp, -6404096, SEEK_END) &&
+ fread (head, 1, 32, ifp) && !strcmp(head,"BRCMn")) {
+ strcpy (make, "OmniVision");
+ data_offset = ftell(ifp) + 0x8000-32;
+ width = raw_width;
+ raw_width = 2611;
+ load_raw = &CLASS nokia_load_raw;
+ filters = 0x16161616;
+ } else is_raw = 0;
+ }
for (i=0; i < sizeof corp / sizeof *corp; i++)
- if (strstr (make, corp[i])) /* Simplify company names */
- strcpy (make, corp[i]);
- if (!strncmp (make,"KODAK",5))
- make[16] = model[16] = 0;
+ if (strcasestr (make, corp[i])) /* Simplify company names */
+ strcpy (make, corp[i]);
+ if ((!strcmp(make,"Kodak") || !strcmp(make,"Leica")) &&
+ ((cp = strcasestr(model," DIGITAL CAMERA")) ||
+ (cp = strstr(model,"FILE VERSION"))))
+ *cp = 0;
+ if (!strncasecmp(model,"PENTAX",6))
+ strcpy (make, "Pentax");
cp = make + strlen(make); /* Remove trailing spaces */
while (*--cp == ' ') *cp = 0;
cp = model + strlen(model);
@@ -6643,57 +8862,128 @@ void CLASS identify()
i = strlen(make); /* Remove make from model */
if (!strncasecmp (model, make, i) && model[i++] == ' ')
memmove (model, model+i, 64-i);
+ if (!strncmp (model,"FinePix ",8))
+ strcpy (model, model+8);
if (!strncmp (model,"Digital Camera ",15))
strcpy (model, model+15);
desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0;
if (!is_raw) goto notraw;
- if (!maximum) maximum = (1 << tiff_bps) - 1;
if (!height) height = raw_height;
if (!width) width = raw_width;
- if (fuji_width) {
- width = height + fuji_width;
- height = width - 1;
- pixel_aspect = 1;
- }
if (height == 2624 && width == 3936) /* Pentax K10D and Samsung GX10 */
{ height = 2616; width = 3896; }
- if (height == 3136 && width == 4864) /* Pentax K20D */
- { height = 3124; width = 4688; }
+ if (height == 3136 && width == 4864) /* Pentax K20D and Samsung GX20 */
+ { height = 3124; width = 4688; filters = 0x16161616; }
+ if (raw_height == 2868 && (!strcmp(model,"K-r") || !strcmp(model,"K-x")))
+ { width = 4309; filters = 0x16161616; }
+ if (raw_height == 3136 && !strcmp(model,"K-7"))
+ { height = 3122; width = 4684; filters = 0x16161616; top_margin = 2; }
+ if (raw_height == 3284 && !strncmp(model,"K-5",3))
+ { left_margin = 10; width = 4950; filters = 0x16161616; }
+ if (raw_height == 3300 && !strncmp(model,"K-50",4))
+ { height = 3288, width = 4952; left_margin = 0; top_margin = 12; }
+ if (raw_height == 3664 && !strncmp(model,"K-S",3))
+ { width = 5492; left_margin = 0; }
+ if (raw_height == 4032 && !strcmp(model,"K-3"))
+ { height = 4032; width = 6040; left_margin = 4; }
+ if (raw_height == 4060 && !strcmp(model,"KP"))
+ { height = 4032; width = 6032; left_margin = 52; top_margin = 28; }
+ if (raw_height == 4950 && !strcmp(model,"K-1"))
+ { height = 4932; width = 7380; left_margin = 4; top_margin = 18; }
+ if (raw_height == 5552 && !strcmp(model,"645D"))
+ { height = 5502; width = 7328; left_margin = 48; top_margin = 29;
+ filters = 0x61616161; }
+ if (height == 3014 && width == 4096) /* Ricoh GX200 */
+ width = 4014;
if (dng_version) {
if (filters == UINT_MAX) filters = 0;
- if (filters) is_raw = tiff_samples;
- else colors = tiff_samples;
- if (tiff_compress == 1)
- load_raw = &CLASS adobe_dng_load_raw_nc;
- if (tiff_compress == 7)
- load_raw = &CLASS adobe_dng_load_raw_lj;
+ if (filters) is_raw *= tiff_samples;
+ else colors = tiff_samples;
+ switch (tiff_compress) {
+ case 0:
+ case 1: load_raw = &CLASS packed_dng_load_raw; break;
+ case 7: load_raw = &CLASS lossless_dng_load_raw; break;
+ case 34892: load_raw = &CLASS lossy_dng_load_raw; break;
+ default: load_raw = 0;
+ }
goto dng_skip;
}
- if ((is_canon = !strcmp(make,"Canon"))) {
- load_raw = memcmp (head+6,"HEAPCCDR",8) ?
- &CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw;
- maximum = 0xfff;
+ if (!strcmp(make,"Canon") && !fsize && tiff_bps != 15) {
+ if (!load_raw)
+ load_raw = &CLASS lossless_jpeg_load_raw;
+ for (i=0; i < sizeof canon / sizeof *canon; i++)
+ if (raw_width == canon[i][0] && raw_height == canon[i][1]) {
+ width = raw_width - (left_margin = canon[i][2]);
+ height = raw_height - (top_margin = canon[i][3]);
+ width -= canon[i][4];
+ height -= canon[i][5];
+ mask[0][1] = canon[i][6];
+ mask[0][3] = -canon[i][7];
+ mask[1][1] = canon[i][8];
+ mask[1][3] = -canon[i][9];
+ if (canon[i][10]) filters = canon[i][10] * 0x01010101;
+ }
+ if ((unique_id | 0x20000) == 0x2720000) {
+ left_margin = 8;
+ top_margin = 16;
+ }
+ }
+ for (i=0; i < sizeof unique / sizeof *unique; i++)
+ if (unique_id == 0x80000000 + unique[i].id) {
+ adobe_coeff ("Canon", unique[i].model);
+ if (model[4] == 'K' && strlen(model) == 8)
+ strcpy (model, unique[i].model);
+ }
+ for (i=0; i < sizeof sonique / sizeof *sonique; i++)
+ if (unique_id == sonique[i].id)
+ strcpy (model, sonique[i].model);
+ for (i=0; i < sizeof panalias / sizeof *panalias; i++)
+ if (panalias[i][0] == '@') orig = panalias[i]+1;
+ else if (!strcmp(model,panalias[i]))
+ adobe_coeff ("Panasonic", orig);
+ if (!strcmp(make,"Nikon")) {
+ if (!load_raw)
+ load_raw = &CLASS packed_load_raw;
+ if (model[0] == 'E')
+ load_flags |= !data_offset << 2 | 2;
}
- if (!strcmp(make,"NIKON") && !load_raw)
- load_raw = &CLASS nikon_load_raw;
/* Set parameters based on camera name (for non-DNG files). */
+ if (!strcmp(model,"KAI-0340")
+ && find_green (16, 16, 3840, 5120) < 25) {
+ height = 480;
+ top_margin = filters = 0;
+ strcpy (model,"C603");
+ }
+ if (!strcmp(make,"Sony") && raw_width > 3888)
+ black = 128 << (tiff_bps - 12);
if (is_foveon) {
if (height*2 < width) pixel_aspect = 0.5;
if (height > width) pixel_aspect = 2;
filters = 0;
- load_raw = &CLASS foveon_load_raw;
simple_coeff(0);
- } else if (is_canon && tiff_samples == 4) {
+ } else if (!strcmp(make,"Canon") && tiff_bps == 15) {
+ switch (width) {
+ case 3344: width -= 66;
+ case 3872: width -= 6;
+ }
+ if (height > width) {
+ SWAP(height,width);
+ SWAP(raw_height,raw_width);
+ }
+ if (width == 7200 && height == 3888) {
+ raw_width = width = 6480;
+ raw_height = height = 4320;
+ }
filters = 0;
+ tiff_samples = colors = 3;
load_raw = &CLASS canon_sraw_load_raw;
} else if (!strcmp(model,"PowerShot 600")) {
height = 613;
width = 854;
raw_width = 896;
- pixel_aspect = 607/628.0;
colors = 4;
filters = 0xe1e4e1e4;
load_raw = &CLASS canon_600_load_raw;
@@ -6703,197 +8993,37 @@ void CLASS identify()
width = 960;
raw_width = 992;
pixel_aspect = 256/235.0;
- colors = 4;
filters = 0x1e4e1e4e;
- load_raw = &CLASS canon_a5_load_raw;
+ goto canon_a5;
} else if (!strcmp(model,"PowerShot A50")) {
height = 968;
width = 1290;
raw_width = 1320;
- colors = 4;
filters = 0x1b4e4b1e;
- load_raw = &CLASS canon_a5_load_raw;
+ goto canon_a5;
} else if (!strcmp(model,"PowerShot Pro70")) {
height = 1024;
width = 1552;
- colors = 4;
filters = 0x1e4b4e1b;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A460")) {
- height = 1960;
- width = 2616;
- raw_height = 1968;
- raw_width = 2664;
- top_margin = 4;
- left_margin = 4;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A530")) {
- height = 1984;
- width = 2620;
- raw_height = 1992;
- raw_width = 2672;
- top_margin = 6;
- left_margin = 10;
- load_raw = &CLASS canon_a5_load_raw;
- raw_color = 0;
- } else if (!strcmp(model,"PowerShot A610")) {
- if (canon_s2is()) strcpy (model+10, "S2 IS");
- height = 1960;
- width = 2616;
- raw_height = 1968;
- raw_width = 2672;
- top_margin = 8;
- left_margin = 12;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A620")) {
- height = 2328;
- width = 3112;
- raw_height = 2340;
- raw_width = 3152;
- top_margin = 12;
- left_margin = 36;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A720")) {
- height = 2472;
- width = 3298;
- raw_height = 2480;
- raw_width = 3336;
- top_margin = 5;
- left_margin = 6;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A630")) {
- height = 2472;
- width = 3288;
- raw_height = 2484;
- raw_width = 3344;
- top_margin = 6;
- left_margin = 12;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A640")) {
- height = 2760;
- width = 3672;
- raw_height = 2772;
- raw_width = 3736;
- top_margin = 6;
- left_margin = 12;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A650")) {
- height = 3024;
- width = 4032;
- raw_height = 3048;
- raw_width = 4104;
- top_margin = 12;
- left_margin = 48;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot S3 IS")) {
- height = 2128;
- width = 2840;
- raw_height = 2136;
- raw_width = 2888;
- top_margin = 8;
- left_margin = 44;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot Pro90 IS")) {
- width = 1896;
+canon_a5:
+ colors = 4;
+ tiff_bps = 10;
+ load_raw = &CLASS packed_load_raw;
+ load_flags = 264;
+ } else if (!strcmp(model,"PowerShot Pro90 IS") ||
+ !strcmp(model,"PowerShot G1")) {
colors = 4;
filters = 0xb4b4b4b4;
- } else if (is_canon && raw_width == 2144) {
- height = 1550;
- width = 2088;
- top_margin = 8;
- left_margin = 4;
- if (!strcmp(model,"PowerShot G1")) {
- colors = 4;
- filters = 0xb4b4b4b4;
- }
- } else if (is_canon && raw_width == 2224) {
- height = 1448;
- width = 2176;
- top_margin = 6;
- left_margin = 48;
- } else if (is_canon && raw_width == 2376) {
- height = 1720;
- width = 2312;
- top_margin = 6;
- left_margin = 12;
- } else if (is_canon && raw_width == 2672) {
- height = 1960;
- width = 2616;
- top_margin = 6;
- left_margin = 12;
- } else if (is_canon && raw_width == 3152) {
- height = 2056;
- width = 3088;
- top_margin = 12;
- left_margin = 64;
- if (unique_id == 0x80000170)
- adobe_coeff ("Canon","EOS 300D");
- maximum = 0xfa0;
- } else if (is_canon && raw_width == 3160) {
- height = 2328;
- width = 3112;
- top_margin = 12;
- left_margin = 44;
- } else if (is_canon && raw_width == 3344) {
- height = 2472;
- width = 3288;
- top_margin = 6;
- left_margin = 4;
+ } else if (!strcmp(model,"PowerShot A610")) {
+ if (canon_s2is()) strcpy (model+10, "S2 IS");
+ } else if (!strcmp(model,"PowerShot SX220 HS")) {
+ mask[1][3] = -4;
} else if (!strcmp(model,"EOS D2000C")) {
filters = 0x61616161;
black = curve[200];
- } else if (is_canon && raw_width == 3516) {
- top_margin = 14;
- left_margin = 42;
- if (unique_id == 0x80000189)
- adobe_coeff ("Canon","EOS 350D");
- goto canon_cr2;
- } else if (is_canon && raw_width == 3596) {
- top_margin = 12;
- left_margin = 74;
- goto canon_cr2;
- } else if (is_canon && raw_width == 3944) {
- height = 2602;
- width = 3908;
- top_margin = 18;
- left_margin = 30;
- maximum = 0x3f60;
- } else if (is_canon && raw_width == 3948) {
- top_margin = 18;
- left_margin = 42;
- height -= 2;
- if (unique_id == 0x80000236)
- adobe_coeff ("Canon","EOS 400D");
- goto canon_cr2;
- } else if (is_canon && raw_width == 3984) {
- top_margin = 20;
- left_margin = 76;
- height -= 2;
- maximum = 0x3bb0;
- goto canon_cr2;
- } else if (is_canon && raw_width == 4104) {
- height = 3024;
- width = 4032;
- top_margin = 12;
- left_margin = 48;
- } else if (is_canon && raw_width == 4476) {
- top_margin = 34;
- left_margin = 90;
- maximum = 0xe6c;
- goto canon_cr2;
- } else if (is_canon && raw_width == 5108) {
- top_margin = 13;
- left_margin = 98;
- maximum = 0xe80;
-canon_cr2:
- height -= top_margin;
- width -= left_margin;
- } else if (is_canon && raw_width == 5712) {
- height = 3752;
- width = 5640;
- top_margin = 20;
- left_margin = 62;
- maximum = 0x3bb0;
+ } else if (!strcmp(model,"EOS 80D")) {
+ top_margin -= 2;
+ height += 2;
} else if (!strcmp(model,"D1")) {
cam_mul[0] *= 256/527.0;
cam_mul[2] *= 256/317.0;
@@ -6901,62 +9031,71 @@ canon_cr2:
width -= 4;
pixel_aspect = 0.5;
} else if (!strcmp(model,"D40X") ||
- !strcmp(model,"D80")) {
+ !strcmp(model,"D60") ||
+ !strcmp(model,"D80") ||
+ !strcmp(model,"D3000")) {
height -= 3;
width -= 4;
+ } else if (!strcmp(model,"D3") ||
+ !strcmp(model,"D3S") ||
+ !strcmp(model,"D700")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"D3100")) {
+ width -= 28;
+ left_margin = 6;
+ } else if (!strcmp(model,"D5000") ||
+ !strcmp(model,"D90")) {
+ width -= 42;
+ } else if (!strcmp(model,"D5100") ||
+ !strcmp(model,"D7000") ||
+ !strcmp(model,"COOLPIX A")) {
+ width -= 44;
+ } else if (!strcmp(model,"D3200") ||
+ !strncmp(model,"D6",2) ||
+ !strncmp(model,"D800",4)) {
+ width -= 46;
+ } else if (!strcmp(model,"D4") ||
+ !strcmp(model,"Df")) {
+ width -= 52;
+ left_margin = 2;
} else if (!strncmp(model,"D40",3) ||
!strncmp(model,"D50",3) ||
!strncmp(model,"D70",3)) {
width--;
} else if (!strcmp(model,"D100")) {
- if (tiff_compress == 34713 && !nikon_is_compressed()) {
- load_raw = &CLASS nikon_load_raw;
+ if (load_flags)
raw_width = (width += 3) + 3;
- }
- maximum = 0xf44;
} else if (!strcmp(model,"D200")) {
left_margin = 1;
width -= 4;
- maximum = 0xfbc;
filters = 0x94949494;
} else if (!strncmp(model,"D2H",3)) {
left_margin = 6;
width -= 14;
- } else if (!strcmp(model,"D2X")) {
- width -= 8;
- maximum = 0xf35;
- } else if (!strcmp(model,"D3")) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"D300")) {
+ } else if (!strncmp(model,"D2X",3)) {
+ if (width == 3264) width -= 32;
+ else width -= 8;
+ } else if (!strncmp(model,"D300",4)) {
width -= 32;
+ } else if (!strncmp(model,"COOLPIX B",9)) {
+ load_flags = 24;
+ } else if (!strncmp(model,"COOLPIX P",9) && raw_width != 4032) {
+ load_flags = 24;
+ filters = 0x94949494;
+ if (model[9] == '7' && iso_speed >= 400)
+ black = 255;
+ } else if (!strncmp(model,"1 ",2)) {
+ height -= 2;
} else if (fsize == 1581060) {
- height = 963;
- width = 1287;
- raw_width = 1632;
- load_raw = &CLASS nikon_e900_load_raw;
- maximum = 0x3f4;
- colors = 4;
- filters = 0x1e1e1e1e;
simple_coeff(3);
pre_mul[0] = 1.2085;
pre_mul[1] = 1.0943;
pre_mul[3] = 1.1103;
- } else if (fsize == 2465792) {
- height = 1203;
- width = 1616;
- raw_width = 2048;
- load_raw = &CLASS nikon_e900_load_raw;
- maximum = 0x3dd;
- colors = 4;
- filters = 0x4b4b4b4b;
- adobe_coeff ("NIKON","E950");
+ } else if (fsize == 3178560) {
+ cam_mul[0] *= 4;
+ cam_mul[2] *= 4;
} else if (fsize == 4771840) {
- height = 1540;
- width = 2064;
- colors = 4;
- filters = 0xe1e1e1e1;
- load_raw = &CLASS nikon_load_raw;
if (!timestamp && nikon_e995())
strcpy (model, "E995");
if (strcmp(model,"E995")) {
@@ -6966,89 +9105,70 @@ canon_cr2:
pre_mul[1] = 1.246;
pre_mul[2] = 1.018;
}
- } else if (!strcmp(model,"E2100")) {
- if (!timestamp && !nikon_e2100()) goto cp_e2500;
- height = 1206;
- width = 1616;
- load_raw = &CLASS nikon_e2100_load_raw;
- } else if (!strcmp(model,"E2500")) {
-cp_e2500:
- strcpy (model, "E2500");
- height = 1204;
- width = 1616;
- colors = 4;
- filters = 0x4b4b4b4b;
+ } else if (fsize == 2940928) {
+ if (!timestamp && !nikon_e2100())
+ strcpy (model,"E2500");
+ if (!strcmp(model,"E2500")) {
+ height -= 2;
+ load_flags = 6;
+ colors = 4;
+ filters = 0x4b4b4b4b;
+ }
} else if (fsize == 4775936) {
- height = 1542;
- width = 2064;
- load_raw = &CLASS nikon_e2100_load_raw;
- pre_mul[0] = 1.818;
- pre_mul[2] = 1.618;
if (!timestamp) nikon_3700();
if (model[0] == 'E' && atoi(model+1) < 3700)
filters = 0x49494949;
if (!strcmp(model,"Optio 33WR")) {
flip = 1;
filters = 0x16161616;
- pre_mul[0] = 1.331;
- pre_mul[2] = 1.820;
+ }
+ if (make[0] == 'O') {
+ i = find_green (12, 32, 1188864, 3576832);
+ c = find_green (12, 32, 2383920, 2387016);
+ if (abs(i) < abs(c)) {
+ SWAP(i,c);
+ load_flags = 24;
+ }
+ if (i < 0) filters = 0x61616161;
}
} else if (fsize == 5869568) {
- height = 1710;
- width = 2288;
- filters = 0x16161616;
if (!timestamp && minolta_z2()) {
strcpy (make, "Minolta");
strcpy (model,"DiMAGE Z2");
}
- if (make[0] == 'M')
- load_raw = &CLASS nikon_e2100_load_raw;
- } else if (!strcmp(model,"E4500")) {
- height = 1708;
- width = 2288;
- colors = 4;
- filters = 0xb4b4b4b4;
- } else if (fsize == 7438336) {
- height = 1924;
- width = 2576;
- colors = 4;
- filters = 0xb4b4b4b4;
- } else if (fsize == 8998912) {
- height = 2118;
- width = 2832;
- maximum = 0xf83;
- load_raw = &CLASS nikon_e2100_load_raw;
- } else if (!strcmp(model,"FinePix S5100") ||
- !strcmp(model,"FinePix S5500")) {
- load_raw = &CLASS unpacked_load_raw;
- maximum = 0x3e00;
- } else if (!strcmp(make,"FUJIFILM")) {
+ load_flags = 6 + 24*(make[0] == 'M');
+ } else if (fsize == 6291456) {
+ fseek (ifp, 0x300000, SEEK_SET);
+ if ((order = guess_byte_order(0x10000)) == 0x4d4d) {
+ height -= (top_margin = 16);
+ width -= (left_margin = 28);
+ maximum = 0xf5c0;
+ strcpy (make, "ISG");
+ model[0] = 0;
+ }
+ } else if (!strcmp(make,"Fujifilm")) {
if (!strcmp(model+7,"S2Pro")) {
- strcpy (model+7," S2Pro");
+ strcpy (model,"S2Pro");
height = 2144;
width = 2880;
flip = 6;
- } else
- maximum = 0x3e00;
- if (is_raw == 2 && shot_select)
- maximum = 0x2f00;
- top_margin = (raw_height - height)/2;
- left_margin = (raw_width - width )/2;
- if (is_raw == 2)
- data_offset += (shot_select > 0) * ( fuji_layout ?
- (raw_width *= 2) : raw_height*raw_width*2 );
- fuji_width = width >> !fuji_layout;
- width = (height >> fuji_layout) + fuji_width;
- raw_height = height;
- height = width - 1;
- load_raw = &CLASS fuji_load_raw;
- if (!(fuji_width & 1)) filters = 0x49494949;
- } else if (!strcmp(model,"RD175")) {
- height = 986;
- width = 1534;
- data_offset = 513;
- filters = 0x61616161;
- load_raw = &CLASS minolta_rd175_load_raw;
+ }
+ top_margin = (raw_height - height) >> 2 << 1;
+ left_margin = (raw_width - width ) >> 2 << 1;
+ if (width == 2848 || width == 3664) filters = 0x16161616;
+ if (width == 4032 || width == 4952 || width == 6032 || width == 8280) left_margin = 0;
+ if (width == 3328 && (width -= 66)) left_margin = 34;
+ if (width == 4936) left_margin = 4;
+ if (!strcmp(model,"HS50EXR") ||
+ !strcmp(model,"F900EXR")) {
+ width += 2;
+ left_margin = 0;
+ filters = 0x16161616;
+ }
+ if (fuji_layout) raw_width *= is_raw;
+ if (filters == 9)
+ FORC(36) ((char *)xtrans)[c] =
+ xtrans_abs[(c/6+top_margin) % 6][(c+left_margin) % 6];
} else if (!strcmp(model,"KD-400Z")) {
height = 1712;
width = 2312;
@@ -7056,21 +9176,20 @@ cp_e2500:
goto konica_400z;
} else if (!strcmp(model,"KD-510Z")) {
goto konica_510z;
- } else if (!strcasecmp(make,"MINOLTA")) {
- load_raw = &CLASS unpacked_load_raw;
- maximum = 0xf7d;
+ } else if (!strcasecmp(make,"Minolta")) {
+ if (!load_raw && (maximum = 0xfff))
+ load_raw = &CLASS unpacked_load_raw;
if (!strncmp(model,"DiMAGE A",8)) {
if (!strcmp(model,"DiMAGE A200"))
filters = 0x49494949;
- load_raw = &CLASS packed_12_load_raw;
- maximum = model[8] == '1' ? 0xf8b : 0xfff;
+ tiff_bps = 12;
+ load_raw = &CLASS packed_load_raw;
} else if (!strncmp(model,"ALPHA",5) ||
!strncmp(model,"DYNAX",5) ||
!strncmp(model,"MAXXUM",6)) {
sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M'));
adobe_coeff (make, model+20);
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xffb;
+ load_raw = &CLASS packed_load_raw;
} else if (!strncmp(model,"DiMAGE G",8)) {
if (model[8] == '4') {
height = 1716;
@@ -7091,127 +9210,69 @@ konica_400z:
maximum = 0x3df;
order = 0x4d4d;
}
+ } else if (!strcmp(model,"*ist D")) {
+ load_raw = &CLASS unpacked_load_raw;
+ data_error = -1;
} else if (!strcmp(model,"*ist DS")) {
height -= 2;
- } else if (!strcmp(model,"K20D")) {
- filters = 0x16161616;
- } else if (!strcmp(model,"Optio S")) {
- if (fsize == 3178560) {
- height = 1540;
- width = 2064;
- load_raw = &CLASS eight_bit_load_raw;
- cam_mul[0] *= 4;
- cam_mul[2] *= 4;
- pre_mul[0] = 1.391;
- pre_mul[2] = 1.188;
- } else {
- height = 1544;
- width = 2068;
- raw_width = 3136;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7c;
- pre_mul[0] = 1.137;
- pre_mul[2] = 1.453;
- }
- } else if (fsize == 6114240) {
- height = 1737;
- width = 2324;
- raw_width = 3520;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7a;
- pre_mul[0] = 1.980;
- pre_mul[2] = 1.570;
- } else if (!strcmp(model,"Optio 750Z")) {
- height = 2302;
- width = 3072;
- load_raw = &CLASS nikon_e2100_load_raw;
- } else if (!strcmp(model,"STV680 VGA")) {
- height = 484;
- width = 644;
- load_raw = &CLASS eight_bit_load_raw;
- flip = 2;
- filters = 0x16161616;
- black = 16;
- pre_mul[0] = 1.097;
- pre_mul[2] = 1.128;
- } else if (!strcmp(model,"KAI-0340")) {
- height = 477;
- width = 640;
+ } else if (!strcmp(make,"Samsung") && raw_width == 4704) {
+ height -= top_margin = 8;
+ width -= 2 * (left_margin = 8);
+ load_flags = 256;
+ } else if (!strcmp(make,"Samsung") && raw_height == 3714) {
+ height -= top_margin = 18;
+ left_margin = raw_width - (width = 5536);
+ if (raw_width != 5600)
+ left_margin = top_margin = 0;
+ filters = 0x61616161;
+ colors = 3;
+ } else if (!strcmp(make,"Samsung") && raw_width == 5632) {
order = 0x4949;
- data_offset = 3840;
- load_raw = &CLASS unpacked_load_raw;
- pre_mul[0] = 1.561;
- pre_mul[2] = 2.454;
- } else if (!strcmp(model,"N95")) {
- height = raw_height - (top_margin = 2);
- } else if (!strcmp(model,"531C")) {
- height = 1200;
- width = 1600;
- load_raw = &CLASS unpacked_load_raw;
- filters = 0x49494949;
- pre_mul[1] = 1.218;
- } else if (!strcmp(model,"F-080C")) {
- height = 768;
- width = 1024;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcmp(model,"F-145C")) {
- height = 1040;
- width = 1392;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcmp(model,"F-201C")) {
- height = 1200;
- width = 1600;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcmp(model,"F-510C")) {
- height = 1958;
- width = 2588;
- load_raw = fsize < 7500000 ?
- &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
- maximum = 0xfff0;
- } else if (!strcmp(model,"F-810C")) {
- height = 2469;
- width = 3272;
- load_raw = &CLASS unpacked_load_raw;
- maximum = 0xfff0;
- } else if (!strcmp(model,"XCD-SX910CR")) {
- height = 1024;
- width = 1375;
- raw_width = 1376;
+ height = 3694;
+ top_margin = 2;
+ width = 5574 - (left_margin = 32 + tiff_bps);
+ if (tiff_bps == 12) load_flags = 80;
+ } else if (!strcmp(make,"Samsung") && raw_width == 5664) {
+ height -= top_margin = 17;
+ left_margin = 96;
+ width = 5544;
filters = 0x49494949;
- maximum = 0x3ff;
- load_raw = fsize < 2000000 ?
- &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
- } else if (!strcmp(model,"2010")) {
- height = 1207;
- width = 1608;
- order = 0x4949;
- filters = 0x16161616;
- data_offset = 3212;
- maximum = 0x3ff;
- load_raw = &CLASS unpacked_load_raw;
- } else if (!strcmp(model,"A782")) {
- height = 3000;
- width = 2208;
- filters = 0x61616161;
- load_raw = fsize < 10000000 ?
- &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
- maximum = 0xffc0;
- } else if (!strcmp(model,"3320AF")) {
- height = 1536;
- raw_width = width = 2048;
+ } else if (!strcmp(make,"Samsung") && raw_width == 6496) {
filters = 0x61616161;
+ black = 1 << (tiff_bps - 7);
+ } else if (!strcmp(model,"EX1")) {
+ order = 0x4949;
+ height -= 20;
+ top_margin = 2;
+ if ((width -= 6) > 3682) {
+ height -= 10;
+ width -= 46;
+ top_margin = 8;
+ }
+ } else if (!strcmp(model,"WB2000")) {
+ order = 0x4949;
+ height -= 3;
+ top_margin = 2;
+ if ((width -= 10) > 3718) {
+ height -= 28;
+ width -= 56;
+ top_margin = 8;
+ }
+ } else if (strstr(model,"WB550")) {
+ strcpy (model, "WB550");
+ } else if (!strcmp(model,"EX2F")) {
+ height = 3045;
+ width = 4070;
+ top_margin = 3;
+ order = 0x4949;
+ filters = 0x49494949;
load_raw = &CLASS unpacked_load_raw;
- maximum = 0x3ff;
- pre_mul[0] = 1.717;
- pre_mul[2] = 1.138;
- fseek (ifp, 0x300000, SEEK_SET);
- if ((order = guess_byte_order(0x10000)) == 0x4d4d) {
- height -= (top_margin = 16);
- width -= (left_margin = 28);
- maximum = 0xf5c0;
- strcpy (make, "ISG");
- model[0] = 0;
- }
+ } else if (!strcmp(model,"STV680 VGA")) {
+ black = 16;
+ } else if (!strcmp(model,"N95")) {
+ height = raw_height - (top_margin = 2);
+ } else if (!strcmp(model,"640x480")) {
+ gamma_curve (0.45, 4.5, 1, 255);
} else if (!strcmp(make,"Hasselblad")) {
if (load_raw == &CLASS lossless_jpeg_load_raw)
load_raw = &CLASS hasselblad_load_raw;
@@ -7221,22 +9282,48 @@ konica_400z:
top_margin = 4;
left_margin = 7;
filters = 0x61616161;
- }
- } else if (!strcmp(make,"Sinar")) {
- if (!memcmp(head,"8BPS",4)) {
- fseek (ifp, 14, SEEK_SET);
- height = get4();
- width = get4();
+ } else if (raw_width == 7410 || raw_width == 8282) {
+ height -= 84;
+ width -= 82;
+ top_margin = 4;
+ left_margin = 41;
filters = 0x61616161;
- data_offset = 68;
+ } else if (raw_width == 8384) {
+ height = 6208;
+ width = 8280;
+ top_margin = 96;
+ left_margin = 46;
+ } else if (raw_width == 9044) {
+ height = 6716;
+ width = 8964;
+ top_margin = 8;
+ left_margin = 40;
+ black += load_flags = 256;
+ maximum = 0x8101;
+ } else if (raw_width == 4090) {
+ strcpy (model, "V96C");
+ height -= (top_margin = 6);
+ width -= (left_margin = 3) + 7;
+ filters = 0x61616161;
+ }
+ if (tiff_samples > 1) {
+ is_raw = tiff_samples+1;
+ if (!shot_select && !half_size) filters = 0;
}
+ } else if (!strcmp(make,"Sinar")) {
if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+ if (is_raw > 1 && !shot_select && !half_size) filters = 0;
maximum = 0x3fff;
} else if (!strcmp(make,"Leaf")) {
maximum = 0x3fff;
+ fseek (ifp, data_offset, SEEK_SET);
+ if (ljpeg_start (&jh, 1) && jh.bits == 15)
+ maximum = 0x1fff;
if (tiff_samples > 1) filters = 0;
- if (tiff_samples > 1 || tile_length < raw_height)
+ if (tiff_samples > 1 || tile_length < raw_height) {
load_raw = &CLASS leaf_hdr_load_raw;
+ raw_width = tile_width;
+ }
if ((width | height) == 2048) {
if (tiff_samples == 1) {
filters = 1;
@@ -7269,133 +9356,69 @@ konica_400z:
width -= 2 * (left_margin = 24);
filters = 0x16161616;
}
- } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) {
- maximum = 0xfff0;
- if ((fsize-data_offset) / (width*8/7) == height)
+ } else if (!strcmp(make,"Leica") || !strcmp(make,"Panasonic")) {
+ if ((flen - data_offset) / (raw_width*8/7) == raw_height)
load_raw = &CLASS panasonic_load_raw;
- if (!load_raw) load_raw = &CLASS unpacked_load_raw;
- switch (width) {
- case 2568:
- adobe_coeff ("Panasonic","DMC-LC1"); break;
- case 3130:
- left_margin = -14;
- case 3170:
- left_margin += 18;
- width = 3096;
- if (height > 2326) {
- height = 2326;
- top_margin = 13;
- filters = 0x49494949;
- }
- maximum = 0xf7f0;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-FZ8"); break;
- case 3177:
- width -= 10;
- filters = 0x49494949;
- maximum = 0xf7fc;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-L1"); break;
- case 3304:
- width -= 16;
- maximum = 0xf94c;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-FZ30"); break;
- case 3330:
- width = 3291;
- left_margin = 9;
- maximum = 0xf7f0;
- goto fz18;
- case 3370:
- width = 3288;
- left_margin = 15;
-fz18: if (height > 2480)
- height = 2480 - (top_margin = 10);
- filters = 0x49494949;
- zero_is_bad = 1;
- break;
- case 3690:
- height += 36;
- left_margin = -14;
- filters = 0x49494949;
- maximum = 0xf7f0;
- case 3770:
- width = 3672;
- if ((height -= 39) == 2760)
- top_margin = 15;
- left_margin += 17;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-FZ50"); break;
- case 3710:
- width = 3682;
- filters = 0x49494949;
- break;
- case 3880:
- width -= 22;
- left_margin = 6;
- maximum = 0xf7f0;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-LX1"); break;
- case 4290:
- height += 38;
- left_margin = -14;
- filters = 0x49494949;
- case 4330:
- width = 4248;
- if ((height -= 39) == 2400)
- top_margin = 15;
- left_margin += 17;
- adobe_coeff ("Panasonic","DMC-LX2"); break;
- }
+ if (!load_raw) {
+ load_raw = &CLASS unpacked_load_raw;
+ load_flags = 4;
+ }
+ zero_is_bad = 1;
+ if ((height += 12) > raw_height) height = raw_height;
+ for (i=0; i < sizeof pana / sizeof *pana; i++)
+ if (raw_width == pana[i][0] && raw_height == pana[i][1]) {
+ left_margin = pana[i][2];
+ top_margin = pana[i][3];
+ width += pana[i][4];
+ height += pana[i][5];
+ }
+ filters = 0x01010101 * (uchar) "\x94\x61\x49\x16"
+ [((filters-1) ^ (left_margin & 1) ^ (top_margin << 1)) & 3];
} else if (!strcmp(model,"C770UZ")) {
height = 1718;
width = 2304;
filters = 0x16161616;
- load_raw = &CLASS nikon_e2100_load_raw;
- } else if (!strcmp(make,"OLYMPUS")) {
+ load_raw = &CLASS packed_load_raw;
+ load_flags = 30;
+ } else if (!strcmp(make,"Olympus")) {
height += height & 1;
- filters = exif_cfa;
- if (!strcmp(model,"E-1") ||
- !strcmp(model,"E-400")) {
- maximum = 0xfff0;
- } else if (!strcmp(model,"E-10") ||
- !strncmp(model,"E-20",4)) {
- maximum = 0xffc0;
- black <<= 2;
- } else if (!strcmp(model,"E-300") ||
- !strcmp(model,"E-500")) {
+ if (exif_cfa) filters = exif_cfa;
+ if (width == 4100) width -= 4;
+ if (width == 4080) width -= 24;
+ if (width == 9280) { width -= 6; height -= 6; }
+ if (load_raw == &CLASS unpacked_load_raw)
+ load_flags = 4;
+ tiff_bps = 12;
+ if (!strcmp(model,"E-300") ||
+ !strcmp(model,"E-500")) {
width -= 20;
if (load_raw == &CLASS unpacked_load_raw) {
- maximum = 0xfc30;
- black = 0;
+ maximum = 0xfc3;
+ memset (cblack, 0, sizeof cblack);
}
} else if (!strcmp(model,"E-330")) {
width -= 30;
if (load_raw == &CLASS unpacked_load_raw)
- maximum = 0xf790;
- } else if (!strcmp(model,"E-3")) {
- maximum = 0xf99;
- goto e410;
- } else if (!strcmp(model,"E-410") ||
- !strcmp(model,"E-510")) {
- maximum = 0xf6a;
-e410: load_raw = &CLASS olympus_e410_load_raw;
- black >>= 4;
+ maximum = 0xf79;
} else if (!strcmp(model,"SP550UZ")) {
- thumb_length = fsize - (thumb_offset = 0xa39800);
+ thumb_length = flen - (thumb_offset = 0xa39800);
thumb_height = 480;
thumb_width = 640;
+ } else if (!strcmp(model,"TG-4")) {
+ width -= 16;
+ } else if (!strcmp(model,"TG-5")) {
+ width -= 6;
}
} else if (!strcmp(model,"N Digital")) {
height = 2047;
width = 3072;
filters = 0x61616161;
data_offset = 0x1a00;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf1e;
+ load_raw = &CLASS packed_load_raw;
} else if (!strcmp(model,"DSC-F828")) {
width = 3288;
left_margin = 5;
+ mask[1][3] = -17;
data_offset = 862144;
load_raw = &CLASS sony_load_raw;
filters = 0x9c9c9c9c;
@@ -7404,82 +9427,94 @@ e410: load_raw = &CLASS olympus_e410_load_raw;
} else if (!strcmp(model,"DSC-V3")) {
width = 3109;
left_margin = 59;
+ mask[0][1] = 9;
data_offset = 787392;
load_raw = &CLASS sony_load_raw;
- } else if (!strcmp(make,"SONY") && raw_width == 3984) {
- adobe_coeff ("SONY","DSC-R1");
+ } else if (!strcmp(make,"Sony") && raw_width == 3984) {
width = 3925;
order = 0x4d4d;
+ } else if (!strcmp(make,"Sony") && raw_width == 4288) {
+ width -= 32;
+ } else if (!strcmp(make,"Sony") && raw_width == 4600) {
+ if (!strcmp(model,"DSLR-A350"))
+ height -= 4;
+ black = 0;
+ } else if (!strcmp(make,"Sony") && raw_width == 4928) {
+ if (height < 3280) width -= 8;
+ } else if (!strcmp(make,"Sony") && raw_width == 5504) {
+ width -= height > 3664 ? 8 : 32;
+ if (!strncmp(model,"DSC",3))
+ black = 200 << (tiff_bps - 12);
+ } else if (!strcmp(make,"Sony") && raw_width == 6048) {
+ width -= 24;
+ if (strstr(model,"RX1") || strstr(model,"A99"))
+ width -= 6;
+ } else if (!strcmp(make,"Sony") && raw_width == 7392) {
+ width -= 30;
+ } else if (!strcmp(make,"Sony") && raw_width == 8000) {
+ width -= 32;
} else if (!strcmp(model,"DSLR-A100")) {
- height--;
- load_raw = &CLASS sony_arw_load_raw;
- maximum = 0xfeb;
- } else if (!strcmp(model,"DSLR-A200")) {
- height = raw_height += 8;
- load_raw = &CLASS sony_arw_load_raw;
- } else if (!strcmp(model,"DSLR-A350")) {
- height = (raw_height += 8) - 4;
- load_raw = &CLASS sony_arw_load_raw;
- maximum = 0x1ffe;
- } else if (!strncmp(model,"P850",4)) {
- maximum = 0xf7c;
- } else if (!strcmp(model,"C330")) {
- height = 1744;
- width = 2336;
- raw_height = 1779;
- raw_width = 2338;
- top_margin = 33;
- left_margin = 1;
+ if (width == 3880) {
+ height--;
+ width = ++raw_width;
+ } else {
+ height -= 4;
+ width -= 4;
+ order = 0x4d4d;
+ load_flags = 2;
+ }
+ filters = 0x61616161;
+ } else if (!strcmp(model,"PIXL")) {
+ height -= top_margin = 4;
+ width -= left_margin = 32;
+ gamma_curve (0, 7, 1, 255);
+ } else if (!strcmp(model,"C603") || !strcmp(model,"C330")
+ || !strcmp(model,"12MP")) {
order = 0x4949;
- if ((data_offset = fsize - raw_height*raw_width)) {
- fseek (ifp, 168, SEEK_SET);
+ if (filters && data_offset) {
+ fseek (ifp, data_offset < 4096 ? 168 : 5252, SEEK_SET);
read_shorts (curve, 256);
- } else use_gamma = 0;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcasecmp(make,"KODAK")) {
+ } else gamma_curve (0, 3.875, 1, 255);
+ load_raw = filters ? &CLASS eight_bit_load_raw :
+ strcmp(model,"C330") ? &CLASS kodak_c603_load_raw :
+ &CLASS kodak_c330_load_raw;
+ load_flags = tiff_bps > 16;
+ tiff_bps = 8;
+ } else if (!strncasecmp(model,"EasyShare",9)) {
+ data_offset = data_offset < 0x15000 ? 0x15000 : 0x17000;
+ load_raw = &CLASS packed_load_raw;
+ } else if (!strcasecmp(make,"Kodak")) {
if (filters == UINT_MAX) filters = 0x61616161;
- if (!strncmp(model,"NC2000",6)) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"EOSDCS3B")) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"EOSDCS1")) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"DCS420")) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"DCS460")) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"DCS460A")) {
+ if (!strncmp(model,"NC2000",6) ||
+ !strncmp(model,"EOSDCS",6) ||
+ !strncmp(model,"DCS4",4)) {
width -= 4;
left_margin = 2;
- colors = 1;
- filters = 0;
+ if (model[6] == ' ') model[6] = 0;
+ if (!strcmp(model,"DCS460A")) goto bw;
} else if (!strcmp(model,"DCS660M")) {
black = 214;
- colors = 1;
- filters = 0;
+ goto bw;
} else if (!strcmp(model,"DCS760M")) {
- colors = 1;
+bw: colors = 1;
filters = 0;
}
+ if (!strcmp(model+4,"20X"))
+ strcpy (cdesc, "MYCY");
if (strstr(model,"DC25")) {
strcpy (model, "DC25");
data_offset = 15424;
}
if (!strncmp(model,"DC2",3)) {
- height = 242;
- if (fsize < 100000) {
+ raw_height = 2 + (height = 242);
+ if (flen < 100000) {
raw_width = 256; width = 249;
pixel_aspect = (4.0*height) / (3.0*width);
} else {
raw_width = 512; width = 501;
pixel_aspect = (493.0*height) / (373.0*width);
}
- data_offset += raw_width + 1;
+ top_margin = left_margin = 1;
colors = 4;
filters = 0x8d8d8d8d;
simple_coeff(1);
@@ -7493,6 +9528,7 @@ e410: load_raw = &CLASS olympus_e410_load_raw;
width = 768;
data_offset = 1152;
load_raw = &CLASS kodak_radc_load_raw;
+ tiff_bps = 12;
} else if (strstr(model,"DC50")) {
strcpy (model, "DC50");
height = 512;
@@ -7512,10 +9548,6 @@ e410: load_raw = &CLASS olympus_e410_load_raw;
thumb_offset = 6144;
thumb_misc = 360;
write_thumb = &CLASS layer_thumb;
- height = 1024;
- width = 1536;
- data_offset = 79872;
- load_raw = &CLASS eight_bit_load_raw;
black = 17;
}
} else if (!strcmp(model,"Fotoman Pixtura")) {
@@ -7525,17 +9557,17 @@ e410: load_raw = &CLASS olympus_e410_load_raw;
load_raw = &CLASS kodak_radc_load_raw;
filters = 0x61616161;
simple_coeff(2);
- } else if (!strcmp(model,"QuickTake 100")) {
- data_offset = 736;
- load_raw = &CLASS quicktake_100_load_raw;
- goto qt_common;
- } else if (!strcmp(model,"QuickTake 150")) {
- data_offset = 738 - head[5];
+ } else if (!strncmp(model,"QuickTake",9)) {
if (head[5]) strcpy (model+10, "200");
- load_raw = &CLASS kodak_radc_load_raw;
-qt_common:
- height = 480;
- width = 640;
+ fseek (ifp, 544, SEEK_SET);
+ height = get2();
+ width = get2();
+ data_offset = (get4(),get2()) == 30 ? 738:736;
+ if (height > width) {
+ SWAP(height,width);
+ fseek (ifp, data_offset-6, SEEK_SET);
+ flip = ~get2() & 3 ? 5:6;
+ }
filters = 0x61616161;
} else if (!strcmp(make,"Rollei") && !load_raw) {
switch (raw_width) {
@@ -7553,100 +9585,10 @@ qt_common:
}
filters = 0x16161616;
load_raw = &CLASS rollei_load_raw;
- pre_mul[0] = 1.8;
- pre_mul[2] = 1.3;
- } else if (!strcmp(model,"PC-CAM 600")) {
- height = 768;
- data_offset = width = 1024;
- filters = 0x49494949;
- load_raw = &CLASS eight_bit_load_raw;
- pre_mul[0] = 1.14;
- pre_mul[2] = 2.73;
- } else if (!strcmp(model,"QV-2000UX")) {
- height = 1208;
- width = 1632;
- data_offset = width * 2;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (fsize == 3217760) {
- height = 1546;
- width = 2070;
- raw_width = 2080;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcmp(model,"QV-4000")) {
- height = 1700;
- width = 2260;
- load_raw = &CLASS unpacked_load_raw;
- maximum = 0xffff;
- } else if (!strcmp(model,"QV-5700")) {
- height = 1924;
- width = 2576;
- load_raw = &CLASS casio_qv5700_load_raw;
- } else if (!strcmp(model,"QV-R41")) {
- height = 1720;
- width = 2312;
- raw_width = 3520;
- left_margin = 2;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7f;
- } else if (!strcmp(model,"QV-R51")) {
- height = 1926;
- width = 2580;
- raw_width = 3904;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7f;
- pre_mul[0] = 1.340;
- pre_mul[2] = 1.672;
- } else if (!strcmp(model,"EX-S100")) {
- height = 1544;
- width = 2058;
- raw_width = 3136;
- load_raw = &CLASS packed_12_load_raw;
- pre_mul[0] = 1.631;
- pre_mul[2] = 1.106;
- } else if (!strcmp(model,"EX-Z50")) {
- height = 1931;
- width = 2570;
- raw_width = 3904;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7f;
- pre_mul[0] = 2.529;
- pre_mul[2] = 1.185;
- } else if (!strcmp(model,"EX-Z55")) {
- height = 1960;
- width = 2570;
- raw_width = 3904;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7f;
- pre_mul[0] = 1.520;
- pre_mul[2] = 1.316;
- } else if (!strcmp(model,"EX-P505")) {
- height = 1928;
- width = 2568;
- raw_width = 3852;
- load_raw = &CLASS packed_12_load_raw;
- pre_mul[0] = 2.07;
- pre_mul[2] = 1.88;
- } else if (fsize == 9313536) { /* EX-P600 or QV-R61 */
- height = 2142;
- width = 2844;
- raw_width = 4288;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7f;
- pre_mul[0] = 1.797;
- pre_mul[2] = 1.219;
- } else if (!strcmp(model,"EX-P700")) {
- height = 2318;
- width = 3082;
- raw_width = 4672;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7f;
- pre_mul[0] = 1.758;
- pre_mul[2] = 1.504;
}
if (!model[0])
sprintf (model, "%dx%d", width, height);
if (filters == UINT_MAX) filters = 0x94949494;
- if (raw_color) adobe_coeff (make, model);
if (thumb_offset && !thumb_height) {
fseek (ifp, thumb_offset, SEEK_SET);
if (ljpeg_start (&jh, 1)) {
@@ -7655,31 +9597,58 @@ qt_common:
}
}
dng_skip:
- if (!load_raw || height < 22) is_raw = 0;
-#ifdef HAVE_JPEG
- if (load_raw == kodak_jpeg_load_raw) {
- fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname);
+ if ((use_camera_matrix & (use_camera_wb || dng_version))
+ && cmatrix[0][0] > 0.125) {
+ memcpy (rgb_cam, cmatrix, sizeof cmatrix);
+ raw_color = 0;
+ }
+ if (raw_color) adobe_coeff (make, model);
+ if (load_raw == &CLASS kodak_radc_load_raw)
+ if (raw_color) adobe_coeff ("Apple","Quicktake");
+ if (fuji_width) {
+ fuji_width = width >> !fuji_layout;
+ filters = fuji_width & 1 ? 0x94949494 : 0x49494949;
+ width = (height >> fuji_layout) + fuji_width;
+ height = width - 1;
+ pixel_aspect = 1;
+ } else {
+ if (raw_height < height) raw_height = height;
+ if (raw_width < width ) raw_width = width;
+ }
+ if (!tiff_bps) tiff_bps = 12;
+ if (!maximum) maximum = (1 << tiff_bps) - 1;
+ if (!load_raw || height < 22 || width < 22 ||
+ tiff_bps > 16 || tiff_samples > 6 || colors > 4)
+ is_raw = 0;
+#ifdef NO_JASPER
+ if (load_raw == &CLASS redcine_load_raw) {
+ fprintf (stderr,_("%s: You must link dcraw with %s!!\n"),
+ ifname, "libjasper");
+ is_raw = 0;
+ }
+#endif
+#ifdef NO_JPEG
+ if (load_raw == &CLASS kodak_jpeg_load_raw ||
+ load_raw == &CLASS lossy_dng_load_raw) {
+ fprintf (stderr,_("%s: You must link dcraw with %s!!\n"),
+ ifname, "libjpeg");
is_raw = 0;
}
#endif
if (!cdesc[0])
- strcpy (cdesc, colors == 3 ? "RGB":"GMCY");
+ strcpy (cdesc, colors == 3 ? "RGBG":"GMCY");
if (!raw_height) raw_height = height;
if (!raw_width ) raw_width = width;
- if (filters && colors == 3)
- for (i=0; i < 32; i+=4) {
- if ((filters >> i & 15) == 9)
- filters |= 2 << i;
- if ((filters >> i & 15) == 6)
- filters |= 8 << i;
- }
+ if (filters > 999 && colors == 3)
+ filters |= ((filters >> 2 & 0x22222222) |
+ (filters << 2 & 0x88888888)) & filters << 1;
notraw:
- if (flip == -1) flip = tiff_flip;
- if (flip == -1) flip = 0;
+ if (flip == UINT_MAX) flip = tiff_flip;
+ if (flip == UINT_MAX) flip = 0;
}
#ifndef NO_LCMS
-void CLASS apply_profile (char *input, char *output)
+void CLASS apply_profile (const char *input, const char *output)
{
char *prof;
cmsHPROFILE hInProfile=0, hOutProfile=0;
@@ -7687,9 +9656,6 @@ void CLASS apply_profile (char *input, char *output)
FILE *fp;
unsigned size;
-#if LCMS_VERSION < 2000
- cmsErrorAction (LCMS_ERROR_SHOW);
-#endif
if (strcmp (input, "embed"))
hInProfile = cmsOpenProfileFromFile (input, "r");
else if (profile_length) {
@@ -7755,10 +9721,14 @@ void CLASS convert_to_rgb()
{ { 0.529317, 0.330092, 0.140588 },
{ 0.098368, 0.873465, 0.028169 },
{ 0.016879, 0.117663, 0.865457 } };
+ static const double aces_rgb[3][3] =
+ { { 0.432996, 0.375380, 0.189317 },
+ { 0.089427, 0.816523, 0.102989 },
+ { 0.019165, 0.118150, 0.941914 } };
static const double (*out_rgb[])[3] =
- { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb };
+ { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb, aces_rgb };
static const char *name[] =
- { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" };
+ { "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 };
@@ -7776,9 +9746,10 @@ void CLASS convert_to_rgb()
static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };
unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 };
+ gamma_curve (gamm[0], gamm[1], 0, 0);
memcpy (out_cam, rgb_cam, sizeof out_cam);
raw_color |= colors == 1 || document_mode ||
- output_color < 1 || output_color > 5;
+ output_color < 1 || output_color > 6;
if (!raw_color) {
oprof = (unsigned *) calloc (phead[0], 1);
merror (oprof, "convert_to_rgb()");
@@ -7793,12 +9764,7 @@ void CLASS convert_to_rgb()
memcpy (oprof+32, pbody, sizeof pbody);
oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1;
memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite);
- if (output_bps == 8)
-#ifdef SRGB_GAMMA
- pcurve[3] = 0x2330000;
-#else
- pcurve[3] = 0x1f00000;
-#endif
+ 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);
@@ -7806,7 +9772,7 @@ void CLASS convert_to_rgb()
for (j=0; j < 3; j++) {
for (num = k=0; k < 3; k++)
num += xyzd50_srgb[i][k] * inverse[j][k];
- oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5;
+ oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5;
}
for (i=0; i < phead[0]/4; i++)
oprof[i] = htonl(oprof[i]);
@@ -7834,7 +9800,7 @@ void CLASS convert_to_rgb()
FORC3 img[c] = CLIP((int) out[c]);
}
else if (document_mode)
- img[0] = img[FC(row,col)];
+ img[0] = img[fcol(row,col)];
FORCC histogram[c][img[c] >> 3]++;
}
if (colors == 4 && output_color) colors = 3;
@@ -7856,7 +9822,7 @@ void CLASS fuji_rotate()
step = sqrt(0.5);
wide = fuji_width / step;
high = (height - fuji_width) / step;
- img = (ushort (*)[4]) calloc (wide*high, sizeof *img);
+ img = (ushort (*)[4]) calloc (high, wide*sizeof *img);
merror (img, "fuji_rotate()");
for (row=0; row < high; row++)
@@ -7889,7 +9855,7 @@ void CLASS stretch()
if (verbose) fprintf (stderr,_("Stretching the image...\n"));
if (pixel_aspect < 1) {
newdim = height / pixel_aspect + 0.5;
- img = (ushort (*)[4]) calloc (width*newdim, sizeof *img);
+ img = (ushort (*)[4]) calloc (width, newdim*sizeof *img);
merror (img, "stretch()");
for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) {
frac = rc - (c = rc);
@@ -7901,7 +9867,7 @@ void CLASS stretch()
height = newdim;
} else {
newdim = width * pixel_aspect + 0.5;
- img = (ushort (*)[4]) calloc (height*newdim, sizeof *img);
+ img = (ushort (*)[4]) calloc (height, newdim*sizeof *img);
merror (img, "stretch()");
for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) {
frac = rc - (c = rc);
@@ -7924,33 +9890,6 @@ int CLASS flip_index (int row, int col)
return row * iwidth + col;
}
-void CLASS gamma_lut (uchar lut[0x10000])
-{
- int perc, c, val, total, i;
- float white=0, r;
-
- perc = width * height * 0.01; /* 99th percentile white level */
- if (fuji_width) perc /= 2;
- if ((highlight & ~2) || no_auto_bright) perc = -1;
- FORCC {
- for (val=0x2000, total=0; --val > 32; )
- if ((total += histogram[c][val]) > perc) break;
- if (white < val) white = val;
- }
- white *= 8 / bright;
- for (i=0; i < 0x10000; i++) {
- r = i / white;
- val = 256 * ( !use_gamma ? r :
-#ifdef SRGB_GAMMA
- r <= 0.00304 ? r*12.92 : pow(r,2.5/6)*1.055-0.055 );
-#else
- r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099 );
-#endif
- if (val > 255) val = 255;
- lut[i] = val;
- }
-}
-
struct tiff_tag {
ushort tag, type;
int count;
@@ -7973,21 +9912,25 @@ struct tiff_hdr {
char desc[512], make[64], model[64], soft[32], date[20], artist[64];
};
-void CLASS tiff_set (ushort *ntag,
+void CLASS tiff_set (struct tiff_hdr *th, ushort *ntag,
ushort tag, ushort type, int count, int val)
{
struct tiff_tag *tt;
int c;
tt = (struct tiff_tag *)(ntag+1) + (*ntag)++;
- tt->tag = tag;
- tt->type = type;
- tt->count = count;
- if (type < 3 && count <= 4)
+ tt->val.i = val;
+ if (type == 1 && count <= 4)
FORC(4) tt->val.c[c] = val >> (c << 3);
- else if (type == 3 && count <= 2)
+ else if (type == 2) {
+ count = strnlen((char *)th + val, count-1) + 1;
+ if (count <= 4)
+ FORC(4) tt->val.c[c] = ((char *)th)[val+c];
+ } else if (type == 3 && count <= 2)
FORC(2) tt->val.s[c] = val >> (c << 4);
- else tt->val.i = val;
+ tt->count = count;
+ tt->type = type;
+ tt->tag = tag;
}
#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
@@ -8001,55 +9944,6 @@ void CLASS tiff_head (struct tiff_hdr *th, int full)
th->order = htonl(0x4d4d4949) >> 16;
th->magic = 42;
th->ifd = 10;
- if (full) {
- tiff_set (&th->ntag, 254, 4, 1, 0);
- tiff_set (&th->ntag, 256, 4, 1, width);
- tiff_set (&th->ntag, 257, 4, 1, height);
- tiff_set (&th->ntag, 258, 3, colors, output_bps);
- if (colors > 2)
- th->tag[th->ntag-1].val.i = TOFF(th->bps);
- FORC4 th->bps[c] = output_bps;
- tiff_set (&th->ntag, 259, 3, 1, 1);
- tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1));
- }
- tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc));
- tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make));
- tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model));
- if (full) {
- if (oprof) psize = ntohl(oprof[0]);
- tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize);
- tiff_set (&th->ntag, 277, 3, 1, colors);
- tiff_set (&th->ntag, 278, 4, 1, height);
- tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8);
- } else
- tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0');
- tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
- tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
- tiff_set (&th->ntag, 284, 3, 1, 1);
- tiff_set (&th->ntag, 296, 3, 1, 2);
- tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft));
- tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date));
- tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist));
- tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif));
- if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th);
- tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
- tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
- tiff_set (&th->nexif, 34855, 3, 1, iso_speed);
- tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
- if (gpsdata[1]) {
- tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps));
- tiff_set (&th->ngps, 0, 1, 4, 0x202);
- tiff_set (&th->ngps, 1, 2, 2, gpsdata[29]);
- tiff_set (&th->ngps, 2, 5, 3, TOFF(th->gps[0]));
- tiff_set (&th->ngps, 3, 2, 2, gpsdata[30]);
- tiff_set (&th->ngps, 4, 5, 3, TOFF(th->gps[6]));
- tiff_set (&th->ngps, 5, 1, 1, gpsdata[31]);
- tiff_set (&th->ngps, 6, 5, 1, TOFF(th->gps[18]));
- tiff_set (&th->ngps, 7, 5, 3, TOFF(th->gps[12]));
- tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20]));
- tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23]));
- memcpy (th->gps, gpsdata, sizeof th->gps);
- }
th->rat[0] = th->rat[2] = 300;
th->rat[1] = th->rat[3] = 1;
FORC(6) th->rat[4+c] = 1000000;
@@ -8059,14 +9953,63 @@ void CLASS tiff_head (struct tiff_hdr *th, int full)
strncpy (th->desc, desc, 512);
strncpy (th->make, make, 64);
strncpy (th->model, model, 64);
- strcpy (th->soft, "dcraw v" DCRAW_VERSION);
- t = gmtime (&timestamp);
+ strcpy (th->soft, "dcraw v"DCRAW_VERSION);
+ t = localtime (&timestamp);
sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d",
t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
strncpy (th->artist, artist, 64);
+ if (full) {
+ tiff_set (th, &th->ntag, 254, 4, 1, 0);
+ tiff_set (th, &th->ntag, 256, 4, 1, width);
+ tiff_set (th, &th->ntag, 257, 4, 1, height);
+ tiff_set (th, &th->ntag, 258, 3, colors, output_bps);
+ if (colors > 2)
+ th->tag[th->ntag-1].val.i = TOFF(th->bps);
+ FORC4 th->bps[c] = output_bps;
+ tiff_set (th, &th->ntag, 259, 3, 1, 1);
+ tiff_set (th, &th->ntag, 262, 3, 1, 1 + (colors > 1));
+ }
+ tiff_set (th, &th->ntag, 270, 2, 512, TOFF(th->desc));
+ tiff_set (th, &th->ntag, 271, 2, 64, TOFF(th->make));
+ tiff_set (th, &th->ntag, 272, 2, 64, TOFF(th->model));
+ if (full) {
+ if (oprof) psize = ntohl(oprof[0]);
+ tiff_set (th, &th->ntag, 273, 4, 1, sizeof *th + psize);
+ tiff_set (th, &th->ntag, 277, 3, 1, colors);
+ tiff_set (th, &th->ntag, 278, 4, 1, height);
+ tiff_set (th, &th->ntag, 279, 4, 1, height*width*colors*output_bps/8);
+ } else
+ tiff_set (th, &th->ntag, 274, 3, 1, "12435867"[flip]-'0');
+ tiff_set (th, &th->ntag, 282, 5, 1, TOFF(th->rat[0]));
+ tiff_set (th, &th->ntag, 283, 5, 1, TOFF(th->rat[2]));
+ tiff_set (th, &th->ntag, 284, 3, 1, 1);
+ tiff_set (th, &th->ntag, 296, 3, 1, 2);
+ tiff_set (th, &th->ntag, 305, 2, 32, TOFF(th->soft));
+ tiff_set (th, &th->ntag, 306, 2, 20, TOFF(th->date));
+ tiff_set (th, &th->ntag, 315, 2, 64, TOFF(th->artist));
+ tiff_set (th, &th->ntag, 34665, 4, 1, TOFF(th->nexif));
+ if (psize) tiff_set (th, &th->ntag, 34675, 7, psize, sizeof *th);
+ tiff_set (th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
+ tiff_set (th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
+ tiff_set (th, &th->nexif, 34855, 3, 1, iso_speed);
+ tiff_set (th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
+ if (gpsdata[1]) {
+ tiff_set (th, &th->ntag, 34853, 4, 1, TOFF(th->ngps));
+ tiff_set (th, &th->ngps, 0, 1, 4, 0x202);
+ tiff_set (th, &th->ngps, 1, 2, 2, gpsdata[29]);
+ tiff_set (th, &th->ngps, 2, 5, 3, TOFF(th->gps[0]));
+ tiff_set (th, &th->ngps, 3, 2, 2, gpsdata[30]);
+ tiff_set (th, &th->ngps, 4, 5, 3, TOFF(th->gps[6]));
+ tiff_set (th, &th->ngps, 5, 1, 1, gpsdata[31]);
+ tiff_set (th, &th->ngps, 6, 5, 1, TOFF(th->gps[18]));
+ tiff_set (th, &th->ngps, 7, 5, 3, TOFF(th->gps[12]));
+ tiff_set (th, &th->ngps, 18, 2, 12, TOFF(th->gps[20]));
+ tiff_set (th, &th->ngps, 29, 2, 12, TOFF(th->gps[23]));
+ memcpy (th->gps, gpsdata, sizeof th->gps);
+ }
}
-void CLASS jpeg_thumb (FILE *tfp)
+void CLASS jpeg_thumb()
{
char *thumb;
ushort exif[5];
@@ -8075,26 +10018,36 @@ void CLASS jpeg_thumb (FILE *tfp)
thumb = (char *) malloc (thumb_length);
merror (thumb, "jpeg_thumb()");
fread (thumb, 1, thumb_length, ifp);
- fputc (0xff, tfp);
- fputc (0xd8, tfp);
+ fputc (0xff, ofp);
+ fputc (0xd8, ofp);
if (strcmp (thumb+6, "Exif")) {
memcpy (exif, "\xff\xe1 Exif\0\0", 10);
exif[1] = htons (8 + sizeof th);
- fwrite (exif, 1, sizeof exif, tfp);
+ fwrite (exif, 1, sizeof exif, ofp);
tiff_head (&th, 0);
- fwrite (&th, 1, sizeof th, tfp);
+ fwrite (&th, 1, sizeof th, ofp);
}
- fwrite (thumb+2, 1, thumb_length-2, tfp);
+ fwrite (thumb+2, 1, thumb_length-2, ofp);
free (thumb);
}
-void CLASS write_ppm_tiff (FILE *ofp)
+void CLASS write_ppm_tiff()
{
struct tiff_hdr th;
- uchar *ppm, lut[0x10000];
+ uchar *ppm;
ushort *ppm2;
int c, row, col, soff, rstep, cstep;
+ int perc, val, total, white=0x2000;
+ perc = width * height * 0.01; /* 99th percentile white level */
+ if (fuji_width) perc /= 2;
+ if (!((highlight & ~2) || no_auto_bright))
+ for (white=c=0; c < colors; c++) {
+ for (val=0x2000, total=0; --val > 32; )
+ if ((total += histogram[c][val]) > perc) break;
+ if (white < val) white = val;
+ }
+ gamma_curve (gamm[0], gamm[1], 2, (white << 3)/bright);
iheight = height;
iwidth = width;
if (flip & 4) SWAP(height,width);
@@ -8113,16 +10066,14 @@ void CLASS write_ppm_tiff (FILE *ofp)
else
fprintf (ofp, "P%d\n%d %d\n%d\n",
colors/2+5, width, height, (1 << output_bps)-1);
-
- if (output_bps == 8) gamma_lut (lut);
soff = flip_index (0, 0);
cstep = flip_index (0, 1) - soff;
rstep = flip_index (1, 0) - flip_index (0, width);
for (row=0; row < height; row++, soff += rstep) {
for (col=0; col < width; col++, soff += cstep)
if (output_bps == 8)
- FORCC ppm [col*colors+c] = lut[image[soff][c]];
- else FORCC ppm2[col*colors+c] = image[soff][c];
+ FORCC ppm [col*colors+c] = curve[image[soff][c]] >> 8;
+ else FORCC ppm2[col*colors+c] = curve[image[soff][c]];
if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
swab (ppm2, ppm2, width*colors*2);
fwrite (ppm, colors*output_bps/8, width, ofp);
@@ -8130,22 +10081,21 @@ void CLASS write_ppm_tiff (FILE *ofp)
free (ppm);
}
-int CLASS main (int argc, char **argv)
+int CLASS main (int argc, const char **argv)
{
- int arg, status=0;
+ int arg, status=0, quality, i, c;
int timestamp_only=0, thumbnail_only=0, identify_only=0;
int user_qual=-1, user_black=-1, user_sat=-1, user_flip=-1;
- int use_fuji_rotate=1, write_to_stdout=0, quality, i, c;
- char opm, opt, *ofname, *sp, *cp, *bpfile=0, *dark_frame=0;
- const char *write_ext;
+ int use_fuji_rotate=1, write_to_stdout=0, read_from_stdin=0;
+ const char *sp, *bpfile=0, *dark_frame=0, *write_ext;
+ char opm, opt, *ofname, *cp;
struct utimbuf ut;
- FILE *ofp;
#ifndef NO_LCMS
- char *cam_profile=0, *out_profile=0;
+ const char *cam_profile=0, *out_profile=0;
#endif
#ifndef LOCALTIME
- putenv ("TZ=UTC");
+ putenv ((char *) "TZ=UTC");
#endif
#ifdef LOCALEDIR
setlocale (LC_CTYPE, "");
@@ -8155,7 +10105,7 @@ int CLASS main (int argc, char **argv)
#endif
if (argc == 1) {
- printf(_("\nRaw photo decoder \"dcraw\" v%s"), VERSION);
+ printf(_("\nRaw photo decoder \"dcraw\" v%s"), DCRAW_VERSION);
printf(_("\nby Dave Coffin, dcoffin a cybercom o net\n"));
printf(_("\nUsage: %s [OPTION]... [FILE]...\n\n"), argv[0]);
puts(_("-v Print verbose messages"));
@@ -8177,7 +10127,7 @@ int CLASS main (int argc, char **argv)
puts(_("-n <num> Set threshold for wavelet denoising"));
puts(_("-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)"));
puts(_("-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)"));
- puts(_("-o [0-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)"));
+ puts(_("-o [0-6] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ,ACES)"));
#ifndef NO_LCMS
puts(_("-o <file> Apply output ICC profile from file"));
puts(_("-p <file> Apply camera ICC profile from file or \"embed\""));
@@ -8187,12 +10137,14 @@ int CLASS main (int argc, char **argv)
puts(_("-j Don't stretch or rotate raw pixels"));
puts(_("-W Don't automatically brighten the image"));
puts(_("-b <num> Adjust brightness (default = 1.0)"));
+ puts(_("-g <p ts> Set custom gamma curve (default = 2.222 4.5)"));
puts(_("-q [0-3] Set the interpolation quality"));
puts(_("-h Half-size color image (twice as fast as \"-q 0\")"));
puts(_("-f Interpolate RGGB as four colors"));
puts(_("-m <num> Apply a 3x3 median filter to R-G and B-G"));
puts(_("-s [0..N-1] Select one raw image or \"all\" from each file"));
- puts(_("-4 Write 16-bit linear instead of 8-bit with gamma"));
+ puts(_("-6 Write 16-bit instead of 8-bit"));
+ puts(_("-4 Linear 16-bit, same as \"-6 -W -g 1 1\""));
puts(_("-T Write TIFF instead of PPM"));
puts("");
return 1;
@@ -8200,8 +10152,8 @@ int CLASS main (int argc, char **argv)
argv[argc] = "";
for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) {
opt = argv[arg++][1];
- if ((cp = strchr (sp="nbrkStqmHAC", opt)))
- for (i=0; i < "11411111142"[cp-sp]-'0'; i++)
+ if ((cp = (char *) strchr (sp="nbrkStqmHACg", opt)))
+ for (i=0; i < "114111111422"[cp-sp]-'0'; i++)
if (!isdigit(argv[arg+i][0])) {
fprintf (stderr,_("Non-numeric argument to \"-%c\"\n"), opt);
return 1;
@@ -8213,6 +10165,9 @@ int CLASS main (int argc, char **argv)
FORC4 user_mul[c] = atof(argv[arg++]); break;
case 'C': aber[0] = 1 / atof(argv[arg++]);
aber[2] = 1 / atof(argv[arg++]); break;
+ case 'g': gamm[0] = atof(argv[arg++]);
+ gamm[1] = atof(argv[arg++]);
+ if (gamm[0]) gamm[0] = 1/gamm[0]; break;
case 'k': user_black = atoi(argv[arg++]); break;
case 'S': user_sat = atoi(argv[arg++]); break;
case 't': user_flip = atoi(argv[arg++]); break;
@@ -8239,25 +10194,27 @@ int CLASS main (int argc, char **argv)
case 'i': identify_only = 1; break;
case 'c': write_to_stdout = 1; break;
case 'v': verbose = 1; break;
- case 'h': half_size = 1; /* "-h" implies "-f" */
+ case 'h': half_size = 1; break;
case 'f': four_color_rgb = 1; break;
case 'A': FORC4 greybox[c] = atoi(argv[arg++]);
case 'a': use_auto_wb = 1; break;
case 'w': use_camera_wb = 1; break;
- case 'M': use_camera_matrix = (opm == '+'); break;
- case 'D':
- case 'd': document_mode = 1 + (opt == 'D');
+ case 'M': use_camera_matrix = 3 * (opm == '+'); break;
+ case 'I': read_from_stdin = 1; break;
+ case 'E': document_mode++;
+ case 'D': document_mode++;
+ case 'd': document_mode++;
case 'j': use_fuji_rotate = 0; break;
case 'W': no_auto_bright = 1; break;
case 'T': output_tiff = 1; break;
- case '4': output_bps = 16; break;
+ case '4': gamm[0] = gamm[1] =
+ no_auto_bright = 1;
+ case '6': output_bps = 16; break;
default:
fprintf (stderr,_("Unknown option \"-%c\".\n"), opt);
return 1;
}
}
- if (use_camera_matrix < 0)
- use_camera_matrix = use_camera_wb;
if (arg == argc) {
fprintf (stderr,_("No files to process.\n"));
return 1;
@@ -8276,6 +10233,7 @@ int CLASS main (int argc, char **argv)
}
for ( ; arg < argc; arg++) {
status = 1;
+ raw_image = 0;
image = 0;
oprof = 0;
meta_data = ofname = 0;
@@ -8323,6 +10281,7 @@ int CLASS main (int argc, char **argv)
height = thumb_height;
width = thumb_width;
filters = 0;
+ colors = 3;
} else {
fseek (ifp, thumb_offset, SEEK_SET);
write_fun = write_thumb;
@@ -8336,8 +10295,7 @@ int CLASS main (int argc, char **argv)
if (identify_only && verbose && make[0]) {
printf (_("\nFilename: %s\n"), ifname);
printf (_("Timestamp: %s"), ctime(&timestamp));
- printf (_("Camera: %s\n"), make);
- printf (_("Model: %s\n"), model);
+ printf (_("Camera: %s %s\n"), make, model);
if (artist[0])
printf (_("Owner: %s\n"), artist);
if (dng_version) {
@@ -8362,12 +10320,19 @@ int CLASS main (int argc, char **argv)
} else if (!is_raw)
fprintf (stderr,_("Cannot decode file %s\n"), ifname);
if (!is_raw) goto next;
- shrink = filters &&
- (half_size || threshold || aber[0] != 1 || aber[2] != 1);
+ shrink = filters && (half_size || (!identify_only &&
+ (threshold || aber[0] != 1 || aber[2] != 1)));
iheight = (height + shrink) >> shrink;
iwidth = (width + shrink) >> shrink;
if (identify_only) {
if (verbose) {
+ if (document_mode == 3) {
+ top_margin = left_margin = fuji_width = 0;
+ height = raw_height;
+ width = raw_width;
+ }
+ iheight = (height + shrink) >> shrink;
+ iwidth = (width + shrink) >> shrink;
if (use_fuji_rotate) {
if (fuji_width) {
fuji_width = (fuji_width - 1 + shrink) >> shrink;
@@ -8384,10 +10349,15 @@ int CLASS main (int argc, char **argv)
printf (_("Output size: %4d x %d\n"), iwidth, iheight);
printf (_("Raw colors: %d"), colors);
if (filters) {
+ int fhigh = 2, fwide = 2;
+ if ((filters ^ (filters >> 8)) & 0xff) fhigh = 4;
+ if ((filters ^ (filters >> 16)) & 0xffff) fhigh = 8;
+ if (filters == 1) fhigh = fwide = 16;
+ if (filters == 9) fhigh = fwide = 6;
printf (_("\nFilter pattern: "));
- if (!cdesc[3]) cdesc[3] = 'G';
- for (i=0; i < 16; i++)
- putchar (cdesc[fc(i >> 1,i & 1)]);
+ for (i=0; i < fhigh; i++)
+ for (c = i && putchar('/') && 0; c < fwide; c++)
+ putchar (cdesc[fcol(i,c)]);
}
printf (_("\nDaylight multipliers:"));
FORCC printf (" %f", pre_mul[c]);
@@ -8402,16 +10372,17 @@ next:
fclose(ifp);
continue;
}
- if (use_camera_matrix && cmatrix[0][0] > 0.25) {
- memcpy (rgb_cam, cmatrix, sizeof cmatrix);
- raw_color = 0;
- }
- image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image);
- merror (image, "main()");
if (meta_length) {
meta_data = (char *) malloc (meta_length);
merror (meta_data, "main()");
}
+ if (filters || colors == 1) {
+ raw_image = (ushort *) calloc ((raw_height+7), raw_width*2);
+ merror (raw_image, "main()");
+ } else {
+ image = (ushort (*)[4]) calloc (iheight, iwidth*sizeof *image);
+ merror (image, "main()");
+ }
if (verbose)
fprintf (stderr,_("Loading %s %s image from %s ...\n"),
make, model, ifname);
@@ -8419,28 +10390,62 @@ next:
fprintf (stderr,_("%s: \"-s %d\" requests a nonexistent image!\n"),
ifname, shot_select);
fseeko (ifp, data_offset, SEEK_SET);
- (*load_raw)();
+ if (raw_image && read_from_stdin)
+ fread (raw_image, 2, raw_height*raw_width, stdin);
+ else (*load_raw)();
+ if (document_mode == 3) {
+ top_margin = left_margin = fuji_width = 0;
+ height = raw_height;
+ width = raw_width;
+ }
+ iheight = (height + shrink) >> shrink;
+ iwidth = (width + shrink) >> shrink;
+ if (raw_image) {
+ image = (ushort (*)[4]) calloc (iheight, iwidth*sizeof *image);
+ merror (image, "main()");
+ crop_masked_pixels();
+ free (raw_image);
+ }
if (zero_is_bad) remove_zeroes();
bad_pixels (bpfile);
if (dark_frame) subtract (dark_frame);
quality = 2 + !fuji_width;
if (user_qual >= 0) quality = user_qual;
+ i = cblack[3];
+ FORC3 if (i > cblack[c]) i = cblack[c];
+ FORC4 cblack[c] -= i;
+ black += i;
+ i = cblack[6];
+ FORC (cblack[4] * cblack[5])
+ if (i > cblack[6+c]) i = cblack[6+c];
+ FORC (cblack[4] * cblack[5])
+ cblack[6+c] -= i;
+ black += i;
if (user_black >= 0) black = user_black;
+ FORC4 cblack[c] += black;
if (user_sat > 0) maximum = user_sat;
#ifdef COLORCHECK
colorcheck();
#endif
- if (is_foveon && !document_mode) foveon_interpolate();
- if (!is_foveon && document_mode < 2) scale_colors();
+ if (is_foveon) {
+ if (document_mode || load_raw == &CLASS foveon_dp_load_raw) {
+ for (i=0; i < height*width*4; i++)
+ if ((short) image[0][i] < 0) image[0][i] = 0;
+ } else foveon_interpolate();
+ } else if (document_mode < 2)
+ scale_colors();
pre_interpolate();
if (filters && !document_mode) {
if (quality == 0)
lin_interpolate();
else if (quality == 1 || colors > 3)
vng_interpolate();
- else if (quality == 2)
+ else if (quality == 2 && filters > 1000)
ppg_interpolate();
- else ahd_interpolate();
+ else if (filters == 9)
+ xtrans_interpolate (quality*2-3);
+ else
+ ahd_interpolate();
}
if (mix_green)
for (colors=3, i=0; i < height*width; i++)
@@ -8483,7 +10488,7 @@ thumbnail:
}
if (verbose)
fprintf (stderr,_("Writing data to %s ...\n"), ofname);
- (*write_fun)(ofp);
+ (*write_fun)();
fclose(ifp);
if (ofp != stdout) fclose(ofp);
cleanup:
diff --git a/libkdcraw/libkdcraw/kdcraw.cpp b/libkdcraw/libkdcraw/kdcraw.cpp
index c70b315..c0c9107 100644
--- a/libkdcraw/libkdcraw/kdcraw.cpp
+++ b/libkdcraw/libkdcraw/kdcraw.cpp
@@ -173,7 +173,8 @@ bool KDcraw::loadHalfPreview(TQImage& image, const TQString& path)
raw.imgdata.params.half_size = 1; // Half-size color image (3x faster than -q).
// NOTE: new magic option introduced by LibRaw 0.7.0 to to make better noise filtration.
- raw.imgdata.params.filtering_mode = LIBRAW_FILTERING_AUTOMATIC;
+ //not with us in libraw 0.14+
+ //raw.imgdata.params.filtering_mode = LIBRAW_FILTERING_AUTOMATIC;
int ret = raw.open_file((const char*)(TQFile::encodeName(path)));
if (ret != LIBRAW_SUCCESS)
@@ -292,7 +293,7 @@ bool KDcraw::extractRAWData(const TQString& filePath, TQByteArray &rawData, Dcra
d->setProgress(0.3);
raw.imgdata.params.output_bps = 16;
- raw.imgdata.params.document_mode = 2;
+ //raw.imgdata.params.document_mode = 2;
ret = raw.unpack();
if (ret != LIBRAW_SUCCESS)
@@ -387,12 +388,13 @@ bool KDcraw::loadFromDcraw(const TQString& filePath, TQByteArray &imageData,
TQByteArray outputProfile = TQFile::encodeName(m_rawDecodingSettings.outputProfile);
// NOTE: new magic option introduced by LibRaw 0.7.0 to to make better noise/etc filtration.
- raw.imgdata.params.filtering_mode = LIBRAW_FILTERING_AUTOMATIC;
+ //Not in 0.14
+ //raw.imgdata.params.filtering_mode = LIBRAW_FILTERING_AUTOMATIC;
if (m_rawDecodingSettings.gamma16bit)
{
// 16 bits color depth auto-gamma is not implemented in dcraw.
- raw.imgdata.params.gamma_16bit = 1;
+ //raw.imgdata.params.gamma_16bit = 1;
}
if (m_rawDecodingSettings.sixteenBitsImage)
diff --git a/libkdcraw/libkdcraw/kdcrawprivate.cpp b/libkdcraw/libkdcraw/kdcrawprivate.cpp
index df95fd0..567e6b3 100644
--- a/libkdcraw/libkdcraw/kdcrawprivate.cpp
+++ b/libkdcraw/libkdcraw/kdcrawprivate.cpp
@@ -135,7 +135,7 @@ void KDcrawPriv::fillIndentifyInfo(LibRaw *raw, DcrawInfoContainer& identify)
{
if (!raw->imgdata.idata.cdesc[3]) raw->imgdata.idata.cdesc[3] = 'G';
for (int i=0; i < 16; i++)
- identify.filterPattern.append(raw->imgdata.idata.cdesc[raw->fc(i >> 1,i & 1)]);
+ identify.filterPattern.append(raw->imgdata.idata.cdesc[raw->FC(i >> 1,i & 1)]);
}
for(int c = 0 ; c < raw->imgdata.idata.colors ; c++)
diff --git a/libkdcraw/libraw/CMakeLists.txt b/libkdcraw/libraw/CMakeLists.txt
index 5ef466a..47b0be4 100644
--- a/libkdcraw/libraw/CMakeLists.txt
+++ b/libkdcraw/libraw/CMakeLists.txt
@@ -20,9 +20,10 @@ tde_add_library( raw STATIC_PIC AUTOMOC
SOURCES
src/libraw_cxx.cpp
src/libraw_c_api.cpp
+ src/libraw_datastream.cpp
internal/dcraw_common.cpp
+ internal/demosaic_packs.cpp
internal/dcraw_fileio.cpp
- internal/foveon.cpp
LINK
${LCMS_LIBRARIES}
diff --git a/libkdcraw/libraw/internal/dcraw_common.cpp b/libkdcraw/libraw/internal/dcraw_common.cpp
index 31ae01d..a277526 100644
--- a/libkdcraw/libraw/internal/dcraw_common.cpp
+++ b/libkdcraw/libraw/internal/dcraw_common.cpp
@@ -1,8295 +1,68 @@
-/*
- GENERATED FILE, DO NOT EDIT
- Generated from dcraw/dcraw.c at Tue Apr 7 15:14:48 2009
- Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
- for copyright information.
-*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define CLASS LibRaw::
-#include "libraw/libraw_types.h"
-#define LIBRAW_LIBRARY_BUILD
-#define LIBRAW_IO_REDEFINED
-#include "libraw/libraw.h"
-#include "internal/defines.h"
-#include "internal/var_defines.h"
-
-
-#ifndef __GLIBC__
-char *my_memmem (char *haystack, size_t haystacklen,
- char *needle, size_t needlelen)
-{
- char *c;
- for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
- if (!memcmp (c, needle, needlelen))
- return c;
- return 0;
-}
-#define memmem my_memmem
-#endif
-
-
-ushort CLASS sget2 (uchar *s)
-{
- if (order == 0x4949) /* "II" means little-endian */
- return s[0] | s[1] << 8;
- else /* "MM" means big-endian */
- return s[0] << 8 | s[1];
-}
-
-ushort CLASS get2()
-{
- uchar str[2] = { 0xff,0xff };
- fread (str, 1, 2, ifp);
- return sget2(str);
-}
-
-unsigned CLASS sget4 (uchar *s)
-{
- if (order == 0x4949)
- return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
- else
- return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
-}
-#define sget4(s) sget4((uchar *)s)
-
-unsigned CLASS get4()
-{
- uchar str[4] = { 0xff,0xff,0xff,0xff };
- fread (str, 1, 4, ifp);
- return sget4(str);
-}
-
-unsigned CLASS getint (int type)
-{
- return type == 3 ? get2() : get4();
-}
-
-float CLASS int_to_float (int i)
-{
- union { int i; float f; } u;
- u.i = i;
- return u.f;
-}
-
-double CLASS getreal (int type)
-{
- union { char c[8]; double d; } u;
- int i, rev;
-
- switch (type) {
- case 3: return (unsigned short) get2();
- case 4: return (unsigned int) get4();
- case 5: u.d = (unsigned int) get4();
- return u.d / (unsigned int) get4();
- case 8: return (signed short) get2();
- case 9: return (signed int) get4();
- case 10: u.d = (signed int) get4();
- return u.d / (signed int) get4();
- case 11: return int_to_float (get4());
- case 12:
- rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234));
- for (i=0; i < 8; i++)
- u.c[i ^ rev] = fgetc(ifp);
- return u.d;
- default: return fgetc(ifp);
- }
-}
-
-void CLASS read_shorts (ushort *pixel, int count)
-{
- if (fread (pixel, 2, count, ifp) < count) derror();
- if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
- swab ((char*)pixel, (char*)pixel, count*2);
-}
-void CLASS canon_black (double dark[2])
-{
- int c, diff, row, col;
-
- if (raw_width < width+4) return;
- FORC(2) dark[c] /= (raw_width-width-2) * height >> 1;
-#ifdef LIBRAW_LIBRARY_BUILD
- if(!( filtering_mode & LIBRAW_FILTERING_NOBLACKS) )
- {
-#endif
- if ((diff = dark[0] - dark[1]))
- for (row=0; row < height; row++)
- for (col=1; col < width; col+=2)
- BAYER(row,col) += diff;
-#ifdef LIBRAW_LIBRARY_BUILD
- }
-#endif
- dark[1] += diff;
- black = (dark[0] + dark[1] + 1) / 2;
-}
-
-void CLASS canon_600_fixed_wb (int temp)
-{
- static const short mul[4][5] = {
- { 667, 358,397,565,452 },
- { 731, 390,367,499,517 },
- { 1119, 396,348,448,537 },
- { 1399, 485,431,508,688 } };
- int lo, hi, i;
- float frac=0;
-
- for (lo=4; --lo; )
- if (*mul[lo] <= temp) break;
- for (hi=0; hi < 3; hi++)
- if (*mul[hi] >= temp) break;
- if (lo != hi)
- frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
- for (i=1; i < 5; i++)
- pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
-}
-
-/* Return values: 0 = white 1 = near white 2 = not white */
-int CLASS canon_600_color (int ratio[2], int mar)
-{
- int clipped=0, target, miss;
-
- if (flash_used) {
- if (ratio[1] < -104)
- { ratio[1] = -104; clipped = 1; }
- if (ratio[1] > 12)
- { ratio[1] = 12; clipped = 1; }
- } else {
- if (ratio[1] < -264 || ratio[1] > 461) return 2;
- if (ratio[1] < -50)
- { ratio[1] = -50; clipped = 1; }
- if (ratio[1] > 307)
- { ratio[1] = 307; clipped = 1; }
- }
- target = flash_used || ratio[1] < 197
- ? -38 - (398 * ratio[1] >> 10)
- : -123 + (48 * ratio[1] >> 10);
- if (target - mar <= ratio[0] &&
- target + 20 >= ratio[0] && !clipped) return 0;
- miss = target - ratio[0];
- if (abs(miss) >= mar*4) return 2;
- if (miss < -20) miss = -20;
- if (miss > mar) miss = mar;
- ratio[0] = target - miss;
- return 1;
-}
-
-void CLASS canon_600_auto_wb()
-{
- int mar, row, col, i, j, st, count[] = { 0,0 };
- int test[8], total[2][8], ratio[2][2], stat[2];
-
- memset (&total, 0, sizeof total);
- i = canon_ev + 0.5;
- if (i < 10) mar = 150;
- else if (i > 12) mar = 20;
- else mar = 280 - 20 * i;
- if (flash_used) mar = 80;
- for (row=14; row < height-14; row+=4)
- for (col=10; col < width; col+=2) {
- for (i=0; i < 8; i++)
- test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] =
- BAYER(row+(i >> 1),col+(i & 1));
- for (i=0; i < 8; i++)
- if (test[i] < 150 || test[i] > 1500) goto next;
- for (i=0; i < 4; i++)
- if (abs(test[i] - test[i+4]) > 50) goto next;
- for (i=0; i < 2; i++) {
- for (j=0; j < 4; j+=2)
- ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j];
- stat[i] = canon_600_color (ratio[i], mar);
- }
- if ((st = stat[0] | stat[1]) > 1) goto next;
- for (i=0; i < 2; i++)
- if (stat[i])
- for (j=0; j < 2; j++)
- test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10;
- for (i=0; i < 8; i++)
- total[st][i] += test[i];
- count[st]++;
-next: ;
- }
- if (count[0] | count[1]) {
- st = count[0]*200 < count[1];
- for (i=0; i < 4; i++)
- pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CALCULATED;
-#endif
- }
-}
-
-void CLASS canon_600_coeff()
-{
- static const short table[6][12] = {
- { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
- { -1203,1715,-1136,1648, 1388,-876,267,245, -1641,2153,3921,-3409 },
- { -615,1127,-1563,2075, 1437,-925,509,3, -756,1268,2519,-2007 },
- { -190,702,-1886,2398, 2153,-1641,763,-251, -452,964,3040,-2528 },
- { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
- { -807,1319,-1785,2297, 1388,-876,769,-257, -230,742,2067,-1555 } };
- int t=0, i, c;
- float mc, yc;
-
- mc = pre_mul[1] / pre_mul[2];
- yc = pre_mul[3] / pre_mul[2];
- if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1;
- if (mc > 1.28 && mc <= 2) {
- if (yc < 0.8789) t=3;
- else if (yc <= 2) t=4;
- }
- if (flash_used) t=5;
- for (raw_color = i=0; i < 3; i++)
- FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.rgb_cam_state = LIBRAW_COLORSTATE_CALCULATED;
-#endif
-}
-
-void CLASS canon_600_load_raw()
-{
- uchar data[1120], *dp;
- ushort pixel[896], *pix;
- int irow, row, col, val;
- static const short mul[4][2] =
- { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
-
- for (irow=row=0; irow < height; irow++) {
- if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror();
- for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) {
- pix[0] = (dp[0] << 2) + (dp[1] >> 6 );
- pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
- pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
- pix[3] = (dp[4] << 2) + (dp[1] & 3);
- pix[4] = (dp[5] << 2) + (dp[9] & 3);
- pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
- pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
- pix[7] = (dp[8] << 2) + (dp[9] >> 6 );
- }
- for (col=0; col < width; col++)
- BAYER(row,col) = pixel[col];
- for (col=width; col < raw_width; col++)
- {
- black += pixel[col];
-#ifdef LIBRAW_LIBRARY_BUILD
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = pixel[col];
-#endif
- }
- if ((row+=2) > height) row = 1;
- }
- if (raw_width > width)
- black = black / ((raw_width - width) * height) - 4;
- for (row=0; row < height; row++)
- for (col=0; col < width; col++) {
-#ifdef LIBRAW_LIBRARY_BUILD
- if( filtering_mode & LIBRAW_FILTERING_NOBLACKS)
- val = BAYER(row,col);
- else
-#endif
- if ((val = BAYER(row,col) - black) < 0) val = 0;
- val = val * mul[row & 3][col & 1] >> 9;
- BAYER(row,col) = val;
- }
- canon_600_fixed_wb(1311);
- canon_600_auto_wb();
- canon_600_coeff();
- maximum = (0x3ff - black) * 1109 >> 9;
- black = 0;
-}
-
-void CLASS remove_zeroes()
-{
- unsigned row, col, tot, n, r, c;
-
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES,0,2);
-#endif
- for (row=0; row < height; row++)
- for (col=0; col < width; col++)
- if (BAYER(row,col) == 0) {
- tot = n = 0;
- for (r = row-2; r <= row+2; r++)
- for (c = col-2; c <= col+2; c++)
- if (r < height && c < width &&
- FC(r,c) == FC(row,col) && BAYER(r,c))
- tot += (n++,BAYER(r,c));
- if (n) BAYER(row,col) = tot/n;
- }
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES,1,2);
-#endif
-}
-
-int CLASS canon_s2is()
-{
- unsigned row;
-
- for (row=0; row < 100; row++) {
- fseek (ifp, row*3340 + 3284, SEEK_SET);
- if (getc(ifp) > 15) return 1;
- }
- return 0;
-}
-
-void CLASS canon_a5_load_raw()
-{
- ushort data[2565], *dp, pixel;
- int vbits=0, buf=0, row, col, bc=0;
-
- order = 0x4949;
- for (row=-top_margin; row < raw_height-top_margin; row++) {
- read_shorts (dp=data, raw_width * 10 / 16);
- for (col=-left_margin; col < raw_width-left_margin; col++) {
- if ((vbits -= 10) < 0)
- buf = (vbits += 16, (buf << 16) + *dp++);
- pixel = buf >> vbits & 0x3ff;
-#ifdef LIBRAW_LIBRARY_BUILD
- ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin);
- if(dfp) *dfp = pixel;
-#endif
- if ((unsigned) row < height && (unsigned) col < width)
- BAYER(row,col) = pixel;
- else if (col > 1-left_margin && col != width)
- black += (bc++,pixel);
- }
- }
- if (bc) black /= bc;
- maximum = 0x3ff;
-
-#ifdef LIBRAW_LIBRARY_BUILD
- if(!(filtering_mode & LIBRAW_FILTERING_NOZEROES))
-#endif
- if (raw_width > 1600) remove_zeroes();
-}
-
-/*
- getbits(-1) initializes the buffer
- getbits(n) where 0 <= n <= 25 returns an n-bit integer
- */
-unsigned CLASS getbits (int nbits)
-{
-#ifdef LIBRAW_NOTHREADS
- static unsigned bitbuf=0;
- static int vbits=0, reset=0;
-#else
-#define bitbuf tls->getbits.bitbuf
-#define vbits tls->getbits.vbits
-#define reset tls->getbits.reset
-#endif
- unsigned c;
-
- if (nbits == -1)
- return bitbuf = vbits = reset = 0;
- if (nbits == 0 || reset) return 0;
- while (vbits < nbits) {
- if ((c = fgetc(ifp)) == EOF) derror();
- if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0;
- bitbuf = (bitbuf << 8) + (uchar) c;
- vbits += 8;
- }
- vbits -= nbits;
- return bitbuf << (32-nbits-vbits) >> (32-nbits);
-#ifndef LIBRAW_NOTHREADS
-#undef bitbuf
-#undef vbits
-#undef reset
-#endif
-}
-
-void CLASS init_decoder()
-{
- memset (first_decode, 0, sizeof first_decode);
- free_decode = first_decode;
-}
-
-/*
- Construct a decode tree according to the specification in *source.
- The first 16 bytes specify how many codes should be 1-bit, 2-bit
- 3-bit, etc. Bytes after that are the leaf values.
-
- For example, if the source is
-
- { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
- 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
-
- then the code is
-
- 00 0x04
- 010 0x03
- 011 0x05
- 100 0x06
- 101 0x02
- 1100 0x07
- 1101 0x01
- 11100 0x08
- 11101 0x09
- 11110 0x00
- 111110 0x0a
- 1111110 0x0b
- 1111111 0xff
- */
-uchar * CLASS make_decoder (const uchar *source, int level)
-{
- struct decode *cur;
-#ifndef LIBRAW_NOTHREADS
-#define t_leaf tls->make_decoder_leaf
-#else
- static int t_leaf;
-#endif
- int i, next;
-
- if (level==0) t_leaf=0;
- cur = free_decode++;
- if (free_decode > first_decode+2048) {
-#ifdef LIBRAW_LIBRARY_BUILD
- throw LIBRAW_EXCEPTION_DECODE_RAW;
-#else
- fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
- longjmp (failure, 2);
-#endif
- }
- for (i=next=0; i <= t_leaf && next < 16; )
- i += source[next++];
- if (i > t_leaf) {
- if (level < next) {
- cur->branch[0] = free_decode;
- make_decoder (source, level+1);
- cur->branch[1] = free_decode;
- make_decoder (source, level+1);
- } else
- cur->leaf = source[16 + t_leaf++];
- }
- return (uchar *) source + 16 + t_leaf;
-#ifndef LIBRAW_NOTHREADS
-#undef t_leaf
-#endif
-}
-
-void CLASS crw_init_tables (unsigned table)
-{
- static const uchar first_tree[3][29] = {
- { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
- 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
- { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
- 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff },
- { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
- 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff },
- };
- static const uchar second_tree[3][180] = {
- { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
- 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
- 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
- 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
- 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
- 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
- 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
- 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
- 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
- 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
- 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
- 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
- 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
- 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
- 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff },
- { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
- 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
- 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
- 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
- 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
- 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
- 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
- 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
- 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
- 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
- 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
- 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
- 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
- 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
- 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff },
- { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
- 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
- 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
- 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
- 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
- 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
- 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
- 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
- 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
- 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
- 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
- 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
- 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
- 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
- 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff }
- };
- if (table > 2) table = 2;
- init_decoder();
- make_decoder ( first_tree[table], 0);
- second_decode = free_decode;
- make_decoder (second_tree[table], 0);
-}
-
-/*
- Return 0 if the image starts with compressed data,
- 1 if it starts with uncompressed low-order bits.
-
- In Canon compressed data, 0xff is always followed by 0x00.
- */
-int CLASS canon_has_lowbits()
-{
- uchar test[0x4000];
- int ret=1, i;
-
- fseek (ifp, 0, SEEK_SET);
- fread (test, 1, sizeof test, ifp);
- for (i=540; i < sizeof test - 1; i++)
- if (test[i] == 0xff) {
- if (test[i+1]) return 1;
- ret=0;
- }
- return ret;
-}
-
-void CLASS canon_compressed_load_raw()
-{
- ushort *pixel, *prow;
- int nblocks, lowbits, i, row, r, col, save, val;
- unsigned irow, icol;
- struct decode *decode, *dindex;
- int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
- double dark[2] = { 0,0 };
- uchar c;
-
- crw_init_tables (tiff_compress);
- pixel = (ushort *) calloc (raw_width*8, sizeof *pixel);
- merror (pixel, "canon_compressed_load_raw()");
- lowbits = canon_has_lowbits();
- if (!lowbits) maximum = 0x3ff;
- fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET);
- zero_after_ff = 1;
- getbits(-1);
- for (row=0; row < raw_height; row+=8) {
- nblocks = MIN (8, raw_height-row) * raw_width >> 6;
- for (block=0; block < nblocks; block++) {
- memset (diffbuf, 0, sizeof diffbuf);
- decode = first_decode;
- for (i=0; i < 64; i++ ) {
- for (dindex=decode; dindex->branch[0]; )
- dindex = dindex->branch[getbits(1)];
- leaf = dindex->leaf;
- decode = second_decode;
- if (leaf == 0 && i) break;
- if (leaf == 0xff) continue;
- i += leaf >> 4;
- len = leaf & 15;
- if (len == 0) continue;
- diff = getbits(len);
- if ((diff & (1 << (len-1))) == 0)
- diff -= (1 << len) - 1;
- if (i < 64) diffbuf[i] = diff;
- }
- diffbuf[0] += carry;
- carry = diffbuf[0];
- for (i=0; i < 64; i++ ) {
- if (pnum++ % raw_width == 0)
- base[0] = base[1] = 512;
- if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
- derror();
- }
- }
- if (lowbits) {
- save = ftell(ifp);
- fseek (ifp, 26 + row*raw_width/4, SEEK_SET);
- for (prow=pixel, i=0; i < raw_width*2; i++) {
- c = fgetc(ifp);
- for (r=0; r < 8; r+=2, prow++) {
- val = (*prow << 2) + ((c >> r) & 3);
- if (raw_width == 2672 && val < 512) val += 2;
- *prow = val;
- }
- }
- fseek (ifp, save, SEEK_SET);
- }
- for (r=0; r < 8; r++) {
- irow = row - top_margin + r;
-#ifndef LIBRAW_LIBRARY_BUILD
- if (irow >= height) continue;
-#endif
- for (col=0; col < raw_width; col++) {
-#ifdef LIBRAW_LIBRARY_BUILD
- ushort *dfp = get_masked_pointer(row+r,col);
- if(dfp) *dfp = pixel[r*raw_width+col];
- if (irow >= height) continue; // skip for top/bottom rows
-#endif
- icol = col - left_margin;
- if (icol < width)
- BAYER(irow,icol) = pixel[r*raw_width+col];
- else if (col > 1)
- dark[icol & 1] += pixel[r*raw_width+col];
- }
- }
- }
- free (pixel);
- canon_black (dark);
-}
-
-int CLASS ljpeg_start (struct jhead *jh, int info_only)
-{
- int c, tag, len;
- uchar data[0x10000], *dp;
-
- if (!info_only) init_decoder();
- memset (jh, 0, sizeof *jh);
- FORC(6) jh->huff[c] = free_decode;
- jh->restart = INT_MAX;
- fread (data, 2, 1, ifp);
- if (data[1] != 0xd8) return 0;
- do {
- fread (data, 2, 2, ifp);
- tag = data[0] << 8 | data[1];
- len = (data[2] << 8 | data[3]) - 2;
- if (tag <= 0xff00) return 0;
- fread (data, 1, len, ifp);
- switch (tag) {
- case 0xffc3:
- jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
- case 0xffc0:
- jh->bits = data[0];
- jh->high = data[1] << 8 | data[2];
- jh->wide = data[3] << 8 | data[4];
- jh->clrs = data[5] + jh->sraw;
- if (len == 9 && !dng_version) getc(ifp);
- break;
- case 0xffc4:
- if (info_only) break;
- for (dp = data; dp < data+len && *dp < 4; ) {
- jh->huff[*dp] = free_decode;
- dp = make_decoder (++dp, 0);
- }
- break;
- case 0xffda:
- jh->psv = data[1+data[0]*2];
- jh->bits -= data[3+data[0]*2] & 15;
- break;
- case 0xffdd:
- jh->restart = data[0] << 8 | data[1];
- }
- } while (tag != 0xffda);
- if (info_only) return 1;
- if (jh->sraw) {
- FORC(4) jh->huff[2+c] = jh->huff[1];
- FORC(jh->sraw) jh->huff[1+c] = jh->huff[0];
- }
- jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4);
- merror (jh->row, "ljpeg_start()");
- return zero_after_ff = 1;
-}
-
-int CLASS ljpeg_diff (struct decode *dindex)
-{
- int len, diff;
-
- while (dindex->branch[0])
- dindex = dindex->branch[getbits(1)];
- len = dindex->leaf;
- if (len == 16 && (!dng_version || dng_version >= 0x1010000))
- return -32768;
- diff = getbits(len);
- if ((diff & (1 << (len-1))) == 0)
- diff -= (1 << len) - 1;
- return diff;
-}
-
-ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
-{
- int col, c, diff, pred, spred=0;
- ushort mark=0, *row[3];
-
- if (jrow * jh->wide % jh->restart == 0) {
- FORC(6) jh->vpred[c] = 1 << (jh->bits-1);
- if (jrow)
- do mark = (mark << 8) + (c = fgetc(ifp));
- while (c != EOF && mark >> 4 != 0xffd);
- getbits(-1);
- }
- FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
- for (col=0; col < jh->wide; col++)
- FORC(jh->clrs) {
- diff = ljpeg_diff (jh->huff[c]);
- if (jh->sraw && c <= jh->sraw && (col | c))
- pred = spred;
- else if (col) pred = row[0][-jh->clrs];
- else pred = (jh->vpred[c] += diff) - diff;
- if (jrow && col) switch (jh->psv) {
- case 1: break;
- case 2: pred = row[1][0]; break;
- case 3: pred = row[1][-jh->clrs]; break;
- case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break;
- case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1); break;
- case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1); break;
- case 7: pred = (pred + row[1][0]) >> 1; break;
- default: pred = 0;
- }
- if ((**row = pred + diff) >> jh->bits) derror();
- if (c <= jh->sraw) spred = **row;
- row[0]++; row[1]++;
- }
- return row[2];
-}
-
-void CLASS lossless_jpeg_load_raw()
-{
- int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0;
- double dark[2] = { 0,0 };
- struct jhead jh;
- int min=INT_MAX;
- ushort *rp;
-
- if (!ljpeg_start (&jh, 0)) return;
- jwide = jh.wide * jh.clrs;
-
- for (jrow=0; jrow < jh.high; jrow++) {
- rp = ljpeg_row (jrow, &jh);
- for (jcol=0; jcol < jwide; jcol++) {
- val = *rp++;
- if (jh.bits <= 12)
-#ifdef LIBRAW_LIBRARY_BUILD
- if( !(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
-#endif
- val = curve[val & 0xfff];
- if (cr2_slice[0]) {
- jidx = jrow*jwide + jcol;
- i = jidx / (cr2_slice[1]*jh.high);
- if ((j = i >= cr2_slice[0]))
- i = cr2_slice[0];
- jidx -= i * (cr2_slice[1]*jh.high);
- row = jidx / cr2_slice[1+j];
- col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
- }
- if (raw_width == 3984 && (col -= 2) < 0)
- col += (row--,raw_width);
-#ifdef LIBRAW_LIBRARY_BUILD
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = val;
-#endif
- if ((unsigned) (row-top_margin) < height) {
- if ((unsigned) (col-left_margin) < width) {
- BAYER(row-top_margin,col-left_margin) = val;
- if (min > val) min = val;
- } else if (col > 1)
- dark[(col-left_margin) & 1] += val;
- }
- if (++col >= raw_width)
- col = (row++,0);
- }
- }
- free (jh.row);
- canon_black (dark);
- if (!strcasecmp(make,"KODAK"))
- black = min;
-}
-
-void CLASS canon_sraw_load_raw()
-{
- struct jhead jh;
- short *rp=0, (*ip)[4];
- int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
- int v[3]={0,0,0}, ver, hue;
- char *cp;
-
- if (!ljpeg_start (&jh, 0)) return;
- jwide = (jh.wide >>= 1) * jh.clrs;
-
- for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
- scol = ecol;
- ecol += cr2_slice[1] * 2 / jh.clrs;
- if (!cr2_slice[0] || ecol > raw_width-1) ecol = raw_width & -2;
- for (row=0; row < height; row += (jh.clrs >> 1) - 1) {
- ip = (short (*)[4]) image + row*width;
- for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
- if ((jcol %= jwide) == 0)
- rp = (short *) ljpeg_row (jrow++, &jh);
- if (col >= width) continue;
- FORC (jh.clrs-2)
- ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c];
- ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
- ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
- }
- }
- }
- for (cp=model2; *cp && !isdigit(*cp); cp++);
- sscanf (cp, "%d.%d.%d", v, v+1, v+2);
- ver = (v[0]*1000 + v[1])*1000 + v[2];
- hue = (jh.sraw+1) << 2;
- if (unique_id == 0x80000218 && ver > 1000006 && ver < 3000000)
- hue = jh.sraw << 1;
- ip = (short (*)[4]) image;
- rp = ip[0];
- for (row=0; row < height; row++, ip+=width) {
- if (row & (jh.sraw >> 1))
- for (col=0; col < width; col+=2)
- for (c=1; c < 3; c++)
- if (row == height-1)
- ip[col][c] = ip[col-width][c];
- else ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1;
- for (col=1; col < width; col+=2)
- for (c=1; c < 3; c++)
- if (col == width-1)
- ip[col][c] = ip[col-1][c];
- else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
- }
- for ( ; rp < ip[0]; rp+=4) {
- if (unique_id < 0x80000200) {
- pix[0] = rp[0] + rp[2] - 512;
- pix[2] = rp[0] + rp[1] - 512;
- pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12) - 512;
- } else {
- rp[1] = (rp[1] << 2) + hue;
- rp[2] = (rp[2] << 2) + hue;
- pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 14);
- pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
- pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 14);
- }
- FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
- }
- free (jh.row);
- maximum = 0x3fff;
-}
-
-void CLASS adobe_copy_pixel (int row, int col, ushort **rp)
-{
- unsigned r, c;
-
- r = row -= top_margin;
- c = col -= left_margin;
- if (is_raw == 2 && shot_select) (*rp)++;
- if (filters) {
-#ifndef LIBRAW_LIBRARY_BUILD
- if (fuji_width) {
- r = row + fuji_width - 1 - (col >> 1);
- c = row + ((col+1) >> 1);
- }
-#endif
-#ifdef LIBRAW_LIBRARY_BUILD
- ushort val = **rp;
- if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
- val = **rp < 0x1000 ? curve[**rp] : **rp;
- if (r < height && c < width)
- BAYER(r,c) = val;
- else
- {
- ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin);
- if(dfp) *dfp = val;
- }
-#else
- if (r < height && c < width)
- BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp;
-#endif
- *rp += is_raw;
- } else {
- if (r < height && c < width)
- FORC(tiff_samples)
- image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c];
- *rp += tiff_samples;
- }
- if (is_raw == 2 && shot_select) (*rp)--;
-}
-
-void CLASS adobe_dng_load_raw_lj()
-{
- unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
- struct jhead jh;
- ushort *rp;
-
- while (trow < raw_height) {
- save = ftell(ifp);
- if (tile_length < INT_MAX)
- fseek (ifp, get4(), SEEK_SET);
- if (!ljpeg_start (&jh, 0)) break;
- jwide = jh.wide;
- if (filters) jwide *= jh.clrs;
- jwide /= is_raw;
- for (row=col=jrow=0; jrow < jh.high; jrow++) {
- rp = ljpeg_row (jrow, &jh);
- for (jcol=0; jcol < jwide; jcol++) {
- adobe_copy_pixel (trow+row, tcol+col, &rp);
- if (++col >= tile_width || col >= raw_width)
- row += 1 + (col = 0);
- }
- }
- fseek (ifp, save+4, SEEK_SET);
- if ((tcol += tile_width) >= raw_width)
- trow += tile_length + (tcol = 0);
- free (jh.row);
- }
-}
-
-void CLASS adobe_dng_load_raw_nc()
-{
- ushort *pixel, *rp;
- int row, col;
-
- pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel);
- merror (pixel, "adobe_dng_load_raw_nc()");
- for (row=0; row < raw_height; row++) {
- if (tiff_bps == 16)
- read_shorts (pixel, raw_width * tiff_samples);
- else {
- getbits(-1);
- for (col=0; col < raw_width * tiff_samples; col++)
- pixel[col] = getbits(tiff_bps);
- }
- for (rp=pixel, col=0; col < raw_width; col++)
- adobe_copy_pixel (row, col, &rp);
- }
- free (pixel);
-}
-
-void CLASS pentax_tree()
-{
- ushort bit[2][13];
- struct decode *cur;
- int c, i, j;
-
- init_decoder();
- FORC(13) bit[0][c] = get2();
- FORC(13) bit[1][c] = fgetc(ifp) & 15;
- FORC(13) {
- cur = first_decode;
- for (i=0; i < bit[1][c]; i++) {
- j = bit[0][c] >> (11-i) & 1;
- if (!cur->branch[j]) cur->branch[j] = ++free_decode;
- cur = cur->branch[j];
- }
- cur->leaf = c;
- }
-}
-
-void CLASS pentax_k10_load_raw()
-{
- int row, col, diff;
- ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
-
- getbits(-1);
- for (row=0; row < raw_height; row++)
- {
-#ifndef LIBRAW_LIBRARY_BUILD
- if(row >= height) break;
-#endif
- for (col=0; col < raw_width; col++) {
- diff = ljpeg_diff (first_decode);
- if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
- else hpred[col & 1] += diff;
- if (col < width && row < height)
- BAYER(row,col) = hpred[col & 1];
-#ifdef LIBRAW_LIBRARY_BUILD
- else
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = hpred[col & 1];
- }
-
- if (col < width && row < height)
-#endif
- if (hpred[col & 1] >> 12) derror();
- }
- }
-}
-
-void CLASS nikon_compressed_load_raw()
-{
- static const uchar nikon_tree[][32] = {
- { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */
- 5,4,3,6,2,7,1,0,8,9,11,10,12 },
- { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */
- 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 },
- { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */
- 5,4,6,3,7,2,8,1,9,0,10,11,12 },
- { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */
- 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 },
- { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */
- 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
- { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */
- 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
- struct decode *dindex;
- ushort ver0, ver1, vpred[2][2], hpred[2], csize;
- int i, min, max, step=0, huff=0, split=0, row, col, len, shl, diff;
-
- fseek (ifp, meta_offset, SEEK_SET);
- ver0 = fgetc(ifp);
- ver1 = fgetc(ifp);
- if (ver0 == 0x49 || ver1 == 0x58)
- fseek (ifp, 2110, SEEK_CUR);
- if (ver0 == 0x46) huff = 2;
- if (tiff_bps == 14) huff += 3;
- read_shorts (vpred[0], 4);
- max = 1 << tiff_bps & 0x7fff;
- if ((csize = get2()) > 1)
- step = max / (csize-1);
- if (ver0 == 0x44 && ver1 == 0x20 && step > 0) {
- for (i=0; i < csize; i++)
- curve[i*step] = get2();
- for (i=0; i < max; i++)
- curve[i] = ( curve[i-i%step]*(step-i%step) +
- curve[i-i%step+step]*(i%step) ) / step;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- fseek (ifp, meta_offset+562, SEEK_SET);
- split = get2();
- } else if (ver0 != 0x46 && csize <= 0x4001)
- {
- read_shorts (curve, max=csize);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- while (curve[max-2] == curve[max-1]) max--;
- init_decoder();
- make_decoder (nikon_tree[huff], 0);
- fseek (ifp, data_offset, SEEK_SET);
- getbits(-1);
- for (min=row=0; row < height; row++) {
- if (split && row == split) {
- init_decoder();
- make_decoder (nikon_tree[huff+1], 0);
- max += (min = 16) << 1;
- }
- for (col=0; col < raw_width; col++) {
- for (dindex=first_decode; dindex->branch[0]; )
- dindex = dindex->branch[getbits(1)];
- len = dindex->leaf & 15;
- shl = dindex->leaf >> 4;
- diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
- if ((diff & (1 << (len-1))) == 0)
- diff -= (1 << len) - !shl;
- if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
- else hpred[col & 1] += diff;
- if ((ushort)(hpred[col & 1] + min) >= max) derror();
-#ifndef LIBRAW_LIBRARY_BUILD
- if ((unsigned) (col-left_margin) < width)
- BAYER(row,col-left_margin) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
-#else
- ushort xval = hpred[col & 1];
- if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
- xval = curve[LIM((short)xval,0,0x3fff)];
- if ((unsigned) (col-left_margin) < width)
- {
- BAYER(row,col-left_margin) = xval;
- }
- else
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = xval;
- }
-#endif
-
- }
- }
-}
-
-/*
- Figure out if a NEF file is compressed. These fancy heuristics
- are only needed for the D100, thanks to a bug in some cameras
- that tags all images as "compressed".
- */
-int CLASS nikon_is_compressed()
-{
- uchar test[256];
- int i;
-
- fseek (ifp, data_offset, SEEK_SET);
- fread (test, 1, 256, ifp);
- for (i=15; i < 256; i+=16)
- if (test[i]) return 1;
- return 0;
-}
-
-/*
- Returns 1 for a Coolpix 995, 0 for anything else.
- */
-int CLASS nikon_e995()
-{
- int i, histo[256];
- const uchar often[] = { 0x00, 0x55, 0xaa, 0xff };
-
- memset (histo, 0, sizeof histo);
- fseek (ifp, -2000, SEEK_END);
- for (i=0; i < 2000; i++)
- histo[fgetc(ifp)]++;
- for (i=0; i < 4; i++)
- if (histo[often[i]] < 200)
- return 0;
- return 1;
-}
-
-/*
- Returns 1 for a Coolpix 2100, 0 for anything else.
- */
-int CLASS nikon_e2100()
-{
- uchar t[12];
- int i;
-
- fseek (ifp, 0, SEEK_SET);
- for (i=0; i < 1024; i++) {
- fread (t, 1, 12, ifp);
- if (((t[2] & t[4] & t[7] & t[9]) >> 4
- & t[1] & t[6] & t[8] & t[11] & 3) != 3)
- return 0;
- }
- return 1;
-}
-
-void CLASS nikon_3700()
-{
- int bits, i;
- uchar dp[24];
- static const struct {
- int bits;
- char t_make[12], t_model[15];
- } table[] = {
- { 0x00, "PENTAX", "Optio 33WR" },
- { 0x03, "NIKON", "E3200" },
- { 0x32, "NIKON", "E3700" },
- { 0x33, "OLYMPUS", "C740UZ" } };
-
- fseek (ifp, 3072, SEEK_SET);
- fread (dp, 1, 24, ifp);
- bits = (dp[8] & 3) << 4 | (dp[20] & 3);
- for (i=0; i < sizeof table / sizeof *table; i++)
- if (bits == table[i].bits) {
- strcpy (make, table[i].t_make );
- strcpy (model, table[i].t_model);
- }
-}
-
-/*
- Separates a Minolta DiMAGE Z2 from a Nikon E4300.
- */
-int CLASS minolta_z2()
-{
- int i, nz;
- char tail[424];
-
- fseek (ifp, -sizeof tail, SEEK_END);
- fread (tail, 1, sizeof tail, ifp);
- for (nz=i=0; i < sizeof tail; i++)
- if (tail[i]) nz++;
- return nz > 20;
-}
-
-/* Here raw_width is in bytes, not pixels. */
-void CLASS nikon_e900_load_raw()
-{
- int offset=0, irow, row, col;
-
- for (irow=0; irow < height; irow++) {
- row = irow * 2 % height;
- if (row == 1)
- offset = - (-offset & -4096);
- fseek (ifp, offset, SEEK_SET);
- offset += raw_width;
- getbits(-1);
- for (col=0; col < width; col++)
- BAYER(row,col) = getbits(10);
- }
-}
-
-/*
- The Fuji Super CCD is just a Bayer grid rotated 45 degrees.
- */
-void CLASS fuji_load_raw()
-{
- ushort *pixel;
-#ifndef LIBRAW_LIBRARY_BUILD
- int wide, row, col, r, c;
-
- fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
- wide = fuji_width << !fuji_layout;
- pixel = (ushort *) calloc (wide, sizeof *pixel);
- merror (pixel, "fuji_load_raw()");
- for (row=0; row < raw_height; row++) {
- read_shorts (pixel, wide);
- fseek (ifp, 2*(raw_width - wide), SEEK_CUR);
- for (col=0; col < wide; col++) {
- if (fuji_layout) {
- r = fuji_width - 1 - col + (row >> 1);
- c = col + ((row+1) >> 1);
- } else {
- r = fuji_width - 1 + row - (col >> 1);
- c = row + ((col+1) >> 1);
- }
- BAYER(r,c) = pixel[col];
- }
- }
- free (pixel);
-#else
- int row,col;
- int wide, r, c;
- pixel = (ushort *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "fuji_load_raw()");
- for (row=0; row < raw_height; row++) {
- read_shorts (pixel, raw_width);
- for (col=0; col < raw_width; col++) {
- if(col >= left_margin && col < width+left_margin
- && row >= top_margin && row < height+top_margin)
- {
- int rrow = row-top_margin;
- int ccol = col-left_margin;
- if (fuji_layout) {
- r = fuji_width - 1 - ccol + (rrow >> 1);
- c = ccol + ((rrow+1) >> 1);
- } else {
- r = fuji_width - 1 + rrow - (ccol >> 1);
- c = rrow + ((ccol+1) >> 1);
- }
-
- image[((row-top_margin) >> shrink)*iwidth + ((col-left_margin) >> shrink)][FC(r,c)] = pixel[col];
- }
- else
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = pixel[col];
- }
- }
- }
- free (pixel);
-#endif
-}
-void CLASS ppm_thumb (FILE *tfp)
-{
- char *thumb;
- thumb_length = thumb_width*thumb_height*3;
- thumb = (char *) malloc (thumb_length);
- merror (thumb, "ppm_thumb()");
- fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
- fread (thumb, 1, thumb_length, ifp);
- fwrite (thumb, 1, thumb_length, tfp);
- free (thumb);
-}
-
-void CLASS layer_thumb (FILE *tfp)
-{
- int i, c;
- char *thumb, map[][4] = { "012","102" };
-
- colors = thumb_misc >> 5 & 7;
- thumb_length = thumb_width*thumb_height;
- thumb = (char *) calloc (colors, thumb_length);
- merror (thumb, "layer_thumb()");
- fprintf (tfp, "P%d\n%d %d\n255\n",
- 5 + (colors >> 1), thumb_width, thumb_height);
- fread (thumb, thumb_length, colors, ifp);
- for (i=0; i < thumb_length; i++)
- FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], tfp);
- free (thumb);
-}
-
-void CLASS rollei_thumb (FILE *tfp)
-{
- unsigned i;
- ushort *thumb;
-
- thumb_length = thumb_width * thumb_height;
- thumb = (ushort *) calloc (thumb_length, 2);
- merror (thumb, "rollei_thumb()");
- fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
- read_shorts (thumb, thumb_length);
- for (i=0; i < thumb_length; i++) {
- putc (thumb[i] << 3, tfp);
- putc (thumb[i] >> 5 << 2, tfp);
- putc (thumb[i] >> 11 << 3, tfp);
- }
- free (thumb);
-}
-
-void CLASS rollei_load_raw()
-{
- uchar pixel[10];
- unsigned iten=0, isix, i, buffer=0, row, col, todo[16];
-
- isix = raw_width * raw_height * 5 / 8;
- while (fread (pixel, 1, 10, ifp) == 10) {
- for (i=0; i < 10; i+=2) {
- todo[i] = iten++;
- todo[i+1] = pixel[i] << 8 | pixel[i+1];
- buffer = pixel[i] >> 2 | buffer << 6;
- }
- for ( ; i < 16; i+=2) {
- todo[i] = isix++;
- todo[i+1] = buffer >> (14-i)*5;
- }
- for (i=0; i < 16; i+=2) {
- row = todo[i] / raw_width - top_margin;
- col = todo[i] % raw_width - left_margin;
- if (row < height && col < width)
- BAYER(row,col) = (todo[i+1] & 0x3ff);
-#ifdef LIBRAW_LIBRARY_BUILD
- else
- {
- ushort *dfp = get_masked_pointer(todo[i] / raw_width,todo[i] % raw_width);
- if(dfp) *dfp = (todo[i+1] & 0x3ff);
- }
-#endif
- }
- }
- maximum = 0x3ff;
-}
-
-int CLASS bayer (unsigned row, unsigned col)
-{
- return (row < height && col < width) ? BAYER(row,col) : 0;
-}
-
-void CLASS phase_one_flat_field (int is_float, int nc)
-{
- ushort head[8];
- unsigned wide, y, x, c, rend, cend, row, col;
- float *mrow, num, mult[4];
-
- read_shorts (head, 8);
- wide = head[2] / head[4];
- mrow = (float *) calloc (nc*wide, sizeof *mrow);
- merror (mrow, "phase_one_flat_field()");
- for (y=0; y < head[3] / head[5]; y++) {
- for (x=0; x < wide; x++)
- for (c=0; c < nc; c+=2) {
- num = is_float ? getreal(11) : get2()/32768.0;
- if (y==0) mrow[c*wide+x] = num;
- else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
- }
- if (y==0) continue;
- rend = head[1]-top_margin + y*head[5];
- for (row = rend-head[5]; row < height && row < rend; row++) {
- for (x=1; x < wide; x++) {
- for (c=0; c < nc; c+=2) {
- mult[c] = mrow[c*wide+x-1];
- mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
- }
- cend = head[0]-left_margin + x*head[4];
- for (col = cend-head[4]; col < width && col < cend; col++) {
- c = nc > 2 ? FC(row,col) : 0;
- if (!(c & 1)) {
- c = BAYER(row,col) * mult[c];
- BAYER(row,col) = LIM(c,0,65535);
- }
- for (c=0; c < nc; c+=2)
- mult[c] += mult[c+1];
- }
- }
- for (x=0; x < wide; x++)
- for (c=0; c < nc; c+=2)
- mrow[c*wide+x] += mrow[(c+1)*wide+x];
- }
- }
- free (mrow);
-}
-
-void CLASS phase_one_correct()
-{
- unsigned entries, tag, data, save, col, row, type;
- int len, i, j, k, cip, val[4], dev[4], sum, max;
- int head[9], diff, mindiff=INT_MAX, off_412=0;
- static const signed char dir[12][2] =
- { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
- {-2,-2}, {-2,2}, {2,-2}, {2,2} };
- float poly[8], num, cfrac, frac, mult[2], *yval[2];
- ushort t_curve[0x10000], *xval[2];
-
- if (half_size || !meta_length) return;
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("Phase One correction...\n"));
-#endif
- fseek (ifp, meta_offset, SEEK_SET);
- order = get2();
- fseek (ifp, 6, SEEK_CUR);
- fseek (ifp, meta_offset+get4(), SEEK_SET);
- entries = get4(); get4();
- while (entries--) {
- tag = get4();
- len = get4();
- data = get4();
- save = ftell(ifp);
- fseek (ifp, meta_offset+data, SEEK_SET);
- if (tag == 0x419) { /* Polynomial curve */
- for (get4(), i=0; i < 8; i++)
- poly[i] = getreal(11);
- poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1;
- for (i=0; i < 0x10000; i++) {
- num = (poly[5]*i + poly[3])*i + poly[1];
- t_curve[i] = LIM(num,0,65535);
- } goto apply; /* apply to right half */
- } else if (tag == 0x41a) { /* Polynomial curve */
- for (i=0; i < 4; i++)
- poly[i] = getreal(11);
- for (i=0; i < 0x10000; i++) {
- for (num=0, j=4; j--; )
- num = num * i + poly[j];
- t_curve[i] = LIM(num+i,0,65535);
- } apply: /* apply to whole image */
- for (row=0; row < height; row++)
- for (col = (tag & 1)*ph1.split_col; col < width; col++)
- BAYER(row,col) = t_curve[BAYER(row,col)];
- } else if (tag == 0x400) { /* Sensor defects */
- while ((len -= 8) >= 0) {
- col = get2() - left_margin;
- row = get2() - top_margin;
- type = get2(); get2();
- if (col >= width) continue;
- if (type == 131) /* Bad column */
- for (row=0; row < height; row++)
- if (FC(row,col) == 1) {
- for (sum=i=0; i < 4; i++)
- sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]);
- for (max=i=0; i < 4; i++) {
- dev[i] = abs((val[i] << 2) - sum);
- if (dev[max] < dev[i]) max = i;
- }
- BAYER(row,col) = (sum - val[max])/3.0 + 0.5;
- } else {
- for (sum=0, i=8; i < 12; i++)
- sum += bayer (row+dir[i][0], col+dir[i][1]);
- BAYER(row,col) = 0.5 + sum * 0.0732233 +
- (bayer(row,col-2) + bayer(row,col+2)) * 0.3535534;
- }
- else if (type == 129) { /* Bad pixel */
- if (row >= height) continue;
- j = (FC(row,col) != 1) * 4;
- for (sum=0, i=j; i < j+8; i++)
- sum += bayer (row+dir[i][0], col+dir[i][1]);
- BAYER(row,col) = (sum + 4) >> 3;
- }
- }
- } else if (tag == 0x401) { /* All-color flat fields */
- phase_one_flat_field (1, 2);
- } else if (tag == 0x416 || tag == 0x410) {
- phase_one_flat_field (0, 2);
- } else if (tag == 0x40b) { /* Red+blue flat field */
- phase_one_flat_field (0, 4);
- } else if (tag == 0x412) {
- fseek (ifp, 36, SEEK_CUR);
- diff = abs (get2() - ph1.tag_21a);
- if (mindiff > diff) {
- mindiff = diff;
- off_412 = ftell(ifp) - 38;
- }
- }
- fseek (ifp, save, SEEK_SET);
- }
- if (off_412) {
- fseek (ifp, off_412, SEEK_SET);
- for (i=0; i < 9; i++) head[i] = get4() & 0x7fff;
- yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6);
- merror (yval[0], "phase_one_correct()");
- yval[1] = (float *) (yval[0] + head[1]*head[3]);
- xval[0] = (ushort *) (yval[1] + head[2]*head[4]);
- xval[1] = (ushort *) (xval[0] + head[1]*head[3]);
- get2();
- for (i=0; i < 2; i++)
- for (j=0; j < head[i+1]*head[i+3]; j++)
- yval[i][j] = getreal(11);
- for (i=0; i < 2; i++)
- for (j=0; j < head[i+1]*head[i+3]; j++)
- xval[i][j] = get2();
- for (row=0; row < height; row++)
- for (col=0; col < width; col++) {
- cfrac = (float) col * head[3] / raw_width;
- cfrac -= cip = cfrac;
- num = BAYER(row,col) * 0.5;
- for (i=cip; i < cip+2; i++) {
- for (k=j=0; j < head[1]; j++)
- if (num < xval[0][k = head[1]*i+j]) break;
- frac = (j == 0 || j == head[1]) ? 0 :
- (xval[0][k] - num) / (xval[0][k] - xval[0][k-1]);
- mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac);
- }
- i = ((mult[0] * (1-cfrac) + mult[1] * cfrac)
- * (row + top_margin) + num) * 2;
- BAYER(row,col) = LIM(i,0,65535);
- }
- free (yval[0]);
- }
-}
-
-void CLASS phase_one_load_raw()
-{
- int row, col, a, b;
- ushort *pixel, akey, bkey, mask;
-
- fseek (ifp, ph1.key_off, SEEK_SET);
- akey = get2();
- bkey = get2();
- mask = ph1.format == 1 ? 0x5555:0x1354;
-#ifndef LIBRAW_LIBRARY_BUILD
- fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET);
- pixel = (ushort *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "phase_one_load_raw()");
- for (row=0; row < height; row++) {
- read_shorts (pixel, raw_width);
- for (col=0; col < raw_width; col+=2) {
- a = pixel[col+0] ^ akey;
- b = pixel[col+1] ^ bkey;
- pixel[col+0] = (a & mask) | (b & ~mask);
- pixel[col+1] = (b & mask) | (a & ~mask);
- }
- for (col=0; col < width; col++)
- BAYER(row,col) = pixel[col+left_margin];
- }
- free (pixel);
-#else
- fseek (ifp, data_offset, SEEK_SET);
- pixel = (ushort *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "phase_one_load_raw()");
- for (row=0; row < raw_height; row++) {
- read_shorts (pixel, raw_width);
- for (col=0; col < raw_width; col+=2) {
- a = pixel[col+0] ^ akey;
- b = pixel[col+1] ^ bkey;
- pixel[col+0] = (a & mask) | (b & ~mask);
- pixel[col+1] = (b & mask) | (a & ~mask);
- }
- for (col=0; col < raw_width; col++)
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp)
- *dfp = pixel[col];
- else
- BAYER(row,col-left_margin) = pixel[col];
- }
- }
- free (pixel);
- if(!( filtering_mode & LIBRAW_FILTERING_NORAWCURVE) )
-#endif
- phase_one_correct();
-}
-
-unsigned CLASS ph1_bits (int nbits)
-{
-#ifndef LIBRAW_NOTHREADS
-#define bitbuf tls->ph1_bits.bitbuf
-#define vbits tls->ph1_bits.vbits
-#else
- static UINT64 bitbuf=0;
- static int vbits=0;
-#endif
- if (nbits == -1)
- return bitbuf = vbits = 0;
- if (nbits == 0) return 0;
- if ((vbits -= nbits) < 0) {
- bitbuf = bitbuf << 32 | get4();
- vbits += 32;
- }
- return bitbuf << (64-nbits-vbits) >> (64-nbits);
-#ifndef LIBRAW_NOTHREADS
-#undef bitbuf
-#undef vbits
-#endif
-}
-
-void CLASS phase_one_load_raw_c()
-{
- static const int length[] = { 8,7,6,9,11,10,5,12,14,13 };
- int *offset, len[2], pred[2], row, col, i, j;
- ushort *pixel;
- short (*t_black)[2];
-
- pixel = (ushort *) calloc (raw_width + raw_height*4, 2);
- merror (pixel, "phase_one_load_raw_c()");
- offset = (int *) (pixel + raw_width);
- fseek (ifp, strip_offset, SEEK_SET);
- for (row=0; row < raw_height; row++)
- offset[row] = get4();
- t_black = (short (*)[2]) offset + raw_height;
- fseek (ifp, ph1.black_off, SEEK_SET);
- if (ph1.black_off)
- {
- read_shorts ((ushort *) t_black[0], raw_height*2);
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.masked_pixels.ph1_black = (ushort (*)[2])calloc(raw_height*2,sizeof(ushort));
- merror (imgdata.masked_pixels.ph1_black, "phase_one_load_raw_c()");
- memmove(imgdata.masked_pixels.ph1_black,(ushort *) t_black[0],raw_height*2*sizeof(ushort));
-#endif
- }
- for (i=0; i < 256; i++)
- curve[i] = i*i / 3.969 + 0.5;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.curve_state = LIBRAW_COLORSTATE_CALCULATED;
-#endif
- for (row=0; row < raw_height; row++) {
- fseek (ifp, data_offset + offset[row], SEEK_SET);
- ph1_bits(-1);
- pred[0] = pred[1] = 0;
- for (col=0; col < raw_width; col++) {
- if (col >= (raw_width & -8))
- len[0] = len[1] = 14;
- else if ((col & 7) == 0)
- for (i=0; i < 2; i++) {
- for (j=0; j < 5 && !ph1_bits(1); j++);
- if (j--) len[i] = length[j*2 + ph1_bits(1)];
- }
- if ((i = len[col & 1]) == 14)
- pixel[col] = pred[col & 1] = ph1_bits(16);
- else
- pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1));
- if (pred[col & 1] >> 16) derror();
-#ifdef LIBRAW_LIBRARY_BUILD
- if(!( filtering_mode & LIBRAW_FILTERING_NORAWCURVE) )
-#endif
- if (ph1.format == 5 && pixel[col] < 256)
- pixel[col] = curve[pixel[col]];
- }
- if ((unsigned) (row-top_margin) < height)
-#ifndef LIBRAW_LIBRARY_BUILD
- for (col=0; col < width; col++) {
- i = (pixel[col+left_margin] << 2)
- - ph1.t_black + t_black[row][col >= ph1.split_col];
- if (i > 0) BAYER(row-top_margin,col) = i;
- }
-#else
- {
- for (col=0; col < raw_width; col++) {
- if( filtering_mode & LIBRAW_FILTERING_NOBLACKS)
- i = (pixel[col] << 2);
- else
- i = (pixel[col] << 2)
- - ph1.t_black + t_black[row][(col /* - left_margin */) >= ph1.split_col]; // changed to fix Coffin's bug!
- if(col >= left_margin && col < width+left_margin)
- {
- if (i > 0) BAYER(row-top_margin,col-left_margin) = i;
- }
- else
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(i>0 && dfp) *dfp = i;
- }
- }
- }
- else
- {
- // top-bottom fields
- for (col=0; col < raw_width; col++) {
- i = (pixel[col] << 2)
- - ph1.t_black + t_black[row][(col+left_margin) >= ph1.split_col];
- if (i > 0)
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = i;
- }
- }
- }
-#endif
- }
- free (pixel);
-#ifdef LIBRAW_LIBRARY_BUILD
- if(!( filtering_mode & LIBRAW_FILTERING_NORAWCURVE) )
-#endif
- phase_one_correct();
- maximum = 0xfffc - ph1.t_black;
-}
-
-void CLASS hasselblad_load_raw()
-{
- struct jhead jh;
- struct decode *dindex;
- int row, col, pred[2], len[2], diff, i;
-
- if (!ljpeg_start (&jh, 0)) return;
- free (jh.row);
- order = 0x4949;
- ph1_bits(-1);
- for (row=-top_margin; row < raw_height-top_margin; row++) {
- pred[0] = pred[1] = 0x8000;
- for (col=-left_margin; col < raw_width-left_margin; col+=2) {
- for (i=0; i < 2; i++) {
- for (dindex=jh.huff[0]; dindex->branch[0]; )
- dindex = dindex->branch[ph1_bits(1)];
- len[i] = dindex->leaf;
- }
- for (i=0; i < 2; i++) {
- diff = ph1_bits(len[i]);
- if ((diff & (1 << (len[i]-1))) == 0)
- diff -= (1 << len[i]) - 1;
- if (diff == 65535) diff = -32768;
- pred[i] += diff;
- if (row >= 0 && row < height && (unsigned)(col+i) < width)
- BAYER(row,col+i) = pred[i];
-#ifdef LIBRAW_LIBRARY_BUILD
- else
- {
- ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin);
- if(dfp) *dfp = pred[i];
- }
-#endif
- }
- }
- }
- maximum = 0xffff;
-}
-
-void CLASS leaf_hdr_load_raw()
-{
- ushort *pixel;
- unsigned tile=0, r, c, row, col;
-
- pixel = (ushort *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "leaf_hdr_load_raw()");
- FORC(tiff_samples)
- for (r=0; r < raw_height; r++) {
- if (r % tile_length == 0) {
- fseek (ifp, data_offset + 4*tile++, SEEK_SET);
- fseek (ifp, get4() + 2*left_margin, SEEK_SET);
- }
- if (filters && c != shot_select) continue;
- read_shorts (pixel, raw_width);
- if ((row = r - top_margin) >= height) continue;
- for (col=0; col < width; col++)
- if (filters) BAYER(row,col) = pixel[col];
- else image[row*width+col][c] = pixel[col];
- }
- free (pixel);
- if (!filters) {
- maximum = 0xffff;
- raw_color = 1;
- }
-}
-
-void CLASS sinar_4shot_load_raw()
-{
- ushort *pixel;
- unsigned shot, row, col, r, c;
-
- if ((shot = shot_select) || half_size) {
- if (shot) shot--;
- if (shot > 3) shot = 3;
- fseek (ifp, data_offset + shot*4, SEEK_SET);
- fseek (ifp, get4(), SEEK_SET);
- unpacked_load_raw();
- return;
- }
- free (image);
- image = (ushort (*)[4])
- calloc ((iheight=height)*(iwidth=width), sizeof *image);
- merror (image, "sinar_4shot_load_raw()");
- pixel = (ushort *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "sinar_4shot_load_raw()");
- for (shot=0; shot < 4; shot++) {
- fseek (ifp, data_offset + shot*4, SEEK_SET);
- fseek (ifp, get4(), SEEK_SET);
- for (row=0; row < raw_height; row++) {
- read_shorts (pixel, raw_width);
- if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue;
- for (col=0; col < raw_width; col++) {
- if ((c = col-left_margin - (shot & 1)) >= width) continue;
- image[r*width+c][FC(row,col)] = pixel[col];
- }
- }
- }
- free (pixel);
- shrink = filters = 0;
-}
-
-void CLASS imacon_full_load_raw()
-{
- int row, col;
-
- for (row=0; row < height; row++)
- for (col=0; col < width; col++)
- read_shorts (image[row*width+col], 3);
-}
-
-void CLASS packed_12_load_raw()
-{
- int vbits=0, rbits=0, irow, row, col;
- UINT64 bitbuf=0;
-
- if (raw_width * 2 >= width * 3) { /* If raw_width is in bytes, */
- rbits = raw_width * 8;
- raw_width = raw_width * 2 / 3; /* convert it to pixels and */
- rbits -= raw_width * 12; /* save the remainder. */
- }
- order = load_flags & 1 ? 0x4949 : 0x4d4d;
- for (irow=0; irow < height; irow++) {
- row = irow;
- if (load_flags & 2 &&
- (row = irow * 2 % height + irow / (height/2)) == 1 &&
- load_flags & 4) {
- if (vbits=0, tiff_compress)
- fseek (ifp, data_offset - (-width*height*3/4 & -2048), SEEK_SET);
- else {
- fseek (ifp, 0, SEEK_END);
- fseek (ifp, ftell(ifp)/2, SEEK_SET);
- }
- }
- for (col=0; col < raw_width; col++) {
- if ((vbits -= 12) < 0) {
- bitbuf = bitbuf << 32 | get4();
- vbits += 32;
- }
- if ((unsigned) (col-left_margin) < width)
- BAYER(row,col-left_margin) = bitbuf << (52-vbits) >> 52;
-#ifdef LIBRAW_LIBRARY_BUILD
- else
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = bitbuf << (52-vbits) >> 52;
- }
-#endif
- if (load_flags & 8 && (col % 10) == 9)
- if (vbits=0, bitbuf & 255) derror();
- }
- vbits -= rbits;
- }
- if (!strcmp(make,"OLYMPUS")) black >>= 4;
-}
-
-void CLASS unpacked_load_raw()
-{
- ushort *pixel;
- int row, col, bits=0;
-
- while (1 << ++bits < maximum);
-#ifndef LIBRAW_LIBRARY_BUILD
- fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
- pixel = (ushort *) calloc (width, sizeof *pixel);
- merror (pixel, "unpacked_load_raw()");
- for (row=0; row < height; row++) {
- read_shorts (pixel, width);
- fseek (ifp, 2*(raw_width - width), SEEK_CUR);
- for (col=0; col < width; col++)
- if ((BAYER2(row,col) = pixel[col]) >> bits) derror();
- }
- free (pixel);
-#else
- // fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
- pixel = (ushort *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "unpacked_load_raw()");
- for (row=0; row < raw_height; row++) {
- read_shorts (pixel, raw_width);
- //fseek (ifp, 2*(raw_width - width), SEEK_CUR);
- for (col=0; col < raw_width; col++)
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp)
- *dfp = pixel[col];
- else
- {
- if ((BAYER2(row-top_margin,col-left_margin) = pixel[col]) >> bits) derror();
- }
- }
- }
- free (pixel);
-#endif
-}
-
-void CLASS nokia_load_raw()
-{
- uchar *data, *dp;
- ushort *pixel, *pix;
- int dwide, row, c;
-
- dwide = raw_width * 5 / 4;
- data = (uchar *) malloc (dwide + raw_width*2);
- merror (data, "nokia_load_raw()");
- pixel = (ushort *) (data + dwide);
- for (row=0; row < raw_height; row++) {
- if (fread (data, 1, dwide, ifp) < dwide) derror();
- for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=5, pix+=4)
- FORC4 pix[c] = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
- if (row < top_margin)
-#ifdef LIBRAW_LIBRARY_BUILD
- {
- int col;
- for(col=0;col<width;col++)
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp)
- *dfp = pixel[col];
- }
- FORC(width) black += pixel[c];
- }
-#else
- FORC(width) black += pixel[c];
-#endif
- else
- FORC(width) BAYER(row-top_margin,c) = pixel[c];
- }
- free (data);
- if (top_margin) black /= top_margin * width;
- maximum = 0x3ff;
-}
-
-unsigned CLASS pana_bits (int nbits)
-{
-#ifndef LIBRAW_NOTHREADS
-#define buf tls->pana_bits.buf
-#define vbits tls->pana_bits.vbits
-#else
- static uchar buf[0x4000];
- static int vbits;
-#endif
- int byte;
-
- if (!nbits) return vbits=0;
- if (!vbits) {
- fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
- fread (buf, 1, load_flags, ifp);
- }
- vbits = (vbits - nbits) & 0x1ffff;
- byte = vbits >> 3 ^ 0x3ff0;
- return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
-#ifndef LIBRAW_NOTHREADS
-#undef buf
-#undef vbits
-#endif
-}
-
-void CLASS panasonic_load_raw()
-{
- int row, col, i, j, sh=0, pred[2], nonz[2];
-
- pana_bits(0);
- for (row=0; row < height; row++)
- for (col=0; col < raw_width; col++) {
- if ((i = col % 14) == 0)
- pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
- if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
- if (nonz[i & 1]) {
- if ((j = pana_bits(8))) {
- if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
- pred[i & 1] &= ~(-1 << sh);
- pred[i & 1] += j << sh;
- }
- } else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
- pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
- if (col < width)
- if ((BAYER(row,col) = pred[col & 1]) > 4098) derror();
-#ifdef LIBRAW_LIBRARY_BUILD
- if(col>=width)
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp)*dfp = pred[col & 1];
- }
-#endif
- }
-}
-
-void CLASS olympus_e300_load_raw()
-{
- uchar *data, *dp;
- ushort *pixel, *pix;
- int dwide, row, col;
-
- dwide = raw_width * 16 / 10;
-#ifndef LIBRAW_LIBRARY_BUILD
- fseek (ifp, dwide*top_margin, SEEK_CUR);
-#endif
- data = (uchar *) malloc (dwide + raw_width*2);
- merror (data, "olympus_e300_load_raw()");
- pixel = (ushort *) (data + dwide);
-#ifndef LIBRAW_LIBRARY_BUILD
- for (row=0; row < height; row++)
-#else
- for (row=0; row < raw_height; row++)
-#endif
- {
- if (fread (data, 1, dwide, ifp) < dwide) derror();
- for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) {
- if (((dp-data) & 15) == 15)
- if (*dp++ && pix < pixel+width+left_margin) derror();
- pix[0] = dp[1] << 8 | dp[0];
- pix[1] = dp[2] << 4 | dp[1] >> 4;
- }
-#ifndef LIBRAW_LIBRARY_BUILD
- for (col=0; col < width; col++)
- BAYER(row,col) = (pixel[col+left_margin] & 0xfff);
-#else
- for (col=0; col < raw_width; col++)
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp)
- *dfp = (pixel[col] & 0xfff);
- else
- BAYER(row-top_margin,col-left_margin) = (pixel[col] & 0xfff);
- }
-
-#endif
- }
- free (data);
- maximum >>= 4;
- black >>= 4;
-}
-
-void CLASS olympus_e410_load_raw()
-{
- int row, col, nbits, sign, low, high, i, w, n, nw;
- int acarry[2][3], *carry, pred, diff;
-
- fseek (ifp, 7, SEEK_CUR);
- getbits(-1);
- for (row=0; row < height; row++) {
- memset (acarry, 0, sizeof acarry);
- for (col=0; col < width; col++) {
- carry = acarry[col & 1];
- i = 2 * (carry[2] < 3);
- for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++);
- sign = getbits(1) * -1;
- low = getbits(2);
- for (high=0; high < 12; high++)
- if (getbits(1)) break;
- if (high == 12)
- high = getbits(16-nbits) >> 1;
- carry[0] = (high << nbits) | getbits(nbits);
- diff = (carry[0] ^ sign) + carry[1];
- carry[1] = (diff*3 + carry[1]) >> 5;
- carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
- if (row < 2 && col < 2) pred = 0;
- else if (row < 2) pred = BAYER(row,col-2);
- else if (col < 2) pred = BAYER(row-2,col);
- else {
- w = BAYER(row,col-2);
- n = BAYER(row-2,col);
- nw = BAYER(row-2,col-2);
- if ((w < nw && nw < n) || (n < nw && nw < w)) {
- if (ABS(w-nw) > 32 || ABS(n-nw) > 32)
- pred = w + n - nw;
- else pred = (w + n) >> 1;
- } else pred = ABS(w-nw) > ABS(n-nw) ? w : n;
- }
- if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
- }
- }
-}
-
-void CLASS minolta_rd175_load_raw()
-{
- uchar pixel[768];
- unsigned irow, box, row, col;
-
- for (irow=0; irow < 1481; irow++) {
- if (fread (pixel, 1, 768, ifp) < 768) derror();
- box = irow / 82;
- row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2);
- switch (irow) {
- case 1477: case 1479: continue;
- case 1476: row = 984; break;
- case 1480: row = 985; break;
- case 1478: row = 985; box = 1;
- }
- if ((box < 12) && (box & 1)) {
- for (col=0; col < 1533; col++, row ^= 1)
- if (col != 1) BAYER(row,col) = (col+1) & 2 ?
- pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
- BAYER(row,1) = pixel[1] << 1;
- BAYER(row,1533) = pixel[765] << 1;
- } else
- for (col=row & 1; col < 1534; col+=2)
- BAYER(row,col) = pixel[col/2] << 1;
- }
- maximum = 0xff << 1;
-}
-
-void CLASS casio_qv5700_load_raw()
-{
- uchar data[3232], *dp;
- ushort pixel[2576], *pix;
- int row, col;
-
- for (row=0; row < height; row++) {
- fread (data, 1, 3232, ifp);
- for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) {
- pix[0] = (dp[0] << 2) + (dp[1] >> 6);
- pix[1] = (dp[1] << 4) + (dp[2] >> 4);
- pix[2] = (dp[2] << 6) + (dp[3] >> 2);
- pix[3] = (dp[3] << 8) + (dp[4] );
- }
- for (col=0; col < width; col++)
- BAYER(row,col) = (pixel[col] & 0x3ff);
- }
- maximum = 0x3fc;
-}
-
-void CLASS quicktake_100_load_raw()
-{
- uchar pixel[484][644];
- static const short gstep[16] =
- { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 };
- static const short rstep[6][4] =
- { { -3,-1,1,3 }, { -5,-1,1,5 }, { -8,-2,2,8 },
- { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } };
- static const short t_curve[256] =
- { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
- 28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53,
- 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,
- 79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116,
- 118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155,
- 158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195,
- 197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244,
- 248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322,
- 326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400,
- 405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479,
- 483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643,
- 654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844,
- 855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 };
- int rb, row, col, sharp, val=0;
-
- getbits(-1);
- memset (pixel, 0x80, sizeof pixel);
- for (row=2; row < height+2; row++) {
- for (col=2+(row & 1); col < width+2; col+=2) {
- val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] +
- pixel[row][col-2]) >> 2) + gstep[getbits(4)];
- pixel[row][col] = val = LIM(val,0,255);
- if (col < 4)
- pixel[row][col-2] = pixel[row+1][~row & 1] = val;
- if (row == 2)
- pixel[row-1][col+1] = pixel[row-1][col+3] = val;
- }
- pixel[row][col] = val;
- }
- for (rb=0; rb < 2; rb++)
- for (row=2+rb; row < height+2; row+=2)
- for (col=3-(row & 1); col < width+2; col+=2) {
- if (row < 4 || col < 4) sharp = 2;
- else {
- val = ABS(pixel[row-2][col] - pixel[row][col-2])
- + ABS(pixel[row-2][col] - pixel[row-2][col-2])
- + ABS(pixel[row][col-2] - pixel[row-2][col-2]);
- sharp = val < 4 ? 0 : val < 8 ? 1 : val < 16 ? 2 :
- val < 32 ? 3 : val < 48 ? 4 : 5;
- }
- val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1)
- + rstep[sharp][getbits(2)];
- pixel[row][col] = val = LIM(val,0,255);
- if (row < 4) pixel[row-2][col+2] = val;
- if (col < 4) pixel[row+2][col-2] = val;
- }
- for (row=2; row < height+2; row++)
- for (col=3-(row & 1); col < width+2; col+=2) {
- val = ((pixel[row][col-1] + (pixel[row][col] << 2) +
- pixel[row][col+1]) >> 1) - 0x100;
- pixel[row][col] = LIM(val,0,255);
- }
- for (row=0; row < height; row++)
- for (col=0; col < width; col++)
- BAYER(row,col) = t_curve[pixel[row+2][col+2]];
- maximum = 0x3ff;
-}
-
-const int * CLASS make_decoder_int (const int *source, int level)
-{
- struct decode *cur;
-
- cur = free_decode++;
- if (level < source[0]) {
- cur->branch[0] = free_decode;
- source = make_decoder_int (source, level+1);
- cur->branch[1] = free_decode;
- source = make_decoder_int (source, level+1);
- } else {
- cur->leaf = source[1];
- source += 2;
- }
- return source;
-}
-
-int CLASS radc_token (int tree)
-{
- int t;
-#ifndef LIBRAW_NOTHREADS
-#define dstart tls->radc_token.dstart
-#define dindex tls->radc_token.dindex
-#define s tls->radc_token.s
-
- static const int source[] = {
-#else
- static struct decode *dstart[18], *dindex;
- static const int *s, source[] = {
-#endif
- 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8,
- 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8,
- 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8,
- 2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8,
- 2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8,
- 2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8,
- 2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8,
- 2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8,
- 2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4,
- 2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8,
- 1,0, 2,2, 2,-2,
- 1,-3, 1,3,
- 2,-17, 2,-5, 2,5, 2,17,
- 2,-7, 2,2, 2,9, 2,18,
- 2,-18, 2,-9, 2,-2, 2,7,
- 2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79,
- 2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76,
- 2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37
- };
-
- if (free_decode == first_decode)
- for (s=source, t=0; t < 18; t++) {
- dstart[t] = free_decode;
- s = make_decoder_int (s, 0);
- }
- if (tree == 18) {
- if (kodak_cbpp == 243)
- return (getbits(6) << 2) + 2; /* most DC50 photos */
- else
- return (getbits(5) << 3) + 4; /* DC40, Fotoman Pixtura */
- }
- for (dindex = dstart[tree]; dindex->branch[0]; )
- dindex = dindex->branch[getbits(1)];
- return dindex->leaf;
-
-#ifndef LIBRAW_NOTHREADS
-#undef dstart
-#undef dindex
-#undef s
-#endif
-}
-
-#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
-
-#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
-: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
-
-void CLASS kodak_radc_load_raw()
-{
- int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
- short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];
-
- init_decoder();
- getbits(-1);
- for (i=0; i < sizeof(buf)/sizeof(short); i++)
- buf[0][0][i] = 2048;
- for (row=0; row < height; row+=4) {
- FORC3 mul[c] = getbits(6);
- FORC3 {
- val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
- s = val > 65564 ? 10:12;
- x = ~(-1 << (s-1));
- val <<= 12-s;
- for (i=0; i < sizeof(buf[0])/sizeof(short); i++)
- buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
- last[c] = mul[c];
- for (r=0; r <= !c; r++) {
- buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
- for (tree=1, col=width/2; col > 0; ) {
- if ((tree = radc_token(tree))) {
- col -= 2;
- if (tree == 8)
- FORYX buf[c][y][x] = radc_token(tree+10) * mul[c];
- else
- FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
- } else
- do {
- nreps = (col > 2) ? radc_token(9) + 1 : 1;
- for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
- col -= 2;
- FORYX buf[c][y][x] = PREDICTOR;
- if (rep & 1) {
- step = radc_token(10) << 4;
- FORYX buf[c][y][x] += step;
- }
- }
- } while (nreps == 9);
- }
- for (y=0; y < 2; y++)
- for (x=0; x < width/2; x++) {
- val = (buf[c][y+1][x] << 4) / mul[c];
- if (val < 0) val = 0;
- if (c) BAYER(row+y*2+c-1,x*2+2-c) = val;
- else BAYER(row+r*2+y,x*2+y) = val;
- }
- memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
- }
- }
- for (y=row; y < row+4; y++)
- for (x=0; x < width; x++)
- if ((x+y) & 1) {
- r = x ? x-1 : x+1;
- s = x+1 < width ? x+1 : x-1;
- val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2;
- if (val < 0) val = 0;
- BAYER(y,x) = val;
- }
- }
- maximum = 0xfff;
- use_gamma = 0;
-}
-
-#undef FORYX
-#undef PREDICTOR
-
-#ifdef NO_JPEG
-void CLASS kodak_jpeg_load_raw() {}
-#else
-
-METHODDEF(boolean)
-fill_input_buffer (j_decompress_ptr cinfo)
-{
-#ifndef LIBRAW_NOTHREADS
-#define jpeg_buffer tls->jpeg_buffer
-#else
- static uchar jpeg_buffer[4096];
-#endif
- size_t nbytes;
-
- nbytes = fread (jpeg_buffer, 1, 4096, ifp);
- swab (jpeg_buffer, jpeg_buffer, nbytes);
- cinfo->src->next_input_byte = jpeg_buffer;
- cinfo->src->bytes_in_buffer = nbytes;
- return TRUE;
-#ifndef LIBRAW_NOTHREADS
-#undef jpeg_buffer
-#endif
-}
-
-void CLASS kodak_jpeg_load_raw()
-{
- struct jpeg_decompress_struct cinfo;
- struct jpeg_error_mgr jerr;
- JSAMPARRAY buf;
- JSAMPLE (*pixel)[3];
- int row, col;
-
- cinfo.err = jpeg_std_error (&jerr);
- jpeg_create_decompress (&cinfo);
- jpeg_stdio_src (&cinfo, ifp);
- cinfo.src->fill_input_buffer = fill_input_buffer;
- jpeg_read_header (&cinfo, TRUE);
- jpeg_start_decompress (&cinfo);
- if ((cinfo.output_width != width ) ||
- (cinfo.output_height*2 != height ) ||
- (cinfo.output_components != 3 )) {
-#ifdef DCRAW_VERBOSE
- fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname);
-#endif
- jpeg_destroy_decompress (&cinfo);
-#ifdef LIBRAW_LIBRARY_BUILD
- throw LIBRAW_EXCEPTION_DECODE_JPEG;
-#else
- longjmp (failure, 3);
-#endif
- }
- buf = (*cinfo.mem->alloc_sarray)
- ((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1);
-
- while (cinfo.output_scanline < cinfo.output_height) {
- row = cinfo.output_scanline * 2;
- jpeg_read_scanlines (&cinfo, buf, 1);
- pixel = (JSAMPLE (*)[3]) buf[0];
- for (col=0; col < width; col+=2) {
- BAYER(row+0,col+0) = pixel[col+0][1] << 1;
- BAYER(row+1,col+1) = pixel[col+1][1] << 1;
- BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
- BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
- }
- }
- jpeg_finish_decompress (&cinfo);
- jpeg_destroy_decompress (&cinfo);
- maximum = 0xff << 1;
-}
-#endif
-
-void CLASS kodak_dc120_load_raw()
-{
- static const int mul[4] = { 162, 192, 187, 92 };
- static const int add[4] = { 0, 636, 424, 212 };
- uchar pixel[848];
- int row, shift, col;
-
- for (row=0; row < height; row++) {
- if (fread (pixel, 1, 848, ifp) < 848) derror();
- shift = row * mul[row & 3] + add[row & 3];
- for (col=0; col < width; col++)
- BAYER(row,col) = (ushort) pixel[(col + shift) % 848];
- }
- maximum = 0xff;
-}
-
-void CLASS eight_bit_load_raw()
-{
- uchar *pixel;
- unsigned row, col, val, lblack=0;
-
- pixel = (uchar *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "eight_bit_load_raw()");
-#ifndef LIBRAW_LIBRARY_BUILD
- fseek (ifp, top_margin*raw_width, SEEK_CUR);
- for (row=0; row < height; row++) {
- if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
- for (col=0; col < raw_width; col++) {
- val = curve[pixel[col]];
- if ((unsigned) (col-left_margin) < width)
- BAYER(row,col-left_margin) = val;
- else lblack += val;
- }
- }
-#else
- for (row=0; row < raw_height; row++) {
- if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
- for (col=0; col < raw_width; col++) {
- if(filtering_mode & LIBRAW_FILTERING_NORAWCURVE)
- {
- val = pixel[col];
- if(val>maximum) maximum = val;
- }
- else
- val = curve[pixel[col]];
- if((unsigned) (row-top_margin)< height)
- {
- if ((unsigned) (col-left_margin) < width)
- BAYER(row,col-left_margin) = val;
- else
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = val;
- lblack += val;
- }
- }
- else // top/bottom margins
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = val;
- }
- }
- }
-#endif
-
- free (pixel);
- if (raw_width > width+1)
- black = lblack / ((raw_width - width) * height);
- if (!strncmp(model,"DC2",3))
- black = 0;
-#ifdef LIBRAW_LIBRARY_BUILD
- if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
-#endif
- maximum = curve[0xff];
-}
-
-void CLASS kodak_yrgb_load_raw()
-{
- uchar *pixel;
- int row, col, y, cb, cr, rgb[3], c;
-
- pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
- merror (pixel, "kodak_yrgb_load_raw()");
- for (row=0; row < height; row++) {
- if (~row & 1)
- if (fread (pixel, raw_width, 3, ifp) < 3) derror();
- for (col=0; col < raw_width; col++) {
- y = pixel[width*2*(row & 1) + col];
- cb = pixel[width + (col & -2)] - 128;
- cr = pixel[width + (col & -2)+1] - 128;
- rgb[1] = y-((cb + cr + 2) >> 2);
- rgb[2] = rgb[1] + cb;
- rgb[0] = rgb[1] + cr;
- FORC3 image[row*width+col][c] = LIM(rgb[c],0,255);
- }
- }
- free (pixel);
- use_gamma = 0;
-}
-
-void CLASS kodak_262_load_raw()
-{
- static const uchar kodak_tree[2][26] =
- { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 },
- { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } };
- struct decode *decode[2];
- uchar *pixel;
- int *strip, ns, i, row, col, chess, pi=0, pi1, pi2, pred, val;
-
- init_decoder();
- for (i=0; i < 2; i++) {
- decode[i] = free_decode;
- make_decoder (kodak_tree[i], 0);
- }
- ns = (raw_height+63) >> 5;
- pixel = (uchar *) malloc (raw_width*32 + ns*4);
- merror (pixel, "kodak_262_load_raw()");
- strip = (int *) (pixel + raw_width*32);
- order = 0x4d4d;
- for (i=0; i < ns; i++)
- strip[i] = get4();
- for (row=0; row < raw_height; row++) {
- if ((row & 31) == 0) {
- fseek (ifp, strip[row >> 5], SEEK_SET);
- getbits(-1);
- pi = 0;
- }
- for (col=0; col < raw_width; col++) {
- chess = (row + col) & 1;
- pi1 = chess ? pi-2 : pi-raw_width-1;
- pi2 = chess ? pi-2*raw_width : pi-raw_width+1;
- if (col <= chess) pi1 = -1;
- if (pi1 < 0) pi1 = pi2;
- if (pi2 < 0) pi2 = pi1;
- if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
- pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
- pixel[pi] = val = pred + ljpeg_diff (decode[chess]);
- if (val >> 8) derror();
-#ifdef LIBRAW_LIBRARY_BUILD
- if(filtering_mode & LIBRAW_FILTERING_NORAWCURVE)
- val = pixel[pi++];
- else
- val = curve[pixel[pi++]];
-#else
- val = curve[pixel[pi++]];
-#endif
- if ((unsigned) (col-left_margin) < width)
- BAYER(row,col-left_margin) = val;
- else
-#ifndef LIBRAW_LIBRARY_BUILD
- black += val;
-#else
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = val;
- black += val;
- }
-#endif
- }
- }
- free (pixel);
- if (raw_width > width)
- black /= (raw_width - width) * height;
-}
-
-int CLASS kodak_65000_decode (short *out, int bsize)
-{
- uchar c, blen[768];
- ushort raw[6];
- INT64 bitbuf=0;
- int save, bits=0, i, j, len, diff;
-
- save = ftell(ifp);
- bsize = (bsize + 3) & -4;
- for (i=0; i < bsize; i+=2) {
- c = fgetc(ifp);
- if ((blen[i ] = c & 15) > 12 ||
- (blen[i+1] = c >> 4) > 12 ) {
- fseek (ifp, save, SEEK_SET);
- for (i=0; i < bsize; i+=8) {
- read_shorts (raw, 6);
- out[i ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
- out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
- for (j=0; j < 6; j++)
- out[i+2+j] = raw[j] & 0xfff;
- }
- return 1;
- }
- }
- if ((bsize & 7) == 4) {
- bitbuf = fgetc(ifp) << 8;
- bitbuf += fgetc(ifp);
- bits = 16;
- }
- for (i=0; i < bsize; i++) {
- len = blen[i];
- if (bits < len) {
- for (j=0; j < 32; j+=8)
- bitbuf += (INT64) fgetc(ifp) << (bits+(j^8));
- bits += 32;
- }
- diff = bitbuf & (0xffff >> (16-len));
- bitbuf >>= len;
- bits -= len;
- if ((diff & (1 << (len-1))) == 0)
- diff -= (1 << len) - 1;
- out[i] = diff;
- }
- return 0;
-}
-
-void CLASS kodak_65000_load_raw()
-{
- short buf[256];
- int row, col, len, pred[2], ret, i;
-
- for (row=0; row < height; row++)
- for (col=0; col < width; col+=256) {
- pred[0] = pred[1] = 0;
- len = MIN (256, width-col);
- ret = kodak_65000_decode (buf, len);
- for (i=0; i < len; i++)
-#ifndef LIBRAW_LIBRARY_BUILD
- if ((BAYER(row,col+i) = curve[ret ? buf[i] :
- (pred[i & 1] += buf[i])]) >> 12) derror();
-#else
- {
- ushort val = ret ? buf[i] : (pred[i & 1] += buf[i]);
- if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
- val = curve[val];
- BAYER(row,col+i)=val;
- if(curve[val]>>12) derror();
- }
-#endif
- }
-}
-
-void CLASS kodak_ycbcr_load_raw()
-{
- short buf[384], *bp;
- int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
- ushort *ip;
-
- for (row=0; row < height; row+=2)
- for (col=0; col < width; col+=128) {
- len = MIN (128, width-col);
- kodak_65000_decode (buf, len*3);
- y[0][1] = y[1][1] = cb = cr = 0;
- for (bp=buf, i=0; i < len; i+=2, bp+=2) {
- cb += bp[4];
- cr += bp[5];
- rgb[1] = -((cb + cr + 2) >> 2);
- rgb[2] = rgb[1] + cb;
- rgb[0] = rgb[1] + cr;
- for (j=0; j < 2; j++)
- for (k=0; k < 2; k++) {
- if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror();
- ip = image[(row+j)*width + col+i+k];
-#ifndef LIBRAW_LIBRARY_BUILD
- FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
-#else
- if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
- FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
- else
- FORC3 ip[c] = y[j][k]+rgb[c];;
-#endif
- }
- }
- }
-}
-
-void CLASS kodak_rgb_load_raw()
-{
- short buf[768], *bp;
- int row, col, len, c, i, rgb[3];
- ushort *ip=image[0];
-
- for (row=0; row < height; row++)
- for (col=0; col < width; col+=256) {
- len = MIN (256, width-col);
- kodak_65000_decode (buf, len*3);
- memset (rgb, 0, sizeof rgb);
- for (bp=buf, i=0; i < len; i++, ip+=4)
- FORC3 if ((ip[c] = rgb[c] += *bp++) >> 12) derror();
- }
-}
-
-void CLASS kodak_thumb_load_raw()
-{
- int row, col;
- colors = thumb_misc >> 5;
- for (row=0; row < height; row++)
- for (col=0; col < width; col++)
- read_shorts (image[row*width+col], colors);
- maximum = (1 << (thumb_misc & 31)) - 1;
-}
-
-void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
-{
-#ifndef LIBRAW_NOTHREADS
-#define pad tls->sony_decrypt.pad
-#define p tls->sony_decrypt.p
-#else
- static unsigned pad[128], p;
-#endif
-
- if (start) {
- for (p=0; p < 4; p++)
- pad[p] = key = key * 48828125 + 1;
- pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
- for (p=4; p < 127; p++)
- pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
- for (p=0; p < 127; p++)
- pad[p] = htonl(pad[p]);
- }
- while (len--)
- *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
-#ifndef LIBRAW_NOTHREADS
-#undef pad
-#undef p
-#endif
-}
-
-void CLASS sony_load_raw()
-{
- uchar head[40];
- ushort *pixel;
- unsigned i, key, row, col;
-
- fseek (ifp, 200896, SEEK_SET);
- fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR);
- order = 0x4d4d;
- key = get4();
- fseek (ifp, 164600, SEEK_SET);
- fread (head, 1, 40, ifp);
- sony_decrypt ((unsigned int *) head, 10, 1, key);
- for (i=26; i-- > 22; )
- key = key << 8 | head[i];
- fseek (ifp, data_offset, SEEK_SET);
- pixel = (ushort *) calloc (raw_width, sizeof *pixel);
- merror (pixel, "sony_load_raw()");
- for (row=0; row < height; row++) {
- if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
- sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
-#ifdef LIBRAW_LIBRARY_BUILD
- for (col=0; col < left_margin; col++)
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = ntohs(pixel[col]);
- }
- for (col=left_margin+width; col < raw_width; col++)
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = ntohs(pixel[col]);
- }
-#endif
- for (col=9; col < left_margin; col++)
- black += ntohs(pixel[col]);
- for (col=0; col < width; col++)
- if ((BAYER(row,col) = ntohs(pixel[col+left_margin])) >> 14)
- derror();
- }
- free (pixel);
- if (left_margin > 9)
- black /= (left_margin-9) * height;
- maximum = 0x3ff0;
-}
-
-void CLASS sony_arw_load_raw()
-{
- int col, row, len, diff, sum=0;
-
- getbits(-1);
- for (col = raw_width; col--; )
- for (row=0; row < raw_height+1; row+=2) {
- if (row == raw_height) row = 1;
- len = 4 - getbits(2);
- if (len == 3 && getbits(1)) len = 0;
- if (len == 4)
- while (len < 17 && !getbits(1)) len++;
- diff = getbits(len);
- if ((diff & (1 << (len-1))) == 0)
- diff -= (1 << len) - 1;
- if ((sum += diff) >> 12) derror();
- if (row < height) BAYER(row,col) = sum;
-#ifdef LIBRAW_LIBRARY_BUILD
- else
- {
- ushort *dfp = get_masked_pointer(row,col);
- if(dfp) *dfp = sum;
- }
-#endif
- }
-}
-
-void CLASS sony_arw2_load_raw()
-{
- uchar *data, *dp;
- ushort pix[16];
- int row, col, val, max, min, imax, imin, sh, bit, i;
-
- data = (uchar *) malloc (raw_width*tiff_bps >> 3);
- merror (data, "sony_arw2_load_raw()");
- for (row=0; row < height; row++) {
- fread (data, 1, raw_width*tiff_bps >> 3, ifp);
- if (tiff_bps == 8) {
- for (dp=data, col=0; col < width-30; dp+=16) {
- max = 0x7ff & (val = sget4(dp));
- min = 0x7ff & val >> 11;
- imax = 0x0f & val >> 22;
- imin = 0x0f & val >> 26;
- for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++);
- for (bit=30, i=0; i < 16; i++)
- if (i == imax) pix[i] = max;
- else if (i == imin) pix[i] = min;
- else {
- pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
- if (pix[i] > 0x7ff) pix[i] = 0x7ff;
- bit += 7;
- }
- for (i=0; i < 16; i++, col+=2)
-#ifndef LIBRAW_LIBRARY_BUILD
- BAYER(row,col) = curve[pix[i] << 1] >> 1;
-#else
- {
- ushort val = pix[i];
- if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
- val = curve[val<<1]>>1;
- BAYER(row,col)=val;
- }
-#endif
- col -= col & 1 ? 1:31;
- }
- } else if (tiff_bps == 12)
- for (dp=data, col=0; col < width; dp+=3, col+=2) {
- BAYER(row,col) = ((dp[1] << 8 | dp[0]) & 0xfff) << 1;
- BAYER(row,col+1) = (dp[2] << 4 | dp[1] >> 4) << 1;
- }
- }
- free (data);
-}
-
-#define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1)
-
-/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
-void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
-{
- uchar hist[3][13] = {
- { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
- { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
- { 3, 3, 0, 0, 63, 47, 31, 15, 0 } };
- int low, high=0xff, carry=0, nbits=8;
- int s, count, bin, next, i, sym[3];
- uchar diff, pred[]={0,0};
- ushort data=0, range=0;
- unsigned pix, row, col;
-
- fseek (ifp, seg[0][1]+1, SEEK_SET);
- getbits(-1);
- for (pix=seg[0][0]; pix < seg[1][0]; pix++) {
- for (s=0; s < 3; s++) {
- data = data << nbits | getbits(nbits);
- if (carry < 0)
- carry = (nbits += carry+1) < 1 ? nbits-1 : 0;
- while (--nbits >= 0)
- if ((data >> nbits & 0xff) == 0xff) break;
- if (nbits > 0)
- data = ((data & ((1 << (nbits-1)) - 1)) << 1) |
- ((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits));
- if (nbits >= 0) {
- data += getbits(1);
- carry = nbits - 8;
- }
- count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4);
- for (bin=0; hist[s][bin+5] > count; bin++);
- low = hist[s][bin+5] * (high >> 4) >> 2;
- if (bin) high = hist[s][bin+4] * (high >> 4) >> 2;
- high -= low;
- for (nbits=0; high << nbits < 128; nbits++);
- range = (range+low) << nbits;
- high <<= nbits;
- next = hist[s][1];
- if (++hist[s][2] > hist[s][3]) {
- next = (next+1) & hist[s][0];
- hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2;
- hist[s][2] = 1;
- }
- if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) {
- if (bin < hist[s][1])
- for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--;
- else if (next <= bin)
- for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++;
- }
- hist[s][1] = next;
- sym[s] = bin;
- }
- diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
- if (sym[0] & 4)
- diff = diff ? -diff : 0x80;
- if (ftell(ifp) + 12 >= seg[1][1])
- diff = 0;
- pred[pix & 1] += diff;
- row = pix / raw_width - top_margin;
- col = pix % raw_width - left_margin;
- if (row < height && col < width)
- BAYER(row,col) = pred[pix & 1];
-#ifdef LIBRAW_LIBRARY_BUILD
- else
- {
- ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin);
- if(dfp) *dfp = pred[pix &1];
- }
-#endif
- if (!(pix & 1) && HOLE(row)) pix += 2;
- }
- maximum = 0xff;
-}
-
-void CLASS smal_v6_load_raw()
-{
- unsigned seg[2][2];
-
- fseek (ifp, 16, SEEK_SET);
- seg[0][0] = 0;
- seg[0][1] = get2();
- seg[1][0] = raw_width * raw_height;
- seg[1][1] = INT_MAX;
- smal_decode_segment (seg, 0);
- use_gamma = 0;
-}
-
-int CLASS median4 (int *p)
-{
- int min, max, sum, i;
-
- min = max = sum = p[0];
- for (i=1; i < 4; i++) {
- sum += p[i];
- if (min > p[i]) min = p[i];
- if (max < p[i]) max = p[i];
- }
- return (sum - min - max) >> 1;
-}
-
-void CLASS fill_holes (int holes)
-{
- int row, col, val[4];
-
- for (row=2; row < height-2; row++) {
- if (!HOLE(row)) continue;
- for (col=1; col < width-1; col+=4) {
- val[0] = BAYER(row-1,col-1);
- val[1] = BAYER(row-1,col+1);
- val[2] = BAYER(row+1,col-1);
- val[3] = BAYER(row+1,col+1);
- BAYER(row,col) = median4(val);
- }
- for (col=2; col < width-2; col+=4)
- if (HOLE(row-2) || HOLE(row+2))
- BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1;
- else {
- val[0] = BAYER(row,col-2);
- val[1] = BAYER(row,col+2);
- val[2] = BAYER(row-2,col);
- val[3] = BAYER(row+2,col);
- BAYER(row,col) = median4(val);
- }
- }
-}
-
-void CLASS smal_v9_load_raw()
-{
- unsigned seg[256][2], offset, nseg, holes, i;
-
- fseek (ifp, 67, SEEK_SET);
- offset = get4();
- nseg = fgetc(ifp);
- fseek (ifp, offset, SEEK_SET);
- for (i=0; i < nseg*2; i++)
- seg[0][i] = get4() + data_offset*(i & 1);
- fseek (ifp, 78, SEEK_SET);
- holes = fgetc(ifp);
- fseek (ifp, 88, SEEK_SET);
- seg[nseg][0] = raw_height * raw_width;
- seg[nseg][1] = get4() + data_offset;
- for (i=0; i < nseg; i++)
- smal_decode_segment (seg+i, holes);
- if (holes) fill_holes (holes);
-}
-
-void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
-{
- double work[3][6], num;
- int i, j, k;
-
- for (i=0; i < 3; i++) {
- for (j=0; j < 6; j++)
- work[i][j] = j == i+3;
- for (j=0; j < 3; j++)
- for (k=0; k < size; k++)
- work[i][j] += in[k][i] * in[k][j];
- }
- for (i=0; i < 3; i++) {
- num = work[i][i];
- for (j=0; j < 6; j++)
- work[i][j] /= num;
- for (k=0; k < 3; k++) {
- if (k==i) continue;
- num = work[k][i];
- for (j=0; j < 6; j++)
- work[k][j] -= work[i][j] * num;
- }
- }
- for (i=0; i < size; i++)
- for (j=0; j < 3; j++)
- for (out[i][j]=k=0; k < 3; k++)
- out[i][j] += work[j][k+3] * in[i][k];
-}
-
-void CLASS cam_xyz_coeff (double cam_xyz[4][3])
-{
- double cam_rgb[4][3], inverse[4][3], num;
- int i, j, k;
-
- for (i=0; i < colors; i++) /* Multiply out XYZ colorspace */
- for (j=0; j < 3; j++)
- for (cam_rgb[i][j] = k=0; k < 3; k++)
- cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j];
-
- for (i=0; i < colors; i++) { /* Normalize cam_rgb so that */
- for (num=j=0; j < 3; j++) /* cam_rgb * (1,1,1) is (1,1,1,1) */
- num += cam_rgb[i][j];
- for (j=0; j < 3; j++)
- cam_rgb[i][j] /= num;
- pre_mul[i] = 1 / num;
- }
- pseudoinverse (cam_rgb, inverse, colors);
- for (raw_color = i=0; i < 3; i++)
- for (j=0; j < colors; j++)
- rgb_cam[i][j] = inverse[j][i];
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
- color_flags.rgb_cam_state = LIBRAW_COLORSTATE_CONST;
-#endif
-}
-
-#ifdef COLORCHECK
-void CLASS colorcheck()
-{
-#define NSQ 24
-// Coordinates of the GretagMacbeth ColorChecker squares
-// width, height, 1st_column, 1st_row
- static const int cut[NSQ][4] = {
- { 241, 231, 234, 274 },
- { 251, 235, 534, 274 },
- { 255, 239, 838, 272 },
- { 255, 240, 1146, 274 },
- { 251, 237, 1452, 278 },
- { 243, 238, 1758, 288 },
- { 253, 253, 218, 558 },
- { 255, 249, 524, 562 },
- { 261, 253, 830, 562 },
- { 260, 255, 1144, 564 },
- { 261, 255, 1450, 566 },
- { 247, 247, 1764, 576 },
- { 255, 251, 212, 862 },
- { 259, 259, 518, 862 },
- { 263, 261, 826, 864 },
- { 265, 263, 1138, 866 },
- { 265, 257, 1450, 872 },
- { 257, 255, 1762, 874 },
- { 257, 253, 212, 1164 },
- { 262, 251, 516, 1172 },
- { 263, 257, 826, 1172 },
- { 263, 255, 1136, 1176 },
- { 255, 252, 1452, 1182 },
- { 257, 253, 1760, 1180 } };
-// ColorChecker Chart under 6500-kelvin illumination
- static const double gmb_xyY[NSQ][3] = {
- { 0.400, 0.350, 10.1 }, // Dark Skin
- { 0.377, 0.345, 35.8 }, // Light Skin
- { 0.247, 0.251, 19.3 }, // Blue Sky
- { 0.337, 0.422, 13.3 }, // Foliage
- { 0.265, 0.240, 24.3 }, // Blue Flower
- { 0.261, 0.343, 43.1 }, // Bluish Green
- { 0.506, 0.407, 30.1 }, // Orange
- { 0.211, 0.175, 12.0 }, // Purplish Blue
- { 0.453, 0.306, 19.8 }, // Moderate Red
- { 0.285, 0.202, 6.6 }, // Purple
- { 0.380, 0.489, 44.3 }, // Yellow Green
- { 0.473, 0.438, 43.1 }, // Orange Yellow
- { 0.187, 0.129, 6.1 }, // Blue
- { 0.305, 0.478, 23.4 }, // Green
- { 0.539, 0.313, 12.0 }, // Red
- { 0.448, 0.470, 59.1 }, // Yellow
- { 0.364, 0.233, 19.8 }, // Magenta
- { 0.196, 0.252, 19.8 }, // Cyan
- { 0.310, 0.316, 90.0 }, // White
- { 0.310, 0.316, 59.1 }, // Neutral 8
- { 0.310, 0.316, 36.2 }, // Neutral 6.5
- { 0.310, 0.316, 19.8 }, // Neutral 5
- { 0.310, 0.316, 9.0 }, // Neutral 3.5
- { 0.310, 0.316, 3.1 } }; // Black
- double gmb_cam[NSQ][4], gmb_xyz[NSQ][3];
- double inverse[NSQ][3], cam_xyz[4][3], num;
- int c, i, j, k, sq, row, col, count[4];
-
- memset (gmb_cam, 0, sizeof gmb_cam);
- for (sq=0; sq < NSQ; sq++) {
- FORCC count[c] = 0;
- for (row=cut[sq][3]; row < cut[sq][3]+cut[sq][1]; row++)
- for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) {
- c = FC(row,col);
- if (c >= colors) c -= 2;
- gmb_cam[sq][c] += BAYER(row,col);
- count[c]++;
- }
- FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black;
- gmb_xyz[sq][0] = gmb_xyY[sq][2] * gmb_xyY[sq][0] / gmb_xyY[sq][1];
- gmb_xyz[sq][1] = gmb_xyY[sq][2];
- gmb_xyz[sq][2] = gmb_xyY[sq][2] *
- (1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1];
- }
- pseudoinverse (gmb_xyz, inverse, NSQ);
- for (i=0; i < colors; i++)
- for (j=0; j < 3; j++)
- for (cam_xyz[i][j] = k=0; k < NSQ; k++)
- cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j];
- cam_xyz_coeff (cam_xyz);
-#ifdef DCRAW_VERBOSE
- if (verbose) {
- printf (" { \"%s %s\", %d,\n\t{", make, model, black);
- num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]);
- FORCC for (j=0; j < 3; j++)
- printf ("%c%d", (c | j) ? ',':' ', (int) (cam_xyz[c][j] * num + 0.5));
- puts (" } },");
- }
-#endif
-#undef NSQ
-}
-#endif
-
-void CLASS hat_transform (float *temp, float *base, int st, int size, int sc)
-{
- int i;
- for (i=0; i < sc; i++)
- temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)];
- for (; i+sc < size; i++)
- temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)];
- for (; i < size; i++)
- temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))];
-}
-
-#ifndef _OPENMP
-void CLASS wavelet_denoise()
-{
- float *fimg=0, *temp, thold, mul[2], avg, diff;
- int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
- ushort *window[4];
- static const float noise[] =
- { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
-
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
-#endif
-
- while (maximum << scale < 0x10000) scale++;
- maximum <<= --scale;
- black <<= scale;
- if ((size = iheight*iwidth) < 0x15550000)
- fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
- merror (fimg, "wavelet_denoise()");
- temp = fimg + size*3;
- if ((nc = colors) == 3 && filters) nc++;
- FORC(nc) { /* denoise R,G1,B,G3 individually */
- for (i=0; i < size; i++)
- fimg[i] = 256 * sqrt((double)(image[i][c] << scale));
- for (hpass=lev=0; lev < 5; lev++) {
- lpass = size*((lev & 1)+1);
- for (row=0; row < iheight; row++) {
- hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
- for (col=0; col < iwidth; col++)
- fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
- }
- for (col=0; col < iwidth; col++) {
- hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev);
- for (row=0; row < iheight; row++)
- fimg[lpass + row*iwidth + col] = temp[row] * 0.25;
- }
- thold = threshold * noise[lev];
- for (i=0; i < size; i++) {
- fimg[hpass+i] -= fimg[lpass+i];
- if (fimg[hpass+i] < -thold) fimg[hpass+i] += thold;
- else if (fimg[hpass+i] > thold) fimg[hpass+i] -= thold;
- else fimg[hpass+i] = 0;
- if (hpass) fimg[i] += fimg[hpass+i];
- }
- hpass = lpass;
- }
- for (i=0; i < size; i++)
- image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
- }
- if (filters && colors == 3) { /* pull G1 and G3 closer together */
- for (row=0; row < 2; row++)
- mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
- for (i=0; i < 4; i++)
- window[i] = (ushort *) fimg + width*i;
- for (wlast=-1, row=1; row < height-1; row++) {
- while (wlast < row+1) {
- for (wlast++, i=0; i < 4; i++)
- window[(i+3) & 3] = window[i];
- for (col = FC(wlast,1) & 1; col < width; col+=2)
- window[2][col] = BAYER(wlast,col);
- }
- thold = threshold/512;
- for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
- avg = ( window[0][col-1] + window[0][col+1] +
- window[2][col-1] + window[2][col+1] - black*4 )
- * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
- avg = avg < 0 ? 0 : sqrt(avg);
- diff = sqrt((double)(BAYER(row,col))) - avg;
- if (diff < -thold) diff += thold;
- else if (diff > thold) diff -= thold;
- else diff = 0;
- BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5);
- }
- }
- }
- free (fimg);
-}
-#else
-void CLASS wavelet_denoise()
-{
- float *fimg=0, *temp, thold, mul[2], avg, diff;
- int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
- ushort *window[4];
- static const float noise[] =
- { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
-
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
-#endif
-
- while (maximum << scale < 0x10000) scale++;
- maximum <<= --scale;
- black <<= scale;
- if ((size = iheight*iwidth) < 0x15550000)
- fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
- merror (fimg, "wavelet_denoise()");
- temp = fimg + size*3;
- if ((nc = colors) == 3 && filters) nc++;
-#ifdef LIBRAW_LIBRARY_BUILD
-#pragma omp parallel default(shared) private(i,col,row,thold,lev,lpass,hpass,temp) firstprivate(c,scale,size)
-#endif
- {
- temp = (float*)malloc( (iheight + iwidth) * sizeof *fimg);
- FORC(nc) { /* denoise R,G1,B,G3 individually */
-#ifdef LIBRAW_LIBRARY_BUILD
-#pragma omp for
-#endif
- for (i=0; i < size; i++)
- fimg[i] = 256 * sqrt((double)(image[i][c] << scale));
- for (hpass=lev=0; lev < 5; lev++) {
- lpass = size*((lev & 1)+1);
-#ifdef LIBRAW_LIBRARY_BUILD
-#pragma omp for
-#endif
- for (row=0; row < iheight; row++) {
- hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
- for (col=0; col < iwidth; col++)
- fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
- }
-#ifdef LIBRAW_LIBRARY_BUILD
-#pragma omp for
-#endif
- for (col=0; col < iwidth; col++) {
- hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev);
- for (row=0; row < iheight; row++)
- fimg[lpass + row*iwidth + col] = temp[row] * 0.25;
- }
- thold = threshold * noise[lev];
-#ifdef LIBRAW_LIBRARY_BUILD
-#pragma omp for
-#endif
- for (i=0; i < size; i++) {
- fimg[hpass+i] -= fimg[lpass+i];
- if (fimg[hpass+i] < -thold) fimg[hpass+i] += thold;
- else if (fimg[hpass+i] > thold) fimg[hpass+i] -= thold;
- else fimg[hpass+i] = 0;
- if (hpass) fimg[i] += fimg[hpass+i];
- }
- hpass = lpass;
- }
-#ifdef LIBRAW_LIBRARY_BUILD
-#pragma omp for
-#endif
- for (i=0; i < size; i++)
- image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
- }
- free(temp);
- } /* end omp parallel */
-/* the following loops are hard to parallize, no idea yes,
- * problem is wlast which is carrying dependency
- * second part should be easyer, but did not yet get it right.
- */
- if (filters && colors == 3) { /* pull G1 and G3 closer together */
- for (row=0; row < 2; row++)
- mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
- for (i=0; i < 4; i++)
- window[i] = (ushort *) fimg + width*i;
- for (wlast=-1, row=1; row < height-1; row++) {
- while (wlast < row+1) {
- for (wlast++, i=0; i < 4; i++)
- window[(i+3) & 3] = window[i];
- for (col = FC(wlast,1) & 1; col < width; col+=2)
- window[2][col] = BAYER(wlast,col);
- }
- thold = threshold/512;
- for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
- avg = ( window[0][col-1] + window[0][col+1] +
- window[2][col-1] + window[2][col+1] - black*4 )
- * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
- avg = avg < 0 ? 0 : sqrt(avg);
- diff = sqrt(BAYER(row,col)) - avg;
- if (diff < -thold) diff += thold;
- else if (diff > thold) diff -= thold;
- else diff = 0;
- BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5);
- }
- }
- }
- free (fimg);
-}
-
-#endif
-
-void CLASS scale_colors()
-{
- unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8];
- int val, dark, sat;
- double dsum[8], dmin, dmax;
- float scale_mul[4], fr, fc;
- ushort *img=0, *pix;
-
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS,0,2);
-#endif
-
- if (user_mul[0])
- memcpy (pre_mul, user_mul, sizeof pre_mul);
- if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) {
- 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 = FC(y,x);
- val = BAYER(y,x);
- } else
- val = image[y*width+x][c];
- if (val > maximum-25) goto skip_block;
- if ((val -= black) < 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];
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CALCULATED;
-#endif
- }
- if (use_camera_wb && cam_mul[0] != -1) {
- 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] - black) > 0)
- sum[c] += val;
- sum[c+4]++;
- }
- if (sum[0] && sum[1] && sum[2] && sum[3])
- {
- FORC4 pre_mul[c] = (float) sum[c+4] / sum[c];
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CALCULATED;
-#endif
- }
- else if (cam_mul[0] && cam_mul[2])
- {
- memcpy (pre_mul, cam_mul, sizeof pre_mul);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state =color_flags.pre_mul_state;
-#endif
- }
- else
- {
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.process_warnings |= LIBRAW_WARN_BAD_CAMERA_WB;
-#endif
-#ifdef DCRAW_VERBOSE
- fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname);
-#endif
- }
- }
- if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
- dark = black;
- sat = maximum;
- 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;
- FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum;
-#ifdef DCRAW_VERBOSE
- if (verbose) {
- fprintf (stderr,
- _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat);
- FORC4 fprintf (stderr, " %f", pre_mul[c]);
- fputc ('\n', stderr);
- }
-#endif
- size = iheight*iwidth;
- for (i=0; i < size*4; i++) {
- val = image[0][i];
- if (!val) continue;
- val -= black;
- val *= scale_mul[i & 3];
- image[0][i] = CLIP(val);
- }
- if ((aber[0] != 1 || aber[2] != 1) && colors == 3) {
-#ifdef DCRAW_VERBOSE
- if (verbose)
- fprintf (stderr,_("Correcting chromatic aberration...\n"));
-#endif
- 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 > iheight-2) continue;
- fr -= ur;
- for (col=0; col < iwidth; col++) {
- uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5;
- if (uc > 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);
- }
- }
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS,1,2);
-#endif
-}
-
-void CLASS pre_interpolate()
-{
- ushort (*img)[4];
- int row, col, c;
-
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE,0,2);
-#endif
- if (shrink) {
- if (half_size) {
- height = iheight;
- width = iwidth;
- } else {
- img = (ushort (*)[4]) calloc (height*width, sizeof *img);
- merror (img, "pre_interpolate()");
- for (row=0; row < height; row++)
- for (col=0; col < width; col++) {
- c = fc(row,col);
- img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c];
- }
- free (image);
- image = img;
- shrink = 0;
- }
- }
- if (filters && colors == 3) {
- if ((mix_green = four_color_rgb)) colors++;
- else {
- for (row = FC(1,0) >> 1; row < height; row+=2)
- for (col = FC(row,1) & 1; col < width; col+=2)
- image[row*width+col][1] = image[row*width+col][3];
- filters &= ~((filters & 0x55555555) << 1);
- }
- }
- if (half_size) filters = 0;
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE,1,2);
-#endif
-}
-
-void CLASS border_interpolate (int border)
-{
- unsigned row, col, y, x, f, c, sum[8];
-
- for (row=0; row < height; row++)
- for (col=0; col < width; col++) {
- if (col==border && row >= border && row < height-border)
- col = width-border;
- memset (sum, 0, sizeof sum);
- for (y=row-1; y != row+2; y++)
- for (x=col-1; x != col+2; x++)
- if (y < height && x < width) {
- f = fc(y,x);
- sum[f] += image[y*width+x][f];
- sum[f+4]++;
- }
- f = fc(row,col);
- FORCC if (c != f && sum[c+4])
- image[row*width+col][c] = sum[c] / sum[c+4];
- }
-}
-
-void CLASS lin_interpolate()
-{
- int code[16][16][32], *ip, sum[4];
- int c, i, x, y, row, col, shift, color;
- ushort *pix;
-
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
-#endif
-
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,0,3);
-#endif
- border_interpolate(1);
- for (row=0; row < 16; row++)
- for (col=0; col < 16; col++) {
- ip = code[row][col];
- memset (sum, 0, sizeof sum);
- for (y=-1; y <= 1; y++)
- for (x=-1; x <= 1; x++) {
- shift = (y==0) + (x==0);
- if (shift == 2) continue;
- color = fc(row+y,col+x);
- *ip++ = (width*y + x)*4 + color;
- *ip++ = shift;
- *ip++ = color;
- sum[color] += 1 << shift;
- }
- FORCC
- if (c != fc(row,col)) {
- *ip++ = c;
- *ip++ = 256 / sum[c];
- }
- }
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,1,3);
-#endif
- for (row=1; row < height-1; row++)
- for (col=1; col < width-1; col++) {
- pix = image[row*width+col];
- ip = code[row & 15][col & 15];
- memset (sum, 0, sizeof sum);
- for (i=8; i--; ip+=3)
- sum[ip[2]] += pix[ip[0]] << ip[1];
- for (i=colors; --i; ip+=2)
- pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
- }
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,2,3);
-#endif
-}
-
/*
- This algorithm is officially called:
+ Copyright 2008-2020 LibRaw LLC ([email protected])
- "Interpolation using a Threshold-based variable number of gradients"
+ * This file is provided for compatibility w/ old build scripts/tools:
+ * It includes multiple separate files that should be built separately
+ * if new build tools are used
- described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html
+ LibRaw is free software; you can redistribute it and/or modify
+ it under the terms of the one of two licenses as you choose:
- I've extended the basic idea to work with non-Bayer filter arrays.
- Gradients are numbered clockwise from NW=0 to W=7.
- */
-void CLASS vng_interpolate()
-{
- struct interpolate_terms {
- signed char y1, x1, y2, x2, weight;
- unsigned char grads;
- };
- static const interpolate_terms terms[] = {
- {-2,-2,+0,-1,0,0x01}, {-2,-2,+0,+0,1,0x01}, {-2,-1,-1,+0,0,0x01},
- {-2,-1,+0,-1,0,0x02}, {-2,-1,+0,+0,0,0x03}, {-2,-1,+0,+1,1,0x01},
- {-2,+0,+0,-1,0,0x06}, {-2,+0,+0,+0,1,0x02}, {-2,+0,+0,+1,0,0x03},
- {-2,+1,-1,+0,0,0x04}, {-2,+1,+0,-1,1,0x04}, {-2,+1,+0,+0,0,0x06},
- {-2,+1,+0,+1,0,0x02}, {-2,+2,+0,+0,1,0x04}, {-2,+2,+0,+1,0,0x04},
- {-1,-2,-1,+0,0,0x80}, {-1,-2,+0,-1,0,0x01}, {-1,-2,+1,-1,0,0x01},
- {-1,-2,+1,+0,1,0x01}, {-1,-1,-1,+1,0,0x88}, {-1,-1,+1,-2,0,0x40},
- {-1,-1,+1,-1,0,0x22}, {-1,-1,+1,+0,0,0x33}, {-1,-1,+1,+1,1,0x11},
- {-1,+0,-1,+2,0,0x08}, {-1,+0,+0,-1,0,0x44}, {-1,+0,+0,+1,0,0x11},
- {-1,+0,+1,-2,1,0x40}, {-1,+0,+1,-1,0,0x66}, {-1,+0,+1,+0,1,0x22},
- {-1,+0,+1,+1,0,0x33}, {-1,+0,+1,+2,1,0x10}, {-1,+1,+1,-1,1,0x44},
- {-1,+1,+1,+0,0,0x66}, {-1,+1,+1,+1,0,0x22}, {-1,+1,+1,+2,0,0x10},
- {-1,+2,+0,+1,0,0x04}, {-1,+2,+1,+0,1,0x04}, {-1,+2,+1,+1,0,0x04},
- {+0,-2,+0,+0,1,0x80}, {+0,-1,+0,+1,1,0x88}, {+0,-1,+1,-2,0,0x40},
- {+0,-1,+1,+0,0,0x11}, {+0,-1,+2,-2,0,0x40}, {+0,-1,+2,-1,0,0x20},
- {+0,-1,+2,+0,0,0x30}, {+0,-1,+2,+1,1,0x10}, {+0,+0,+0,+2,1,0x08},
- {+0,+0,+2,-2,1,0x40}, {+0,+0,+2,-1,0,0x60}, {+0,+0,+2,+0,1,0x20},
- {+0,+0,+2,+1,0,0x30}, {+0,+0,+2,+2,1,0x10}, {+0,+1,+1,+0,0,0x44},
- {+0,+1,+1,+2,0,0x10}, {+0,+1,+2,-1,1,0x40}, {+0,+1,+2,+0,0,0x60},
- {+0,+1,+2,+1,0,0x20}, {+0,+1,+2,+2,0,0x10}, {+1,-2,+1,+0,0,0x80},
- {+1,-1,+1,+1,0,0x88}, {+1,+0,+1,+2,0,0x08}, {+1,+0,+2,-1,0,0x40},
- {+1,+0,+2,+1,0,0x10}
- };
- const interpolate_terms *cpt;
- signed char *cp;
- signed char chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
- ushort (*brow[5])[4], *pix;
- int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
- int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
- int g, diff, thold, num, c;
- lin_interpolate();
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("VNG interpolation...\n"));
-#endif
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+ (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
- if (filters == 1) prow = pcol = 15;
- ip = (int *) calloc ((prow+1)*(pcol+1), 1280);
- merror (ip, "vng_interpolate()");
- for (row=0; row <= prow; row++) /* Precalculate for VNG */
- for (col=0; col <= pcol; col++) {
- code[row][col] = ip;
- for (cpt=&terms[0], t=0; t < 64, cpt = &terms[t]; t++) {
- y1 = cpt->y1; x1 = cpt->x1;
- y2 = cpt->y2; x2 = cpt->x2;
- weight = cpt->weight;
- grads = cpt->grads;
- color = fc(row+y1,col+x1);
- if (fc(row+y2,col+x2) != color) continue;
- diag = (fc(row,col+1) == color && fc(row+1,col) == color) ? 2:1;
- if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
- *ip++ = (y1*width + x1)*4 + color;
- *ip++ = (y2*width + x2)*4 + color;
- *ip++ = weight;
- for (g=0; g < 8; g++)
- if (grads & 1<<g) *ip++ = g;
- *ip++ = -1;
- }
- *ip++ = INT_MAX;
- for (cp=chood, g=0; g < 8; g++) {
- y = *cp++; x = *cp++;
- *ip++ = (y*width + x) * 4;
- color = fc(row,col);
- if (fc(row+y,col+x) != color && fc(row+y*2,col+x*2) == color)
- *ip++ = (y*width + x) * 8 + color;
- else
- *ip++ = 0;
- }
- }
- brow[4] = (ushort (*)[4]) calloc (width*3, sizeof **brow);
- merror (brow[4], "vng_interpolate()");
- for (row=0; row < 3; row++)
- brow[row] = brow[4] + row*width;
- for (row=2; row < height-2; row++) { /* Do VNG interpolation */
-#ifdef LIBRAW_LIBRARY_BUILD
- if(!((row-2)%256))RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(row-2)/256+1,((height-3)/256)+1);
-#endif
- for (col=2; col < width-2; col++) {
- pix = image[row*width+col];
- ip = code[row & prow][col & pcol];
- memset (gval, 0, sizeof gval);
- while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */
- diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
- gval[ip[3]] += diff;
- ip += 5;
- if ((g = ip[-1]) == -1) continue;
- gval[g] += diff;
- while ((g = *ip++) != -1)
- gval[g] += diff;
- }
- ip++;
- gmin = gmax = gval[0]; /* Choose a threshold */
- for (g=1; g < 8; g++) {
- if (gmin > gval[g]) gmin = gval[g];
- if (gmax < gval[g]) gmax = gval[g];
- }
- if (gmax == 0) {
- memcpy (brow[2][col], pix, sizeof *image);
- continue;
- }
- thold = gmin + (gmax >> 1);
- memset (sum, 0, sizeof sum);
- color = fc(row,col);
- for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */
- if (gval[g] <= thold) {
- FORCC
- if (c == color && ip[1])
- sum[c] += (pix[c] + pix[ip[1]]) >> 1;
- else
- sum[c] += pix[ip[0] + c];
- num++;
- }
- }
- FORCC { /* Save to buffer */
- t = pix[color];
- if (c != color)
- t += (sum[c] - sum[color]) / num;
- brow[2][col][c] = CLIP(t);
- }
- }
- if (row > 3) /* Write buffer to image */
- memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
- for (g=0; g < 4; g++)
- brow[(g-1) & 3] = brow[g];
- }
- memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
- memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image);
- free (brow[4]);
- free (code[0][0]);
-}
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
-/*
- Patterned Pixel Grouping Interpolation by Alain Desbiolles
*/
-void CLASS ppg_interpolate()
-{
- int dir[5] = { 1, width, -1, -width, 1 };
- int row, col, diff[2], guess[2], c, d, i;
- ushort (*pix)[4];
-
- border_interpolate(3);
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("PPG interpolation...\n"));
-#endif
-
-/* Fill in the green layer with gradients and pattern recognition: */
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,0,3);
-#endif
- for (row=3; row < height-3; row++)
- for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) {
- pix = image + row*width+col;
- for (i=0; (d=dir[i]) > 0; i++) {
- guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
- - pix[-2*d][c] - pix[2*d][c];
- diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) +
- ABS(pix[ 2*d][c] - pix[ 0][c]) +
- ABS(pix[ -d][1] - pix[ d][1]) ) * 3 +
- ( ABS(pix[ 3*d][1] - pix[ d][1]) +
- ABS(pix[-3*d][1] - pix[-d][1]) ) * 2;
- }
- d = dir[i = diff[0] > diff[1]];
- pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
- }
-/* Calculate red and blue for each green pixel: */
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,1,3);
-#endif
- for (row=1; row < height-1; row++)
- for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) {
- pix = image + row*width+col;
- for (i=0; (d=dir[i]) > 0; c=2-c, i++)
- pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1]
- - pix[-d][1] - pix[d][1]) >> 1);
- }
-/* Calculate blue for red pixels and vice versa: */
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,2,3);
-#endif
- for (row=1; row < height-1; row++)
- for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) {
- pix = image + row*width+col;
- for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) {
- diff[i] = ABS(pix[-d][c] - pix[d][c]) +
- ABS(pix[-d][1] - pix[0][1]) +
- ABS(pix[ d][1] - pix[0][1]);
- guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1]
- - pix[-d][1] - pix[d][1];
- }
- if (diff[0] != diff[1])
- pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
- else
- pix[0][c] = CLIP((guess[0]+guess[1]) >> 2);
- }
-}
-
-/*
- Adaptive Homogeneity-Directed interpolation is based on
- the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
- */
-#define TS 256 /* Tile Size */
-#ifndef _OPENMP
-void CLASS ahd_interpolate()
-{
- int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
- ushort (*pix)[4], (*rix)[3];
- static const int dir[4] = { -1, 1, -TS, TS };
- unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
- float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
- ushort (*rgb)[TS][TS][3];
- short (*lab)[TS][TS][3], (*lix)[3];
- char (*homo)[TS][TS], *buffer;
-
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
-#endif
-
- for (i=0; i < 0x10000; i++) {
- r = i / 65535.0;
- cbrt[i] = r > 0.008856 ? pow((double)r,1/3.0) : 7.787*r + 16/116.0;
- }
- for (i=0; i < 3; i++)
- for (j=0; j < colors; j++)
- for (xyz_cam[i][j] = k=0; k < 3; k++)
- xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
-
- border_interpolate(5);
- buffer = (char *) malloc (26*TS*TS); /* 1664 kB */
- merror (buffer, "ahd_interpolate()");
- rgb = (ushort(*)[TS][TS][3]) buffer;
- lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
- homo = (char (*)[TS][TS]) (buffer + 24*TS*TS);
-
- for (top=2; top < height-5; top += TS-6)
- {
-
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(top-2)/(TS-6),(height-7)/(TS-6)+1);
-#endif
- for (left=2; left < width-5; left += TS-6) {
-
-/* Interpolate green horizontally and vertically: */
- for (row = top; row < top+TS && row < height-2; row++) {
- col = left + (FC(row,left) & 1);
- for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
- pix = image + row*width+col;
- val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
- - pix[-2][c] - pix[2][c]) >> 2;
- rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
- val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2
- - pix[-2*width][c] - pix[2*width][c]) >> 2;
- rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
- }
- }
-/* Interpolate red and blue, and convert to CIELab: */
- for (d=0; d < 2; d++)
- for (row=top+1; row < top+TS-1 && row < height-3; row++)
- for (col=left+1; col < left+TS-1 && col < width-3; col++) {
- pix = image + row*width+col;
- rix = &rgb[d][row-top][col-left];
- lix = &lab[d][row-top][col-left];
- if ((c = 2 - FC(row,col)) == 1) {
- c = FC(row+1,col);
- val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
- - rix[-1][1] - rix[1][1] ) >> 1);
- rix[0][2-c] = CLIP(val);
- val = pix[0][1] + (( pix[-width][c] + pix[width][c]
- - rix[-TS][1] - rix[TS][1] ) >> 1);
- } else
- val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
- + pix[+width-1][c] + pix[+width+1][c]
- - rix[-TS-1][1] - rix[-TS+1][1]
- - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
- rix[0][c] = CLIP(val);
- c = FC(row,col);
- rix[0][c] = pix[0][c];
- xyz[0] = xyz[1] = xyz[2] = 0.5;
- FORCC {
- xyz[0] += xyz_cam[0][c] * rix[0][c];
- xyz[1] += xyz_cam[1][c] * rix[0][c];
- xyz[2] += xyz_cam[2][c] * rix[0][c];
- }
- xyz[0] = cbrt[CLIP((int) xyz[0])];
- xyz[1] = cbrt[CLIP((int) xyz[1])];
- xyz[2] = cbrt[CLIP((int) xyz[2])];
- lix[0][0] = 64 * (116 * xyz[1] - 16);
- lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
- lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
- }
-/* Build homogeneity maps from the CIELab images: */
- memset (homo, 0, 2*TS*TS);
- for (row=top+2; row < top+TS-2 && row < height-4; row++) {
- tr = row-top;
- for (col=left+2; col < left+TS-2 && col < width-4; col++) {
- tc = col-left;
- for (d=0; d < 2; d++) {
- lix = &lab[d][tr][tc];
- for (i=0; i < 4; i++) {
- ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
- abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
- + SQR(lix[0][2]-lix[dir[i]][2]);
- }
- }
- leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
- MAX(ldiff[1][2],ldiff[1][3]));
- abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
- MAX(abdiff[1][2],abdiff[1][3]));
- for (d=0; d < 2; d++)
- for (i=0; i < 4; i++)
- if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
- homo[d][tr][tc]++;
- }
- }
-/* Combine the most homogenous pixels for the final result: */
- for (row=top+3; row < top+TS-3 && row < height-5; row++) {
- tr = row-top;
- for (col=left+3; col < left+TS-3 && col < width-5; col++) {
- tc = col-left;
- for (d=0; d < 2; d++)
- for (hm[d]=0, i=tr-1; i <= tr+1; i++)
- for (j=tc-1; j <= tc+1; j++)
- hm[d] += homo[d][i][j];
- if (hm[0] != hm[1])
- FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
- else
- FORC3 image[row*width+col][c] =
- (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
- }
- }
- }
- }
- free (buffer);
-}
-#else
-void CLASS ahd_interpolate()
-{
- int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
- ushort (*pix)[4], (*rix)[3];
- static const int dir[4] = { -1, 1, -TS, TS };
- unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
- float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
- ushort (*rgb)[TS][TS][3];
- short (*lab)[TS][TS][3], (*lix)[3];
- char (*homo)[TS][TS], *buffer;
-
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
-#endif
-
- for (i=0; i < 0x10000; i++) {
- r = i / 65535.0;
- cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0;
- }
- for (i=0; i < 3; i++)
- for (j=0; j < colors; j++)
- for (xyz_cam[i][j] = k=0; k < 3; k++)
- xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
-
- border_interpolate(5);
-
-#ifdef LIBRAW_LIBRARY_BUILD
-#pragma omp parallel private(buffer,rgb,lab,homo,top,left,row,c,col,pix,val,d,rix,xyz,lix,tc,tr,ldiff,abdiff,leps,abeps,hm,i,j) firstprivate(cbrt) shared(xyz_cam)
-#endif
- {
- buffer = (char *) malloc (26*TS*TS); /* 1664 kB */
- merror (buffer, "ahd_interpolate()");
- rgb = (ushort(*)[TS][TS][3]) buffer;
- lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
- homo = (char (*)[TS][TS]) (buffer + 24*TS*TS);
-
-#pragma omp for schedule(dynamic)
- for (top=2; top < height-5; top += TS-6){
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(top-2)/(TS-6)+1,(height-7)/(TS-6)+1);
-#endif
- for (left=2; left < width-5; left += TS-6) {
-
- /* Interpolate green horizontally and vertically: */
- for (row = top; row < top+TS && row < height-2; row++) {
- col = left + (FC(row,left) & 1);
- for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
- pix = image + row*width+col;
- val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
- - pix[-2][c] - pix[2][c]) >> 2;
- rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
- val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2
- - pix[-2*width][c] - pix[2*width][c]) >> 2;
- rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
- }
- }
- /* Interpolate red and blue, and convert to CIELab: */
- for (d=0; d < 2; d++)
- for (row=top+1; row < top+TS-1 && row < height-3; row++)
- for (col=left+1; col < left+TS-1 && col < width-3; col++) {
- pix = image + row*width+col;
- rix = &rgb[d][row-top][col-left];
- lix = &lab[d][row-top][col-left];
- if ((c = 2 - FC(row,col)) == 1) {
- c = FC(row+1,col);
- val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
- - rix[-1][1] - rix[1][1] ) >> 1);
- rix[0][2-c] = CLIP(val);
- val = pix[0][1] + (( pix[-width][c] + pix[width][c]
- - rix[-TS][1] - rix[TS][1] ) >> 1);
- } else
- val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
- + pix[+width-1][c] + pix[+width+1][c]
- - rix[-TS-1][1] - rix[-TS+1][1]
- - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
- rix[0][c] = CLIP(val);
- c = FC(row,col);
- rix[0][c] = pix[0][c];
- xyz[0] = xyz[1] = xyz[2] = 0.5;
- FORCC {
- xyz[0] += xyz_cam[0][c] * rix[0][c];
- xyz[1] += xyz_cam[1][c] * rix[0][c];
- xyz[2] += xyz_cam[2][c] * rix[0][c];
- }
- xyz[0] = cbrt[CLIP((int) xyz[0])];
- xyz[1] = cbrt[CLIP((int) xyz[1])];
- xyz[2] = cbrt[CLIP((int) xyz[2])];
- lix[0][0] = 64 * (116 * xyz[1] - 16);
- lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
- lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
- }
- /* Build homogeneity maps from the CIELab images: */
- memset (homo, 0, 2*TS*TS);
- for (row=top+2; row < top+TS-2 && row < height-4; row++) {
- tr = row-top;
- for (col=left+2; col < left+TS-2 && col < width-4; col++) {
- tc = col-left;
- for (d=0; d < 2; d++) {
- lix = &lab[d][tr][tc];
- for (i=0; i < 4; i++) {
- ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
- abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
- + SQR(lix[0][2]-lix[dir[i]][2]);
- }
- }
- leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
- MAX(ldiff[1][2],ldiff[1][3]));
- abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
- MAX(abdiff[1][2],abdiff[1][3]));
- for (d=0; d < 2; d++)
- for (i=0; i < 4; i++)
- if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
- homo[d][tr][tc]++;
- }
- }
- /* Combine the most homogenous pixels for the final result: */
- for (row=top+3; row < top+TS-3 && row < height-5; row++) {
- tr = row-top;
- for (col=left+3; col < left+TS-3 && col < width-5; col++) {
- tc = col-left;
- for (d=0; d < 2; d++)
- for (hm[d]=0, i=tr-1; i <= tr+1; i++)
- for (j=tc-1; j <= tc+1; j++)
- hm[d] += homo[d][i][j];
- if (hm[0] != hm[1])
- FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
- else
- FORC3 image[row*width+col][c] =
- (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
- }
- }
- }
- }
- free (buffer);
- }
-}
-
-#endif
-#undef TS
-
-void CLASS median_filter()
-{
- ushort (*pix)[4];
- int pass, c, i, j, k, med[9];
- static const uchar opt[] = /* Optimal 9-element median search */
- { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8,
- 0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 };
-
- for (pass=1; pass <= med_passes; pass++) {
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_MEDIAN_FILTER,pass-1,med_passes);
-#endif
-#ifdef DCRAW_VERBOSE
- if (verbose)
- fprintf (stderr,_("Median filter pass %d...\n"), pass);
-#endif
- for (c=0; c < 3; c+=2) {
- for (pix = image; pix < image+width*height; pix++)
- pix[0][3] = pix[0][c];
- for (pix = image+width; pix < image+width*(height-1); pix++) {
- if ((pix-image+1) % width < 2) continue;
- for (k=0, i = -width; i <= width; i += width)
- for (j = i-1; j <= i+1; j++)
- med[k++] = pix[j][3] - pix[j][1];
- for (i=0; i < sizeof opt; i+=2)
- if (med[opt[i]] > med[opt[i+1]])
- SWAP (med[opt[i]] , med[opt[i+1]]);
- pix[0][c] = CLIP(med[4] + pix[0][1]);
- }
- }
- }
-}
-
-void CLASS blend_highlights()
-{
- int clip=INT_MAX, row, col, c, i, j;
- static const float trans[2][4][4] =
- { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } },
- { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
- static const float itrans[2][4][4] =
- { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } },
- { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
- float cam[2][4], lab[2][4], sum[2], chratio;
-
- if ((unsigned) (colors-3) > 1) return;
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("Blending highlights...\n"));
-#endif
- FORCC if (clip > (i = 65535*pre_mul[c])) clip = i;
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,0,2);
-#endif
- for (row=0; row < height; row++)
- for (col=0; col < width; col++) {
- FORCC if (image[row*width+col][c] > clip) break;
- if (c == colors) continue;
- FORCC {
- cam[0][c] = image[row*width+col][c];
- cam[1][c] = MIN(cam[0][c],clip);
- }
- for (i=0; i < 2; i++) {
- FORCC for (lab[i][c]=j=0; j < colors; j++)
- lab[i][c] += trans[colors-3][c][j] * cam[i][j];
- for (sum[i]=0,c=1; c < colors; c++)
- sum[i] += SQR(lab[i][c]);
- }
- chratio = sqrt(sum[1]/sum[0]);
- for (c=1; c < colors; c++)
- lab[0][c] *= chratio;
- FORCC for (cam[0][c]=j=0; j < colors; j++)
- cam[0][c] += itrans[colors-3][c][j] * lab[0][j];
- FORCC image[row*width+col][c] = cam[0][c] / colors;
- }
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,1,2);
-#endif
-}
-
-#define SCALE (4 >> shrink)
-void CLASS recover_highlights()
-{
- float *map, sum, wgt, grow;
- int hsat[4], count, spread, change, val, i;
- unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x;
- ushort *pixel;
- static const signed char dir[8][2] =
- { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} };
-
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("Rebuilding highlights...\n"));
-#endif
-
- grow = pow (2.0, 4.0-highlight);
- FORCC hsat[c] = 32000 * pre_mul[c];
- for (kc=0, c=1; c < colors; c++)
- if (pre_mul[kc] < pre_mul[c]) kc = c;
- high = height / SCALE;
- wide = width / SCALE;
- map = (float *) calloc (high*wide, sizeof *map);
- merror (map, "recover_highlights()");
- FORCC if (c != kc) {
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,c-1,colors-1);
-#endif
- memset (map, 0, high*wide*sizeof *map);
- for (mrow=0; mrow < high; mrow++)
- for (mcol=0; mcol < wide; mcol++) {
- sum = wgt = count = 0;
- for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
- for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
- pixel = image[row*width+col];
- if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) {
- sum += pixel[c];
- wgt += pixel[kc];
- count++;
- }
- }
- if (count == SCALE*SCALE)
- map[mrow*wide+mcol] = sum / wgt;
- }
- for (spread = 32/grow; spread--; ) {
- for (mrow=0; mrow < high; mrow++)
- for (mcol=0; mcol < wide; mcol++) {
- if (map[mrow*wide+mcol]) continue;
- sum = count = 0;
- for (d=0; d < 8; d++) {
- y = mrow + dir[d][0];
- x = mcol + dir[d][1];
- if (y < high && x < wide && map[y*wide+x] > 0) {
- sum += (1 + (d & 1)) * map[y*wide+x];
- count += 1 + (d & 1);
- }
- }
- if (count > 3)
- map[mrow*wide+mcol] = - (sum+grow) / (count+grow);
- }
- for (change=i=0; i < high*wide; i++)
- if (map[i] < 0) {
- map[i] = -map[i];
- change = 1;
- }
- if (!change) break;
- }
- for (i=0; i < high*wide; i++)
- if (map[i] == 0) map[i] = 1;
- for (mrow=0; mrow < high; mrow++)
- for (mcol=0; mcol < wide; mcol++) {
- for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
- for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
- pixel = image[row*width+col];
- if (pixel[c] / hsat[c] > 1) {
- val = pixel[kc] * map[mrow*wide+mcol];
- if (pixel[c] < val) pixel[c] = CLIP(val);
- }
- }
- }
- }
- free (map);
-}
-#undef SCALE
-
-void CLASS tiff_get (unsigned base,
- unsigned *tag, unsigned *type, unsigned *len, unsigned *save)
-{
- *tag = get2();
- *type = get2();
- *len = get4();
- *save = ftell(ifp) + 4;
- if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4)
- fseek (ifp, get4()+base, SEEK_SET);
-}
-
-void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen)
-{
- unsigned entries, tag, type, len, save;
-
- entries = get2();
- while (entries--) {
- tiff_get (base, &tag, &type, &len, &save);
- if (tag == toff) thumb_offset = get4()+base;
- if (tag == tlen) thumb_length = get4();
- fseek (ifp, save, SEEK_SET);
- }
-}
-
-void CLASS parse_makernote (int base, int uptag)
-{
- static const uchar xlat[2][256] = {
- { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
- 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
- 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
- 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
- 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
- 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
- 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
- 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
- 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
- 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
- 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
- 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
- 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
- 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
- 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
- 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 },
- { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
- 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
- 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
- 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
- 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
- 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
- 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
- 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
- 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
- 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
- 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
- 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
- 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
- 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
- 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
- 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } };
- unsigned offset=0, entries, tag, type, len, save, c;
- unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
- uchar buf97[324], ci, cj, ck;
- short sorder=order;
- char buf[10];
-/*
- The MakerNote might have its own TIFF header (possibly with
- its own byte-order!), or it might just be a table.
- */
- fread (buf, 1, 10, ifp);
- if (!strncmp (buf,"KDK" ,3) || /* these aren't TIFF tables */
- !strncmp (buf,"VER" ,3) ||
- !strncmp (buf,"IIII",4) ||
- !strncmp (buf,"MMMM",4)) return;
- if (!strncmp (buf,"KC" ,2) || /* Konica KD-400Z, KD-510Z */
- !strncmp (buf,"MLY" ,3)) { /* Minolta DiMAGE G series */
- order = 0x4d4d;
- while ((i=ftell(ifp)) < data_offset && i < 16384) {
- wb[0] = wb[2]; wb[2] = wb[1]; wb[1] = wb[3];
- wb[3] = get2();
- if (wb[1] == 256 && wb[3] == 256 &&
- wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640)
- FORC4 cam_mul[c] = wb[c];
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- goto quit;
- }
- if (!strcmp (buf,"Nikon")) {
- base = ftell(ifp);
- order = get2();
- if (get2() != 42) goto quit;
- offset = get4();
- fseek (ifp, offset-8, SEEK_CUR);
- } else if (!strcmp (buf,"OLYMPUS")) {
- base = ftell(ifp)-10;
- fseek (ifp, -2, SEEK_CUR);
- order = get2(); get2();
- } else if (!strncmp (buf,"FUJIFILM",8) ||
- !strncmp (buf,"SONY",4) ||
- !strcmp (buf,"Panasonic")) {
- order = 0x4949;
- fseek (ifp, 2, SEEK_CUR);
- } else if (!strcmp (buf,"OLYMP") ||
- !strcmp (buf,"LEICA") ||
- !strcmp (buf,"Ricoh") ||
- !strcmp (buf,"EPSON"))
- fseek (ifp, -2, SEEK_CUR);
- else if (!strcmp (buf,"AOC") ||
- !strcmp (buf,"QVC"))
- fseek (ifp, -4, SEEK_CUR);
- else fseek (ifp, -10, SEEK_CUR);
-
- entries = get2();
- if (entries > 1000) return;
- while (entries--) {
- tiff_get (base, &tag, &type, &len, &save);
- tag |= uptag << 16;
- if (tag == 2 && strstr(make,"NIKON"))
- iso_speed = (get2(),get2());
- if (tag == 4 && len > 26 && len < 35) {
- if ((i=(get4(),get2())) != 0x7fff && !iso_speed)
- iso_speed = 50 * pow (2, i/32.0 - 4);
- if ((i=(get2(),get2())) != 0x7fff && !aperture)
- aperture = pow (2, i/64.0);
- if ((i=get2()) != 0xffff && !shutter)
- shutter = pow (2, (short) i/-32.0);
- wbi = (get2(),get2());
- shot_order = (get2(),get2());
- }
- if (tag == 7 && type == 2 && len > 20)
- fgets (model2, 64, ifp);
- if (tag == 8 && type == 4)
- shot_order = get4();
- if (tag == 9 && !strcmp(make,"Canon"))
- fread (artist, 64, 1, ifp);
- if (tag == 0xc && len == 4) {
- cam_mul[0] = getreal(type);
- cam_mul[2] = getreal(type);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if (tag == 0x10 && type == 4)
- unique_id = get4();
- if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) {
- fseek (ifp, get4()+base, SEEK_SET);
- parse_tiff_ifd (base);
- }
- if (tag == 0x14 && len == 2560 && type == 7) {
- fseek (ifp, 1248, SEEK_CUR);
- goto get2_256;
- }
- if (tag == 0x15 && type == 2 && is_raw)
- fread (model, 64, 1, ifp);
- if (strstr(make,"PENTAX")) {
- if (tag == 0x1b) tag = 0x1018;
- if (tag == 0x1c) tag = 0x1017;
- }
- if (tag == 0x1d)
- while ((c = fgetc(ifp)) && c != EOF)
- serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
- if (tag == 0x81 && type == 4) {
- data_offset = get4();
- fseek (ifp, data_offset + 41, SEEK_SET);
- raw_height = get2() * 2;
- raw_width = get2();
- filters = 0x61616161;
- }
- if (tag == 0x29 && type == 1) {
- c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
- fseek (ifp, 8 + c*32, SEEK_CUR);
- FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if ((tag == 0x81 && type == 7) ||
- (tag == 0x100 && type == 7) ||
- (tag == 0x280 && type == 1)) {
- thumb_offset = ftell(ifp);
- thumb_length = len;
- }
- if (tag == 0x88 && type == 4 && (thumb_offset = get4()))
- thumb_offset += base;
- if (tag == 0x89 && type == 4)
- thumb_length = get4();
- if (tag == 0x8c || tag == 0x96)
- meta_offset = ftell(ifp);
- if (tag == 0x97) {
- for (i=0; i < 4; i++)
- ver97 = ver97 * 10 + fgetc(ifp)-'0';
- switch (ver97) {
- case 100:
- fseek (ifp, 68, SEEK_CUR);
- FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- break;
- case 102:
- fseek (ifp, 6, SEEK_CUR);
- goto get2_rggb;
- case 103:
- fseek (ifp, 16, SEEK_CUR);
- FORC4 cam_mul[c] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if (ver97 >= 200) {
- if (ver97 != 205) fseek (ifp, 280, SEEK_CUR);
- fread (buf97, 324, 1, ifp);
- }
- }
- if (tag == 0xa4 && type == 3) {
- fseek (ifp, wbi*48, SEEK_CUR);
- FORC3 cam_mul[c] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !cam_mul[0]) {
- ci = xlat[0][serial & 0xff];
- cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)];
- ck = 0x60;
- for (i=0; i < 324; i++)
- buf97[i] ^= (cj += ci * ck++);
- i = "66666>666;6A"[ver97-200] - '0';
- FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
- sget2 (buf97 + (i & -2) + c*2);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if (tag == 0x200 && len == 3)
- shot_order = (get4(),get4());
- if (tag == 0x200 && len == 4)
- black = (get2()+get2()+get2()+get2())/4;
- if (tag == 0x201 && len == 4)
- goto get2_rggb;
- if (tag == 0x220 && len == 53) {
- fseek (ifp, 14, SEEK_CUR);
- pentax_tree();
- }
- if (tag == 0x401 && len == 4) {
- black = (get4()+get4()+get4()+get4())/4;
- }
- if (tag == 0xe01) { /* Nikon Capture Note */
- type = order;
- order = 0x4949;
- fseek (ifp, 22, SEEK_CUR);
- for (offset=22; offset+22 < len; offset += 22+i) {
- tag = get4();
- fseek (ifp, 14, SEEK_CUR);
- i = get4()-4;
- if (tag == 0x76a43207) flip = get2();
- else fseek (ifp, i, SEEK_CUR);
- }
- order = type;
- }
- if (tag == 0xe80 && len == 256 && type == 7) {
- fseek (ifp, 48, SEEK_CUR);
- cam_mul[0] = get2() * 508 * 1.078 / 0x10000;
- cam_mul[2] = get2() * 382 * 1.173 / 0x10000;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if (tag == 0xf00 && type == 7) {
- if (len == 614)
- fseek (ifp, 176, SEEK_CUR);
- else if (len == 734 || len == 1502)
- fseek (ifp, 148, SEEK_CUR);
- else goto next;
- goto get2_256;
- }
- if ((tag == 0x1011 && len == 9) || tag == 0x20400200)
- {
- for (i=0; i < 3; i++)
- FORC3 cmatrix[i][c] = ((short) get2()) / 256.0;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cmatrix_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
- for (black = i=0; i < 4; i++)
- black += get2() << 2;
- if (tag == 0x1017 || tag == 0x20400100)
- {
- cam_mul[0] = get2() / 256.0;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if (tag == 0x1018 || tag == 0x20400100)
- {
- cam_mul[2] = get2() / 256.0;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if (tag == 0x2011 && len == 2) {
-get2_256:
- order = 0x4d4d;
- cam_mul[0] = get2() / 256.0;
- cam_mul[2] = get2() / 256.0;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if ((tag | 0x70) == 0x2070 && type == 4)
- fseek (ifp, get4()+base, SEEK_SET);
- if (tag == 0x2010 && type != 7)
- load_raw = &CLASS olympus_e410_load_raw;
- if (tag == 0x2020)
- parse_thumb_note (base, 257, 258);
- if (tag == 0x2040)
- parse_makernote (base, 0x2040);
- if (tag == 0xb028) {
- fseek (ifp, get4(), SEEK_SET);
- parse_thumb_note (base, 136, 137);
- }
- if (tag == 0x4001 && len > 500) {
- i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
- fseek (ifp, i, SEEK_CUR);
-get2_rggb:
- FORC4 cam_mul[c ^ (c >> 1)] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- fseek (ifp, 22, SEEK_CUR);
- FORC4 sraw_mul[c ^ (c >> 1)] = get2();
- }
-next:
- fseek (ifp, save, SEEK_SET);
- }
-quit:
- order = sorder;
-}
-
-/*
- Since the TIFF DateTime string has no timezone information,
- assume that the camera's clock was set to Universal Time.
- */
-void CLASS get_timestamp (int reversed)
-{
- struct tm t;
- char str[20];
- int i;
-
- str[19] = 0;
- if (reversed)
- for (i=19; i--; ) str[i] = fgetc(ifp);
- else
- fread (str, 19, 1, ifp);
- memset (&t, 0, sizeof t);
- if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
- &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
- return;
- t.tm_year -= 1900;
- t.tm_mon -= 1;
- if (mktime(&t) > 0)
- timestamp = mktime(&t);
-}
-
-void CLASS parse_exif (int base)
-{
- unsigned kodak, entries, tag, type, len, save, c;
- double expo;
-
- kodak = !strncmp(make,"EASTMAN",7);
- entries = get2();
- while (entries--) {
- tiff_get (base, &tag, &type, &len, &save);
- switch (tag) {
- case 33434: shutter = getreal(type); break;
- case 33437: aperture = getreal(type); break;
- case 34855: iso_speed = get2(); break;
- case 36867:
- case 36868: get_timestamp(0); break;
- case 37377: if ((expo = -getreal(type)) < 128)
- shutter = pow (2, expo); break;
- case 37378: aperture = pow (2, getreal(type)/2); break;
- case 37386: focal_len = getreal(type); break;
- case 37500: parse_makernote (base, 0); break;
- case 40962: if (kodak) raw_width = get4(); break;
- case 40963: if (kodak) raw_height = get4(); break;
- case 41730:
- if (get4() == 0x20002)
- for (exif_cfa=c=0; c < 8; c+=2)
- exif_cfa |= fgetc(ifp) * 0x01010101 << c;
- }
- fseek (ifp, save, SEEK_SET);
- }
-}
-
-void CLASS parse_gps (int base)
-{
- unsigned entries, tag, type, len, save, c;
-
- entries = get2();
- while (entries--) {
- tiff_get (base, &tag, &type, &len, &save);
- switch (tag) {
- case 1: case 3: case 5:
- gpsdata[29+tag/2] = getc(ifp); break;
- case 2: case 4: case 7:
- FORC(6) gpsdata[tag/3*6+c] = get4(); break;
- case 6:
- FORC(2) gpsdata[18+c] = get4(); break;
- case 18: case 29:
- fgets ((char *) (gpsdata+14+tag/3), MIN(len,12), ifp);
- }
- fseek (ifp, save, SEEK_SET);
- }
-}
-
-void CLASS romm_coeff (float romm_cam[3][3])
-{
- static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */
- { { 2.034193, -0.727420, -0.306766 },
- { -0.228811, 1.231729, -0.002922 },
- { -0.008565, -0.153273, 1.161839 } };
- int i, j, k;
-
- for (i=0; i < 3; i++)
- for (j=0; j < 3; j++)
- for (cmatrix[i][j] = k=0; k < 3; k++)
- cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j];
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cmatrix_state = LIBRAW_COLORSTATE_CALCULATED;
-#endif
-}
-
-void CLASS parse_mos (int offset)
-{
- char data[40];
- int skip, from, i, c, neut[4], planes=0, frot=0;
- static const char *mod[] =
- { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22",
- "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65",
- "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7" };
- float romm_cam[3][3];
-
- fseek (ifp, offset, SEEK_SET);
- while (1) {
- if (get4() != 0x504b5453) break;
- get4();
- fread (data, 1, 40, ifp);
- skip = get4();
- from = ftell(ifp);
- if (!strcmp(data,"JPEG_preview_data")) {
- thumb_offset = from;
- thumb_length = skip;
- }
- if (!strcmp(data,"icc_camera_profile")) {
- profile_offset = from;
- profile_length = skip;
- }
- if (!strcmp(data,"ShootObj_back_type")) {
- fscanf (ifp, "%d", &i);
- if ((unsigned) i < sizeof mod / sizeof (*mod))
- strcpy (model, mod[i]);
- }
- if (!strcmp(data,"icc_camera_to_tone_matrix")) {
- for (i=0; i < 9; i++)
- romm_cam[0][i] = int_to_float(get4());
- romm_coeff (romm_cam);
- }
- if (!strcmp(data,"CaptProf_color_matrix")) {
- for (i=0; i < 9; i++)
- fscanf (ifp, "%f", &romm_cam[0][i]);
- romm_coeff (romm_cam);
- }
- if (!strcmp(data,"CaptProf_number_of_planes"))
- fscanf (ifp, "%d", &planes);
- if (!strcmp(data,"CaptProf_raw_data_rotation"))
- fscanf (ifp, "%d", &flip);
- if (!strcmp(data,"CaptProf_mosaic_pattern"))
- FORC4 {
- fscanf (ifp, "%d", &i);
- if (i == 1) frot = c ^ (c >> 1);
- }
- if (!strcmp(data,"ImgProf_rotation_angle")) {
- fscanf (ifp, "%d", &i);
- flip = i - flip;
- }
- if (!strcmp(data,"NeutObj_neutrals") && !cam_mul[0]) {
- FORC4 fscanf (ifp, "%d", neut+c);
- FORC3 cam_mul[c] = (float) neut[0] / neut[c+1];
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- parse_mos (from);
- fseek (ifp, skip+from, SEEK_SET);
- }
- if (planes)
- filters = (planes == 1) * 0x01010101 *
- (uchar) "\x94\x61\x16\x49"[(flip/90 + frot) & 3];
-}
-
-void CLASS linear_table (unsigned len)
-{
- int i;
- if (len > 0x1000) len = 0x1000;
- read_shorts (curve, len);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- for (i=len; i < 0x1000; i++)
- curve[i] = curve[i-1];
- maximum = curve[0xfff];
-}
-
-void CLASS parse_kodak_ifd (int base)
-{
- unsigned entries, tag, type, len, save;
- int i, c, wbi=-2, wbtemp=6500;
- float mul[3], num;
-
- entries = get2();
- if (entries > 1024) return;
- while (entries--) {
- tiff_get (base, &tag, &type, &len, &save);
- if (tag == 1020) wbi = getint(type);
- if (tag == 1021 && len == 72) { /* WB set in software */
- fseek (ifp, 40, SEEK_CUR);
- FORC3 cam_mul[c] = 2048.0 / get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- wbi = -2;
- }
- if (tag == 2118) wbtemp = getint(type);
- if (tag == 2130 + wbi)
- FORC3 mul[c] = getreal(type);
- if (tag == 2140 + wbi && wbi >= 0)
- {
- FORC3 {
- for (num=i=0; i < 4; i++)
- num += getreal(type) * pow (wbtemp/100.0, i);
- cam_mul[c] = 2048 / (num * mul[c]);
- }
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if (tag == 2317) linear_table (len);
- if (tag == 6020) iso_speed = getint(type);
- fseek (ifp, save, SEEK_SET);
- }
-}
-
-int CLASS parse_tiff_ifd (int base)
-{
- unsigned entries, tag, type, len, plen=16, save;
- int ifd, use_cm=0, cfa, i, j, c, ima_len=0;
- char software[64], *cbuf, *cp;
- uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256];
- double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num;
- double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 };
- unsigned sony_curve[] = { 0,0,0,0,0,4095 };
- unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
- struct jhead jh;
- FILE *sfp;
-
- if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
- return 1;
- ifd = tiff_nifds++;
- for (j=0; j < 4; j++)
- for (i=0; i < 4; i++)
- cc[j][i] = i == j;
- entries = get2();
- if (entries > 512) return 1;
- while (entries--) {
- tiff_get (base, &tag, &type, &len, &save);
- switch (tag) {
- case 17: case 18:
- if (type == 3 && len == 1)
- {
- cam_mul[(tag-17)*2] = get2() / 256.0;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- break;
- case 23:
- if (type == 3) iso_speed = get2();
- break;
- case 36: case 37: case 38:
- cam_mul[tag-0x24] = get2();
- break;
- case 39:
- if (len < 50 || cam_mul[0]) break;
- fseek (ifp, 12, SEEK_CUR);
- FORC3 cam_mul[c] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- break;
- case 46:
- if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break;
- thumb_offset = ftell(ifp) - 2;
- thumb_length = len;
- break;
- case 2: case 256: /* ImageWidth */
- tiff_ifd[ifd].t_width = getint(type);
- break;
- case 3: case 257: /* ImageHeight */
- tiff_ifd[ifd].t_height = getint(type);
- break;
- case 258: /* BitsPerSample */
- tiff_ifd[ifd].samples = len & 7;
- tiff_ifd[ifd].bps = get2();
- break;
- case 259: /* Compression */
- tiff_ifd[ifd].comp = get2();
- break;
- case 262: /* PhotometricInterpretation */
- tiff_ifd[ifd].phint = get2();
- break;
- case 270: /* ImageDescription */
- fread (desc, 512, 1, ifp);
- break;
- case 271: /* Make */
- fgets (make, 64, ifp);
- break;
- case 272: /* Model */
- fgets (model, 64, ifp);
- break;
- case 280: /* Panasonic RW2 offset */
- if (type != 4) break;
- load_raw = &CLASS panasonic_load_raw;
- load_flags = 0x2008;
- case 273: /* StripOffset */
- case 513:
- tiff_ifd[ifd].offset = get4()+base;
- if (!tiff_ifd[ifd].bps) {
- fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
- if (ljpeg_start (&jh, 1)) {
- tiff_ifd[ifd].comp = 6;
- tiff_ifd[ifd].t_width = jh.wide << (jh.clrs == 2);
- tiff_ifd[ifd].t_height = jh.high;
- tiff_ifd[ifd].bps = jh.bits;
- tiff_ifd[ifd].samples = jh.clrs;
- }
- }
- break;
- case 274: /* Orientation */
- tiff_ifd[ifd].t_flip = "50132467"[get2() & 7]-'0';
- break;
- case 277: /* SamplesPerPixel */
- tiff_ifd[ifd].samples = getint(type) & 7;
- break;
- case 279: /* StripByteCounts */
- case 514:
- tiff_ifd[ifd].bytes = get4();
- break;
- case 305: case 11: /* Software */
- fgets (software, 64, ifp);
- if (!strncmp(software,"Adobe",5) ||
- !strncmp(software,"dcraw",5) ||
- !strncmp(software,"UFRaw",5) ||
- !strncmp(software,"Bibble",6) ||
- !strncmp(software,"Nikon Scan",10) ||
- !strcmp (software,"Digital Photo Professional"))
- is_raw = 0;
- break;
- case 306: /* DateTime */
- get_timestamp(0);
- break;
- case 315: /* Artist */
- fread (artist, 64, 1, ifp);
- break;
- case 322: /* TileWidth */
- tile_width = getint(type);
- break;
- case 323: /* TileLength */
- tile_length = getint(type);
- break;
- case 324: /* TileOffsets */
- tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
- if (len == 4) {
- load_raw = &CLASS sinar_4shot_load_raw;
- is_raw = 5;
- }
- break;
- case 330: /* SubIFDs */
- if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].t_width == 3872) {
- load_raw = &CLASS sony_arw_load_raw;
- data_offset = get4()+base;
- ifd++; break;
- }
- while (len--) {
- i = ftell(ifp);
- fseek (ifp, get4()+base, SEEK_SET);
- if (parse_tiff_ifd (base)) break;
- fseek (ifp, i+4, SEEK_SET);
- }
- break;
- case 400:
- strcpy (make, "Sarnoff");
- maximum = 0xfff;
- break;
- case 28688:
- FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff;
- for (i=0; i < 5; i++)
- for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++)
- curve[j] = curve[j-1] + (1 << i);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- break;
- case 29184: sony_offset = get4(); break;
- case 29185: sony_length = get4(); break;
- case 29217: sony_key = get4(); break;
- case 29264:
- parse_minolta (ftell(ifp));
- raw_width = 0;
- break;
- case 29443:
- FORC4 cam_mul[c ^ (c < 2)] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- break;
- case 29459:
- FORC4 cam_mul[c ^ (c >> 1)] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- break;
- case 33405: /* Model2 */
- fgets (model2, 64, ifp);
- break;
- case 33422: /* CFAPattern */
- case 64777: /* Kodak P-series */
- if ((plen=len) > 16) plen = 16;
- fread (cfa_pat, 1, plen, ifp);
- for (colors=cfa=i=0; i < plen; i++) {
- colors += !(cfa & (1 << cfa_pat[i]));
- cfa |= 1 << cfa_pat[i];
- }
- if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3); /* CMY */
- if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4); /* GMCY */
- goto guess_cfa_pc;
- case 33424:
- fseek (ifp, get4()+base, SEEK_SET);
- parse_kodak_ifd (base);
- break;
- case 33434: /* ExposureTime */
- shutter = getreal(type);
- break;
- case 33437: /* FNumber */
- aperture = getreal(type);
- break;
- case 34306: /* Leaf white balance */
- FORC4 cam_mul[c ^ 1] = 4096.0 / get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- break;
- case 34307: /* Leaf CatchLight color matrix */
- fread (software, 1, 7, ifp);
- if (strncmp(software,"MATRIX",6)) break;
- colors = 4;
- for (raw_color = i=0; i < 3; i++) {
- FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]);
- if (!use_camera_wb) continue;
- num = 0;
- FORC4 num += rgb_cam[i][c];
- FORC4 rgb_cam[i][c] /= num;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.rgb_cam_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- break;
- case 34310: /* Leaf metadata */
- parse_mos (ftell(ifp));
- case 34303:
- strcpy (make, "Leaf");
- break;
- case 34665: /* EXIF tag */
- fseek (ifp, get4()+base, SEEK_SET);
- parse_exif (base);
- break;
- case 34853: /* GPSInfo tag */
- fseek (ifp, get4()+base, SEEK_SET);
- parse_gps (base);
- break;
- case 34675: /* InterColorProfile */
- case 50831: /* AsShotICCProfile */
- profile_offset = ftell(ifp);
- profile_length = len;
- break;
- case 37122: /* CompressedBitsPerPixel */
- kodak_cbpp = get4();
- break;
- case 37386: /* FocalLength */
- focal_len = getreal(type);
- break;
- case 37393: /* ImageNumber */
- shot_order = getint(type);
- break;
- case 37400: /* old Kodak KDC tag */
- for (raw_color = i=0; i < 3; i++) {
- getreal(type);
- FORC3 rgb_cam[i][c] = getreal(type);
- }
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.rgb_cam_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- break;
- case 46275: /* Imacon tags */
- strcpy (make, "Imacon");
- data_offset = ftell(ifp);
- ima_len = len;
- break;
- case 46279:
- if (!ima_len) break;
- fseek (ifp, 78, SEEK_CUR);
- raw_width = get4();
- raw_height = get4();
- left_margin = get4() & 7;
- width = raw_width - left_margin - (get4() & 7);
- top_margin = get4() & 7;
- height = raw_height - top_margin - (get4() & 7);
- if (raw_width == 7262) {
- height = 5444;
- width = 7244;
- left_margin = 7;
- }
- fseek (ifp, 52, SEEK_CUR);
- FORC3 cam_mul[c] = getreal(11);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- fseek (ifp, 114, SEEK_CUR);
- flip = (get2() >> 7) * 90;
- if (width * height * 6 == ima_len) {
- if (flip % 180 == 90) SWAP(width,height);
- filters = flip = 0;
- }
- sprintf (model, "Ixpress %d-Mp", height*width/1000000);
- load_raw = &CLASS imacon_full_load_raw;
- if (filters) {
- if (left_margin & 1) filters = 0x61616161;
- load_raw = &CLASS unpacked_load_raw;
- }
- maximum = 0xffff;
- break;
- case 50454: /* Sinar tag */
- case 50455:
- if (!(cbuf = (char *) malloc(len))) break;
- fread (cbuf, 1, len, ifp);
- for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n'))
- if (!strncmp (++cp,"Neutral ",8))
- {
- sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- free (cbuf);
- break;
- case 50458:
- if (!make[0]) strcpy (make, "Hasselblad");
- break;
- case 50459: /* Hasselblad tag */
- i = order;
- j = ftell(ifp);
- c = tiff_nifds;
- order = get2();
- fseek (ifp, j+(get2(),get4()), SEEK_SET);
- parse_tiff_ifd (j);
- maximum = 0xffff;
- tiff_nifds = c;
- order = i;
- break;
- case 50706: /* DNGVersion */
- FORC4 dng_version = (dng_version << 8) + fgetc(ifp);
- if (!make[0]) strcpy (make, "DNG");
- is_raw = 1;
- break;
- case 50710: /* CFAPlaneColor */
- if (len > 4) len = 4;
- colors = len;
- fread (cfa_pc, 1, colors, ifp);
-guess_cfa_pc:
- FORCC tab[cfa_pc[c]] = c;
- cdesc[c] = 0;
- for (i=16; i--; )
- filters = filters << 2 | tab[cfa_pat[i % plen]];
- break;
- case 50711: /* CFALayout */
- if (get2() == 2) {
- fuji_width = 1;
- filters = 0x49494949;
- }
- break;
- case 291:
- case 50712: /* LinearizationTable */
- linear_table (len);
- break;
- case 50714: /* BlackLevel */
- case 50715: /* BlackLevelDeltaH */
- case 50716: /* BlackLevelDeltaV */
- for (dblack=i=0; i < len; i++)
- dblack += getreal(type);
- black += dblack/len + 0.5;
- break;
- case 50717: /* WhiteLevel */
- maximum = getint(type);
- break;
- case 50718: /* DefaultScale */
- pixel_aspect = getreal(type);
- pixel_aspect /= getreal(type);
- break;
- case 50721: /* ColorMatrix1 */
- case 50722: /* ColorMatrix2 */
- FORCC for (j=0; j < 3; j++)
- cm[c][j] = getreal(type);
- use_cm = 1;
- break;
- case 50723: /* CameraCalibration1 */
- case 50724: /* CameraCalibration2 */
- for (i=0; i < colors; i++)
- FORCC cc[i][c] = getreal(type);
- case 50727: /* AnalogBalance */
- FORCC ab[c] = getreal(type);
- break;
- case 50728: /* AsShotNeutral */
- FORCC asn[c] = getreal(type);
- break;
- case 50729: /* AsShotWhiteXY */
- xyz[0] = getreal(type);
- xyz[1] = getreal(type);
- xyz[2] = 1 - xyz[0] - xyz[1];
- FORC3 xyz[c] /= d65_white[c];
- break;
- case 50740: /* DNGPrivateData */
- if (dng_version) break;
- parse_minolta (j = get4()+base);
- fseek (ifp, j, SEEK_SET);
- parse_tiff_ifd (base);
- break;
- case 50752:
- read_shorts (cr2_slice, 3);
- break;
- case 50829: /* ActiveArea */
- top_margin = getint(type);
- left_margin = getint(type);
- height = getint(type) - top_margin;
- width = getint(type) - left_margin;
- break;
- case 64772: /* Kodak P-series */
- fseek (ifp, 16, SEEK_CUR);
- data_offset = get4();
- fseek (ifp, 28, SEEK_CUR);
- data_offset += get4();
- load_raw = &CLASS packed_12_load_raw;
- }
- fseek (ifp, save, SEEK_SET);
- }
- if (sony_length && (buf = (unsigned *) malloc(sony_length))) {
- fseek (ifp, sony_offset, SEEK_SET);
- fread (buf, sony_length, 1, ifp);
- sony_decrypt (buf, sony_length/4, 1, sony_key);
-#ifndef LIBRAW_LIBRARY_BUILD
- sfp = ifp;
- if ((ifp = tmpfile())) {
- fwrite (buf, sony_length, 1, ifp);
- fseek (ifp, 0, SEEK_SET);
- parse_tiff_ifd (-sony_offset);
- fclose (ifp);
- }
- ifp = sfp;
-#else
- if( !ifp->tempbuffer_open(buf,sony_length))
- {
- parse_tiff_ifd(-sony_offset);
- ifp->tempbuffer_close();
- }
-#endif
- free (buf);
- }
- for (i=0; i < colors; i++)
- FORCC cc[i][c] *= ab[i];
- if (use_cm) {
- FORCC for (i=0; i < 3; i++)
- for (cam_xyz[c][i]=j=0; j < colors; j++)
- cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i];
- cam_xyz_coeff (cam_xyz);
- }
- if (asn[0]) {
- cam_mul[3] = 0;
- FORCC cam_mul[c] = 1 / asn[c];
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if (!use_cm)
- {
- FORCC pre_mul[c] /= cc[c][c];
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
-
- return 0;
-}
-
-void CLASS parse_tiff (int base)
-{
- int doff, max_samp=0, raw=-1, thm=-1, i;
- struct jhead jh;
-
- fseek (ifp, base, SEEK_SET);
- order = get2();
- if (order != 0x4949 && order != 0x4d4d) return;
- get2();
- memset (tiff_ifd, 0, sizeof tiff_ifd);
- tiff_nifds = 0;
- while ((doff = get4())) {
- fseek (ifp, doff+base, SEEK_SET);
- if (parse_tiff_ifd (base)) break;
- }
- thumb_misc = 16;
- if (thumb_offset) {
- fseek (ifp, thumb_offset, SEEK_SET);
- if (ljpeg_start (&jh, 1)) {
- thumb_misc = jh.bits;
- thumb_width = jh.wide;
- thumb_height = jh.high;
- }
- }
- for (i=0; i < tiff_nifds; i++) {
- if (max_samp < tiff_ifd[i].samples)
- max_samp = tiff_ifd[i].samples;
- if (max_samp > 3) max_samp = 3;
- if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) &&
- tiff_ifd[i].t_width*tiff_ifd[i].t_height > raw_width*raw_height) {
- raw_width = tiff_ifd[i].t_width;
- raw_height = tiff_ifd[i].t_height;
- tiff_bps = tiff_ifd[i].bps;
- tiff_compress = tiff_ifd[i].comp;
- data_offset = tiff_ifd[i].offset;
- tiff_flip = tiff_ifd[i].t_flip;
- tiff_samples = tiff_ifd[i].samples;
- raw = i;
- }
- }
- fuji_width *= (raw_width+1)/2;
- if (tiff_ifd[0].t_flip) tiff_flip = tiff_ifd[0].t_flip;
- if (raw >= 0 && !load_raw)
- switch (tiff_compress) {
- case 0: case 1:
- switch (tiff_bps) {
- case 8: load_raw = &CLASS eight_bit_load_raw; break;
- case 12: load_raw = &CLASS packed_12_load_raw;
- if (tiff_ifd[raw].phint == 2)
- load_flags = 6;
- if (strncmp(make,"PENTAX",6)) break;
- case 14:
- case 16: load_raw = &CLASS unpacked_load_raw; break;
- }
- if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8)
- load_raw = &CLASS olympus_e300_load_raw;
- break;
- case 6: case 7: case 99:
- load_raw = &CLASS lossless_jpeg_load_raw; break;
- case 262:
- load_raw = &CLASS kodak_262_load_raw; break;
- case 32767:
- load_raw = &CLASS sony_arw2_load_raw;
- if (tiff_ifd[raw].bytes*8 == raw_width*raw_height*tiff_bps)
- break;
- raw_height += 8;
- load_raw = &CLASS sony_arw_load_raw; break;
- case 32769:
- load_flags = 8;
- case 32773:
- load_raw = &CLASS packed_12_load_raw; break;
- case 34713:
- load_raw = &CLASS nikon_compressed_load_raw; break;
- case 65535:
- load_raw = &CLASS pentax_k10_load_raw; break;
- case 65000:
- switch (tiff_ifd[raw].phint) {
- case 2: load_raw = &CLASS kodak_rgb_load_raw; filters = 0; break;
- case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0; break;
- case 32803: load_raw = &CLASS kodak_65000_load_raw;
- }
- case 32867: break;
- default: is_raw = 0;
- }
- if (!dng_version && tiff_samples == 3)
- if (tiff_ifd[raw].bytes && tiff_bps != 14 && tiff_bps != 2048)
- is_raw = 0;
- if (!dng_version && tiff_bps == 8 && tiff_compress == 1 &&
- tiff_ifd[raw].phint == 1) is_raw = 0;
- if (tiff_bps == 8 && tiff_samples == 4) is_raw = 0;
- for (i=0; i < tiff_nifds; i++)
- if (i != raw && tiff_ifd[i].samples == max_samp &&
- tiff_ifd[i].t_width * tiff_ifd[i].t_height / SQR(tiff_ifd[i].bps+1) >
- thumb_width * thumb_height / SQR(thumb_misc+1)) {
- thumb_width = tiff_ifd[i].t_width;
- thumb_height = tiff_ifd[i].t_height;
- thumb_offset = tiff_ifd[i].offset;
- thumb_length = tiff_ifd[i].bytes;
- thumb_misc = tiff_ifd[i].bps;
- thm = i;
- }
- if (thm >= 0) {
- thumb_misc |= tiff_ifd[thm].samples << 5;
- switch (tiff_ifd[thm].comp) {
- case 0:
- write_thumb = &CLASS layer_thumb;
- break;
- case 1:
- if (tiff_ifd[thm].bps > 8)
- thumb_load_raw = &CLASS kodak_thumb_load_raw;
- else
- write_thumb = &CLASS ppm_thumb;
- break;
- case 65000:
- thumb_load_raw = tiff_ifd[thm].phint == 6 ?
- &CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw;
- }
- }
-}
-
-void CLASS parse_minolta (int base)
-{
- int save, tag, len, offset, high=0, wide=0, i, c;
- short sorder=order;
-
- fseek (ifp, base, SEEK_SET);
- if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return;
- order = fgetc(ifp) * 0x101;
- offset = base + get4() + 8;
- while ((save=ftell(ifp)) < offset) {
- for (tag=i=0; i < 4; i++)
- tag = tag << 8 | fgetc(ifp);
- len = get4();
- switch (tag) {
- case 0x505244: /* PRD */
- fseek (ifp, 8, SEEK_CUR);
- high = get2();
- wide = get2();
- break;
- case 0x574247: /* WBG */
- get4();
- i = strcmp(model,"DiMAGE A200") ? 0:3;
- FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- break;
- case 0x545457: /* TTW */
- parse_tiff (ftell(ifp));
- data_offset = offset;
- }
- fseek (ifp, save+len+8, SEEK_SET);
- }
- raw_height = high;
- raw_width = wide;
- order = sorder;
-}
-
-/*
- Many cameras have a "debug mode" that writes JPEG and raw
- at the same time. The raw file has no header, so try to
- to open the matching JPEG file and read its metadata.
- */
-void CLASS parse_external_jpeg()
-{
- char *file, *ext, *jname, *jfile, *jext;
-#ifndef LIBRAW_LIBRARY_BUILD
- FILE *save=ifp;
-#else
- if(!ifp->fname())
- {
- imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
- return;
- }
-#endif
-
- ext = strrchr (ifname, '.');
- file = strrchr (ifname, '/');
- if (!file) file = strrchr (ifname, '\\');
-#ifndef LIBRAW_LIBRARY_BUILD
- if (!file) file = ifname-1;
-#else
- if (!file) file = (char*)ifname-1;
-#endif
- file++;
- if (!ext || strlen(ext) != 4 || ext-file != 8) return;
- jname = (char *) malloc (strlen(ifname) + 1);
- merror (jname, "parse_external_jpeg()");
- strcpy (jname, ifname);
- jfile = file - ifname + jname;
- jext = ext - ifname + jname;
- if (strcasecmp (ext, ".jpg")) {
- strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
- if (isdigit(*file)) {
- memcpy (jfile, file+4, 4);
- memcpy (jfile+4, file, 4);
- }
- } else
- while (isdigit(*--jext)) {
- if (*jext != '9') {
- (*jext)++;
- break;
- }
- *jext = '0';
- }
-#ifndef LIBRAW_LIBRARY_BUILD
- if (strcmp (jname, ifname)) {
- if ((ifp = fopen (jname, "rb"))) {
-#ifdef DCRAW_VERBOSE
- if (verbose)
- fprintf (stderr,_("Reading metadata from %s ...\n"), jname);
-#endif
- parse_tiff (12);
- thumb_offset = 0;
- is_raw = 1;
- fclose (ifp);
- }
- }
-#else
- if (strcmp (jname, ifname))
- {
- if(!ifp->subfile_open(jname))
- {
- parse_tiff (12);
- thumb_offset = 0;
- is_raw = 1;
- ifp->subfile_close();
- }
- else
- imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
- }
-#endif
- if (!timestamp)
- {
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
-#endif
-#ifdef DCRAW_VERBOSE
- fprintf (stderr,_("Failed to read metadata from %s\n"), jname);
-#endif
- }
- free (jname);
-#ifndef LIBRAW_LIBRARY_BUILD
- ifp = save;
-#endif
-}
-
-/*
- CIFF block 0x1030 contains an 8x8 white sample.
- Load this into white[][] for use in scale_colors().
- */
-void CLASS ciff_block_1030()
-{
- static const ushort key[] = { 0x410, 0x45f3 };
- int i, bpp, row, col, vbits=0;
- unsigned long bitbuf=0;
-
- if ((get2(),get4()) != 0x80008 || !get4()) return;
- bpp = get2();
- if (bpp != 10 && bpp != 12) return;
- for (i=row=0; row < 8; row++)
- for (col=0; col < 8; col++) {
- if (vbits < bpp) {
- bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
- vbits += 16;
- }
- white[row][col] =
- bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
- vbits -= bpp;
- }
-}
-
-/*
- Parse a CIFF file, better known as Canon CRW format.
- */
-void CLASS parse_ciff (int offset, int length)
-{
- int tboff, nrecs, c, type, len, save, wbi=-1;
- ushort key[] = { 0x410, 0x45f3 };
-
- fseek (ifp, offset+length-4, SEEK_SET);
- tboff = get4() + offset;
- fseek (ifp, tboff, SEEK_SET);
- nrecs = get2();
- if (nrecs > 100) return;
- while (nrecs--) {
- type = get2();
- len = get4();
- save = ftell(ifp) + 4;
- fseek (ifp, offset+get4(), SEEK_SET);
- if ((((type >> 8) + 8) | 8) == 0x38)
- parse_ciff (ftell(ifp), len); /* Parse a sub-table */
-
- if (type == 0x0810)
- fread (artist, 64, 1, ifp);
- if (type == 0x080a) {
- fread (make, 64, 1, ifp);
- fseek (ifp, strlen(make) - 63, SEEK_CUR);
- fread (model, 64, 1, ifp);
- }
- if (type == 0x1810) {
- fseek (ifp, 12, SEEK_CUR);
- flip = get4();
- }
- if (type == 0x1835) /* Get the decoder table */
- tiff_compress = get4();
- if (type == 0x2007) {
- thumb_offset = ftell(ifp);
- thumb_length = len;
- }
- if (type == 0x1818) {
- shutter = pow (2.0f, -int_to_float((get4(),get4())));
- aperture = pow (2.0f, int_to_float(get4())/2);
- }
- if (type == 0x102a) {
- iso_speed = pow (2, (get4(),get2())/32.0 - 4) * 50;
- aperture = pow (2, (get2(),(short)get2())/64.0);
- shutter = pow (2,-((short)get2())/32.0);
- wbi = (get2(),get2());
- if (wbi > 17) wbi = 0;
- fseek (ifp, 32, SEEK_CUR);
- if (shutter > 1e6) shutter = get2()/10.0;
- }
- if (type == 0x102c) {
- if (get2() > 512) { /* Pro90, G1 */
- fseek (ifp, 118, SEEK_CUR);
- FORC4 cam_mul[c ^ 2] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- } else { /* G2, S30, S40 */
- fseek (ifp, 98, SEEK_CUR);
- FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- }
- if (type == 0x0032) {
- if (len == 768) { /* EOS D30 */
- fseek (ifp, 72, SEEK_CUR);
- FORC4 cam_mul[c ^ (c >> 1)] = 1024.0 / get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- if (!wbi) cam_mul[0] = -1; /* use my auto white balance */
- } else if (!cam_mul[0]) {
- if (get2() == key[0]) /* Pro1, G6, S60, S70 */
- c = (strstr(model,"Pro1") ?
- "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2;
- else { /* G3, G5, S45, S50 */
- c = "023457000000006000"[wbi]-'0';
- key[0] = key[1] = 0;
- }
- fseek (ifp, 78 + c*8, SEEK_CUR);
- FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2() ^ key[c & 1];
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- if (!wbi) cam_mul[0] = -1;
- }
- }
- if (type == 0x10a9) { /* D60, 10D, 300D, and clones */
- if (len > 66) wbi = "0134567028"[wbi]-'0';
- fseek (ifp, 2 + wbi*8, SEEK_CUR);
- FORC4 cam_mul[c ^ (c >> 1)] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- if (type == 0x1030 && (0x18040 >> wbi & 1))
- ciff_block_1030(); /* all that don't have 0x10a9 */
- if (type == 0x1031) {
- raw_width = (get2(),get2());
- raw_height = get2();
- }
- if (type == 0x5029) {
- focal_len = len >> 16;
- if ((len & 0xffff) == 2) focal_len /= 32;
- }
- if (type == 0x5813) flash_used = int_to_float(len);
- if (type == 0x5814) canon_ev = int_to_float(len);
- if (type == 0x5817) shot_order = len;
- if (type == 0x5834) unique_id = len;
- if (type == 0x580e) timestamp = len;
- if (type == 0x180e) timestamp = get4();
-#ifdef LOCALTIME
- if ((type | 0x4000) == 0x580e)
- timestamp = mktime (gmtime (&timestamp));
-#endif
- fseek (ifp, save, SEEK_SET);
- }
-}
-
-void CLASS parse_rollei()
-{
- char line[128], *val;
- struct tm t;
-
- fseek (ifp, 0, SEEK_SET);
- memset (&t, 0, sizeof t);
- do {
- fgets (line, 128, ifp);
- if ((val = strchr(line,'=')))
- *val++ = 0;
- else
- val = line + strlen(line);
- if (!strcmp(line,"DAT"))
- sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
- if (!strcmp(line,"TIM"))
- sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
- if (!strcmp(line,"HDR"))
- thumb_offset = atoi(val);
- if (!strcmp(line,"X "))
- raw_width = atoi(val);
- if (!strcmp(line,"Y "))
- raw_height = atoi(val);
- if (!strcmp(line,"TX "))
- thumb_width = atoi(val);
- if (!strcmp(line,"TY "))
- thumb_height = atoi(val);
- } while (strncmp(line,"EOHD",4));
- data_offset = thumb_offset + thumb_width * thumb_height * 2;
- t.tm_year -= 1900;
- t.tm_mon -= 1;
- if (mktime(&t) > 0)
- timestamp = mktime(&t);
- strcpy (make, "Rollei");
- strcpy (model,"d530flex");
- write_thumb = &CLASS rollei_thumb;
-}
-
-void CLASS parse_sinar_ia()
-{
- int entries, off;
- char str[8], *cp;
-
- order = 0x4949;
- fseek (ifp, 4, SEEK_SET);
- entries = get4();
- fseek (ifp, get4(), SEEK_SET);
- while (entries--) {
- off = get4(); get4();
- fread (str, 8, 1, ifp);
- if (!strcmp(str,"META")) meta_offset = off;
- if (!strcmp(str,"THUMB")) thumb_offset = off;
- if (!strcmp(str,"RAW0")) data_offset = off;
- }
- fseek (ifp, meta_offset+20, SEEK_SET);
- fread (make, 64, 1, ifp);
- make[63] = 0;
- if ((cp = strchr(make,' '))) {
- strcpy (model, cp+1);
- *cp = 0;
- }
- raw_width = get2();
- raw_height = get2();
- load_raw = &CLASS unpacked_load_raw;
- thumb_width = (get4(),get2());
- thumb_height = get2();
- write_thumb = &CLASS ppm_thumb;
- maximum = 0x3fff;
-}
-
-void CLASS parse_phase_one (int base)
-{
- unsigned entries, tag, type, len, data, save, i, c;
- float romm_cam[3][3];
- char *cp;
-
- memset (&ph1, 0, sizeof ph1);
- fseek (ifp, base, SEEK_SET);
- order = get4() & 0xffff;
- if (get4() >> 8 != 0x526177) return; /* "Raw" */
- fseek (ifp, get4()+base, SEEK_SET);
- entries = get4();
- get4();
- while (entries--) {
- tag = get4();
- type = get4();
- len = get4();
- data = get4();
- save = ftell(ifp);
- fseek (ifp, base+data, SEEK_SET);
- switch (tag) {
- case 0x100: flip = "0653"[data & 3]-'0'; break;
- case 0x106:
- for (i=0; i < 9; i++)
- romm_cam[0][i] = getreal(11);
- romm_coeff (romm_cam);
- break;
- case 0x107:
- FORC3 cam_mul[c] = getreal(11);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- break;
- case 0x108: raw_width = data; break;
- case 0x109: raw_height = data; break;
- case 0x10a: left_margin = data; break;
- case 0x10b: top_margin = data; break;
- case 0x10c: width = data; break;
- case 0x10d: height = data; break;
- case 0x10e: ph1.format = data; break;
- case 0x10f: data_offset = data+base; break;
- case 0x110: meta_offset = data+base;
- meta_length = len; break;
- case 0x112: ph1.key_off = save - 4; break;
- case 0x210: ph1.tag_210 = int_to_float(data); break;
- case 0x21a: ph1.tag_21a = data; break;
- case 0x21c: strip_offset = data+base; break;
- case 0x21d: ph1.t_black = data; break;
- case 0x222: ph1.split_col = data - left_margin; break;
- case 0x223: ph1.black_off = data+base; break;
- case 0x301:
- model[63] = 0;
- fread (model, 1, 63, ifp);
- if ((cp = strstr(model," camera"))) *cp = 0;
- }
- fseek (ifp, save, SEEK_SET);
- }
- load_raw = ph1.format < 3 ?
- &CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c;
- maximum = 0xffff;
- strcpy (make, "Phase One");
- if (model[0]) return;
- switch (raw_height) {
- case 2060: strcpy (model,"LightPhase"); break;
- case 2682: strcpy (model,"H 10"); break;
- case 4128: strcpy (model,"H 20"); break;
- case 5488: strcpy (model,"H 25"); break;
- }
-}
-
-void CLASS parse_fuji (int offset)
-{
- unsigned entries, tag, len, save, c;
-
- fseek (ifp, offset, SEEK_SET);
- entries = get4();
- if (entries > 255) return;
- while (entries--) {
- tag = get2();
- len = get2();
- save = ftell(ifp);
- if (tag == 0x100) {
- raw_height = get2();
- raw_width = get2();
- } else if (tag == 0x121) {
- height = get2();
- if ((width = get2()) == 4284) width += 3;
- } else if (tag == 0x130)
- fuji_layout = fgetc(ifp) >> 7;
- if (tag == 0x2ff0)
- {
- FORC4 cam_mul[c ^ 1] = get2();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- }
- fseek (ifp, save+len, SEEK_SET);
- }
- height <<= fuji_layout;
- width >>= fuji_layout;
-}
-
-int CLASS parse_jpeg (int offset)
-{
- int len, save, hlen, mark;
-
- fseek (ifp, offset, SEEK_SET);
- if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return 0;
-
- while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) {
- order = 0x4d4d;
- len = get2() - 2;
- save = ftell(ifp);
- if (mark == 0xc0 || mark == 0xc3) {
- fgetc(ifp);
- raw_height = get2();
- raw_width = get2();
- }
- order = get2();
- hlen = get4();
- if (get4() == 0x48454150) /* "HEAP" */
- parse_ciff (save+hlen, len-hlen);
- parse_tiff (save+6);
- fseek (ifp, save+len, SEEK_SET);
- }
- return 1;
-}
-
-void CLASS parse_riff()
-{
- unsigned i, size, end;
- char tag[4], date[64], month[64];
- static const char mon[12][4] =
- { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
- struct tm t;
-
- order = 0x4949;
- fread (tag, 4, 1, ifp);
- size = get4();
- end = ftell(ifp) + size;
- if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) {
- get4();
- while (ftell(ifp)+7 < end)
- parse_riff();
- } else if (!memcmp(tag,"nctg",4)) {
- while (ftell(ifp)+7 < end) {
- i = get2();
- size = get2();
- if ((i+1) >> 1 == 10 && size == 20)
- get_timestamp(0);
- else fseek (ifp, size, SEEK_CUR);
- }
- } else if (!memcmp(tag,"IDIT",4) && size < 64) {
- fread (date, 64, 1, ifp);
- date[size] = 0;
- memset (&t, 0, sizeof t);
- if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday,
- &t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) {
- for (i=0; i < 12 && strcasecmp(mon[i],month); i++);
- t.tm_mon = i;
- t.tm_year -= 1900;
- if (mktime(&t) > 0)
- timestamp = mktime(&t);
- }
- } else
- fseek (ifp, size, SEEK_CUR);
-}
-
-void CLASS parse_smal (int offset, int fsize)
-{
- int ver;
-
- fseek (ifp, offset+2, SEEK_SET);
- order = 0x4949;
- ver = fgetc(ifp);
- if (ver == 6)
- fseek (ifp, 5, SEEK_CUR);
- if (get4() != fsize) return;
- if (ver > 6) data_offset = get4();
- raw_height = height = get2();
- raw_width = width = get2();
- strcpy (make, "SMaL");
- sprintf (model, "v%d %dx%d", ver, width, height);
- if (ver == 6) load_raw = &CLASS smal_v6_load_raw;
- if (ver == 9) load_raw = &CLASS smal_v9_load_raw;
-}
-
-void CLASS parse_cine()
-{
- unsigned off_head, off_setup, off_image, i;
-
- order = 0x4949;
- fseek (ifp, 4, SEEK_SET);
- is_raw = get2() == 2;
- fseek (ifp, 14, SEEK_CUR);
- is_raw *= get4();
- off_head = get4();
- off_setup = get4();
- off_image = get4();
- timestamp = get4();
- if ((i = get4())) timestamp = i;
- fseek (ifp, off_head+4, SEEK_SET);
- raw_width = get4();
- raw_height = get4();
- switch (get2(),get2()) {
- case 8: load_raw = &CLASS eight_bit_load_raw; break;
- case 16: load_raw = &CLASS unpacked_load_raw;
- }
- fseek (ifp, off_setup+792, SEEK_SET);
- strcpy (make, "CINE");
- sprintf (model, "%d", get4());
- fseek (ifp, 12, SEEK_CUR);
- switch ((i=get4()) & 0xffffff) {
- case 3: filters = 0x94949494; break;
- case 4: filters = 0x49494949; break;
- default: is_raw = 0;
- }
- fseek (ifp, 72, SEEK_CUR);
- switch ((get4()+3600) % 360) {
- case 270: flip = 4; break;
- case 180: flip = 1; break;
- case 90: flip = 7; break;
- case 0: flip = 2;
- }
- cam_mul[0] = getreal(11);
- cam_mul[2] = getreal(11);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- maximum = ~(-1 << get4());
- fseek (ifp, 668, SEEK_CUR);
- shutter = get4()/1000000000.0;
- fseek (ifp, off_image, SEEK_SET);
- if (shot_select < is_raw)
- fseek (ifp, shot_select*8, SEEK_CUR);
- data_offset = (INT64) get4() + 8;
- data_offset += (INT64) get4() << 32;
-}
-#ifdef LIBRAW_LIBRARY_BUILD
-void CLASS adobe_coeff (const char *p_make, const char *p_model)
-#else
-void CLASS adobe_coeff (char *p_make, char *p_model)
-#endif
-{
- static const struct {
- const char *prefix;
- unsigned short t_black, t_maximum;
- short trans[12];
- } table[] = {
- { "Apple QuickTake", 0, 0, /* DJC */
- { 17576,-3191,-3318,5210,6733,-1942,9031,1280,-124 } },
- { "Canon EOS D2000", 0, 0,
- { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
- { "Canon EOS D6000", 0, 0,
- { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
- { "Canon EOS D30", 0, 0,
- { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } },
- { "Canon EOS D60", 0, 0xfa0,
- { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } },
- { "Canon EOS 5D Mark II", 0, 0x3cf0,
- { 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } },
- { "Canon EOS 5D", 0, 0xe6c,
- { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } },
- { "Canon EOS 10D", 0, 0xfa0,
- { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
- { "Canon EOS 20Da", 0, 0,
- { 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } },
- { "Canon EOS 20D", 0, 0xfff,
- { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } },
- { "Canon EOS 30D", 0, 0,
- { 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } },
- { "Canon EOS 40D", 0, 0x3f60,
- { 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } },
- { "Canon EOS 50D", 0, 0x3d93,
- { 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } },
- { "Canon EOS 300D", 0, 0xfa0,
- { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
- { "Canon EOS 350D", 0, 0xfff,
- { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
- { "Canon EOS 400D", 0, 0xe8e,
- { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
- { "Canon EOS 450D", 0, 0x390d,
- { 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } },
- { "Canon EOS 1000D", 0, 0xe43,
- { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } },
- { "Canon EOS-1Ds Mark III", 0, 0x3bb0,
- { 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } },
- { "Canon EOS-1Ds Mark II", 0, 0xe80,
- { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } },
- { "Canon EOS-1D Mark II N", 0, 0xe80,
- { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
- { "Canon EOS-1D Mark III", 0, 0x3bb0,
- { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } },
- { "Canon EOS-1D Mark II", 0, 0xe80,
- { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } },
- { "Canon EOS-1DS", 0, 0xe20,
- { 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } },
- { "Canon EOS-1D", 0, 0xe20,
- { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
- { "Canon EOS", 0, 0,
- { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
- { "Canon PowerShot A50", 0, 0,
- { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } },
- { "Canon PowerShot A5", 0, 0,
- { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } },
- { "Canon PowerShot G10", 0, 0,
- { 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } },
- { "Canon PowerShot G1", 0, 0,
- { -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } },
- { "Canon PowerShot G2", 0, 0,
- { 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } },
- { "Canon PowerShot G3", 0, 0,
- { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } },
- { "Canon PowerShot G5", 0, 0,
- { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } },
- { "Canon PowerShot G6", 0, 0,
- { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } },
- { "Canon PowerShot G9", 0, 0,
- { 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } },
- { "Canon PowerShot Pro1", 0, 0,
- { 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } },
- { "Canon PowerShot Pro70", 34, 0,
- { -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } },
- { "Canon PowerShot Pro90", 0, 0,
- { -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } },
- { "Canon PowerShot S30", 0, 0,
- { 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } },
- { "Canon PowerShot S40", 0, 0,
- { 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } },
- { "Canon PowerShot S45", 0, 0,
- { 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } },
- { "Canon PowerShot S50", 0, 0,
- { 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } },
- { "Canon PowerShot S60", 0, 0,
- { 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } },
- { "Canon PowerShot S70", 0, 0,
- { 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } },
- { "Canon PowerShot A610", 0, 0, /* DJC */
- { 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } },
- { "Canon PowerShot A620", 0, 0, /* DJC */
- { 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } },
- { "Canon PowerShot A630", 0, 0, /* DJC */
- { 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } },
- { "Canon PowerShot A640", 0, 0, /* DJC */
- { 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } },
- { "Canon PowerShot A650", 0, 0, /* DJC */
- { 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } },
- { "Canon PowerShot A720", 0, 0, /* DJC */
- { 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } },
- { "Canon PowerShot S3 IS", 0, 0, /* DJC */
- { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } },
- { "CINE 650", 0, 0,
- { 3390,480,-500,-800,3610,340,-550,2336,1192 } },
- { "CINE 660", 0, 0,
- { 3390,480,-500,-800,3610,340,-550,2336,1192 } },
- { "CINE", 0, 0,
- { 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } },
- { "Contax N Digital", 0, 0xf1e,
- { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } },
- { "EPSON R-D1", 0, 0,
- { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } },
- { "FUJIFILM FinePix E550", 0, 0,
- { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
- { "FUJIFILM FinePix E900", 0, 0,
- { 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
- { "FUJIFILM FinePix F8", 0, 0,
- { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
- { "FUJIFILM FinePix F7", 0, 0,
- { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
- { "FUJIFILM FinePix S100FS", 514, 0,
- { 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } },
- { "FUJIFILM FinePix S20Pro", 0, 0,
- { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
- { "FUJIFILM FinePix S2Pro", 128, 0,
- { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } },
- { "FUJIFILM FinePix S3Pro", 0, 0,
- { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
- { "FUJIFILM FinePix S5Pro", 0, 0,
- { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
- { "FUJIFILM FinePix S5000", 0, 0,
- { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
- { "FUJIFILM FinePix S5100", 0, 0x3e00,
- { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
- { "FUJIFILM FinePix S5500", 0, 0x3e00,
- { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
- { "FUJIFILM FinePix S5200", 0, 0,
- { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
- { "FUJIFILM FinePix S5600", 0, 0,
- { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
- { "FUJIFILM FinePix S6", 0, 0,
- { 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
- { "FUJIFILM FinePix S7000", 0, 0,
- { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
- { "FUJIFILM FinePix S9000", 0, 0,
- { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
- { "FUJIFILM FinePix S9500", 0, 0,
- { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
- { "FUJIFILM FinePix S9100", 0, 0,
- { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
- { "FUJIFILM FinePix S9600", 0, 0,
- { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
- { "FUJIFILM IS-1", 0, 0,
- { 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } },
- { "FUJIFILM IS Pro", 0, 0,
- { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
- { "Imacon Ixpress", 0, 0, /* DJC */
- { 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } },
- { "KODAK NC2000", 0, 0,
- { 13891,-6055,-803,-465,9919,642,2121,82,1291 } },
- { "Kodak DCS315C", 8, 0,
- { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } },
- { "Kodak DCS330C", 8, 0,
- { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } },
- { "KODAK DCS420", 0, 0,
- { 10868,-1852,-644,-1537,11083,484,2343,628,2216 } },
- { "KODAK DCS460", 0, 0,
- { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
- { "KODAK EOSDCS1", 0, 0,
- { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
- { "KODAK EOSDCS3B", 0, 0,
- { 9898,-2700,-940,-2478,12219,206,1985,634,1031 } },
- { "Kodak DCS520C", 180, 0,
- { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
- { "Kodak DCS560C", 188, 0,
- { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
- { "Kodak DCS620C", 180, 0,
- { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
- { "Kodak DCS620X", 185, 0,
- { 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
- { "Kodak DCS660C", 214, 0,
- { 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } },
- { "Kodak DCS720X", 0, 0,
- { 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } },
- { "Kodak DCS760C", 0, 0,
- { 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } },
- { "Kodak DCS Pro SLR", 0, 0,
- { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
- { "Kodak DCS Pro 14nx", 0, 0,
- { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
- { "Kodak DCS Pro 14", 0, 0,
- { 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } },
- { "Kodak ProBack645", 0, 0,
- { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } },
- { "Kodak ProBack", 0, 0,
- { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } },
- { "KODAK P712", 0, 0,
- { 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } },
- { "KODAK P850", 0, 0xf7c,
- { 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } },
- { "KODAK P880", 0, 0xfff,
- { 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } },
- { "Leaf CMost", 0, 0,
- { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
- { "Leaf Valeo 6", 0, 0,
- { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
- { "Leaf Aptus 54S", 0, 0,
- { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
- { "Leaf Aptus 65", 0, 0,
- { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
- { "Leaf Aptus 75", 0, 0,
- { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
- { "Leaf", 0, 0,
- { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
- { "Mamiya ZD", 0, 0,
- { 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } },
- { "Micron 2010", 110, 0, /* DJC */
- { 16695,-3761,-2151,155,9682,163,3433,951,4904 } },
- { "Minolta DiMAGE 5", 0, 0xf7d,
- { 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } },
- { "Minolta DiMAGE 7Hi", 0, 0xf7d,
- { 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } },
- { "Minolta DiMAGE 7", 0, 0xf7d,
- { 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } },
- { "Minolta DiMAGE A1", 0, 0xf8b,
- { 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } },
- { "MINOLTA DiMAGE A200", 0, 0,
- { 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } },
- { "Minolta DiMAGE A2", 0, 0xf8f,
- { 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } },
- { "Minolta DiMAGE Z2", 0, 0, /* DJC */
- { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
- { "MINOLTA DYNAX 5", 0, 0xffb,
- { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } },
- { "MINOLTA DYNAX 7", 0, 0xffb,
- { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } },
- { "NIKON D100", 0, 0,
- { 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } },
- { "NIKON D1H", 0, 0,
- { 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } },
- { "NIKON D1X", 0, 0,
- { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } },
- { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */
- { 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } },
- { "NIKON D2H", 0, 0,
- { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } },
- { "NIKON D2X", 0, 0,
- { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } },
- { "NIKON D40X", 0, 0,
- { 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } },
- { "NIKON D40", 0, 0,
- { 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } },
- { "NIKON D50", 0, 0,
- { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
- { "NIKON D60", 0, 0,
- { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
- { "NIKON D700", 0, 0,
- { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
- { "NIKON D70", 0, 0,
- { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
- { "NIKON D80", 0, 0,
- { 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } },
- { "NIKON D90", 0, 0xf00,
- { 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } },
- { "NIKON D200", 0, 0xfbc,
- { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
- { "NIKON D300", 0, 0,
- { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } },
- { "NIKON D3", 0, 0,
- { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
- { "NIKON E950", 0, 0x3dd, /* DJC */
- { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
- { "NIKON E995", 0, 0, /* copied from E5000 */
- { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
- { "NIKON E2100", 0, 0, /* copied from Z2, new white balance */
- { 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} },
- { "NIKON E2500", 0, 0,
- { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
- { "NIKON E4300", 0, 0, /* copied from Minolta DiMAGE Z2 */
- { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
- { "NIKON E4500", 0, 0,
- { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
- { "NIKON E5000", 0, 0,
- { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
- { "NIKON E5400", 0, 0,
- { 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } },
- { "NIKON E5700", 0, 0,
- { -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } },
- { "NIKON E8400", 0, 0,
- { 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } },
- { "NIKON E8700", 0, 0,
- { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
- { "NIKON E8800", 0, 0,
- { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } },
- { "NIKON COOLPIX P6000", 0, 0,
- { 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } },
- { "OLYMPUS C5050", 0, 0,
- { 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } },
- { "OLYMPUS C5060", 0, 0,
- { 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } },
- { "OLYMPUS C7070", 0, 0,
- { 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } },
- { "OLYMPUS C70", 0, 0,
- { 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } },
- { "OLYMPUS C80", 0, 0,
- { 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } },
- { "OLYMPUS E-10", 0, 0xffc0,
- { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
- { "OLYMPUS E-1", 0, 0xfff0,
- { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
- { "OLYMPUS E-20", 0, 0xffc0,
- { 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } },
- { "OLYMPUS E-300", 0, 0,
- { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
- { "OLYMPUS E-330", 0, 0,
- { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
- { "OLYMPUS E-3", 0, 0xf99,
- { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } },
- { "OLYMPUS E-400", 0, 0xfff0,
- { 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
- { "OLYMPUS E-410", 0, 0xf6a,
- { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
- { "OLYMPUS E-420", 0, 0xfd7,
- { 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } },
- { "OLYMPUS E-500", 0, 0,
- { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
- { "OLYMPUS E-510", 0, 0xf6a,
- { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } },
- { "OLYMPUS E-520", 0, 0xfd2,
- { 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } },
- { "OLYMPUS SP350", 0, 0,
- { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
- { "OLYMPUS SP3", 0, 0,
- { 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } },
- { "OLYMPUS SP500UZ", 0, 0xfff,
- { 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
- { "OLYMPUS SP510UZ", 0, 0xffe,
- { 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
- { "OLYMPUS SP550UZ", 0, 0xffe,
- { 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } },
- { "OLYMPUS SP560UZ", 0, 0xff9,
- { 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } },
- { "OLYMPUS SP570UZ", 0, 0,
- { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } },
- { "PENTAX *ist DL2", 0, 0,
- { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
- { "PENTAX *ist DL", 0, 0,
- { 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } },
- { "PENTAX *ist DS2", 0, 0,
- { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
- { "PENTAX *ist DS", 0, 0,
- { 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } },
- { "PENTAX *ist D", 0, 0,
- { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } },
- { "PENTAX K10D", 0, 0,
- { 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } },
- { "PENTAX K1", 0, 0,
- { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } },
- { "PENTAX K20D", 0, 0,
- { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
- { "PENTAX K200D", 0, 0,
- { 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } },
- { "PENTAX K2000", 0, 0,
- { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
- { "PENTAX K-m", 0, 0,
- { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
- { "Panasonic DMC-FZ8", 0, 0xf7f0,
- { 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } },
- { "Panasonic DMC-FZ18", 0, 0,
- { 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } },
- { "Panasonic DMC-FZ28", 15, 0xfff,
- { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
- { "Panasonic DMC-FZ30", 0, 0xf94c,
- { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
- { "Panasonic DMC-FZ50", 0, 0xfff0, /* aka "LEICA V-LUX1" */
- { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
- { "Panasonic DMC-L10", 15, 0xf96,
- { 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } },
- { "Panasonic DMC-L1", 0, 0xf7fc, /* aka "LEICA DIGILUX 3" */
- { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
- { "Panasonic DMC-LC1", 0, 0, /* aka "LEICA DIGILUX 2" */
- { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
- { "Panasonic DMC-LX1", 0, 0xf7f0, /* aka "LEICA D-LUX2" */
- { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
- { "Panasonic DMC-LX2", 0, 0, /* aka "LEICA D-LUX3" */
- { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
- { "Panasonic DMC-LX3", 15, 0xfff, /* aka "LEICA D-LUX4" */
- { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
- { "Panasonic DMC-FX150", 15, 0xfff,
- { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } },
- { "Panasonic DMC-G1", 15, 0xfff,
- { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
- { "Phase One H 20", 0, 0, /* DJC */
- { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } },
- { "Phase One P 2", 0, 0,
- { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
- { "Phase One P 30", 0, 0,
- { 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } },
- { "Phase One P 45", 0, 0,
- { 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } },
- { "SAMSUNG GX-1", 0, 0,
- { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
- { "Sinar", 0, 0, /* DJC */
- { 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } },
- { "SONY DSC-F828", 491, 0,
- { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } },
- { "SONY DSC-R1", 512, 0,
- { 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } },
- { "SONY DSC-V3", 0, 0,
- { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } },
- { "SONY DSLR-A100", 0, 0xfeb,
- { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } },
- { "SONY DSLR-A200", 0, 0,
- { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
- { "SONY DSLR-A300", 0, 0,
- { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
- { "SONY DSLR-A350", 0, 0xffc,
- { 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } },
- { "SONY DSLR-A700", 254, 0x1ffe,
- { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } },
- { "SONY DSLR-A900", 254, 0x1ffe,
- { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }
- };
- double cam_xyz[4][3];
- char name[130];
- int i, j;
-
- sprintf (name, "%s %s", p_make, p_model);
- for (i=0; i < sizeof table / sizeof *table; i++)
- if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) {
- if (table[i].t_black) black = (ushort) table[i].t_black;
- if (table[i].t_maximum) maximum = (ushort) table[i].t_maximum;
- for (j=0; j < 12; j++)
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.color.cam_xyz[0][j] =
-#endif
- cam_xyz[0][j] = table[i].trans[j] / 10000.0;
- cam_xyz_coeff (cam_xyz);
- break;
- }
-}
-
-void CLASS simple_coeff (int index)
-{
- static const float table[][12] = {
- /* index 0 -- all Foveon cameras */
- { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 },
- /* index 1 -- Kodak DC20 and DC25 */
- { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 },
- /* index 2 -- Logitech Fotoman Pixtura */
- { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 },
- /* index 3 -- Nikon E880, E900, and E990 */
- { -1.936280, 1.800443, -1.448486, 2.584324,
- 1.405365, -0.524955, -0.289090, 0.408680,
- -1.204965, 1.082304, 2.941367, -1.818705 }
- };
- int i, c;
-
- for (raw_color = i=0; i < 3; i++)
- FORCC rgb_cam[i][c] = table[index][i*colors+c];
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.rgb_cam_state = LIBRAW_COLORSTATE_CALCULATED;
-#endif
-}
-
-short CLASS guess_byte_order (int words)
-{
- uchar test[4][2];
- int t=2, msb;
- double diff, sum[2] = {0,0};
-
- fread (test[0], 2, 2, ifp);
- for (words-=2; words--; ) {
- fread (test[t], 2, 1, ifp);
- for (msb=0; msb < 2; msb++) {
- diff = (test[t^2][msb] << 8 | test[t^2][!msb])
- - (test[t ][msb] << 8 | test[t ][!msb]);
- sum[msb] += diff*diff;
- }
- t = (t+1) & 3;
- }
- return sum[0] < sum[1] ? 0x4d4d : 0x4949;
-}
-
-/*
- Identify which camera created this file, and set global variables
- accordingly.
- */
-void CLASS identify()
-{
- char head[32], *cp;
- unsigned hlen, fsize, i, c, is_canon;
- struct jhead jh;
- static const struct {
- int fsize;
- char t_make[12], t_model[19], withjpeg;
- } table[] = {
- { 62464, "Kodak", "DC20" ,0 },
- { 124928, "Kodak", "DC20" ,0 },
- { 1652736, "Kodak", "DCS200" ,0 },
- { 4159302, "Kodak", "C330" ,0 },
- { 4162462, "Kodak", "C330" ,0 },
- { 460800, "Kodak", "C603v" ,0 },
- { 614400, "Kodak", "C603v" ,0 },
- { 6163328, "Kodak", "C603" ,0 },
- { 6166488, "Kodak", "C603" ,0 },
- { 9116448, "Kodak", "C603y" ,0 },
- { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */
- { 614400, "Kodak", "KAI-0340" ,0 },
- { 787456, "Creative", "PC-CAM 600" ,0 },
- { 1138688, "Minolta", "RD175" ,0 },
- { 3840000, "Foculus", "531C" ,0 },
- { 786432, "AVT", "F-080C" ,0 },
- { 1447680, "AVT", "F-145C" ,0 },
- { 1920000, "AVT", "F-201C" ,0 },
- { 5067304, "AVT", "F-510C" ,0 },
- { 10134608, "AVT", "F-510C" ,0 },
- { 16157136, "AVT", "F-810C" ,0 },
- { 1409024, "Sony", "XCD-SX910CR" ,0 },
- { 2818048, "Sony", "XCD-SX910CR" ,0 },
- { 3884928, "Micron", "2010" ,0 },
- { 6624000, "Pixelink", "A782" ,0 },
- { 13248000, "Pixelink", "A782" ,0 },
- { 6291456, "RoverShot","3320AF" ,0 },
- { 6553440, "Canon", "PowerShot A460" ,0 },
- { 6653280, "Canon", "PowerShot A530" ,0 },
- { 6573120, "Canon", "PowerShot A610" ,0 },
- { 9219600, "Canon", "PowerShot A620" ,0 },
- { 10341600, "Canon", "PowerShot A720" ,0 },
- { 10383120, "Canon", "PowerShot A630" ,0 },
- { 12945240, "Canon", "PowerShot A640" ,0 },
- { 15636240, "Canon", "PowerShot A650" ,0 },
- { 5298000, "Canon", "PowerShot SD300" ,0 },
- { 7710960, "Canon", "PowerShot S3 IS" ,0 },
- { 5939200, "OLYMPUS", "C770UZ" ,0 },
- { 1581060, "NIKON", "E900" ,1 }, /* or E900s,E910 */
- { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */
- { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */
- { 4771840, "NIKON", "E990" ,1 }, /* or E995, Oly C3030Z */
- { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */
- { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */
- { 5865472, "NIKON", "E4500" ,1 },
- { 7438336, "NIKON", "E5000" ,1 }, /* or E5700 */
- { 8998912, "NIKON", "COOLPIX S6" ,1 },
- { 1976352, "CASIO", "QV-2000UX" ,1 },
- { 3217760, "CASIO", "QV-3*00EX" ,1 },
- { 6218368, "CASIO", "QV-5700" ,1 },
- { 6054400, "CASIO", "QV-R41" ,1 },
- { 7530816, "CASIO", "QV-R51" ,1 },
- { 7684000, "CASIO", "QV-4000" ,1 },
- { 4948608, "CASIO", "EX-S100" ,1 },
- { 7542528, "CASIO", "EX-Z50" ,1 },
- { 7753344, "CASIO", "EX-Z55" ,1 },
- { 7426656, "CASIO", "EX-P505" ,1 },
- { 9313536, "CASIO", "EX-P600" ,1 },
- { 10979200, "CASIO", "EX-P700" ,1 },
- { 3178560, "PENTAX", "Optio S" ,1 },
- { 4841984, "PENTAX", "Optio S" ,1 },
- { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i, CASIO EX-Z4 */
- { 10702848, "PENTAX", "Optio 750Z" ,1 },
- { 16098048, "SAMSUNG", "S85" ,1 },
- { 16215552, "SAMSUNG", "S85" ,1 },
- { 12582980, "Sinar", "" ,0 },
- { 33292868, "Sinar", "" ,0 },
- { 44390468, "Sinar", "" ,0 } };
- static const char *corp[] =
- { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX",
- "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One",
- "SAMSUNG", "Mamiya" };
-
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,0,2);
-#endif
-
- tiff_flip = flip = filters = -1; /* 0 is valid, so -1 is unknown */
- raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
- maximum = height = width = top_margin = left_margin = 0;
- cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
- iso_speed = shutter = aperture = focal_len = unique_id = 0;
- memset (gpsdata, 0, sizeof gpsdata);
- memset (white, 0, sizeof white);
- thumb_offset = thumb_length = thumb_width = thumb_height = 0;
- load_raw = thumb_load_raw = 0;
- write_thumb = &CLASS jpeg_thumb;
- data_offset = meta_length = tiff_bps = tiff_compress = 0;
- kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
- timestamp = shot_order = tiff_samples = black = is_foveon = 0;
- mix_green = profile_length = data_error = zero_is_bad = 0;
- pixel_aspect = is_raw = raw_color = use_gamma = 1;
- tile_width = tile_length = INT_MAX;
- for (i=0; i < 4; i++) {
- cam_mul[i] = i == 1;
- pre_mul[i] = i < 3;
- FORC3 cmatrix[c][i] = 0;
- FORC3 rgb_cam[c][i] = c == i;
- }
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cmatrix_state = LIBRAW_COLORSTATE_INIT;
- color_flags.rgb_cam_state = LIBRAW_COLORSTATE_INIT;
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_INIT;
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_INIT;
-#endif
- colors = 3;
- tiff_bps = 12;
- for (i=0; i < 0x4000; i++) curve[i] = i;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.curve_state = LIBRAW_COLORSTATE_INIT;
-#endif
-
- order = get2();
- hlen = get4();
- fseek (ifp, 0, SEEK_SET);
- fread (head, 1, 32, ifp);
- fseek (ifp, 0, SEEK_END);
- fsize = ftell(ifp);
- if ((cp = (char *) memmem (head, 32, "MMMM", 4)) ||
- (cp = (char *) memmem (head, 32, "IIII", 4))) {
- parse_phase_one (cp-head);
- if (cp-head) parse_tiff(0);
- } else if (order == 0x4949 || order == 0x4d4d) {
- if (!memcmp (head+6,"HEAPCCDR",8)) {
- data_offset = hlen;
- parse_ciff (hlen, fsize - hlen);
- } else {
- parse_tiff(0);
- }
- } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) &&
- !memcmp (head+6,"Exif",4)) {
- fseek (ifp, 4, SEEK_SET);
- data_offset = 4 + get2();
- fseek (ifp, data_offset, SEEK_SET);
- if (fgetc(ifp) != 0xff)
- parse_tiff(12);
- thumb_offset = 0;
- } else if (!memcmp (head+25,"ARECOYK",7)) {
- strcpy (make, "Contax");
- strcpy (model,"N Digital");
- fseek (ifp, 33, SEEK_SET);
- get_timestamp(1);
- fseek (ifp, 60, SEEK_SET);
- FORC4 cam_mul[c ^ (c >> 1)] = get4();
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- } else if (!strcmp (head, "PXN")) {
- strcpy (make, "Logitech");
- strcpy (model,"Fotoman Pixtura");
- } else if (!strcmp (head, "qktk")) {
- strcpy (make, "Apple");
- strcpy (model,"QuickTake 100");
- } else if (!strcmp (head, "qktn")) {
- strcpy (make, "Apple");
- strcpy (model,"QuickTake 150");
- } else if (!memcmp (head,"FUJIFILM",8)) {
- fseek (ifp, 84, SEEK_SET);
- thumb_offset = get4();
- thumb_length = get4();
- fseek (ifp, 92, SEEK_SET);
- parse_fuji (get4());
- if (thumb_offset > 120) {
- fseek (ifp, 120, SEEK_SET);
- is_raw += (i = get4()) && 1;
- if (is_raw == 2 && shot_select)
- parse_fuji (i);
- }
- fseek (ifp, 100, SEEK_SET);
- data_offset = get4();
- parse_tiff (thumb_offset+12);
- } else if (!memcmp (head,"RIFF",4)) {
- fseek (ifp, 0, SEEK_SET);
- parse_riff();
- } else if (!memcmp (head,"\0\001\0\001\0@",6)) {
- fseek (ifp, 6, SEEK_SET);
- fread (make, 1, 8, ifp);
- fread (model, 1, 8, ifp);
- fread (model2, 1, 16, ifp);
- data_offset = get2();
- get2();
- raw_width = get2();
- raw_height = get2();
- load_raw = &CLASS nokia_load_raw;
- filters = 0x61616161;
- } else if (!memcmp (head,"DSC-Image",9))
- parse_rollei();
- else if (!memcmp (head,"PWAD",4))
- parse_sinar_ia();
- else if (!memcmp (head,"\0MRM",4))
- parse_minolta(0);
- else if (!memcmp (head,"FOVb",4))
- parse_foveon();
- else if (!memcmp (head,"CI",2))
- parse_cine();
- else
- for (i=0; i < sizeof table / sizeof *table; i++)
- if (fsize == table[i].fsize) {
- strcpy (make, table[i].t_make );
- strcpy (model, table[i].t_model);
- if (table[i].withjpeg)
- parse_external_jpeg();
- }
- if (make[0] == 0) parse_smal (0, fsize);
- if (make[0] == 0) parse_jpeg (is_raw = 0);
-
- for (i=0; i < sizeof corp / sizeof *corp; i++)
- if (strstr (make, corp[i])) /* Simplify company names */
- strcpy (make, corp[i]);
- if (!strncmp (make,"KODAK",5))
- make[16] = model[16] = 0;
- cp = make + strlen(make); /* Remove trailing spaces */
- while (*--cp == ' ') *cp = 0;
- cp = model + strlen(model);
- while (*--cp == ' ') *cp = 0;
- i = strlen(make); /* Remove make from model */
- if (!strncasecmp (model, make, i) && model[i++] == ' ')
- memmove (model, model+i, 64-i);
- if (!strncmp (model,"Digital Camera ",15))
- strcpy (model, model+15);
- desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0;
- if (!is_raw) goto notraw;
-
- if (!maximum) maximum = (1 << tiff_bps) - 1;
- if (!height) height = raw_height;
- if (!width) width = raw_width;
- if (fuji_width) {
- width = height + fuji_width;
- height = width - 1;
- pixel_aspect = 1;
- }
- if (height == 2624 && width == 3936) /* Pentax K10D and Samsung GX10 */
- { height = 2616; width = 3896; }
- if (height == 3136 && width == 4864) /* Pentax K20D */
- { height = 3124; width = 4688; }
- if (height == 3014 && width == 4096) /* Ricoh GX200 */
- width = 4014;
- if (dng_version) {
- if (filters == UINT_MAX) filters = 0;
- if (filters) is_raw = tiff_samples;
- else colors = tiff_samples;
- if (tiff_compress == 1)
- load_raw = &CLASS adobe_dng_load_raw_nc;
- if (tiff_compress == 7)
- load_raw = &CLASS adobe_dng_load_raw_lj;
- goto dng_skip;
- }
- if ((is_canon = !strcmp(make,"Canon")))
- load_raw = memcmp (head+6,"HEAPCCDR",8) ?
- &CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw;
- if (!strcmp(make,"NIKON")) {
- if (!load_raw)
- load_raw = &CLASS packed_12_load_raw;
- if (model[0] == 'E')
- load_flags |= !data_offset << 2 | 2;
- }
- if (!strcmp(make,"CASIO")) {
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7f;
- }
-
-/* Set parameters based on camera name (for non-DNG files). */
-
- if (is_foveon) {
- if (height*2 < width) pixel_aspect = 0.5;
- if (height > width) pixel_aspect = 2;
- filters = 0;
- load_raw = &CLASS foveon_load_raw;
- simple_coeff(0);
- } else if (is_canon && tiff_bps == 15) {
- switch (width) {
- case 3344: width -= 66;
- case 3872: width -= 6;
- }
- filters = 0;
- load_raw = &CLASS canon_sraw_load_raw;
- } else if (!strcmp(model,"PowerShot 600")) {
- height = 613;
- width = 854;
- raw_width = 896;
- pixel_aspect = 607/628.0;
- colors = 4;
- filters = 0xe1e4e1e4;
- load_raw = &CLASS canon_600_load_raw;
- } else if (!strcmp(model,"PowerShot A5") ||
- !strcmp(model,"PowerShot A5 Zoom")) {
- height = 773;
- width = 960;
- raw_width = 992;
- pixel_aspect = 256/235.0;
- colors = 4;
- filters = 0x1e4e1e4e;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A50")) {
- height = 968;
- width = 1290;
- raw_width = 1320;
- colors = 4;
- filters = 0x1b4e4b1e;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot Pro70")) {
- height = 1024;
- width = 1552;
- colors = 4;
- filters = 0x1e4b4e1b;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot SD300")) {
- height = 1752;
- width = 2344;
- raw_height = 1766;
- raw_width = 2400;
- top_margin = 12;
- left_margin = 12;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A460")) {
- height = 1960;
- width = 2616;
- raw_height = 1968;
- raw_width = 2664;
- top_margin = 4;
- left_margin = 4;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A530")) {
- height = 1984;
- width = 2620;
- raw_height = 1992;
- raw_width = 2672;
- top_margin = 6;
- left_margin = 10;
- load_raw = &CLASS canon_a5_load_raw;
- raw_color = 0;
- } else if (!strcmp(model,"PowerShot A610")) {
- if (canon_s2is()) strcpy (model+10, "S2 IS");
- height = 1960;
- width = 2616;
- raw_height = 1968;
- raw_width = 2672;
- top_margin = 8;
- left_margin = 12;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A620")) {
- height = 2328;
- width = 3112;
- raw_height = 2340;
- raw_width = 3152;
- top_margin = 12;
- left_margin = 36;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A720")) {
- height = 2472;
- width = 3298;
- raw_height = 2480;
- raw_width = 3336;
- top_margin = 5;
- left_margin = 6;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A630")) {
- height = 2472;
- width = 3288;
- raw_height = 2484;
- raw_width = 3344;
- top_margin = 6;
- left_margin = 12;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A640")) {
- height = 2760;
- width = 3672;
- raw_height = 2772;
- raw_width = 3736;
- top_margin = 6;
- left_margin = 12;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot A650")) {
- height = 3024;
- width = 4032;
- raw_height = 3048;
- raw_width = 4104;
- top_margin = 12;
- left_margin = 48;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot S3 IS")) {
- height = 2128;
- width = 2840;
- raw_height = 2136;
- raw_width = 2888;
- top_margin = 8;
- left_margin = 44;
- load_raw = &CLASS canon_a5_load_raw;
- } else if (!strcmp(model,"PowerShot Pro90 IS")) {
- width = 1896;
- colors = 4;
- filters = 0xb4b4b4b4;
- } else if (is_canon && raw_width == 2144) {
- height = 1550;
- width = 2088;
- top_margin = 8;
- left_margin = 4;
- if (!strcmp(model,"PowerShot G1")) {
- colors = 4;
- filters = 0xb4b4b4b4;
- }
- } else if (is_canon && raw_width == 2224) {
- height = 1448;
- width = 2176;
- top_margin = 6;
- left_margin = 48;
- } else if (is_canon && raw_width == 2376) {
- height = 1720;
- width = 2312;
- top_margin = 6;
- left_margin = 12;
- } else if (is_canon && raw_width == 2672) {
- height = 1960;
- width = 2616;
- top_margin = 6;
- left_margin = 12;
- } else if (is_canon && raw_width == 3152) {
- height = 2056;
- width = 3088;
- top_margin = 12;
- left_margin = 64;
- if (unique_id == 0x80000170)
- adobe_coeff ("Canon","EOS 300D");
- } else if (is_canon && raw_width == 3160) {
- height = 2328;
- width = 3112;
- top_margin = 12;
- left_margin = 44;
- } else if (is_canon && raw_width == 3344) {
- height = 2472;
- width = 3288;
- top_margin = 6;
- left_margin = 4;
- } else if (!strcmp(model,"EOS D2000C")) {
- filters = 0x61616161;
- black = curve[200];
- } else if (is_canon && raw_width == 3516) {
- top_margin = 14;
- left_margin = 42;
- if (unique_id == 0x80000189)
- adobe_coeff ("Canon","EOS 350D");
- goto canon_cr2;
- } else if (is_canon && raw_width == 3596) {
- top_margin = 12;
- left_margin = 74;
- goto canon_cr2;
- } else if (is_canon && raw_width == 3944) {
- height = 2602;
- width = 3908;
- top_margin = 18;
- left_margin = 30;
- } else if (is_canon && raw_width == 3948) {
- top_margin = 18;
- left_margin = 42;
- height -= 2;
- if (unique_id == 0x80000236)
- adobe_coeff ("Canon","EOS 400D");
- if (unique_id == 0x80000254)
- adobe_coeff ("Canon","EOS 1000D");
- goto canon_cr2;
- } else if (is_canon && raw_width == 3984) {
- top_margin = 20;
- left_margin = 76;
- height -= 2;
- goto canon_cr2;
- } else if (is_canon && raw_width == 4104) {
- height = 3024;
- width = 4032;
- top_margin = 12;
- left_margin = 48;
- } else if (is_canon && raw_width == 4312) {
- top_margin = 18;
- left_margin = 22;
- height -= 2;
- if (unique_id == 0x80000176)
- adobe_coeff ("Canon","EOS 450D");
- goto canon_cr2;
- } else if (is_canon && raw_width == 4476) {
- top_margin = 34;
- left_margin = 90;
- goto canon_cr2;
- } else if (is_canon && raw_width == 4480) {
- height = 3326;
- width = 4432;
- top_margin = 10;
- left_margin = 12;
- filters = 0x49494949;
- } else if (is_canon && raw_width == 1208) {
- top_margin = 51;
- left_margin = 62;
- raw_width = width *= 4;
- goto canon_cr2;
- } else if (is_canon && raw_width == 1448) {
- top_margin = 51;
- left_margin = 158;
- raw_width = width *= 4;
- goto canon_cr2;
- } else if (is_canon && raw_width == 5108) {
- top_margin = 13;
- left_margin = 98;
-canon_cr2:
- height -= top_margin;
- width -= left_margin;
- } else if (is_canon && raw_width == 5712) {
- height = 3752;
- width = 5640;
- top_margin = 20;
- left_margin = 62;
- } else if (!strcmp(model,"D1")) {
- cam_mul[0] *= 256/527.0;
- cam_mul[2] *= 256/317.0;
- } else if (!strcmp(model,"D1X")) {
- width -= 4;
- pixel_aspect = 0.5;
- } else if (!strcmp(model,"D40X") ||
- !strcmp(model,"D60") ||
- !strcmp(model,"D80")) {
- height -= 3;
- width -= 4;
- } else if (!strcmp(model,"D3") ||
- !strcmp(model,"D700")) {
- width -= 4;
- left_margin = 2;
- } else if (!strncmp(model,"D40",3) ||
- !strncmp(model,"D50",3) ||
- !strncmp(model,"D70",3)) {
- width--;
- } else if (!strcmp(model,"D90")) {
- width -= 42;
- } else if (!strcmp(model,"D100")) {
- if (tiff_compress == 34713 && !nikon_is_compressed()) {
- load_raw = &CLASS packed_12_load_raw;
- load_flags |= 8;
- raw_width = (width += 3) + 3;
- }
- } else if (!strcmp(model,"D200")) {
- left_margin = 1;
- width -= 4;
- filters = 0x94949494;
- } else if (!strncmp(model,"D2H",3)) {
- left_margin = 6;
- width -= 14;
- } else if (!strncmp(model,"D2X",3)) {
- if (width == 3264) width -= 32;
- else width -= 8;
- } else if (!strcmp(model,"D300")) {
- width -= 32;
- } else if (!strcmp(model,"COOLPIX P6000")) {
- load_flags = 1;
- filters = 0x94949494;
- } else if (fsize == 1581060) {
- height = 963;
- width = 1287;
- raw_width = 1632;
- load_raw = &CLASS nikon_e900_load_raw;
- maximum = 0x3f4;
- colors = 4;
- filters = 0x1e1e1e1e;
- simple_coeff(3);
- pre_mul[0] = 1.2085;
- pre_mul[1] = 1.0943;
- pre_mul[3] = 1.1103;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (fsize == 2465792) {
- height = 1203;
- width = 1616;
- raw_width = 2048;
- load_raw = &CLASS nikon_e900_load_raw;
- colors = 4;
- filters = 0x4b4b4b4b;
- adobe_coeff ("NIKON","E950");
- } else if (fsize == 4771840) {
- height = 1540;
- width = 2064;
- colors = 4;
- filters = 0xe1e1e1e1;
- load_raw = &CLASS packed_12_load_raw;
- load_flags = 6;
- if (!timestamp && nikon_e995())
- strcpy (model, "E995");
- if (strcmp(model,"E995")) {
- filters = 0xb4b4b4b4;
- simple_coeff(3);
- pre_mul[0] = 1.196;
- pre_mul[1] = 1.246;
- pre_mul[2] = 1.018;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- }
- } else if (!strcmp(model,"E2100")) {
- if (!timestamp && !nikon_e2100()) goto cp_e2500;
- height = 1206;
- width = 1616;
- load_flags = 7;
- } else if (!strcmp(model,"E2500")) {
-cp_e2500:
- strcpy (model, "E2500");
- height = 1204;
- width = 1616;
- colors = 4;
- filters = 0x4b4b4b4b;
- } else if (fsize == 4775936) {
- height = 1542;
- width = 2064;
- load_raw = &CLASS packed_12_load_raw;
- load_flags = 7;
- pre_mul[0] = 1.818;
- pre_mul[2] = 1.618;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- if (!timestamp) nikon_3700();
- if (model[0] == 'E' && atoi(model+1) < 3700)
- filters = 0x49494949;
- if (!strcmp(model,"Optio 33WR")) {
- flip = 1;
- filters = 0x16161616;
- pre_mul[0] = 1.331;
- pre_mul[2] = 1.820;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- }
- } else if (fsize == 5869568) {
- height = 1710;
- width = 2288;
- filters = 0x16161616;
- if (!timestamp && minolta_z2()) {
- strcpy (make, "Minolta");
- strcpy (model,"DiMAGE Z2");
- }
- load_raw = &CLASS packed_12_load_raw;
- load_flags = 6 + (make[0] == 'M');
- } else if (!strcmp(model,"E4500")) {
- height = 1708;
- width = 2288;
- colors = 4;
- filters = 0xb4b4b4b4;
- } else if (fsize == 7438336) {
- height = 1924;
- width = 2576;
- colors = 4;
- filters = 0xb4b4b4b4;
- } else if (fsize == 8998912) {
- height = 2118;
- width = 2832;
- maximum = 0xf83;
- load_raw = &CLASS packed_12_load_raw;
- load_flags = 7;
- } else if (!strcmp(model,"FinePix S5100") ||
- !strcmp(model,"FinePix S5500")) {
- load_raw = &CLASS unpacked_load_raw;
- } else if (!strcmp(make,"FUJIFILM")) {
- if (!strcmp(model+7,"S2Pro")) {
- strcpy (model+7," S2Pro");
- height = 2144;
- width = 2880;
- flip = 6;
- } else
- maximum = 0x3e00;
- if (is_raw == 2 && shot_select)
- maximum = 0x2f00;
- top_margin = (raw_height - height)/2;
- left_margin = (raw_width - width )/2;
- if (is_raw == 2)
- data_offset += (shot_select > 0) * ( fuji_layout ?
- (raw_width *= 2) : raw_height*raw_width*2 );
- fuji_width = width >> !fuji_layout;
- width = (height >> fuji_layout) + fuji_width;
- raw_height = height;
- height = width - 1;
- load_raw = &CLASS fuji_load_raw;
- if (!(fuji_width & 1)) filters = 0x49494949;
- } else if (!strcmp(model,"RD175")) {
- height = 986;
- width = 1534;
- data_offset = 513;
- filters = 0x61616161;
- load_raw = &CLASS minolta_rd175_load_raw;
- } else if (!strcmp(model,"KD-400Z")) {
- height = 1712;
- width = 2312;
- raw_width = 2336;
- goto konica_400z;
- } else if (!strcmp(model,"KD-510Z")) {
- goto konica_510z;
- } else if (!strcasecmp(make,"MINOLTA")) {
- load_raw = &CLASS unpacked_load_raw;
- maximum = 0xfff;
- if (!strncmp(model,"DiMAGE A",8)) {
- if (!strcmp(model,"DiMAGE A200"))
- filters = 0x49494949;
- load_raw = &CLASS packed_12_load_raw;
- } else if (!strncmp(model,"ALPHA",5) ||
- !strncmp(model,"DYNAX",5) ||
- !strncmp(model,"MAXXUM",6)) {
- sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M'));
- adobe_coeff (make, model+20);
- load_raw = &CLASS packed_12_load_raw;
- } else if (!strncmp(model,"DiMAGE G",8)) {
- if (model[8] == '4') {
- height = 1716;
- width = 2304;
- } else if (model[8] == '5') {
-konica_510z:
- height = 1956;
- width = 2607;
- raw_width = 2624;
- } else if (model[8] == '6') {
- height = 2136;
- width = 2848;
- }
- data_offset += 14;
- filters = 0x61616161;
-konica_400z:
- load_raw = &CLASS unpacked_load_raw;
- maximum = 0x3df;
- order = 0x4d4d;
- }
- } else if (!strcmp(model,"*ist DS")) {
- height -= 2;
- } else if (!strcmp(model,"K20D")) {
- filters = 0x16161616;
- } else if (!strcmp(model,"Optio S")) {
- if (fsize == 3178560) {
- height = 1540;
- width = 2064;
- load_raw = &CLASS eight_bit_load_raw;
- cam_mul[0] *= 4;
- cam_mul[2] *= 4;
- pre_mul[0] = 1.391;
- pre_mul[2] = 1.188;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else {
- height = 1544;
- width = 2068;
- raw_width = 3136;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7c;
- pre_mul[0] = 1.137;
- pre_mul[2] = 1.453;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- }
- } else if (fsize == 6114240) {
- height = 1737;
- width = 2324;
- raw_width = 3520;
- load_raw = &CLASS packed_12_load_raw;
- maximum = 0xf7a;
- pre_mul[0] = 1.980;
- pre_mul[2] = 1.570;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"Optio 750Z")) {
- height = 2302;
- width = 3072;
- load_raw = &CLASS packed_12_load_raw;
- load_flags = 7;
- } else if (!strcmp(model,"S85")) {
- height = 2448;
- width = 3264;
- raw_width = fsize/height/2;
- order = 0x4d4d;
- load_raw = &CLASS unpacked_load_raw;
- maximum = 0xffff;
- } else if (!strcmp(model,"STV680 VGA")) {
- height = 484;
- width = 644;
- load_raw = &CLASS eight_bit_load_raw;
- flip = 2;
- filters = 0x16161616;
- black = 16;
- pre_mul[0] = 1.097;
- pre_mul[2] = 1.128;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"KAI-0340")) {
- height = 477;
- width = 640;
- order = 0x4949;
- data_offset = 3840;
- load_raw = &CLASS unpacked_load_raw;
- pre_mul[0] = 1.561;
- pre_mul[2] = 2.454;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"N95")) {
- height = raw_height - (top_margin = 2);
- } else if (!strcmp(model,"531C")) {
- height = 1200;
- width = 1600;
- load_raw = &CLASS unpacked_load_raw;
- filters = 0x49494949;
- pre_mul[1] = 1.218;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"F-080C")) {
- height = 768;
- width = 1024;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcmp(model,"F-145C")) {
- height = 1040;
- width = 1392;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcmp(model,"F-201C")) {
- height = 1200;
- width = 1600;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcmp(model,"F-510C")) {
- height = 1958;
- width = 2588;
- load_raw = fsize < 7500000 ?
- &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
- maximum = 0xfff0;
- } else if (!strcmp(model,"F-810C")) {
- height = 2469;
- width = 3272;
- load_raw = &CLASS unpacked_load_raw;
- maximum = 0xfff0;
- } else if (!strcmp(model,"XCD-SX910CR")) {
- height = 1024;
- width = 1375;
- raw_width = 1376;
- filters = 0x49494949;
- maximum = 0x3ff;
- load_raw = fsize < 2000000 ?
- &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
- } else if (!strcmp(model,"2010")) {
- height = 1207;
- width = 1608;
- order = 0x4949;
- filters = 0x16161616;
- data_offset = 3212;
- maximum = 0x3ff;
- load_raw = &CLASS unpacked_load_raw;
- } else if (!strcmp(model,"A782")) {
- height = 3000;
- width = 2208;
- filters = 0x61616161;
- load_raw = fsize < 10000000 ?
- &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
- maximum = 0xffc0;
- } else if (!strcmp(model,"3320AF")) {
- height = 1536;
- raw_width = width = 2048;
- filters = 0x61616161;
- load_raw = &CLASS unpacked_load_raw;
- maximum = 0x3ff;
- pre_mul[0] = 1.717;
- pre_mul[2] = 1.138;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- fseek (ifp, 0x300000, SEEK_SET);
- if ((order = guess_byte_order(0x10000)) == 0x4d4d) {
- height -= (top_margin = 16);
- width -= (left_margin = 28);
- maximum = 0xf5c0;
- strcpy (make, "ISG");
- model[0] = 0;
- }
- } else if (!strcmp(make,"Hasselblad")) {
- if (load_raw == &CLASS lossless_jpeg_load_raw)
- load_raw = &CLASS hasselblad_load_raw;
- if (raw_width == 7262) {
- height = 5444;
- width = 7248;
- top_margin = 4;
- left_margin = 7;
- filters = 0x61616161;
- } else if (raw_width == 4090) {
- strcpy (model, "V96C");
- height -= (top_margin = 6);
- width -= (left_margin = 3) + 7;
- filters = 0x61616161;
- }
- } else if (!strcmp(make,"Sinar")) {
- if (!memcmp(head,"8BPS",4)) {
- fseek (ifp, 14, SEEK_SET);
- height = get4();
- width = get4();
- filters = 0x61616161;
- data_offset = 68;
- }
- if (!load_raw) load_raw = &CLASS unpacked_load_raw;
- maximum = 0x3fff;
- } else if (!strcmp(make,"Leaf")) {
- maximum = 0x3fff;
- fseek (ifp, data_offset, SEEK_SET);
- if (ljpeg_start (&jh, 1) && jh.bits == 15)
- maximum = 0x1fff;
- if (tiff_samples > 1) filters = 0;
- if (tiff_samples > 1 || tile_length < raw_height)
- load_raw = &CLASS leaf_hdr_load_raw;
- if ((width | height) == 2048) {
- if (tiff_samples == 1) {
- filters = 1;
- strcpy (cdesc, "RBTG");
- strcpy (model, "CatchLight");
- top_margin = 8; left_margin = 18; height = 2032; width = 2016;
- } else {
- strcpy (model, "DCB2");
- top_margin = 10; left_margin = 16; height = 2028; width = 2022;
- }
- } else if (width+height == 3144+2060) {
- if (!model[0]) strcpy (model, "Cantare");
- if (width > height) {
- top_margin = 6; left_margin = 32; height = 2048; width = 3072;
- filters = 0x61616161;
- } else {
- left_margin = 6; top_margin = 32; width = 2048; height = 3072;
- filters = 0x16161616;
- }
- if (!cam_mul[0] || model[0] == 'V') filters = 0;
- else is_raw = tiff_samples;
- } else if (width == 2116) {
- strcpy (model, "Valeo 6");
- height -= 2 * (top_margin = 30);
- width -= 2 * (left_margin = 55);
- filters = 0x49494949;
- } else if (width == 3171) {
- strcpy (model, "Valeo 6");
- height -= 2 * (top_margin = 24);
- width -= 2 * (left_margin = 24);
- filters = 0x16161616;
- }
- } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) {
- maximum = 0xfff0;
- if ((fsize-data_offset) / (width*8/7) == height)
- load_raw = &CLASS panasonic_load_raw;
- if (!load_raw) load_raw = &CLASS unpacked_load_raw;
- switch (width) {
- case 2568:
- adobe_coeff ("Panasonic","DMC-LC1"); break;
- case 3130:
- left_margin = -14;
- case 3170:
- left_margin += 18;
- width = 3096;
- if (height > 2326) {
- height = 2326;
- top_margin = 13;
- filters = 0x49494949;
- }
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-FZ8"); break;
- case 3213:
- width -= 27;
- case 3177:
- width -= 10;
- filters = 0x49494949;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-L1"); break;
- case 3304:
- width -= 17;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-FZ30"); break;
- case 3330:
- width += 43;
- left_margin = -6;
- maximum = 0xf7f0;
- case 3370:
- width -= 82;
- left_margin += 15;
- if (height > 2480)
- height = 2480 - (top_margin = 10);
- filters = 0x49494949;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-FZ18"); break;
- case 3690:
- height -= 2;
- left_margin = -14;
- maximum = 0xf7f0;
- case 3770:
- width = 3672;
- if (--height == 2798 && (height = 2760))
- top_margin = 15;
- else filters = 0x49494949;
- left_margin += 17;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-FZ50"); break;
- case 3710:
- width = 3682;
- filters = 0x49494949;
- adobe_coeff ("Panasonic","DMC-L10"); break;
- case 3724:
- width -= 14;
- case 3836:
- width -= 42;
-lx3: filters = 0x16161616;
- if (make[0] != 'P')
- adobe_coeff ("Panasonic","DMC-LX3");
- break;
- case 3880:
- width -= 22;
- left_margin = 6;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-LX1"); break;
- case 4060:
- width = 3982;
- if (height == 2250) goto lx3;
- width = 4018;
- filters = 0x49494949;
- zero_is_bad = 1;
- adobe_coeff ("Panasonic","DMC-G1"); break;
- case 4290:
- height += 38;
- left_margin = -14;
- filters = 0x49494949;
- case 4330:
- width = 4248;
- if ((height -= 39) == 2400)
- top_margin = 15;
- left_margin += 17;
- adobe_coeff ("Panasonic","DMC-LX2"); break;
- case 4508:
- height -= 6;
- width = 4429;
- filters = 0x16161616;
- adobe_coeff ("Panasonic","DMC-FX150"); break;
- }
- } else if (!strcmp(model,"C770UZ")) {
- height = 1718;
- width = 2304;
- filters = 0x16161616;
- load_raw = &CLASS packed_12_load_raw;
- load_flags = 7;
- } else if (!strcmp(make,"OLYMPUS")) {
- height += height & 1;
- filters = exif_cfa;
- if (load_raw == &CLASS olympus_e410_load_raw) {
- black >>= 4;
- } else if (!strcmp(model,"E-10") ||
- !strncmp(model,"E-20",4)) {
- black <<= 2;
- } else if (!strcmp(model,"E-300") ||
- !strcmp(model,"E-500")) {
- width -= 20;
- if (load_raw == &CLASS unpacked_load_raw) {
- maximum = 0xfc30;
- black = 0;
- }
- } else if (!strcmp(model,"E-330")) {
- width -= 30;
- if (load_raw == &CLASS unpacked_load_raw)
- maximum = 0xf790;
- } else if (!strcmp(model,"SP550UZ")) {
- thumb_length = fsize - (thumb_offset = 0xa39800);
- thumb_height = 480;
- thumb_width = 640;
- }
- } else if (!strcmp(model,"N Digital")) {
- height = 2047;
- width = 3072;
- filters = 0x61616161;
- data_offset = 0x1a00;
- load_raw = &CLASS packed_12_load_raw;
- } else if (!strcmp(model,"DSC-F828")) {
- width = 3288;
- left_margin = 5;
- data_offset = 862144;
- load_raw = &CLASS sony_load_raw;
- filters = 0x9c9c9c9c;
- colors = 4;
- strcpy (cdesc, "RGBE");
- } else if (!strcmp(model,"DSC-V3")) {
- width = 3109;
- left_margin = 59;
- data_offset = 787392;
- load_raw = &CLASS sony_load_raw;
- } else if (!strcmp(make,"SONY") && raw_width == 3984) {
- adobe_coeff ("SONY","DSC-R1");
- width = 3925;
- order = 0x4d4d;
- } else if (!strcmp(model,"DSLR-A100")) {
- height--;
- } else if (!strcmp(model,"DSLR-A350")) {
- height -= 4;
- } else if (!strcmp(model,"C603v")) {
- height = 480;
- width = 640;
- goto c603v;
- } else if (!strcmp(model,"C603y")) {
- height = 2134;
- width = 2848;
-c603v:
- filters = 0;
- load_raw = &CLASS kodak_yrgb_load_raw;
- } else if (!strcmp(model,"C603")) {
- raw_height = height = 2152;
- raw_width = width = 2864;
- goto c603;
- } else if (!strcmp(model,"C330")) {
- height = 1744;
- width = 2336;
- raw_height = 1779;
- raw_width = 2338;
- top_margin = 33;
- left_margin = 1;
-c603:
- order = 0x4949;
- if ((data_offset = fsize - raw_height*raw_width)) {
- fseek (ifp, 168, SEEK_SET);
- read_shorts (curve, 256);
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
-#endif
- } else use_gamma = 0;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcasecmp(make,"KODAK")) {
- if (filters == UINT_MAX) filters = 0x61616161;
- if (!strncmp(model,"NC2000",6)) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"EOSDCS3B")) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"EOSDCS1")) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"DCS420")) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"DCS460")) {
- width -= 4;
- left_margin = 2;
- } else if (!strcmp(model,"DCS460A")) {
- width -= 4;
- left_margin = 2;
- colors = 1;
- filters = 0;
- } else if (!strcmp(model,"DCS660M")) {
- black = 214;
- colors = 1;
- filters = 0;
- } else if (!strcmp(model,"DCS760M")) {
- colors = 1;
- filters = 0;
- }
- if (!strcmp(model+4,"20X"))
- strcpy (cdesc, "MYCY");
- if (strstr(model,"DC25")) {
- strcpy (model, "DC25");
- data_offset = 15424;
- }
- if (!strncmp(model,"DC2",3)) {
- height = 242;
- if (fsize < 100000) {
- raw_width = 256; width = 249;
- pixel_aspect = (4.0*height) / (3.0*width);
- } else {
- raw_width = 512; width = 501;
- pixel_aspect = (493.0*height) / (373.0*width);
- }
- data_offset += raw_width + 1;
- colors = 4;
- filters = 0x8d8d8d8d;
- simple_coeff(1);
- pre_mul[1] = 1.179;
- pre_mul[2] = 1.209;
- pre_mul[3] = 1.036;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcmp(model,"40")) {
- strcpy (model, "DC40");
- height = 512;
- width = 768;
- data_offset = 1152;
- load_raw = &CLASS kodak_radc_load_raw;
- } else if (strstr(model,"DC50")) {
- strcpy (model, "DC50");
- height = 512;
- width = 768;
- data_offset = 19712;
- load_raw = &CLASS kodak_radc_load_raw;
- } else if (strstr(model,"DC120")) {
- strcpy (model, "DC120");
- height = 976;
- width = 848;
- pixel_aspect = height/0.75/width;
- load_raw = tiff_compress == 7 ?
- &CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw;
- } else if (!strcmp(model,"DCS200")) {
- thumb_height = 128;
- thumb_width = 192;
- thumb_offset = 6144;
- thumb_misc = 360;
- write_thumb = &CLASS layer_thumb;
- height = 1024;
- width = 1536;
- data_offset = 79872;
- load_raw = &CLASS eight_bit_load_raw;
- black = 17;
- }
- } else if (!strcmp(model,"Fotoman Pixtura")) {
- height = 512;
- width = 768;
- data_offset = 3632;
- load_raw = &CLASS kodak_radc_load_raw;
- filters = 0x61616161;
- simple_coeff(2);
- } else if (!strcmp(model,"QuickTake 100")) {
- fseek (ifp, 544, SEEK_SET);
- height = get2();
- width = get2();
- data_offset = (get4(),get2()) == 30 ? 738:736;
- if (height > width) {
- SWAP(height,width);
- fseek (ifp, data_offset-6, SEEK_SET);
- flip = ~get2() & 3 ? 5:6;
- }
- load_raw = &CLASS quicktake_100_load_raw;
- filters = 0x61616161;
- } else if (!strcmp(model,"QuickTake 150")) {
- data_offset = 738 - head[5];
- if (head[5]) strcpy (model+10, "200");
- load_raw = &CLASS kodak_radc_load_raw;
- height = 480;
- width = 640;
- filters = 0x61616161;
- } else if (!strcmp(make,"Rollei") && !load_raw) {
- switch (raw_width) {
- case 1316:
- height = 1030;
- width = 1300;
- top_margin = 1;
- left_margin = 6;
- break;
- case 2568:
- height = 1960;
- width = 2560;
- top_margin = 2;
- left_margin = 8;
- }
- filters = 0x16161616;
- load_raw = &CLASS rollei_load_raw;
- pre_mul[0] = 1.8;
- pre_mul[2] = 1.3;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"PC-CAM 600")) {
- height = 768;
- data_offset = width = 1024;
- filters = 0x49494949;
- load_raw = &CLASS eight_bit_load_raw;
- pre_mul[0] = 1.14;
- pre_mul[2] = 2.73;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"QV-2000UX")) {
- height = 1208;
- width = 1632;
- data_offset = width * 2;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (fsize == 3217760) {
- height = 1546;
- width = 2070;
- raw_width = 2080;
- load_raw = &CLASS eight_bit_load_raw;
- } else if (!strcmp(model,"QV-4000")) {
- height = 1700;
- width = 2260;
- load_raw = &CLASS unpacked_load_raw;
- maximum = 0xffff;
- } else if (!strcmp(model,"QV-5700")) {
- height = 1924;
- width = 2576;
- load_raw = &CLASS casio_qv5700_load_raw;
- } else if (!strcmp(model,"QV-R41")) {
- height = 1720;
- width = 2312;
- raw_width = 3520;
- left_margin = 2;
- } else if (!strcmp(model,"QV-R51")) {
- height = 1926;
- width = 2580;
- raw_width = 3904;
- pre_mul[0] = 1.340;
- pre_mul[2] = 1.672;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"EX-S100")) {
- height = 1544;
- width = 2058;
- raw_width = 3136;
- pre_mul[0] = 1.631;
- pre_mul[2] = 1.106;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"EX-Z50")) {
- height = 1931;
- width = 2570;
- raw_width = 3904;
- pre_mul[0] = 2.529;
- pre_mul[2] = 1.185;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"EX-Z55")) {
- height = 1960;
- width = 2570;
- raw_width = 3904;
- pre_mul[0] = 1.520;
- pre_mul[2] = 1.316;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"EX-P505")) {
- height = 1928;
- width = 2568;
- raw_width = 3852;
- maximum = 0xfff;
- pre_mul[0] = 2.07;
- pre_mul[2] = 1.88;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (fsize == 9313536) { /* EX-P600 or QV-R61 */
- height = 2142;
- width = 2844;
- raw_width = 4288;
- pre_mul[0] = 1.797;
- pre_mul[2] = 1.219;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- } else if (!strcmp(model,"EX-P700")) {
- height = 2318;
- width = 3082;
- raw_width = 4672;
- pre_mul[0] = 1.758;
- pre_mul[2] = 1.504;
-#ifdef LIBRAW_LIBRARY_BUILD
- color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
-#endif
- }
- if (!model[0])
- sprintf (model, "%dx%d", width, height);
- if (filters == UINT_MAX) filters = 0x94949494;
- if (raw_color) adobe_coeff (make, model);
- if (thumb_offset && !thumb_height) {
- fseek (ifp, thumb_offset, SEEK_SET);
- if (ljpeg_start (&jh, 1)) {
- thumb_width = jh.wide;
- thumb_height = jh.high;
- }
- }
-dng_skip:
- if (!load_raw || height < 22) is_raw = 0;
-#ifdef NO_JPEG
- if (load_raw == &CLASS kodak_jpeg_load_raw) {
-#ifdef DCRAW_VERBOSE
- fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname);
-#endif
- is_raw = 0;
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.process_warnings |= LIBRAW_WARN_NO_JPEGLIB;
-#endif
- }
-#endif
- if (!cdesc[0])
- strcpy (cdesc, colors == 3 ? "RGB":"GMCY");
- if (!raw_height) raw_height = height;
- if (!raw_width ) raw_width = width;
- if (filters && colors == 3)
- for (i=0; i < 32; i+=4) {
- if ((filters >> i & 15) == 9)
- filters |= 2 << i;
- if ((filters >> i & 15) == 6)
- filters |= 8 << i;
- }
-notraw:
- if (flip == -1) flip = tiff_flip;
- if (flip == -1) flip = 0;
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,1,2);
-#endif
-}
-void CLASS convert_to_rgb()
-{
- int row, col, c, i, j, k;
- ushort *img;
- float out[3], out_cam[3][4];
- double num, inverse[3][3], bnd[2]={0,0};
- static const double xyzd50_srgb[3][3] =
- { { 0.436083, 0.385083, 0.143055 },
- { 0.222507, 0.716888, 0.060608 },
- { 0.013930, 0.097097, 0.714022 } };
- static const double rgb_rgb[3][3] =
- { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } };
- static const double adobe_rgb[3][3] =
- { { 0.715146, 0.284856, 0.000000 },
- { 0.000000, 1.000000, 0.000000 },
- { 0.000000, 0.041166, 0.958839 } };
- static const double wide_rgb[3][3] =
- { { 0.593087, 0.404710, 0.002206 },
- { 0.095413, 0.843149, 0.061439 },
- { 0.011621, 0.069091, 0.919288 } };
- static const double prophoto_rgb[3][3] =
- { { 0.529317, 0.330092, 0.140588 },
- { 0.098368, 0.873465, 0.028169 },
- { 0.016879, 0.117663, 0.865457 } };
- static const double (*out_rgb[])[3] =
- { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb };
- static const char *name[] =
- { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" };
- 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, /* cprt */
- 0x64657363, 0, 40, /* desc */
- 0x77747074, 0, 20, /* wtpt */
- 0x626b7074, 0, 20, /* bkpt */
- 0x72545243, 0, 14, /* rTRC */
- 0x67545243, 0, 14, /* gTRC */
- 0x62545243, 0, 14, /* bTRC */
- 0x7258595a, 0, 20, /* rXYZ */
- 0x6758595a, 0, 20, /* gXYZ */
- 0x6258595a, 0, 20 }; /* bXYZ */
- static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };
- unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 };
-
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB,0,2);
-#endif
-
- bnd[gamm[1] >= 1] = 1;
- if (gamm[1] && (gamm[1]-1)*(gamm[0]-1) <= 0) {
- for (i=0; i < 36; i++) {
- gamm[2] = (bnd[0] + bnd[1])/2;
- bnd[(pow(gamm[2]/gamm[1],-gamm[0])-1)/gamm[0]-1/gamm[2] > -1] = gamm[2];
- }
- gamm[3] = gamm[2]*(1/gamm[0]-1);
- gamm[2] /= gamm[1];
- }
- gamm[4] = 1 / (gamm[1]/2*SQR(gamm[2]) - gamm[3]*(1-gamm[2]) +
- (1-pow(gamm[2],1+gamm[0]))*(1+gamm[3])/(1+gamm[0])) - 1;
-
- memcpy (out_cam, rgb_cam, sizeof out_cam);
- raw_color |= colors == 1 || document_mode ||
- output_color < 1 || output_color > 5;
- 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 < 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] = strlen(name[output_color-1]) + 1;
- memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite);
- if (output_bps == 8 | gamma_16bit)
- pcurve[3] = (short)(256/gamm[4]+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 += xyzd50_srgb[i][k] * inverse[j][k];
- oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5;
- }
- for (i=0; i < 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, name[output_color-1]);
- 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];
- }
-#ifdef DCRAW_VERBOSE
- if (verbose)
- fprintf (stderr, raw_color ? _("Building histograms...\n") :
- _("Converting to %s colorspace...\n"), name[output_color-1]);
-
-#endif
-#ifdef LIBRAW_LIBRARY_BUILD
- memset(histogram,0,sizeof(int)*LIBRAW_HISTOGRAM_SIZE*4);
-#else
- memset (histogram, 0, sizeof histogram);
-#endif
- for (img=image[0], row=0; row < height; row++)
- for (col=0; col < width; col++, img+=4) {
- if (!raw_color) {
- out[0] = out[1] = out[2] = 0;
- FORCC {
- out[0] += out_cam[0][c] * img[c];
- out[1] += out_cam[1][c] * img[c];
- out[2] += out_cam[2][c] * img[c];
- }
- FORC3 img[c] = CLIP((int) out[c]);
- }
- else if (document_mode)
- img[0] = img[FC(row,col)];
- FORCC histogram[c][img[c] >> 3]++;
- }
- if (colors == 4 && output_color) colors = 3;
- if (document_mode && filters) colors = 1;
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB,1,2);
-#endif
-}
-
-void CLASS fuji_rotate()
-{
- int i, row, col;
- double step;
- float r, c, fr, fc;
- unsigned ur, uc;
- ushort wide, high, (*img)[4], (*pix)[4];
-
- if (!fuji_width) return;
-#ifdef DCRAW_VERBOSE
- if (verbose)
- fprintf (stderr,_("Rotating image 45 degrees...\n"));
-#endif
- fuji_width = (fuji_width - 1 + shrink) >> shrink;
- step = sqrt(0.5);
- wide = fuji_width / step;
- high = (height - fuji_width) / step;
- img = (ushort (*)[4]) calloc (wide*high, sizeof *img);
- merror (img, "fuji_rotate()");
-
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE,0,2);
-#endif
-
- for (row=0; row < high; row++)
- for (col=0; col < wide; col++) {
- ur = r = fuji_width + (row-col)*step;
- uc = c = (row+col)*step;
- if (ur > height-2 || uc > width-2) continue;
- fr = r - ur;
- fc = c - uc;
- pix = image + ur*width + uc;
- for (i=0; i < colors; i++)
- img[row*wide+col][i] =
- (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) +
- (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr;
- }
- free (image);
- width = wide;
- height = high;
- image = img;
- fuji_width = 0;
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE,1,2);
-#endif
-}
-
-void CLASS stretch()
-{
- ushort newdim, (*img)[4], *pix0, *pix1;
- int row, col, c;
- double rc, frac;
-
- if (pixel_aspect == 1) return;
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH,0,2);
-#endif
-#ifdef DCRAW_VERBOSE
- if (verbose) fprintf (stderr,_("Stretching the image...\n"));
-#endif
- if (pixel_aspect < 1) {
- newdim = height / pixel_aspect + 0.5;
- img = (ushort (*)[4]) calloc (width*newdim, sizeof *img);
- merror (img, "stretch()");
- for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) {
- frac = rc - (c = rc);
- pix0 = pix1 = image[c*width];
- if (c+1 < height) pix1 += width*4;
- for (col=0; col < width; col++, pix0+=4, pix1+=4)
- FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
- }
- height = newdim;
- } else {
- newdim = width * pixel_aspect + 0.5;
- img = (ushort (*)[4]) calloc (height*newdim, sizeof *img);
- merror (img, "stretch()");
- for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) {
- frac = rc - (c = rc);
- pix0 = pix1 = image[c];
- if (c+1 < width) pix1 += 4;
- for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4)
- FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
- }
- width = newdim;
- }
- free (image);
- image = img;
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH,1,2);
-#endif
-}
-
-int CLASS flip_index (int row, int col)
-{
- if (flip & 4) SWAP(row,col);
- if (flip & 2) row = iheight - 1 - row;
- if (flip & 1) col = iwidth - 1 - col;
- return row * iwidth + col;
-}
-
-void CLASS gamma_lut (ushort lut[0x10000])
-{
- int perc, c, val, total, i;
- float t_white=0, r;
-
-#ifdef LIBRAW_LIBRARY_BUILD
- perc = width * height * imgdata.params.auto_bright_thr;
-#else
- perc = width * height * 0.01; /* 99th percentile white level */
-#endif
- if (fuji_width) perc /= 2;
- if ((highlight & ~2) || no_auto_bright) perc = -1;
- FORCC {
- for (val=0x2000, total=0; --val > 32; )
- if ((total += histogram[c][val]) > perc) break;
- if (t_white < val) t_white = val;
- }
- t_white *= 8 / bright;
- for (i=0; i < 0x10000; i++) {
- r = i / t_white;
- val = 65535 * ( !use_gamma ? r :
- r <= gamm[2] ? r*gamm[1] : pow((double)r,gamm[0])*(1+gamm[3])-gamm[3]);
- if (val > 65535) val = 65535;
- lut[i] = val;
- }
-}
-
-
-void CLASS tiff_set (ushort *ntag,
- ushort tag, ushort type, int count, int val)
-{
- struct tiff_tag *tt;
- int c;
-
- tt = (struct tiff_tag *)(ntag+1) + (*ntag)++;
- tt->tag = tag;
- tt->type = type;
- tt->count = count;
- if (type < 3 && count <= 4)
- FORC(4) tt->val.c[c] = val >> (c << 3);
- else if (type == 3 && count <= 2)
- FORC(2) tt->val.s[c] = val >> (c << 4);
- else tt->val.i = val;
-}
-
-#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
-
-void CLASS tiff_head (struct tiff_hdr *th, int full)
-{
- int c, psize=0;
- struct tm *t;
-
- memset (th, 0, sizeof *th);
- th->t_order = htonl(0x4d4d4949) >> 16;
- th->magic = 42;
- th->ifd = 10;
- if (full) {
- tiff_set (&th->ntag, 254, 4, 1, 0);
- tiff_set (&th->ntag, 256, 4, 1, width);
- tiff_set (&th->ntag, 257, 4, 1, height);
- tiff_set (&th->ntag, 258, 3, colors, output_bps);
- if (colors > 2)
- th->tag[th->ntag-1].val.i = TOFF(th->bps);
- FORC4 th->bps[c] = output_bps;
- tiff_set (&th->ntag, 259, 3, 1, 1);
- tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1));
- }
- tiff_set (&th->ntag, 270, 2, 512, TOFF(th->t_desc));
- tiff_set (&th->ntag, 271, 2, 64, TOFF(th->t_make));
- tiff_set (&th->ntag, 272, 2, 64, TOFF(th->t_model));
- if (full) {
- if (oprof) psize = ntohl(oprof[0]);
- tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize);
- tiff_set (&th->ntag, 277, 3, 1, colors);
- tiff_set (&th->ntag, 278, 4, 1, height);
- tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8);
- } else
- tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0');
- tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
- tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
- tiff_set (&th->ntag, 284, 3, 1, 1);
- tiff_set (&th->ntag, 296, 3, 1, 2);
- tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft));
- tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date));
- tiff_set (&th->ntag, 315, 2, 64, TOFF(th->t_artist));
- tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif));
- if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th);
- tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
- tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
- tiff_set (&th->nexif, 34855, 3, 1, iso_speed);
- tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
- if (gpsdata[1]) {
- tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps));
- tiff_set (&th->ngps, 0, 1, 4, 0x202);
- tiff_set (&th->ngps, 1, 2, 2, gpsdata[29]);
- tiff_set (&th->ngps, 2, 5, 3, TOFF(th->gps[0]));
- tiff_set (&th->ngps, 3, 2, 2, gpsdata[30]);
- tiff_set (&th->ngps, 4, 5, 3, TOFF(th->gps[6]));
- tiff_set (&th->ngps, 5, 1, 1, gpsdata[31]);
- tiff_set (&th->ngps, 6, 5, 1, TOFF(th->gps[18]));
- tiff_set (&th->ngps, 7, 5, 3, TOFF(th->gps[12]));
- tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20]));
- tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23]));
- memcpy (th->gps, gpsdata, sizeof th->gps);
- }
- th->rat[0] = th->rat[2] = 300;
- th->rat[1] = th->rat[3] = 1;
- FORC(6) th->rat[4+c] = 1000000;
- th->rat[4] *= shutter;
- th->rat[6] *= aperture;
- th->rat[8] *= focal_len;
- strncpy (th->t_desc, desc, 512);
- strncpy (th->t_make, make, 64);
- strncpy (th->t_model, model, 64);
- strcpy (th->soft, "dcraw v" DCRAW_VERSION);
- t = gmtime (&timestamp);
- sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d",
- t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
- strncpy (th->t_artist, artist, 64);
-}
-
-void CLASS jpeg_thumb_writer (FILE *tfp,char *t_humb,int t_humb_length)
-{
- ushort exif[5];
- struct tiff_hdr th;
- fputc (0xff, tfp);
- fputc (0xd8, tfp);
- if (strcmp (t_humb+6, "Exif")) {
- memcpy (exif, "\xff\xe1 Exif\0\0", 10);
- exif[1] = htons (8 + sizeof th);
- fwrite (exif, 1, sizeof exif, tfp);
- tiff_head (&th, 0);
- fwrite (&th, 1, sizeof th, tfp);
- }
- fwrite (t_humb+2, 1, t_humb_length-2, tfp);
-}
-
-
-void CLASS jpeg_thumb (FILE *tfp)
-{
- char *thumb;
- ushort exif[5];
- struct tiff_hdr th;
-
- thumb = (char *) malloc (thumb_length);
- merror (thumb, "jpeg_thumb()");
- fread (thumb, 1, thumb_length, ifp);
-#if 0
- fputc (0xff, tfp);
- fputc (0xd8, tfp);
- if (strcmp (thumb+6, "Exif")) {
- memcpy (exif, "\xff\xe1 Exif\0\0", 10);
- exif[1] = htons (8 + sizeof th);
- fwrite (exif, 1, sizeof exif, tfp);
- tiff_head (&th, 0);
- fwrite (&th, 1, sizeof th, tfp);
- }
- fwrite (thumb+2, 1, thumb_length-2, tfp);
-#else
- jpeg_thumb_writer(tfp,thumb,thumb_length);
-#endif
- free (thumb);
-}
-
-void CLASS write_ppm_tiff (FILE *ofp)
-{
- struct tiff_hdr th;
- uchar *ppm;
- ushort *ppm2,lut16[0x10000];
- int c, row, col, soff, rstep, cstep;
-
- iheight = height;
- iwidth = width;
- if (flip & 4) SWAP(height,width);
- ppm = (uchar *) calloc (width, colors*output_bps/8);
- ppm2 = (ushort *) ppm;
- merror (ppm, "write_ppm_tiff()");
- if (output_tiff) {
- tiff_head (&th, 1);
- fwrite (&th, sizeof th, 1, ofp);
- if (oprof)
- fwrite (oprof, ntohl(oprof[0]), 1, ofp);
- } else if (colors > 3)
- fprintf (ofp,
- "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
- width, height, colors, (1 << output_bps)-1, cdesc);
- else
- fprintf (ofp, "P%d\n%d %d\n%d\n",
- colors/2+5, width, height, (1 << output_bps)-1);
-
- if (output_bps == 8 || gamma_16bit ) gamma_lut (lut16);
- soff = flip_index (0, 0);
- cstep = flip_index (0, 1) - soff;
- rstep = flip_index (1, 0) - flip_index (0, width);
- for (row=0; row < height; row++, soff += rstep) {
- for (col=0; col < width; col++, soff += cstep)
- if (output_bps == 8)
- FORCC ppm [col*colors+c] = lut16[image[soff][c]]/256;
- else if(gamma_16bit) FORCC ppm2[col*colors+c] = lut16[image[soff][c]];
- else FORCC ppm2[col*colors+c] = image[soff][c];
- if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
- swab ((char*)ppm2, (char*)ppm2, width*colors*2);
- fwrite (ppm, colors*output_bps/8, width, ofp);
- }
- free (ppm);
-}
+#include "dcraw_defs.h"
+
+#include "../src/utils/read_utils.cpp"
+#include "../src/utils/curves.cpp"
+#include "../src/utils/utils_dcraw.cpp"
+
+#include "../src/tables/colordata.cpp"
+
+#include "../src/decoders/canon_600.cpp"
+#include "../src/decoders/decoders_dcraw.cpp"
+#include "../src/decoders/decoders_libraw_dcrdefs.cpp"
+#include "../src/decoders/generic.cpp"
+#include "../src/decoders/kodak_decoders.cpp"
+#include "../src/decoders/dng.cpp"
+#include "../src/decoders/smal.cpp"
+#include "../src/decoders/load_mfbacks.cpp"
+
+#include "../src/metadata/sony.cpp"
+#include "../src/metadata/nikon.cpp"
+#include "../src/metadata/samsung.cpp"
+#include "../src/metadata/cr3_parser.cpp"
+#include "../src/metadata/canon.cpp"
+#include "../src/metadata/epson.cpp"
+#include "../src/metadata/olympus.cpp"
+#include "../src/metadata/leica.cpp"
+#include "../src/metadata/fuji.cpp"
+#include "../src/metadata/adobepano.cpp"
+#include "../src/metadata/pentax.cpp"
+#include "../src/metadata/p1.cpp"
+#include "../src/metadata/makernotes.cpp"
+#include "../src/metadata/exif_gps.cpp"
+#include "../src/metadata/kodak.cpp"
+#include "../src/metadata/tiff.cpp"
+#include "../src/metadata/ciff.cpp"
+#include "../src/metadata/mediumformat.cpp"
+#include "../src/metadata/minolta.cpp"
+#include "../src/metadata/identify_tools.cpp"
+#include "../src/metadata/normalize_model.cpp"
+#include "../src/metadata/identify.cpp"
+#include "../src/metadata/hasselblad_model.cpp"
+#include "../src/metadata/misc_parsers.cpp"
+#include "../src/tables/wblists.cpp"
+#include "../src/postprocessing/postprocessing_aux.cpp"
+#include "../src/postprocessing/postprocessing_utils_dcrdefs.cpp"
+#include "../src/postprocessing/aspect_ratio.cpp"
+
+#include "../src/demosaic/misc_demosaic.cpp"
+#include "../src/demosaic/xtrans_demosaic.cpp"
+#include "../src/demosaic/ahd_demosaic.cpp"
+#include "../src/write/file_write.cpp"
diff --git a/libkdcraw/libraw/internal/dcraw_defs.h b/libkdcraw/libraw/internal/dcraw_defs.h
new file mode 100644
index 0000000..574f3a8
--- /dev/null
+++ b/libkdcraw/libraw/internal/dcraw_defs.h
@@ -0,0 +1,66 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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).
+
+ */
+
+#ifndef DCRAW_DEFS_H
+#define DCRAW_DEFS_H
+
+#include <math.h>
+#define LIBRAW_LIBRARY_BUILD
+#define LIBRAW_IO_REDEFINED
+#include "libraw/libraw.h"
+#include "libraw/libraw_types.h"
+#include "internal/defines.h"
+#include "internal/var_defines.h"
+
+#define stmread(buf, maxlen, fp) stread(buf, MIN(maxlen, sizeof(buf)), fp)
+#define strbuflen(buf) strnlen(buf, sizeof(buf) - 1)
+#define makeIs(idx) (maker_index == idx)
+#define strnXcat(buf, string) \
+ strncat(buf, string, LIM(sizeof(buf) - strbuflen(buf) - 1, 0, sizeof(buf)))
+
+// DNG was written by:
+#define nonDNG 0
+#define CameraDNG 1
+#define AdobeDNG 2
+
+// Makernote tag type:
+#define is_0x927c 0 /* most cameras */
+#define is_0xc634 2 /* Adobe DNG, Sony SR2, Pentax */
+
+// abbreviations
+#define ilm imgdata.lens.makernotes
+#define icWBC imgdata.color.WB_Coeffs
+#define icWBCCTC imgdata.color.WBCT_Coeffs
+#define imCanon imgdata.makernotes.canon
+#define imFuji imgdata.makernotes.fuji
+#define imHassy imgdata.makernotes.hasselblad
+#define imKodak imgdata.makernotes.kodak
+#define imNikon imgdata.makernotes.nikon
+#define imOly imgdata.makernotes.olympus
+#define imPana imgdata.makernotes.panasonic
+#define imPentax imgdata.makernotes.pentax
+#define imPhaseOne imgdata.makernotes.phaseone
+#define imRicoh imgdata.makernotes.ricoh
+#define imSamsung imgdata.makernotes.samsung
+#define imSony imgdata.makernotes.sony
+#define imCommon imgdata.makernotes.common
+
+
+#define ph1_bits(n) ph1_bithuff(n, 0)
+#define ph1_huff(h) ph1_bithuff(*h, h + 1)
+#define getbits(n) getbithuff(n, 0)
+#define gethuff(h) getbithuff(*h, h + 1)
+
+#endif
diff --git a/libkdcraw/libraw/internal/dcraw_fileio.cpp b/libkdcraw/libraw/internal/dcraw_fileio.cpp
index 3dc44ec..4cd02a9 100644
--- a/libkdcraw/libraw/internal/dcraw_fileio.cpp
+++ b/libkdcraw/libraw/internal/dcraw_fileio.cpp
@@ -1,213 +1,28 @@
-/*
- GENERATED FILE, DO NOT EDIT
- Generated from dcraw/dcraw.c at Tue Apr 7 15:14:50 2009
- Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
- for copyright information.
-*/
+/*
+ Copyright 2008-2020 LibRaw LLC ([email protected])
-#define CLASS LibRaw::
-#include "libraw/libraw_types.h"
-#define LIBRAW_LIBRARY_BUILD
-#include "libraw/libraw.h"
-#include "internal/defines.h"
-#include "internal/var_defines.h"
+ * This file is provided for compatibility w/ old build scripts/tools:
+ * It includes multiple separate files that should be built separately
+ * if new build tools are used
-/*
- Seach from the current directory up to the root looking for
- a ".badpixels" file, and fix those pixels now.
- */
-void CLASS bad_pixels (char *fname)
-{
- FILE *fp=0;
- char *cp, line[128];
- int len, time, row, col, r, c, rad, tot, n, fixed=0;
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of two licenses as you choose:
- if (!filters) return;
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS,0,2);
-#endif
- if (fname)
- fp = fopen (fname, "r");
- if (!fp)
- {
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.process_warnings |= LIBRAW_WARN_NO_BADPIXELMAP;
-#endif
- 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) && fc(r,c) == fc(row,col)) {
- tot += BAYER2(r,c);
- n++;
- }
- BAYER2(row,col) = tot/n;
-#ifdef DCRAW_VERBOSE
- if (verbose) {
- if (!fixed++)
- fprintf (stderr,_("Fixed dead pixels at:"));
- fprintf (stderr, " %d,%d", col, row);
- }
-#endif
- }
-#ifdef DCRAW_VERBOSE
- if (fixed) fputc ('\n', stderr);
-#endif
- fclose (fp);
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS,1,2);
-#endif
-}
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+ (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
-void CLASS subtract (char *fname)
-{
- FILE *fp;
- int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col;
- ushort *pixel;
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME,0,2);
-#endif
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
- if (!(fp = fopen (fname, "rb"))) {
-#ifdef DCRAW_VERBOSE
- perror (fname);
-#endif
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_FILE;
-#endif
- 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) {
- fprintf (stderr,_("%s is not a valid PGM file!\n"), fname);
- fclose (fp); return;
- } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) {
-#ifdef DCRAW_VERBOSE
- fprintf (stderr,_("%s has the wrong dimensions!\n"), fname);
-#endif
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_DIM;
-#endif
- fclose (fp); return;
- }
- pixel = (ushort *) calloc (width, sizeof *pixel);
- merror (pixel, "subtract()");
- for (row=0; row < height; row++) {
- fread (pixel, 2, width, fp);
- for (col=0; col < width; col++)
- BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0);
- }
- free (pixel);
- black = 0;
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME,1,2);
-#endif
-}
+ This file is generated from Dave Coffin's dcraw.c
+ dcraw.c -- Dave Coffin's raw photo decoder
+ Copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net
+
+ Look into dcraw homepage (probably http://cybercom.net/~dcoffin/dcraw/)
+ for more information
+*/
-#ifndef NO_LCMS
-void CLASS apply_profile (char *input, char *output)
-{
- char *prof;
- cmsHPROFILE hInProfile=0, hOutProfile=0;
- cmsHTRANSFORM hTransform;
- FILE *fp;
- unsigned size;
+#include "dcraw_fileio_defs.h"
-#if LCMS_VERSION < 2000
- cmsErrorAction (LCMS_ERROR_SHOW);
-#endif
- if (strcmp (input, "embed"))
- hInProfile = cmsOpenProfileFromFile (input, "r");
- else if (profile_length) {
-#ifndef LIBRAW_LIBRARY_BUILD
- prof = (char *) malloc (profile_length);
- merror (prof, "apply_profile()");
- fseek (ifp, profile_offset, SEEK_SET);
- fread (prof, 1, profile_length, ifp);
- hInProfile = cmsOpenProfileFromMem (prof, profile_length);
- free (prof);
-#else
- hInProfile = cmsOpenProfileFromMem (imgdata.color.profile, profile_length);
-#endif
- } else
- {
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.process_warnings |= LIBRAW_WARN_NO_EMBEDDED_PROFILE;
-#endif
-#ifdef DCRAW_VERBOSE
- fprintf (stderr,_("%s has no embedded profile.\n"), ifname);
-#endif
- }
- if (!hInProfile)
- {
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.process_warnings |= LIBRAW_WARN_NO_INPUT_PROFILE;
-#endif
- return;
- }
- if (!output)
- hOutProfile = cmsCreate_sRGBProfile();
- else if ((fp = fopen (output, "rb"))) {
- fread (&size, 4, 1, fp);
- fseek (fp, 0, SEEK_SET);
- oprof = (unsigned *) malloc (size = ntohl(size));
- merror (oprof, "apply_profile()");
- fread (oprof, 1, size, fp);
- fclose (fp);
- if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) {
- free (oprof);
- oprof = 0;
- }
-#ifdef DCRAW_VERBOSE
- } else
- fprintf (stderr,_("Cannot open file %s!\n"), output);
-#else
-}
-#endif
- if (!hOutProfile)
- {
-#ifdef LIBRAW_LIBRARY_BUILD
- imgdata.process_warnings |= LIBRAW_WARN_BAD_OUTPUT_PROFILE;
-#endif
- goto quit;
- }
-#ifdef DCRAW_VERBOSE
- if (verbose)
- fprintf (stderr,_("Applying color profile...\n"));
-#endif
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,0,2);
-#endif
- hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16,
- hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0);
- cmsDoTransform (hTransform, image, image, width*height);
- raw_color = 1; /* Don't use rgb_cam with a profile */
- cmsDeleteTransform (hTransform);
- cmsCloseProfile (hOutProfile);
-quit:
- cmsCloseProfile (hInProfile);
-#ifdef LIBRAW_LIBRARY_BUILD
- RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,1,2);
-#endif
-}
-#endif
+#include "../src/preprocessing/ext_preprocess.cpp"
+#include "../src/write/apply_profile.cpp"
diff --git a/libkdcraw/libraw/internal/dcraw_fileio_defs.h b/libkdcraw/libraw/internal/dcraw_fileio_defs.h
new file mode 100644
index 0000000..3d12edc
--- /dev/null
+++ b/libkdcraw/libraw/internal/dcraw_fileio_defs.h
@@ -0,0 +1,25 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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).
+
+ */
+
+#ifndef DCRAW_FILEIO_DEFS_H
+#define DCRAW_FILEIO_DEFS_H
+
+#include <math.h>
+#define LIBRAW_LIBRARY_BUILD
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#include "internal/var_defines.h"
+
+#endif
diff --git a/libkdcraw/libraw/internal/defines.h b/libkdcraw/libraw/internal/defines.h
index 9986b2f..674ad67 100644
--- a/libkdcraw/libraw/internal/defines.h
+++ b/libkdcraw/libraw/internal/defines.h
@@ -1,17 +1,37 @@
-/*
- GENERATED FILE, DO NOT EDIT
- Generated from dcraw/dcraw.c at Tue Apr 7 15:14:48 2009
- Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
- for copyright information.
+/*
+ Copyright 2008-2021 LibRaw LLC ([email protected])
+
+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).
+
+ This file is generated from Dave Coffin's dcraw.c
+ dcraw.c -- Dave Coffin's raw photo decoder
+ Copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net
+
+ Look into dcraw homepage (probably http://cybercom.net/~dcoffin/dcraw/)
+ for more information
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#ifndef LIBRAW_INT_DEFINES_H
+#define LIBRAW_INT_DEFINES_H
+#ifndef USE_JPEG
#define NO_JPEG
-#define DCRAW_VERSION "8.93"
-#define _USE_MATH_DEFINES
+#endif
+#ifndef USE_JASPER
+#define NO_JASPER
+#endif
+#define DCRAW_VERSION "9.26"
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#define _USE_MATH_DEFINES
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -24,38 +44,18 @@
#include <string.h>
#include <time.h>
#include <sys/types.h>
-
-#ifdef _OPENMP
-#include <omp.h>
-#endif
-/*
- NO_JPEG disables decoding of compressed Kodak DC120 files.
- NO_LCMS disables the "-p" option.
- */
-#ifndef NO_JPEG
-#include <jpeglib.h>
-#endif
-#ifndef NO_LCMS
-#include LCMS_HEADER
-#endif
-#ifdef LOCALEDIR
-#include <libintl.h>
-#define _(String) gettext(String)
-#else
-#define _(String) (String)
-#endif
#ifdef __CYGWIN__
#include <io.h>
#endif
-#ifdef WIN32
+#if defined LIBRAW_WIN32_CALLS
#include <sys/utime.h>
+#ifndef LIBRAW_NO_WINSOCK2
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
+#endif
#define snprintf _snprintf
-#define strcasecmp _stricmp
+#define strcasecmp stricmp
#define strncasecmp strnicmp
-typedef __int64 INT64;
-typedef unsigned __int64 UINT64;
#else
#include <unistd.h>
#include <utime.h>
@@ -64,27 +64,74 @@ typedef long long INT64;
typedef unsigned long long UINT64;
#endif
+#ifdef NODEPS
+#define NO_JASPER
+#define NO_JPEG
+#define NO_LCMS
+#endif
+#ifndef NO_JASPER
+#include <jasper/jasper.h> /* Decode Red camera movies */
+#endif
+#ifndef NO_JPEG
+#include <jpeglib.h> /* Decode compressed Kodak DC120 photos */
+#endif /* and Adobe Lossy DNGs */
+#ifndef NO_LCMS
+#ifdef USE_LCMS
+#include <lcms.h> /* Support color profiles */
+#else
+#include <lcms2.h> /* Support color profiles */
+#endif
+#endif
+#ifdef LOCALEDIR
+#include <libintl.h>
+#define _(String) gettext(String)
+#else
+#define _(String) (String)
+#endif
+
#ifdef LJPEG_DECODE
#error Please compile dcraw.c by itself.
#error Do not link it with ljpeg_decode.
#endif
#ifndef LONG_BIT
-#define LONG_BIT (8 * sizeof (long))
+#define LONG_BIT (8 * sizeof(long))
#endif
-#define FORC(cnt) for (c=0; c < cnt; c++)
+#define FORC(cnt) for (c = 0; c < cnt; c++)
#define FORC3 FORC(3)
#define FORC4 FORC(4)
-#define FORCC FORC(colors)
+#define FORCC for (c = 0; c < colors && c < 4; c++)
-#define SQR(x) ((x)*(x))
+#define SQR(x) ((x) * (x))
#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#define LIM(x,min,max) MAX(min,MIN(x,max))
-#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
-#define CLIP(x) LIM(x,0,65535)
-#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define LIM(x, min, max) MAX(min, MIN(x, max))
+#define ULIM(x, y, z) ((y) < (z) ? LIM(x, y, z) : LIM(x, z, y))
+#define CLIP(x) LIM((int)(x), 0, 65535)
+#define CLIP15(x) LIM((int)(x), 0, 32767)
+#define SWAP(a, b) \
+ { \
+ a = a + b; \
+ b = a - b; \
+ a = a - b; \
+ }
+
+#define my_swap(type, i, j) \
+ { \
+ type t = i; \
+ i = j; \
+ j = t; \
+ }
+
+#ifdef __GNUC__
+inline
+#elif defined(_MSC_VER)
+__forceinline
+#else
+static
+#endif
+float fMAX(float a, float b) { return MAX(a, b); }
/*
In order to inline this calculation, I make the risky
@@ -96,37 +143,51 @@ typedef unsigned long long UINT64;
Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
- PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1
- 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4:
-
- 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
- 0 G M G M G M 0 C Y C Y C Y 0 Y C Y C Y C 0 G M G M G M
- 1 C Y C Y C Y 1 M G M G M G 1 M G M G M G 1 Y C Y C Y C
- 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y
- 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M
- 4 C Y C Y C Y 4 Y C Y C Y C
- PowerShot A5 5 G M G M G M 5 G M G M G M
- 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y
- 7 M G M G M G 7 M G M G M G
- 0 1 2 3 4 5
- 0 C Y C Y C Y
- 1 G M G M G M
- 2 C Y C Y C Y
- 3 M G M G M G
+ PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1
+ 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4:
+
+ 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
+ 0 G M G M G M 0 C Y C Y C Y 0 Y C Y C Y C 0 G M G M G M
+ 1 C Y C Y C Y 1 M G M G M G 1 M G M G M G 1 Y C Y C Y C
+ 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y
+ 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M
+ 4 C Y C Y C Y 4 Y C Y C Y C
+ PowerShot A5 5 G M G M G M 5 G M G M G M
+ 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y
+ 7 M G M G M G 7 M G M G M G
+ 0 1 2 3 4 5
+ 0 C Y C Y C Y
+ 1 G M G M G M
+ 2 C Y C Y C Y
+ 3 M G M G M G
All RGB cameras use one of these Bayer grids:
- 0x16161616: 0x61616161: 0x49494949: 0x94949494:
+ 0x16161616: 0x61616161: 0x49494949: 0x94949494:
- 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
- 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G
- 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B
- 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G
- 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B
+ 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
+ 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G
+ 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B
+ 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G
+ 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B
*/
-#define BAYER(row,col) \
- image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
+// _RGBG means R, G1, B, G2 sequence
+#define GRBG_2_RGBG(q) (q ^ (q >> 1) ^ 1)
+#define RGGB_2_RGBG(q) (q ^ (q >> 1))
+#define BG2RG1_2_RGBG(q) (q ^ 2)
+#define G2BRG1_2_RGBG(q) (q ^ (q >> 1) ^ 3)
+#define GRGB_2_RGBG(q) (q ^ 1)
+#define RBGG_2_RGBG(q) ((q >> 1) | ((q & 1) << 1))
+
+#define RAWINDEX(row, col) ((row)*raw_width + (col))
+#define RAW(row, col) raw_image[(row)*raw_width + (col)]
+#define BAYER(row, col) \
+ image[((row) >> shrink) * iwidth + ((col) >> shrink)][FC(row, col)]
-#define BAYER2(row,col) \
- image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)]
+#define BAYER2(row, col) \
+ image[((row) >> shrink) * iwidth + ((col) >> shrink)][fcol(row, col)]
+#define BAYERC(row, col, c) \
+ imgdata.image[((row) >> IO.shrink) * S.iwidth + ((col) >> IO.shrink)][c]
+
+#endif
diff --git a/libkdcraw/libraw/internal/demosaic_packs.cpp b/libkdcraw/libraw/internal/demosaic_packs.cpp
new file mode 100644
index 0000000..66a2513
--- /dev/null
+++ b/libkdcraw/libraw/internal/demosaic_packs.cpp
@@ -0,0 +1,35 @@
+/*
+ Copyright 2008-2013 LibRaw LLC ([email protected])
+
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of two licenses as you choose:
+
+ * This file is provided for compatibility w/ old build scripts/tools:
+ * It includes multiple separate files that should be built separately
+ * if new build tools are used
+
+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 <math.h>
+
+#define LIBRAW_LIBRARY_BUILD
+#define LIBRAW_IO_REDEFINED
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#define SRC_USES_SHRINK
+#define SRC_USES_BLACK
+#define SRC_USES_CURVE
+
+/* DHT and AAHD are LGPL licensed, so include them */
+#include "../src/demosaic/dht_demosaic.cpp"
+#include "../src/demosaic/aahd_demosaic.cpp"
+#include "internal/var_defines.h"
+
+/* DCB is BSD licensed, so include it */
+#include "../src/demosaic/dcb_demosaic.cpp"
diff --git a/libkdcraw/libraw/internal/dmp_include.h b/libkdcraw/libraw/internal/dmp_include.h
new file mode 100644
index 0000000..6b6b5a6
--- /dev/null
+++ b/libkdcraw/libraw/internal/dmp_include.h
@@ -0,0 +1,27 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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).
+
+ */
+
+#ifndef DMP_INCLUDE_H
+#define DMP_INCLUDE_H
+
+#define LIBRAW_LIBRARY_BUILD
+#define LIBRAW_IO_REDEFINED
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#define SRC_USES_SHRINK
+#define SRC_USES_BLACK
+#define SRC_USES_CURVE
+
+#endif
diff --git a/libkdcraw/libraw/internal/libraw_cameraids.h b/libkdcraw/libraw/internal/libraw_cameraids.h
new file mode 100644
index 0000000..4d03006
--- /dev/null
+++ b/libkdcraw/libraw/internal/libraw_cameraids.h
@@ -0,0 +1,320 @@
+/* -*- C++ -*-
+ * File: internal/libraw_cameraids.h
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Sat Aug 17, 2020
+
+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).
+
+ */
+
+#ifndef LIBRAW_CONST_H
+#define LIBRAW_CONST_H
+
+#define CanonID_EOS_M50 0x00000412ULL
+#define CanonID_EOS_M6_Mark_II 0x00000811ULL
+#define CanonID_EOS_M200 0x00000812ULL
+#define CanonID_EOS_D30 0x01140000ULL
+#define CanonID_EOS_D60 0x01668000ULL
+#define CanonID_EOS_M3 0x03740000ULL
+#define CanonID_EOS_M10 0x03840000ULL
+#define CanonID_EOS_M5 0x03940000ULL
+#define CanonID_EOS_M100 0x03980000ULL
+#define CanonID_EOS_M6 0x04070000ULL
+#define CanonID_EOS_1D (0x80000000ULL + 0x001ULL)
+#define CanonID_EOS_1Ds (0x80000000ULL + 0x167ULL)
+#define CanonID_EOS_10D (0x80000000ULL + 0x168ULL)
+#define CanonID_EOS_1D_Mark_III (0x80000000ULL + 0x169ULL)
+#define CanonID_EOS_300D (0x80000000ULL + 0x170ULL)
+#define CanonID_EOS_1D_Mark_II (0x80000000ULL + 0x174ULL)
+#define CanonID_EOS_20D (0x80000000ULL + 0x175ULL)
+#define CanonID_EOS_450D (0x80000000ULL + 0x176ULL)
+#define CanonID_EOS_1Ds_Mark_II (0x80000000ULL + 0x188ULL)
+#define CanonID_EOS_350D (0x80000000ULL + 0x189ULL)
+#define CanonID_EOS_40D (0x80000000ULL + 0x190ULL)
+#define CanonID_EOS_5D (0x80000000ULL + 0x213ULL)
+#define CanonID_EOS_1Ds_Mark_III (0x80000000ULL + 0x215ULL)
+#define CanonID_EOS_5D_Mark_II (0x80000000ULL + 0x218ULL)
+#define CanonID_EOS_1D_Mark_II_N (0x80000000ULL + 0x232ULL)
+#define CanonID_EOS_30D (0x80000000ULL + 0x234ULL)
+#define CanonID_EOS_400D (0x80000000ULL + 0x236ULL)
+#define CanonID_EOS_7D (0x80000000ULL + 0x250ULL)
+#define CanonID_EOS_500D (0x80000000ULL + 0x252ULL)
+#define CanonID_EOS_1000D (0x80000000ULL + 0x254ULL)
+#define CanonID_EOS_50D (0x80000000ULL + 0x261ULL)
+#define CanonID_EOS_1D_X (0x80000000ULL + 0x269ULL)
+#define CanonID_EOS_550D (0x80000000ULL + 0x270ULL)
+#define CanonID_EOS_1D_Mark_IV (0x80000000ULL + 0x281ULL)
+#define CanonID_EOS_5D_Mark_III (0x80000000ULL + 0x285ULL)
+#define CanonID_EOS_600D (0x80000000ULL + 0x286ULL)
+#define CanonID_EOS_60D (0x80000000ULL + 0x287ULL)
+#define CanonID_EOS_1100D (0x80000000ULL + 0x288ULL)
+#define CanonID_EOS_7D_Mark_II (0x80000000ULL + 0x289ULL)
+#define CanonID_EOS_650D (0x80000000ULL + 0x301ULL)
+#define CanonID_EOS_6D (0x80000000ULL + 0x302ULL)
+#define CanonID_EOS_1D_C (0x80000000ULL + 0x324ULL)
+#define CanonID_EOS_70D (0x80000000ULL + 0x325ULL)
+#define CanonID_EOS_700D (0x80000000ULL + 0x326ULL)
+#define CanonID_EOS_1200D (0x80000000ULL + 0x327ULL)
+#define CanonID_EOS_1D_X_Mark_II (0x80000000ULL + 0x328ULL)
+#define CanonID_EOS_M (0x80000000ULL + 0x331ULL)
+#define CanonID_EOS_100D (0x80000000ULL + 0x346ULL)
+#define CanonID_EOS_760D (0x80000000ULL + 0x347ULL)
+#define CanonID_EOS_5D_Mark_IV (0x80000000ULL + 0x349ULL)
+#define CanonID_EOS_80D (0x80000000ULL + 0x350ULL)
+#define CanonID_EOS_M2 (0x80000000ULL + 0x355ULL)
+#define CanonID_EOS_5DS (0x80000000ULL + 0x382ULL)
+#define CanonID_EOS_750D (0x80000000ULL + 0x393ULL)
+#define CanonID_EOS_5DS_R (0x80000000ULL + 0x401ULL)
+#define CanonID_EOS_1300D (0x80000000ULL + 0x404ULL)
+#define CanonID_EOS_800D (0x80000000ULL + 0x405ULL)
+#define CanonID_EOS_6D_Mark_II (0x80000000ULL + 0x406ULL)
+#define CanonID_EOS_77D (0x80000000ULL + 0x408ULL)
+#define CanonID_EOS_200D (0x80000000ULL + 0x417ULL)
+#define CanonID_EOS_R5 (0x80000000ULL + 0x421ULL)
+#define CanonID_EOS_3000D (0x80000000ULL + 0x422ULL)
+#define CanonID_EOS_R (0x80000000ULL + 0x424ULL)
+#define CanonID_EOS_1D_X_Mark_III (0x80000000ULL + 0x428ULL)
+#define CanonID_EOS_1500D (0x80000000ULL + 0x432ULL)
+#define CanonID_EOS_RP (0x80000000ULL + 0x433ULL)
+#define CanonID_EOS_850D (0x80000000ULL + 0x435ULL)
+#define CanonID_EOS_250D (0x80000000ULL + 0x436ULL)
+#define CanonID_EOS_90D (0x80000000ULL + 0x437ULL)
+#define CanonID_EOS_R3 (0x80000000ULL + 0x450ULL)
+#define CanonID_EOS_R6 (0x80000000ULL + 0x453ULL)
+#define CanonID_EOS_R7 (0x80000000ULL + 0x464ULL)
+#define CanonID_EOS_R10 (0x80000000ULL + 0x465ULL)
+#define CanonID_EOS_M50_Mark_II (0x80000000ULL + 0x468ULL)
+
+// CanonID_EOS_D2000C after Canon's TIFF2CR2 convertor:
+#define CanonID_EOS_D2000C (0x80000000ULL + 0x520ULL)
+// CanonID_EOS_D6000C id after Canon's TIFF2CR2 convertor:
+#define CanonID_EOS_D6000C (0x80000000ULL + 0x560ULL)
+
+#define OlyID_str2hex(str) ((unsigned long long)str[0]<<32 | str[1]<<24 | str[2]<<16 | str[3]<<8 | str[4])
+#define OlyID_E_20 OlyID_str2hex("D4029")
+#define OlyID_E_1 OlyID_str2hex("D4040")
+#define OlyID_E_300 OlyID_str2hex("D4041")
+#define OlyID_SP_550UZ OlyID_str2hex("D4321")
+#define OlyID_SP_510UZ OlyID_str2hex("D4322")
+#define OlyID_SP_560UZ OlyID_str2hex("D4355")
+#define OlyID_SP_570UZ OlyID_str2hex("D4364")
+#define OlyID_SP_565UZ OlyID_str2hex("D4374")
+#define OlyID_XZ_1 OlyID_str2hex("D4401")
+#define OlyID_XZ_2 OlyID_str2hex("D4531")
+#define OlyID_XZ_10 OlyID_str2hex("D4546")
+#define OlyID_STYLUS_1 OlyID_str2hex("D4572")
+#define OlyID_SH_2 OlyID_str2hex("D4585")
+#define OlyID_TG_4 OlyID_str2hex("D4586")
+#define OlyID_TG_5 OlyID_str2hex("D4593")
+#define OlyID_TG_6 OlyID_str2hex("D4603")
+#define OlyID_E_10 OlyID_str2hex("D4842")
+#define OlyID_AIR_A01 OlyID_str2hex("K0055")
+#define OlyID_NORMA OlyID_str2hex("NORMA")
+#define OlyID_E_330 OlyID_str2hex("S0003")
+#define OlyID_E_500 OlyID_str2hex("S0004")
+#define OlyID_E_400 OlyID_str2hex("S0009")
+#define OlyID_E_510 OlyID_str2hex("S0010")
+#define OlyID_E_3 OlyID_str2hex("S0011")
+#define OlyID_E_410 OlyID_str2hex("S0013")
+#define OlyID_E_420 OlyID_str2hex("S0016")
+#define OlyID_E_30 OlyID_str2hex("S0017")
+#define OlyID_E_520 OlyID_str2hex("S0018")
+#define OlyID_E_P1 OlyID_str2hex("S0019")
+#define OlyID_E_620 OlyID_str2hex("S0023")
+#define OlyID_E_P2 OlyID_str2hex("S0026")
+#define OlyID_E_PL1 OlyID_str2hex("S0027")
+#define OlyID_E_450 OlyID_str2hex("S0029")
+#define OlyID_E_600 OlyID_str2hex("S0030")
+#define OlyID_E_P3 OlyID_str2hex("S0032")
+#define OlyID_E_5 OlyID_str2hex("S0033")
+#define OlyID_E_PL2 OlyID_str2hex("S0034")
+#define OlyID_E_M5 OlyID_str2hex("S0036")
+#define OlyID_E_PL3 OlyID_str2hex("S0038")
+#define OlyID_E_PM1 OlyID_str2hex("S0039")
+#define OlyID_E_PL1s OlyID_str2hex("S0040")
+#define OlyID_E_PL5 OlyID_str2hex("S0042")
+#define OlyID_E_PM2 OlyID_str2hex("S0043")
+#define OlyID_E_P5 OlyID_str2hex("S0044")
+#define OlyID_E_PL6 OlyID_str2hex("S0045")
+#define OlyID_E_PL7 OlyID_str2hex("S0046")
+#define OlyID_E_M1 OlyID_str2hex("S0047")
+#define OlyID_E_M10 OlyID_str2hex("S0051")
+#define OlyID_E_M5_Mark_II OlyID_str2hex("S0052")
+#define OlyID_E_M10_Mark_II OlyID_str2hex("S0059")
+#define OlyID_PEN_F OlyID_str2hex("S0061")
+#define OlyID_E_PL8 OlyID_str2hex("S0065")
+#define OlyID_E_M1_Mark_II OlyID_str2hex("S0067")
+#define OlyID_E_M10_Mark_III OlyID_str2hex("S0068")
+#define OlyID_E_PL9 OlyID_str2hex("S0076")
+#define OlyID_E_M1X OlyID_str2hex("S0080")
+#define OlyID_E_PL10 OlyID_str2hex("S0085")
+#define OlyID_E_M10_Mark_IV OlyID_str2hex("S0088")
+#define OlyID_E_M5_Mark_III OlyID_str2hex("S0089")
+#define OlyID_E_M1_Mark_III OlyID_str2hex("S0092")
+#define OlyID_E_P7 OlyID_str2hex("S0093")
+#define OlyID_OM_1 OlyID_str2hex("S0095")
+#define OlyID_C_3030Z OlyID_str2hex("SX351")
+#define OlyID_C_5050Z OlyID_str2hex("SX558")
+#define OlyID_C_350Z OlyID_str2hex("SX751")
+#define OlyID_C_740UZ OlyID_str2hex("SX754")
+#define OlyID_C_5060WZ OlyID_str2hex("SX756")
+#define OlyID_C_8080WZ OlyID_str2hex("SX757")
+#define OlyID_C_770UZ OlyID_str2hex("SX772")
+#define OlyID_C_7070WZ OlyID_str2hex("SX851")
+#define OlyID_C_7000Z OlyID_str2hex("SX852")
+#define OlyID_SP_500UZ OlyID_str2hex("SX853")
+#define OlyID_SP_310 OlyID_str2hex("SX854")
+#define OlyID_SP_350 OlyID_str2hex("SX855")
+#define OlyID_SP_320 OlyID_str2hex("SX873")
+
+#define PentaxID_Optio_S 0x1296cULL
+#define PentaxID_Optio_S_V101 0x12971ULL
+#define PentaxID_staristD 0x12994ULL
+#define PentaxID_Optio_33WR 0x129c6ULL
+#define PentaxID_Optio_S4 0x129d5ULL
+#define PentaxID_Optio_750Z 0x12a66ULL
+#define PentaxID_staristDS 0x12aa2ULL
+#define PentaxID_staristDL 0x12b1aULL
+#define PentaxID_staristDS2 0x12b60ULL
+#define PentaxID_GX_1S 0x12b62ULL
+#define PentaxID_staristDL2 0x12b7eULL
+#define PentaxID_GX_1L 0x12b80ULL
+#define PentaxID_K100D 0x12b9cULL
+#define PentaxID_K110D 0x12b9dULL
+#define PentaxID_K100D_Super 0x12ba2ULL
+#define PentaxID_K10D 0x12c1eULL
+#define PentaxID_GX10 0x12c20ULL
+#define PentaxID_K20D 0x12cd2ULL
+#define PentaxID_GX20 0x12cd4ULL
+#define PentaxID_K200D 0x12cfaULL
+#define PentaxID_K2000 0x12d72ULL
+#define PentaxID_K_m 0x12d73ULL
+#define PentaxID_K_7 0x12db8ULL
+#define PentaxID_K_x 0x12dfeULL
+#define PentaxID_645D 0x12e08ULL
+#define PentaxID_K_r 0x12e6cULL
+#define PentaxID_K_5 0x12e76ULL
+#define PentaxID_Q 0x12ee4ULL
+#define PentaxID_K_01 0x12ef8ULL
+#define PentaxID_K_30 0x12f52ULL
+#define PentaxID_Q10 0x12f66ULL
+#define PentaxID_K_5_II 0x12f70ULL
+#define PentaxID_K_5_II_s 0x12f71ULL
+#define PentaxID_Q7 0x12f7aULL
+#define PentaxID_MX_1 0x12f84ULL
+#define PentaxID_K_50 0x12fb6ULL
+#define PentaxID_K_3 0x12fc0ULL
+#define PentaxID_K_500 0x12fcaULL
+#define PentaxID_645Z 0x13010ULL
+#define PentaxID_K_S1 0x1301aULL
+#define PentaxID_K_S2 0x13024ULL
+#define PentaxID_Q_S1 0x1302eULL
+#define PentaxID_K_1 0x13092ULL
+#define PentaxID_K_3_II 0x1309cULL
+#define PentaxID_GR_III 0x1320eULL
+#define PentaxID_K_70 0x13222ULL
+#define PentaxID_KP 0x1322cULL
+#define PentaxID_K_1_Mark_II 0x13240ULL
+#define PentaxID_K_3_III 0x13254ULL
+#define PentaxID_GR_IIIx 0x1329aULL
+
+#define SonyID_DSC_R1 0x002ULL
+#define SonyID_DSLR_A100 0x100ULL
+#define SonyID_DSLR_A900 0x101ULL
+#define SonyID_DSLR_A700 0x102ULL
+#define SonyID_DSLR_A200 0x103ULL
+#define SonyID_DSLR_A350 0x104ULL
+#define SonyID_DSLR_A300 0x105ULL
+#define SonyID_DSLR_A900_APSC 0x106ULL
+#define SonyID_DSLR_A380 0x107ULL
+#define SonyID_DSLR_A330 0x108ULL
+#define SonyID_DSLR_A230 0x109ULL
+#define SonyID_DSLR_A290 0x10aULL
+#define SonyID_DSLR_A850 0x10dULL
+#define SonyID_DSLR_A850_APSC 0x10eULL
+#define SonyID_DSLR_A550 0x111ULL
+#define SonyID_DSLR_A500 0x112ULL
+#define SonyID_DSLR_A450 0x113ULL
+#define SonyID_NEX_5 0x116ULL
+#define SonyID_NEX_3 0x117ULL
+#define SonyID_SLT_A33 0x118ULL
+#define SonyID_SLT_A55 0x119ULL
+#define SonyID_DSLR_A560 0x11aULL
+#define SonyID_DSLR_A580 0x11bULL
+#define SonyID_NEX_C3 0x11cULL
+#define SonyID_SLT_A35 0x11dULL
+#define SonyID_SLT_A65 0x11eULL
+#define SonyID_SLT_A77 0x11fULL
+#define SonyID_NEX_5N 0x120ULL
+#define SonyID_NEX_7 0x121ULL
+#define SonyID_NEX_VG20 0x122ULL
+#define SonyID_SLT_A37 0x123ULL
+#define SonyID_SLT_A57 0x124ULL
+#define SonyID_NEX_F3 0x125ULL
+#define SonyID_SLT_A99 0x126ULL
+#define SonyID_NEX_6 0x127ULL
+#define SonyID_NEX_5R 0x128ULL
+#define SonyID_DSC_RX100 0x129ULL
+#define SonyID_DSC_RX1 0x12aULL
+#define SonyID_NEX_VG900 0x12bULL
+#define SonyID_NEX_VG30 0x12cULL
+#define SonyID_ILCE_3000 0x12eULL
+#define SonyID_SLT_A58 0x12fULL
+#define SonyID_NEX_3N 0x131ULL
+#define SonyID_ILCE_7 0x132ULL
+#define SonyID_NEX_5T 0x133ULL
+#define SonyID_DSC_RX100M2 0x134ULL
+#define SonyID_DSC_RX10 0x135ULL
+#define SonyID_DSC_RX1R 0x136ULL
+#define SonyID_ILCE_7R 0x137ULL
+#define SonyID_ILCE_6000 0x138ULL
+#define SonyID_ILCE_5000 0x139ULL
+#define SonyID_DSC_RX100M3 0x13dULL
+#define SonyID_ILCE_7S 0x13eULL
+#define SonyID_ILCA_77M2 0x13fULL
+#define SonyID_ILCE_5100 0x153ULL
+#define SonyID_ILCE_7M2 0x154ULL
+#define SonyID_DSC_RX100M4 0x155ULL
+#define SonyID_DSC_RX10M2 0x156ULL
+#define SonyID_DSC_RX1RM2 0x158ULL
+#define SonyID_ILCE_QX1 0x15aULL
+#define SonyID_ILCE_7RM2 0x15bULL
+#define SonyID_ILCE_7SM2 0x15eULL
+#define SonyID_ILCA_68 0x161ULL
+#define SonyID_ILCA_99M2 0x162ULL
+#define SonyID_DSC_RX10M3 0x163ULL
+#define SonyID_DSC_RX100M5 0x164ULL
+#define SonyID_ILCE_6300 0x165ULL
+#define SonyID_ILCE_9 0x166ULL
+#define SonyID_ILCE_6500 0x168ULL
+#define SonyID_ILCE_7RM3 0x16aULL
+#define SonyID_ILCE_7M3 0x16bULL
+#define SonyID_DSC_RX0 0x16cULL
+#define SonyID_DSC_RX10M4 0x16dULL
+#define SonyID_DSC_RX100M6 0x16eULL
+#define SonyID_DSC_HX99 0x16fULL
+#define SonyID_DSC_RX100M5A 0x171ULL
+#define SonyID_ILCE_6400 0x173ULL
+#define SonyID_DSC_RX0M2 0x174ULL
+#define SonyID_DSC_RX100M7 0x176ULL
+#define SonyID_ILCE_7RM4 0x177ULL
+#define SonyID_ILCE_9M2 0x178ULL
+#define SonyID_ILCE_6600 0x17aULL
+#define SonyID_ILCE_6100 0x17bULL
+#define SonyID_ZV_1 0x17cULL
+#define SonyID_ILCE_7C 0x17dULL
+#define SonyID_ZV_E10 0x17eULL
+#define SonyID_ILCE_7SM3 0x17fULL
+#define SonyID_ILCE_1 0x180ULL
+#define SonyID_ILME_FX3 0x181ULL
+#define SonyID_ILCE_7RM3A 0x182ULL
+#define SonyID_ILCE_7RM4A 0x183ULL
+#define SonyID_ILCE_7M4 0x184ULL
+#endif
diff --git a/libkdcraw/libraw/internal/libraw_cxx_defs.h b/libkdcraw/libraw/internal/libraw_cxx_defs.h
new file mode 100644
index 0000000..1648493
--- /dev/null
+++ b/libkdcraw/libraw/internal/libraw_cxx_defs.h
@@ -0,0 +1,133 @@
+/* -*- C++ -*-
+ * File: internal/libraw_cxx_defs.h
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Sat Aug 17, 2020
+
+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).
+
+ */
+
+#ifndef _LIBRAW_CXX_DEFS_H
+#define _LIBRAW_CXX_DEFS_H
+
+#include <math.h>
+#include <errno.h>
+#include <float.h>
+#include <new>
+#include <exception>
+#include <sys/types.h>
+#include <sys/stat.h>
+#define LIBRAW_LIBRARY_BUILD
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#ifdef USE_ZLIB
+#include <zlib.h>
+#endif
+
+#ifndef LIBRAW_WIN32_CALLS
+#include <netinet/in.h>
+#else
+#ifndef LIBRAW_NO_WINSOCK2
+#include <winsock2.h>
+#endif
+#include <io.h>
+#endif
+
+#ifdef USE_RAWSPEED
+#include <RawSpeed/StdAfx.h>
+#include <RawSpeed/FileMap.h>
+#include <RawSpeed/RawParser.h>
+#include <RawSpeed/RawDecoder.h>
+#include <RawSpeed/CameraMetaData.h>
+#include <RawSpeed/ColorFilterArray.h>
+extern const char *_rawspeed_data_xml[];
+extern const int RAWSPEED_DATA_COUNT;
+class CameraMetaDataLR : public RawSpeed::CameraMetaData
+{
+public:
+ CameraMetaDataLR() : CameraMetaData() {}
+ CameraMetaDataLR(char *filename) : RawSpeed::CameraMetaData(filename) {}
+ CameraMetaDataLR(char *data, int sz);
+};
+
+CameraMetaDataLR *make_camera_metadata();
+
+#endif
+
+#ifdef USE_DNGSDK
+#include "dng_host.h"
+#include "dng_negative.h"
+#include "dng_simple_image.h"
+#include "dng_info.h"
+#endif
+
+#define P1 imgdata.idata
+#define S imgdata.sizes
+#define O imgdata.params
+#define C imgdata.color
+#define T imgdata.thumbnail
+#define MN imgdata.makernotes
+#define IO libraw_internal_data.internal_output_params
+#define ID libraw_internal_data.internal_data
+
+#define makeIs(idx) (imgdata.idata.maker_index == idx)
+#define mnCamID imgdata.lens.makernotes.CamID
+
+#define EXCEPTION_HANDLER(e) \
+ do \
+ { \
+ switch (e) \
+ { \
+ case LIBRAW_EXCEPTION_MEMPOOL: \
+ recycle(); \
+ return LIBRAW_MEMPOOL_OVERFLOW; \
+ case LIBRAW_EXCEPTION_ALLOC: \
+ recycle(); \
+ return LIBRAW_UNSUFFICIENT_MEMORY; \
+ case LIBRAW_EXCEPTION_TOOBIG: \
+ recycle(); \
+ return LIBRAW_TOO_BIG; \
+ case LIBRAW_EXCEPTION_DECODE_RAW: \
+ case LIBRAW_EXCEPTION_DECODE_JPEG: \
+ recycle(); \
+ return LIBRAW_DATA_ERROR; \
+ case LIBRAW_EXCEPTION_DECODE_JPEG2000: \
+ recycle(); \
+ return LIBRAW_DATA_ERROR; \
+ case LIBRAW_EXCEPTION_IO_EOF: \
+ case LIBRAW_EXCEPTION_IO_CORRUPT: \
+ recycle(); \
+ return LIBRAW_IO_ERROR; \
+ case LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK: \
+ recycle(); \
+ return LIBRAW_CANCELLED_BY_CALLBACK; \
+ case LIBRAW_EXCEPTION_BAD_CROP: \
+ recycle(); \
+ return LIBRAW_BAD_CROP; \
+ case LIBRAW_EXCEPTION_UNSUPPORTED_FORMAT: \
+ recycle(); \
+ return LIBRAW_FILE_UNSUPPORTED; \
+ default: \
+ return LIBRAW_UNSPECIFIED_ERROR; \
+ } \
+ } while (0)
+
+// copy-n-paste from image pipe
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define LIM(x, min, max) MAX(min, MIN(x, max))
+#ifndef CLIP
+#define CLIP(x) LIM(x, 0, 65535)
+#endif
+#define THUMB_READ_BEYOND 16384
+
+#define ZERO(a) memset(&a, 0, sizeof(a))
+
+#endif
diff --git a/libkdcraw/libraw/internal/libraw_internal_funcs.h b/libkdcraw/libraw/internal/libraw_internal_funcs.h
index c52c091..6abdb6b 100644
--- a/libkdcraw/libraw/internal/libraw_internal_funcs.h
+++ b/libkdcraw/libraw/internal/libraw_internal_funcs.h
@@ -1,24 +1,17 @@
-/*
+/* -*- C++ -*-
* File: libraw_internal_funcs.h
- * Copyright 2008 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
* Created: Sat Mar 14, 2008
- *
- * LibRaw internal data structures (not visible outside)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+
+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).
+
*/
#ifndef _LIBRAW_INTERNAL_FUNCS_H
@@ -27,175 +20,393 @@
#ifndef LIBRAW_LIBRARY_BUILD
#error "This file should be used only for libraw library build"
#else
-// inline functions
- ushort sget2 (uchar *s);
- ushort get2();
- unsigned sget4 (uchar *s);
- unsigned getint (int type);
- float int_to_float (int i);
- double getreal (int type);
- void read_shorts (ushort *pixel, int count);
-
-// Canon P&S cameras
- void canon_600_fixed_wb (int temp);
- int canon_600_color (int ratio[2], int mar);
- void canon_600_auto_wb();
- void canon_600_coeff();
- void canon_600_load_raw();
- int canon_s2is();
- void canon_a5_load_raw();
- void parse_ciff (int offset, int length);
- void ciff_block_1030();
+
+/* inline functions */
+ static int stread(char *buf, size_t len, LibRaw_abstract_datastream *fp);
+ static int getwords(char *line, char *words[], int maxwords, int maxlen);
+ static void remove_trailing_spaces(char *string, size_t len);
+ static void remove_caseSubstr(char *string, char *remove);
+ static void removeExcessiveSpaces(char *string);
+ static void trimSpaces(char *s);
+/* static tables/variables */
+ static libraw_static_table_t tagtype_dataunit_bytes;
+ static libraw_static_table_t Canon_wbi2std;
+ static libraw_static_table_t Canon_KeyIsZero_Len2048_linenums_2_StdWBi;
+ static libraw_static_table_t Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi;
+ static libraw_static_table_t Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi;
+ static libraw_static_table_t Canon_D30_linenums_2_StdWBi;
+ static libraw_static_table_t Canon_G9_linenums_2_StdWBi;
+
+ static libraw_static_table_t Fuji_wb_list1;
+ static libraw_static_table_t FujiCCT_K;
+ static libraw_static_table_t Fuji_wb_list2;
+
+ static libraw_static_table_t Pentax_wb_list1;
+ static libraw_static_table_t Pentax_wb_list2;
+
+ static libraw_static_table_t Oly_wb_list1;
+ static libraw_static_table_t Oly_wb_list2;
+
+ static libraw_static_table_t Sony_SRF_wb_list;
+ static libraw_static_table_t Sony_SR2_wb_list;
+ static libraw_static_table_t Sony_SR2_wb_list1;
+/* */
+ int find_ifd_by_offset(int );
+ void libraw_swab(void *arr, size_t len);
+ ushort sget2 (uchar *s);
+ ushort sget2Rev(uchar *s);
+ libraw_area_t get_CanonArea();
+ int parseCR3(INT64 oAtomList, INT64 szAtomList, short &nesting, char *AtomNameStack, short& nTrack, short &TrackType);
+ void selectCRXTrack();
+ void parseCR3_Free();
+ int parseCR3_CTMD(short trackNum);
+ int selectCRXFrame(short trackNum, unsigned frameIndex);
+ void setCanonBodyFeatures (unsigned long long id);
+ void processCanonCameraInfo (unsigned long long id, uchar *CameraInfo, unsigned maxlen, unsigned type, unsigned dng_writer);
+ static float _CanonConvertAperture(ushort in);
+ void Canon_CameraSettings(unsigned len);
+ void Canon_WBpresets (int skip1, int skip2);
+ void Canon_WBCTpresets (short WBCTversion);
+ void parseCanonMakernotes (unsigned tag, unsigned type, unsigned len, unsigned dng_writer);
+ void processNikonLensData (uchar *LensData, unsigned len);
+ void Nikon_NRW_WBtag (int wb, int skip);
+ void parseNikonMakernote (int base, int uptag, unsigned dng_writer);
+ void parseEpsonMakernote (int base, int uptag, unsigned dng_writer);
+ void parseSigmaMakernote (int base, int uptag, unsigned dng_writer);
+ void setOlympusBodyFeatures (unsigned long long id);
+ void getOlympus_CameraType2 ();
+ void getOlympus_SensorTemperature (unsigned len);
+ void parseOlympus_Equipment (unsigned tag, unsigned type, unsigned len, unsigned dng_writer);
+ void parseOlympus_CameraSettings (int base, unsigned tag, unsigned type, unsigned len, unsigned dng_writer);
+ void parseOlympus_ImageProcessing (unsigned tag, unsigned type, unsigned len, unsigned dng_writer);
+ void parseOlympus_RawInfo (unsigned tag, unsigned type, unsigned len, unsigned dng_writer);
+ void parseOlympusMakernotes (int base, unsigned tag, unsigned type, unsigned len, unsigned dng_writer);
+ void setPhaseOneFeatures (unsigned long long id);
+ void setPentaxBodyFeatures (unsigned long long id);
+ void PentaxISO (ushort c);
+ void PentaxLensInfo (unsigned long long id, unsigned len);
+ void parsePentaxMakernotes(int base, unsigned tag, unsigned type, unsigned len, unsigned dng_writer);
+ void parseRicohMakernotes(int base, unsigned tag, unsigned type, unsigned len, unsigned dng_writer);
+ void parseSamsungMakernotes(int base, unsigned tag, unsigned type, unsigned len, unsigned dng_writer);
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ void fixupArri();
+#endif
+ void setSonyBodyFeatures (unsigned long long id);
+ void parseSonyLensType2 (uchar a, uchar b);
+ void parseSonyLensFeatures (uchar a, uchar b);
+ void process_Sony_0x0116 (uchar * buf, ushort, unsigned long long id);
+ void process_Sony_0x2010 (uchar * buf, ushort);
+ void process_Sony_0x9050 (uchar * buf, ushort, unsigned long long id);
+ void process_Sony_0x9400 (uchar * buf, ushort, unsigned long long id);
+ void process_Sony_0x9402 (uchar * buf, ushort);
+ void process_Sony_0x9403 (uchar * buf, ushort);
+ void process_Sony_0x9406 (uchar * buf, ushort);
+ void process_Sony_0x940c (uchar * buf, ushort);
+ void process_Sony_0x940e (uchar * buf, ushort, unsigned long long id);
+ void parseSonyMakernotes (int base, unsigned tag, unsigned type, unsigned len, unsigned dng_writer,
+ uchar *&table_buf_0x0116, ushort &table_buf_0x0116_len,
+ uchar *&table_buf_0x2010, ushort &table_buf_0x2010_len,
+ uchar *&table_buf_0x9050, ushort &table_buf_0x9050_len,
+ uchar *&table_buf_0x9400, ushort &table_buf_0x9400_len,
+ uchar *&table_buf_0x9402, ushort &table_buf_0x9402_len,
+ uchar *&table_buf_0x9403, ushort &table_buf_0x9403_len,
+ uchar *&table_buf_0x9406, ushort &table_buf_0x9406_len,
+ uchar *&table_buf_0x940c, ushort &table_buf_0x940c_len,
+ uchar *&table_buf_0x940e, ushort &table_buf_0x940e_len);
+ void parseSonySR2 (uchar *cbuf_SR2, unsigned SR2SubIFDOffset, unsigned SR2SubIFDLength, unsigned dng_writer);
+ void parseSonySRF (unsigned len);
+ void parseFujiMakernotes (unsigned tag, unsigned type, unsigned len, unsigned dng_writer);
+ const char* HassyRawFormat_idx2HR(unsigned idx);
+ void process_Hassy_Lens (int LensMount);
+ void parseHassyModel ();
+
+ void setLeicaBodyFeatures(int LeicaMakernoteSignature);
+ void parseLeicaLensID();
+ int parseLeicaLensName(unsigned len);
+ int parseLeicaInternalBodySerial(unsigned len);
+ void parseLeicaMakernote(int base, int uptag, unsigned MakernoteTagType);
+ void parseAdobePanoMakernote ();
+ void parseAdobeRAFMakernote ();
+ void GetNormalizedModel ();
+ void SetStandardIlluminants (unsigned, const char* );
+
+ ushort get2();
+ unsigned sget4 (uchar *s);
+ unsigned getint(int type);
+ float int_to_float (int i);
+ double getreal (int type);
+ double sgetreal(int type, uchar *s);
+ void read_shorts (ushort *pixel, unsigned count);
+
+/* Canon P&S cameras */
+ void canon_600_fixed_wb (int temp);
+ int canon_600_color (int ratio[2], int mar);
+ void canon_600_auto_wb();
+ void canon_600_coeff();
+ void canon_600_load_raw();
+ void canon_600_correct();
+ int canon_s2is();
+ void parse_ciff (int offset, int length, int);
+ void ciff_block_1030();
+
// LJPEG decoder
- unsigned getbits (int nbits);
- void init_decoder();
- uchar * make_decoder (const uchar *source, int level);
- int ljpeg_start (struct jhead *jh, int info_only);
- int ljpeg_diff (struct decode *dindex);
- ushort * ljpeg_row (int jrow, struct jhead *jh);
+ unsigned getbithuff (int nbits, ushort *huff);
+ ushort* make_decoder_ref (const uchar **source);
+ ushort* make_decoder (const uchar *source);
+ int ljpeg_start (struct jhead *jh, int info_only);
+ void ljpeg_end(struct jhead *jh);
+ int ljpeg_diff (ushort *huff);
+ ushort * ljpeg_row (int jrow, struct jhead *jh);
+ ushort * ljpeg_row_unrolled (int jrow, struct jhead *jh);
+ void ljpeg_idct (struct jhead *jh);
+ unsigned ph1_bithuff (int nbits, ushort *huff);
// Canon DSLRs
- void crw_init_tables (unsigned table);
- int canon_has_lowbits();
- void canon_compressed_load_raw();
- void lossless_jpeg_load_raw();
- void canon_sraw_load_raw();
- void canon_black(double *);
+ void crw_init_tables (unsigned table, ushort *huff[2]);
+ int canon_has_lowbits();
+ void canon_load_raw();
+ void lossless_jpeg_load_raw();
+ void canon_sraw_load_raw();
// Adobe DNG
- void adobe_copy_pixel (int row, int col, ushort **rp);
- void adobe_dng_load_raw_lj();
- void adobe_dng_load_raw_nc();
+ void adobe_copy_pixel (unsigned int row, unsigned int col, ushort **rp);
+ void lossless_dng_load_raw();
+ void deflate_dng_load_raw();
+ void packed_dng_load_raw();
+ void packed_tiled_dng_load_raw();
+ void uncompressed_fp_dng_load_raw();
+ void lossy_dng_load_raw();
+//void adobe_dng_load_raw_nc();
// Pentax
- void pentax_k10_load_raw();
- void pentax_tree();
+ void pentax_load_raw();
+ void pentax_4shot_load_raw();
+
+ void pentax_tree();
// Nikon (and Minolta Z2)
- void nikon_compressed_load_raw();
- void nikon_load_raw();
- int nikon_is_compressed();
- int nikon_e995();
- int nikon_e2100();
- void nikon_3700();
- int minolta_z2();
- void nikon_e900_load_raw();
- void nikon_e2100_load_raw();
+ void nikon_load_raw();
+ void nikon_he_load_raw_placeholder();
+ void nikon_read_curve();
+ void nikon_load_striped_packed_raw();
+ void nikon_load_padded_packed_raw();
+ void nikon_load_sraw();
+ void nikon_yuv_load_raw();
+ void nikon_coolscan_load_raw();
+ int nikon_e995();
+ int nikon_e2100();
+ void nikon_3700();
+ int minolta_z2();
+// void nikon_e2100_load_raw();
// Fuji
- void fuji_load_raw();
- void parse_fuji (int offset);
-
-
-
+// void fuji_load_raw();
+ int guess_RAFDataGeneration (uchar *RAFData_start);
+ void parse_fuji (int offset);
+ void parse_fuji_thumbnail(int offset);
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+// RedCine
+ void parse_redcine();
+ void redcine_load_raw();
+#endif
// Rollei
- void rollei_load_raw();
- void parse_rollei();
+ void rollei_load_raw();
+ void parse_rollei();
+
+// Contax
+ void parse_kyocera ();
// MF backs
- int bayer (unsigned row, unsigned col);
- void phase_one_flat_field (int is_float, int nc);
- void phase_one_correct();
- void phase_one_load_raw();
- unsigned ph1_bits (int nbits);
- void phase_one_load_raw_c();
- void hasselblad_load_raw();
- void leaf_hdr_load_raw();
- void sinar_4shot_load_raw();
- void imacon_full_load_raw();
- void packed_12_load_raw();
- void unpacked_load_raw();
- void parse_sinar_ia();
- void parse_phase_one (int base);
+//int bayer (unsigned row, unsigned col);
+ int p1raw(unsigned,unsigned);
+ void phase_one_flat_field (int is_float, int nc);
+ int p1rawc(unsigned row, unsigned col, unsigned& count);
+ void phase_one_fix_col_pixel_avg(unsigned row, unsigned col);
+ void phase_one_fix_pixel_grad(unsigned row, unsigned col);
+ void phase_one_load_raw();
+ unsigned ph1_bits (int nbits);
+ void phase_one_load_raw_c();
+ void phase_one_load_raw_s();
+ void hasselblad_load_raw();
+ void leaf_hdr_load_raw();
+ void sinar_4shot_load_raw();
+ void imacon_full_load_raw();
+ void hasselblad_full_load_raw();
+ void packed_load_raw();
+ float find_green(int,int,int,int);
+ void unpacked_load_raw();
+ void unpacked_load_raw_FujiDBP();
+ void unpacked_load_raw_reversed();
+ void unpacked_load_raw_fuji_f700s20();
+ void parse_sinar_ia();
+ void parse_phase_one (int base);
// Misc P&S cameras
- void nokia_load_raw();
- unsigned pana_bits (int nbits);
- void panasonic_load_raw();
- void olympus_e300_load_raw();
- void olympus_e410_load_raw();
- void olympus_cseries_load_raw();
- void minolta_rd175_load_raw();
- void casio_qv5700_load_raw();
- void quicktake_100_load_raw();
- const int* make_decoder_int (const int *source, int level);
- int radc_token (int tree);
- void kodak_radc_load_raw();
- void kodak_jpeg_load_raw();
- void kodak_dc120_load_raw();
- void eight_bit_load_raw();
- void smal_decode_segment (unsigned seg[2][2], int holes);
- void smal_v6_load_raw();
- int median4 (int *p);
- void fill_holes (int holes);
- void smal_v9_load_raw();
- void parse_riff();
- void parse_cine();
- void parse_smal (int offset, int fsize);
- int parse_jpeg (int offset);
+ void parse_broadcom();
+ void broadcom_load_raw();
+ void nokia_load_raw();
+ void android_loose_load_raw();
+ void android_tight_load_raw();
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ void canon_rmf_load_raw();
+#endif
+ unsigned pana_data (int nb, unsigned *bytes);
+ void panasonic_load_raw();
+// void panasonic_16x10_load_raw();
+ void olympus_load_raw();
+// void olympus_cseries_load_raw();
+ void minolta_rd175_load_raw();
+ void quicktake_100_load_raw();
+ const int* make_decoder_int (const int *source, int level);
+ int radc_token (int tree);
+ void kodak_radc_load_raw();
+ void kodak_jpeg_load_raw();
+ void kodak_dc120_load_raw();
+ void eight_bit_load_raw();
+ void smal_decode_segment (unsigned seg[2][2], int holes);
+ void smal_v6_load_raw();
+ int median4 (int *p);
+ void fill_holes (int holes);
+ void smal_v9_load_raw();
+ void parse_riff(int maxdepth);
+ void parse_cine();
+ void parse_smal (int offset, int fsize);
+ int parse_jpeg (int offset);
// Kodak
- void kodak_262_load_raw();
- int kodak_65000_decode (short *out, int bsize);
- void kodak_65000_load_raw();
- void kodak_rgb_load_raw();
- void kodak_yrgb_load_raw();
-
+ void kodak_262_load_raw();
+ int kodak_65000_decode (short *out, int bsize);
+ void kodak_65000_load_raw();
+ void kodak_rgb_load_raw();
+ void kodak_ycbcr_load_raw();
+// void kodak_yrgb_load_raw();
+ void kodak_c330_load_raw();
+ void kodak_c603_load_raw();
+ void kodak_rgb_load_thumb();
+ void kodak_ycbcr_load_thumb();
+ void vc5_dng_load_raw_placeholder();
// It's a Sony (and K&M)
- void sony_decrypt (unsigned *data, int len, int start, int key);
- void sony_load_raw();
- void sony_arw_load_raw();
- void sony_arw2_load_raw();
- void parse_minolta (int base);
+ void sony_decrypt (unsigned *data, int len, int start, int key);
+ void sony_load_raw();
+ void sony_arw_load_raw();
+ void sony_arw2_load_raw();
+ void sony_arq_load_raw();
+ void sony_ljpeg_load_raw();
+ void samsung_load_raw();
+ void samsung2_load_raw();
+ void samsung3_load_raw();
+ void parse_minolta (int base);
-#ifndef NO_FOVEON
+#ifdef USE_X3FTOOLS
// Foveon/Sigma
- void foveon_load_camf();
- void foveon_load_raw();
- const char* foveon_camf_param (const char *block, const char *param);
- void * foveon_camf_matrix (unsigned dim[3], const char *name);
- int foveon_fixed (void *ptr, int size, const char *name);
- float foveon_avg (short *pix, int range[2], float cfilt);
- short * foveon_make_curve (double max, double mul, double filt);
- void foveon_make_curves(short **curvep, float dq[3], float div[3], float filt);
- int foveon_apply_curve (short *curve, int i);
- void foveon_interpolate();
- char * foveon_gets (int offset, char *str, int len);
- void parse_foveon();
+// We always have x3f code compiled in!
+ void parse_x3f();
+ void x3f_load_raw();
+ void x3f_dpq_interpolate_rg();
+ void x3f_dpq_interpolate_af(int xstep, int ystep, int scale); // 1x1 af pixels
+ void x3f_dpq_interpolate_af_sd(int xstart,int ystart, int xend, int yend, int xstep, int ystep, int scale); // sd Quattro interpolation
+#else
+ void parse_x3f() {}
+ void x3f_load_raw(){}
+#endif
+#ifdef USE_6BY9RPI
+ void rpi_load_raw8();
+ void rpi_load_raw12();
+ void rpi_load_raw14();
+ void rpi_load_raw16();
+ void parse_raspberrypi();
#endif
-
// CAM/RGB
- void pseudoinverse (double (*in)[3], double (*out)[3], int size);
- void cam_xyz_coeff (double cam_xyz[4][3]);
- void adobe_coeff (const char *, const char *);
- void simple_coeff (int index);
+ void pseudoinverse (double (*in)[3], double (*out)[3], int size);
+ void simple_coeff (int index);
+
+// Openp
+ char** malloc_omp_buffers(int buffer_count, size_t buffer_size);
+ void free_omp_buffers(char** buffers, int buffer_count);
// Tiff/Exif parsers
- void tiff_get (unsigned base,unsigned *tag, unsigned *type, unsigned *len, unsigned *save);
- void parse_thumb_note (int base, unsigned toff, unsigned tlen);
- void parse_makernote (int base, int uptag);
- void parse_exif (int base);
- void linear_table (unsigned len);
- void parse_kodak_ifd (int base);
- int parse_tiff_ifd (int base);
- void parse_tiff (int base);
- void parse_gps (int base);
- void romm_coeff (float romm_cam[3][3]);
- void parse_mos (int offset);
- void get_timestamp (int reversed);
-
-// External JPEGs, what cameras uses it ?
- void parse_external_jpeg();
+ void tiff_get (unsigned base,unsigned *tag, unsigned *type, unsigned *len, unsigned *save);
+ short tiff_sget(unsigned save, uchar *buf, unsigned buf_len, INT64 *tag_offset,
+ unsigned *tag_id, unsigned *tag_type, INT64 *tag_dataoffset,
+ unsigned *tag_datalen, int *tag_dataunit_len);
+ void parse_thumb_note (int base, unsigned toff, unsigned tlen);
+ void parse_makernote (int base, int uptag);
+ void parse_makernote_0xc634(int base, int uptag, unsigned dng_writer);
+ void parse_exif (int base);
+ void parse_exif_interop(int base);
+ void linear_table(unsigned len);
+ void Kodak_DCR_WBtags(int wb, unsigned type, int wbi);
+ void Kodak_KDC_WBtags(int wb, int wbi);
+ short KodakIllumMatrix (unsigned type, float *romm_camIllum);
+ void parse_kodak_ifd (int base);
+ int parse_tiff_ifd (int base);
+ int parse_tiff (int base);
+ void apply_tiff(void);
+ void parse_gps (int base);
+ void parse_gps_libraw(int base);
+ void aRGB_coeff(double aRGB_cam[3][3]);
+ void romm_coeff(float romm_cam[3][3]);
+ void parse_mos (INT64 offset);
+ void parse_qt (int end);
+ void get_timestamp (int reversed);
// The identify
short guess_byte_order (int words);
-
+ void identify_process_dng_fields();
+ void identify_finetune_pentax();
+ void identify_finetune_by_filesize(int);
+ void identify_finetune_dcr(char head[64],int,int);
// Tiff writer
- void tiff_set (ushort *ntag, ushort tag, ushort type, int count, int val);
- void tiff_head (struct tiff_hdr *th, int full);
+ void tiff_set(struct tiff_hdr *th, ushort *ntag,ushort tag, ushort type, int count, int val);
+ void tiff_head (struct tiff_hdr *th, int full);
+
+// split AHD code
+ void ahd_interpolate_green_h_and_v(int top, int left, ushort (*out_rgb)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3]);
+ void ahd_interpolate_r_and_b_in_rgb_and_convert_to_cielab(int top, int left, ushort (*inout_rgb)[LIBRAW_AHD_TILE][3], short (*out_lab)[LIBRAW_AHD_TILE][3]);
+ void ahd_interpolate_r_and_b_and_convert_to_cielab(int top, int left, ushort (*inout_rgb)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3], short (*out_lab)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3]);
+ void ahd_interpolate_build_homogeneity_map(int top, int left, short (*lab)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3], char (*out_homogeneity_map)[LIBRAW_AHD_TILE][2]);
+ void ahd_interpolate_combine_homogeneous_pixels(int top, int left, ushort (*rgb)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3], char (*homogeneity_map)[LIBRAW_AHD_TILE][2]);
+
+ void init_fuji_compr(struct fuji_compressed_params* info);
+ void init_fuji_block(struct fuji_compressed_block* info, const struct fuji_compressed_params *params, INT64 raw_offset, unsigned dsize);
+ void copy_line_to_xtrans(struct fuji_compressed_block* info, int cur_line, int cur_block, int cur_block_width);
+ void copy_line_to_bayer(struct fuji_compressed_block* info, int cur_line, int cur_block, int cur_block_width);
+ void xtrans_decode_block(struct fuji_compressed_block* info, const struct fuji_compressed_params *params, int cur_line);
+ void fuji_bayer_decode_block(struct fuji_compressed_block* info, const struct fuji_compressed_params *params, int cur_line);
+ void fuji_compressed_load_raw();
+ void fuji_14bit_load_raw();
+ void parse_fuji_compressed_header();
+ void crxLoadRaw();
+ int crxParseImageHeader(uchar *cmp1TagData, int nTrack, int size);
+ void panasonicC6_load_raw();
+ void panasonicC7_load_raw();
+
+ void nikon_14bit_load_raw();
+
+// DCB
+ void dcb_pp();
+ void dcb_copy_to_buffer(float (*image2)[3]);
+ void dcb_restore_from_buffer(float (*image2)[3]);
+ void dcb_color();
+ void dcb_color_full();
+ void dcb_map();
+ void dcb_correction();
+ void dcb_correction2();
+ void dcb_refinement();
+ void rgb_to_lch(double (*image3)[3]);
+ void lch_to_rgb(double (*image3)[3]);
+ void fbdd_correction();
+ void fbdd_correction2(double (*image3)[3]);
+ void fbdd_green();
+ void dcb_ver(float (*image3)[3]);
+ void dcb_hor(float (*image2)[3]);
+ void dcb_color2(float (*image2)[3]);
+ void dcb_color3(float (*image3)[3]);
+ void dcb_decide(float (*image2)[3], float (*image3)[3]);
+ void dcb_nyquist();
#endif
#endif
diff --git a/libkdcraw/libraw/internal/var_defines.h b/libkdcraw/libraw/internal/var_defines.h
index 471c56b..71db9c3 100644
--- a/libkdcraw/libraw/internal/var_defines.h
+++ b/libkdcraw/libraw/internal/var_defines.h
@@ -1,181 +1,215 @@
-/*
+/* -*- C++ -*-
* File: var_defines.h
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
* Created: Sat Mar 8, 2008
*
* LibRaw redefinitions of dcraw internal variables
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+
+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).
+
*/
#ifndef VAR_DEFINES_H
#define VAR_DEFINES_H
-// imgdata.idata
-#define make (imgdata.idata.make)
-#define model (imgdata.idata.model)
-#define is_raw (imgdata.idata.raw_count)
-#define dng_version (imgdata.idata.dng_version)
-#define is_foveon (imgdata.idata.is_foveon)
-#define colors (imgdata.idata.colors)
-#define cdesc (imgdata.idata.cdesc)
-#define filters (imgdata.idata.filters)
+// imgdata.idata
+#define make (imgdata.idata.make)
+#define model (imgdata.idata.model)
+#define software (imgdata.idata.software)
+#define is_raw (imgdata.idata.raw_count)
+#define dng_version (imgdata.idata.dng_version)
+#define is_foveon (imgdata.idata.is_foveon)
+#define colors (imgdata.idata.colors)
+#define cdesc (imgdata.idata.cdesc)
+#define filters (imgdata.idata.filters)
+#define xtrans (imgdata.idata.xtrans)
+#define xtrans_abs (imgdata.idata.xtrans_abs)
+#define xmpdata (imgdata.idata.xmpdata)
+#define xmplen (imgdata.idata.xmplen)
//imgdata image
-#define image (imgdata.image)
+#define image (imgdata.image)
+#define raw_image (imgdata.rawdata.raw_image)
+#define color_image (imgdata.rawdata.color_image)
+#define normalized_make (imgdata.idata.normalized_make)
+#define normalized_model (imgdata.idata.normalized_model)
+#define maker_index (imgdata.idata.maker_index)
// imgdata.sizes
-#define raw_height (imgdata.sizes.raw_height)
-#define raw_width (imgdata.sizes.raw_width)
-#define height (imgdata.sizes.height)
-#define width (imgdata.sizes.width)
-#define top_margin (imgdata.sizes.top_margin)
-#define left_margin (imgdata.sizes.left_margin)
-#define bottom_margin (imgdata.sizes.bottom_margin)
-#define right_margin (imgdata.sizes.right_margin)
-#define iheight (imgdata.sizes.iheight)
-#define iwidth (imgdata.sizes.iwidth)
-#define pixel_aspect (imgdata.sizes.pixel_aspect)
-#define flip (imgdata.sizes.flip)
+#define raw_height (imgdata.sizes.raw_height)
+#define raw_width (imgdata.sizes.raw_width)
+#define raw_pitch (imgdata.sizes.raw_pitch)
+#define height (imgdata.sizes.height)
+#define width (imgdata.sizes.width)
+#define top_margin (imgdata.sizes.top_margin)
+#define left_margin (imgdata.sizes.left_margin)
+#define bottom_margin (imgdata.sizes.bottom_margin)
+#define right_margin (imgdata.sizes.right_margin)
+#define iheight (imgdata.sizes.iheight)
+#define iwidth (imgdata.sizes.iwidth)
+#define pixel_aspect (imgdata.sizes.pixel_aspect)
+#define flip (imgdata.sizes.flip)
+#define mask (imgdata.sizes.mask)
+#define raw_stride (libraw_internal_data.unpacker_data.raw_stride)
//imgdata.color
-#define white (imgdata.color.white)
-#define cam_mul (imgdata.color.cam_mul)
-#define pre_mul (imgdata.color.pre_mul)
-#define cmatrix (imgdata.color.cmatrix)
-#define rgb_cam (imgdata.color.rgb_cam)
+#define white (imgdata.color.white)
+#define cam_mul (imgdata.color.cam_mul)
+#define pre_mul (imgdata.color.pre_mul)
+#define cmatrix (imgdata.color.cmatrix)
+#define rgb_cam (imgdata.color.rgb_cam)
#ifndef SRC_USES_CURVE
-#define curve (imgdata.color.curve)
+#define curve (imgdata.color.curve)
#endif
#ifndef SRC_USES_BLACK
-#define black (imgdata.color.black)
+#define black (imgdata.color.black)
+#define cblack (imgdata.color.cblack)
#endif
-#define maximum (imgdata.color.maximum)
-#define profile_length (imgdata.color.profile_length)
-#define color_flags (imgdata.color.color_flags)
-#define ph1 (imgdata.color.phase_one_data)
-#define flash_used (imgdata.color.flash_used)
-#define canon_ev (imgdata.color.canon_ev)
-#define model2 (imgdata.color.model2)
+#define maximum (imgdata.color.maximum)
+#define channel_maximum (imgdata.color.channel_maximum)
+#define profile_length (imgdata.color.profile_length)
+#define color_flags (imgdata.color.color_flags)
+#define ph1 (imgdata.color.phase_one_data)
+#define flash_used (imgdata.color.flash_used)
+#define canon_ev (imgdata.color.canon_ev)
+#define model2 (imgdata.color.model2)
//imgdata.thumbnail
-
-#define thumb_width (imgdata.thumbnail.twidth)
-#define thumb_height (imgdata.thumbnail.theight)
-#define thumb_length (imgdata.thumbnail.tlength)
+#define thumb_width (imgdata.thumbnail.twidth)
+#define thumb_height (imgdata.thumbnail.theight)
+#define thumb_length (imgdata.thumbnail.tlength)
//imgdata.others
-#define iso_speed (imgdata.other.iso_speed)
-#define shutter (imgdata.other.shutter)
-#define aperture (imgdata.other.aperture)
-#define focal_len (imgdata.other.focal_len)
-#define timestamp (imgdata.other.timestamp)
-#define shot_order (imgdata.other.shot_order)
-#define gpsdata (imgdata.other.gpsdata)
-#define desc (imgdata.other.desc)
-#define artist (imgdata.other.artist)
+#define iso_speed (imgdata.other.iso_speed)
+#define shutter (imgdata.other.shutter)
+#define aperture (imgdata.other.aperture)
+#define focal_len (imgdata.other.focal_len)
+#define timestamp (imgdata.other.timestamp)
+#define shot_order (imgdata.other.shot_order)
+#define gpsdata (imgdata.other.gpsdata)
+#define desc (imgdata.other.desc)
+#define artist (imgdata.other.artist)
+
+#define FujiCropMode (imgdata.makernotes.fuji.CropMode)
//imgdata.output
-#define greybox (imgdata.params.greybox)
-#define aber (imgdata.params.aber)
-#define gamm (imgdata.params.gamm)
-#define user_mul (imgdata.params.user_mul)
-#define shot_select (imgdata.params.shot_select)
-#define bright (imgdata.params.bright)
-#define threshold (imgdata.params.threshold)
-#define half_size (imgdata.params.half_size)
-#define four_color_rgb (imgdata.params.four_color_rgb)
-#define document_mode (imgdata.params.document_mode)
-#define highlight (imgdata.params.highlight)
-//#define verbose (imgdata.params.verbose)
-#define use_auto_wb (imgdata.params.use_auto_wb)
-#define use_camera_wb (imgdata.params.use_camera_wb)
+#define greybox (imgdata.params.greybox)
+#define cropbox (imgdata.params.cropbox)
+#define aber (imgdata.params.aber)
+#define gamm (imgdata.params.gamm)
+#define user_mul (imgdata.params.user_mul)
+#define shot_select (imgdata.rawparams.shot_select)
+#define bright (imgdata.params.bright)
+#define threshold (imgdata.params.threshold)
+#define half_size (imgdata.params.half_size)
+#define four_color_rgb (imgdata.params.four_color_rgb)
+#define highlight (imgdata.params.highlight)
+#define use_auto_wb (imgdata.params.use_auto_wb)
+#define use_camera_wb (imgdata.params.use_camera_wb)
#define use_camera_matrix (imgdata.params.use_camera_matrix)
-#define output_color (imgdata.params.output_color)
-#define output_bps (imgdata.params.output_bps)
-#define gamma_16bit (imgdata.params.gamma_16bit)
-#define output_tiff (imgdata.params.output_tiff)
-#define med_passes (imgdata.params.med_passes)
-#define no_auto_bright (imgdata.params.no_auto_bright)
-#define use_fuji_rotate (imgdata.params.use_fuji_rotate)
-#define filtering_mode (imgdata.params.filtering_mode)
-
-//rgb_constants
-#define xyz_rgb (rgb_constants.xyz_rgb)
-#define d65_white (rgb_constants.d65_white)
+#define output_color (imgdata.params.output_color)
+#define output_bps (imgdata.params.output_bps)
+#define gamma_16bit (imgdata.params.gamma_16bit)
+#define output_tiff (imgdata.params.output_tiff)
+#define med_passes (imgdata.params.med_passes)
+#define no_auto_bright (imgdata.params.no_auto_bright)
+#define auto_bright_thr (imgdata.params.auto_bright_thr)
+#define use_fuji_rotate (imgdata.params.use_fuji_rotate)
+#define filtering_mode (imgdata.params.filtering_mode)
+
+// DCB
+#define dcb_iterations (imgdata.params.iterations)
+#define dcb_enhance_fl (imgdata.params.dcb_enhance)
+#define fbdd_noiserd (imgdata.params.fbdd_noiserd)
//libraw_internal_data.internal_data
-#define meta_data (libraw_internal_data.internal_data.meta_data)
-#define ifp libraw_internal_data.internal_data.input
-#define ifname ((char*)libraw_internal_data.internal_data.input->fname())
-#define profile_offset (libraw_internal_data.internal_data.profile_offset)
-#define thumb_offset (libraw_internal_data.internal_data.toffset)
+#define meta_data (libraw_internal_data.internal_data.meta_data)
+#define ifp libraw_internal_data.internal_data.input
+#define ifname ((char*)libraw_internal_data.internal_data.input->fname())
+#define ofp libraw_internal_data.internal_data.output
+#define profile_offset (libraw_internal_data.internal_data.profile_offset)
+#define thumb_offset (libraw_internal_data.internal_data.toffset)
+#define pana_black (libraw_internal_data.internal_data.pana_black)
//libraw_internal_data.internal_output_params
-#define mix_green (libraw_internal_data.internal_output_params.mix_green)
-#define raw_color (libraw_internal_data.internal_output_params.raw_color)
-#define use_gamma (libraw_internal_data.internal_output_params.use_gamma)
-#define zero_is_bad (libraw_internal_data.internal_output_params.zero_is_bad)
+#define mix_green (libraw_internal_data.internal_output_params.mix_green)
+#define raw_color (libraw_internal_data.internal_output_params.raw_color)
+#define use_gamma (libraw_internal_data.internal_output_params.use_gamma)
+#define zero_is_bad (libraw_internal_data.internal_output_params.zero_is_bad)
#ifndef SRC_USES_SHRINK
-#define shrink (libraw_internal_data.internal_output_params.shrink)
+#define shrink (libraw_internal_data.internal_output_params.shrink)
#endif
-#define fuji_width (libraw_internal_data.internal_output_params.fuji_width)
-
+#define fuji_width (libraw_internal_data.internal_output_params.fuji_width)
+#define thumb_format (libraw_internal_data.unpacker_data.thumb_format)
//libraw_internal_data.output_data
-#define histogram (libraw_internal_data.output_data.histogram)
-#define oprof (libraw_internal_data.output_data.oprof)
+#define histogram (libraw_internal_data.output_data.histogram)
+#define oprof (libraw_internal_data.output_data.oprof)
//libraw_internal_data.identify_data
-#define exif_cfa (libraw_internal_data.identify_data.olympus_exif_cfa)
-#define unique_id (libraw_internal_data.identify_data.unique_id)
-#define tiff_nifds (libraw_internal_data.identify_data.tiff_nifds)
-#define tiff_flip (libraw_internal_data.identify_data.tiff_flip)
+#define exif_cfa (libraw_internal_data.identify_data.olympus_exif_cfa)
+#define unique_id (libraw_internal_data.identify_data.unique_id)
+#define OlyID (libraw_internal_data.identify_data.OlyID)
+#define tiff_nifds (libraw_internal_data.identify_data.tiff_nifds)
+#define tiff_flip (libraw_internal_data.identify_data.tiff_flip)
+#define metadata_blocks (libraw_internal_data.identify_data.metadata_blocks)
//libraw_internal_data.unpacker_data
-#define order (libraw_internal_data.unpacker_data.order)
-#define data_error (libraw_internal_data.unpacker_data.data_error)
-#define cr2_slice (libraw_internal_data.unpacker_data.cr2_slice)
-#define sraw_mul (libraw_internal_data.unpacker_data.sraw_mul)
-#define kodak_cbpp (libraw_internal_data.unpacker_data.kodak_cbpp)
-#define strip_offset (libraw_internal_data.unpacker_data.strip_offset)
-#define data_offset (libraw_internal_data.unpacker_data.data_offset)
-#define meta_offset (libraw_internal_data.unpacker_data.meta_offset)
-#define meta_length (libraw_internal_data.unpacker_data.meta_length)
-#define thumb_misc (libraw_internal_data.unpacker_data.thumb_misc)
-#define fuji_layout (libraw_internal_data.unpacker_data.fuji_layout)
-#define tiff_samples (libraw_internal_data.unpacker_data.tiff_samples)
-#define tiff_bps (libraw_internal_data.unpacker_data.tiff_bps)
-#define tiff_compress (libraw_internal_data.unpacker_data.tiff_compress)
-#define zero_after_ff (libraw_internal_data.unpacker_data.zero_after_ff)
-#define tile_width (libraw_internal_data.unpacker_data.tile_width)
-#define tile_length (libraw_internal_data.unpacker_data.tile_length)
-#define load_flags (libraw_internal_data.unpacker_data.load_flags)
+#define order (libraw_internal_data.unpacker_data.order)
+#define data_error (libraw_internal_data.unpacker_data.data_error)
+#define cr2_slice (libraw_internal_data.unpacker_data.cr2_slice)
+#define sraw_mul (libraw_internal_data.unpacker_data.sraw_mul)
+#define kodak_cbpp (libraw_internal_data.unpacker_data.kodak_cbpp)
+#define strip_offset (libraw_internal_data.unpacker_data.strip_offset)
+#define data_offset (libraw_internal_data.unpacker_data.data_offset)
+#define data_size (libraw_internal_data.unpacker_data.data_size)
+#define meta_offset (libraw_internal_data.unpacker_data.meta_offset)
+#define meta_length (libraw_internal_data.unpacker_data.meta_length)
+#define thumb_misc (libraw_internal_data.unpacker_data.thumb_misc)
+#define fuji_layout (libraw_internal_data.unpacker_data.fuji_layout)
+#define tiff_samples (libraw_internal_data.unpacker_data.tiff_samples)
+#define tiff_bps (libraw_internal_data.unpacker_data.tiff_bps)
+#define tiff_compress (libraw_internal_data.unpacker_data.tiff_compress)
+#define tiff_sampleformat (libraw_internal_data.unpacker_data.tiff_sampleformat)
+#define zero_after_ff (libraw_internal_data.unpacker_data.zero_after_ff)
+#define tile_width (libraw_internal_data.unpacker_data.tile_width)
+#define tile_length (libraw_internal_data.unpacker_data.tile_length)
+#define load_flags (libraw_internal_data.unpacker_data.load_flags)
+#define pana_encoding (libraw_internal_data.unpacker_data.pana_encoding)
+#define pana_bpp (libraw_internal_data.unpacker_data.pana_bpp)
+#define CM_found (libraw_internal_data.unpacker_data.CM_found)
+
+#define is_NikonTransfer (libraw_internal_data.unpacker_data.is_NikonTransfer)
+#define is_Olympus (libraw_internal_data.unpacker_data.is_Olympus)
+#define OlympusDNG_SubDirOffsetValid (libraw_internal_data.unpacker_data.OlympusDNG_SubDirOffsetValid)
+#define is_Sony (libraw_internal_data.unpacker_data.is_Sony)
+#define is_PentaxRicohMakernotes (libraw_internal_data.unpacker_data.is_PentaxRicohMakernotes)
+#define is_pana_raw (libraw_internal_data.unpacker_data.is_pana_raw)
+
#ifdef LIBRAW_IO_REDEFINED
-#define fread(ptr,size,n,stream) stream->read(ptr,size,n)
-#define fseek(stream,o,w) stream->seek(o,w)
-#define fseeko(stream,o,w) stream->seek(o,w)
-#define ftell(stream) stream->tell()
-#define ftello(stream) stream->tell()
-#define getc(stream) stream->get_char()
-#define fgetc(stream) stream->get_char()
-#define fgets(str,n,stream) stream->gets(str,n)
-#define fscanf(stream,fmt,ptr) stream->scanf_one(fmt,ptr)
+#define fread(ptr,size,n,stream) stream->read(ptr,size,n)
+#define fseek(stream,o,w) stream->seek(o,w)
+#define fseeko(stream,o,w) stream->seek(o,w)
+#define ftell(stream) stream->tell()
+#define ftello(stream) stream->tell()
+#define feof(stream) stream->eof()
+#ifdef getc
+#undef getc
+#endif
+#define getc(stream) stream->get_char()
+#define fgetc(stream) stream->get_char()
+#define fgetcb(stream) stream->get_char_buf()
+#define fgets(str,n,stream) stream->gets(str,n)
+#define fscanf(stream,fmt,ptr) stream->scanf_one(fmt,ptr)
#endif
#endif
diff --git a/libkdcraw/libraw/internal/x3f_tools.h b/libkdcraw/libraw/internal/x3f_tools.h
new file mode 100644
index 0000000..84bb00c
--- /dev/null
+++ b/libkdcraw/libraw/internal/x3f_tools.h
@@ -0,0 +1,539 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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).
+ */
+
+/* Library for accessing X3F Files
+----------------------------------------------------------------
+BSD-style License
+----------------------------------------------------------------
+
+* Copyright (c) 2010, Roland Karlsson ([email protected])
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of the organization nor the
+* names of its contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY ROLAND KARLSSON ''AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ROLAND KARLSSON BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef X3F_TOOLS_H
+#define X3F_TOOLS_H
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+#include "../libraw/libraw_datastream.h"
+
+/* From X3F_IO.H */
+
+#define SIZE_UNIQUE_IDENTIFIER 16
+#define SIZE_WHITE_BALANCE 32
+#define SIZE_COLOR_MODE 32
+#define NUM_EXT_DATA_2_1 32
+#define NUM_EXT_DATA_3_0 64
+#define NUM_EXT_DATA NUM_EXT_DATA_3_0
+
+#define X3F_VERSION(MAJ, MIN) (uint32_t)(((MAJ) << 16) + MIN)
+#define X3F_VERSION_2_0 X3F_VERSION(2, 0)
+#define X3F_VERSION_2_1 X3F_VERSION(2, 1)
+#define X3F_VERSION_2_2 X3F_VERSION(2, 2)
+#define X3F_VERSION_2_3 X3F_VERSION(2, 3)
+#define X3F_VERSION_3_0 X3F_VERSION(3, 0)
+#define X3F_VERSION_4_0 X3F_VERSION(4, 0)
+
+/* Main file identifier */
+#define X3F_FOVb (uint32_t)(0x62564f46)
+/* Directory identifier */
+#define X3F_SECd (uint32_t)(0x64434553)
+/* Property section identifiers */
+#define X3F_PROP (uint32_t)(0x504f5250)
+#define X3F_SECp (uint32_t)(0x70434553)
+/* Image section identifiers */
+#define X3F_IMAG (uint32_t)(0x46414d49)
+#define X3F_IMA2 (uint32_t)(0x32414d49)
+#define X3F_SECi (uint32_t)(0x69434553)
+/* CAMF section identifiers */
+#define X3F_CAMF (uint32_t)(0x464d4143)
+#define X3F_SECc (uint32_t)(0x63434553)
+/* CAMF entry identifiers */
+#define X3F_CMbP (uint32_t)(0x50624d43)
+#define X3F_CMbT (uint32_t)(0x54624d43)
+#define X3F_CMbM (uint32_t)(0x4d624d43)
+#define X3F_CMb (uint32_t)(0x00624d43)
+/* SDQ section identifiers ? - TODO */
+#define X3F_SPPA (uint32_t)(0x41505053)
+#define X3F_SECs (uint32_t)(0x73434553)
+
+#define X3F_IMAGE_THUMB_PLAIN (uint32_t)(0x00020003)
+#define X3F_IMAGE_THUMB_HUFFMAN (uint32_t)(0x0002000b)
+#define X3F_IMAGE_THUMB_JPEG (uint32_t)(0x00020012)
+#define X3F_IMAGE_THUMB_SDQ (uint32_t)(0x00020019) /* SDQ ? - TODO */
+
+#define X3F_IMAGE_RAW_HUFFMAN_X530 (uint32_t)(0x00030005)
+#define X3F_IMAGE_RAW_HUFFMAN_10BIT (uint32_t)(0x00030006)
+#define X3F_IMAGE_RAW_TRUE (uint32_t)(0x0003001e)
+#define X3F_IMAGE_RAW_MERRILL (uint32_t)(0x0001001e)
+#define X3F_IMAGE_RAW_QUATTRO (uint32_t)(0x00010023)
+#define X3F_IMAGE_RAW_SDQ (uint32_t)(0x00010025)
+#define X3F_IMAGE_RAW_SDQH (uint32_t)(0x00010027)
+#define X3F_IMAGE_RAW_SDQH2 (uint32_t)(0x00010029)
+
+#define X3F_IMAGE_HEADER_SIZE 28
+#define X3F_CAMF_HEADER_SIZE 28
+#define X3F_PROPERTY_LIST_HEADER_SIZE 24
+
+typedef uint16_t utf16_t;
+
+typedef int bool_t;
+
+typedef enum x3f_extended_types_e
+{
+ X3F_EXT_TYPE_NONE = 0,
+ X3F_EXT_TYPE_EXPOSURE_ADJUST = 1,
+ X3F_EXT_TYPE_CONTRAST_ADJUST = 2,
+ X3F_EXT_TYPE_SHADOW_ADJUST = 3,
+ X3F_EXT_TYPE_HIGHLIGHT_ADJUST = 4,
+ X3F_EXT_TYPE_SATURATION_ADJUST = 5,
+ X3F_EXT_TYPE_SHARPNESS_ADJUST = 6,
+ X3F_EXT_TYPE_RED_ADJUST = 7,
+ X3F_EXT_TYPE_GREEN_ADJUST = 8,
+ X3F_EXT_TYPE_BLUE_ADJUST = 9,
+ X3F_EXT_TYPE_FILL_LIGHT_ADJUST = 10
+} x3f_extended_types_t;
+
+typedef struct x3f_property_s
+{
+ /* Read from file */
+ uint32_t name_offset;
+ uint32_t value_offset;
+
+ /* Computed */
+ utf16_t *name; /* 0x0000 terminated UTF 16 */
+ utf16_t *value; /* 0x0000 terminated UTF 16 */
+} x3f_property_t;
+
+typedef struct x3f_property_table_s
+{
+ uint32_t size;
+ x3f_property_t *element;
+} x3f_property_table_t;
+
+typedef struct x3f_property_list_s
+{
+ /* 2.0 Fields */
+ uint32_t num_properties;
+ uint32_t character_format;
+ uint32_t reserved;
+ uint32_t total_length;
+
+ x3f_property_table_t property_table;
+
+ void *data;
+
+ uint32_t data_size;
+
+} x3f_property_list_t;
+
+typedef struct x3f_table8_s
+{
+ uint32_t size;
+ uint8_t *element;
+} x3f_table8_t;
+
+typedef struct x3f_table16_s
+{
+ uint32_t size;
+ uint16_t *element;
+} x3f_table16_t;
+
+typedef struct x3f_table32_s
+{
+ uint32_t size;
+ uint32_t *element;
+} x3f_table32_t;
+
+typedef struct
+{
+ uint8_t *data; /* Pointer to actual image data */
+ void *buf; /* Pointer to allocated buffer for free() */
+ uint32_t rows;
+ uint32_t columns;
+ uint32_t channels;
+ uint32_t row_stride;
+} x3f_area8_t;
+
+typedef struct
+{
+ uint16_t *data; /* Pointer to actual image data */
+ void *buf; /* Pointer to allocated buffer for free() */
+ uint32_t rows;
+ uint32_t columns;
+ uint32_t channels;
+ uint32_t row_stride;
+} x3f_area16_t;
+
+#define UNDEFINED_LEAF 0xffffffff
+
+typedef struct x3f_huffnode_s
+{
+ struct x3f_huffnode_s *branch[2];
+ uint32_t leaf;
+} x3f_huffnode_t;
+
+typedef struct x3f_hufftree_s
+{
+ uint32_t free_node_index; /* Free node index in huffman tree array */
+ uint32_t total_node_index;
+ x3f_huffnode_t *nodes; /* Coding tree */
+} x3f_hufftree_t;
+
+typedef struct x3f_true_huffman_element_s
+{
+ uint8_t code_size;
+ uint8_t code;
+} x3f_true_huffman_element_t;
+
+typedef struct x3f_true_huffman_s
+{
+ uint32_t size;
+ x3f_true_huffman_element_t *element;
+} x3f_true_huffman_t;
+
+/* 0=bottom, 1=middle, 2=top */
+#define TRUE_PLANES 3
+
+typedef struct x3f_true_s
+{
+ uint16_t seed[TRUE_PLANES]; /* Always 512,512,512 */
+ uint16_t unknown; /* Always 0 */
+ x3f_true_huffman_t table; /* Huffman table - zero
+ terminated. size is the number of
+ leaves plus 1.*/
+
+ x3f_table32_t plane_size; /* Size of the 3 planes */
+ uint8_t *plane_address[TRUE_PLANES]; /* computed offset to the planes */
+ x3f_hufftree_t tree; /* Coding tree */
+ x3f_area16_t x3rgb16; /* 3x16 bit X3-RGB data */
+} x3f_true_t;
+
+typedef struct x3f_quattro_s
+{
+ struct
+ {
+ uint16_t columns;
+ uint16_t rows;
+ } plane[TRUE_PLANES];
+ uint32_t unknown;
+
+ bool_t quattro_layout;
+ x3f_area16_t top16; /* Container for the bigger top layer */
+} x3f_quattro_t;
+
+typedef struct x3f_huffman_s
+{
+ x3f_table16_t mapping; /* Value Mapping = X3F lossy compression */
+ x3f_table32_t table; /* Coding Table */
+ x3f_hufftree_t tree; /* Coding tree */
+ x3f_table32_t row_offsets; /* Row offsets */
+ x3f_area8_t rgb8; /* 3x8 bit RGB data */
+ x3f_area16_t x3rgb16; /* 3x16 bit X3-RGB data */
+} x3f_huffman_t;
+
+typedef struct x3f_image_data_s
+{
+ /* 2.0 Fields */
+ /* ------------------------------------------------------------------ */
+ /* Known combinations of type and format are:
+ 1-6, 2-3, 2-11, 2-18, 3-6 */
+ uint32_t type; /* 1 = RAW X3 (SD1)
+ 2 = thumbnail or maybe just RGB
+ 3 = RAW X3 */
+ uint32_t format; /* 3 = 3x8 bit pixmap
+ 6 = 3x10 bit huffman with map table
+ 11 = 3x8 bit huffman
+ 18 = JPEG */
+ uint32_t type_format; /* type<<16 + format */
+ /* ------------------------------------------------------------------ */
+
+ uint32_t columns; /* width / row size in pixels */
+ uint32_t rows; /* height */
+ uint32_t row_stride; /* row size in bytes */
+
+ /* NULL if not used */
+ x3f_huffman_t *huffman; /* Huffman help data */
+ x3f_true_t *tru; /* TRUE help data */
+ x3f_quattro_t *quattro; /* Quattro help data */
+
+ void *data; /* Take from file if NULL. Otherwise,
+ this is the actual data bytes in
+ the file. */
+ uint32_t data_size;
+
+} x3f_image_data_t;
+
+typedef struct camf_dim_entry_s
+{
+ uint32_t size;
+ uint32_t name_offset;
+ uint32_t n; /* 0,1,2,3... */
+ char *name;
+} camf_dim_entry_t;
+
+typedef enum
+{
+ M_FLOAT,
+ M_INT,
+ M_UINT
+} matrix_type_t;
+
+typedef struct camf_entry_s
+{
+ /* pointer into decoded data */
+ void *entry;
+
+ /* entry header */
+ uint32_t id;
+ uint32_t version;
+ uint32_t entry_size;
+ uint32_t name_offset;
+ uint32_t value_offset;
+
+ /* computed values */
+ char *name_address;
+ void *value_address;
+ uint32_t name_size;
+ uint32_t value_size;
+
+ /* extracted values for explicit CAMF entry types*/
+ uint32_t text_size;
+ char *text;
+
+ uint32_t property_num;
+ char **property_name;
+ uint8_t **property_value;
+
+ uint32_t matrix_dim;
+ camf_dim_entry_t *matrix_dim_entry;
+
+ /* Offset, pointer and size and type of raw data */
+ uint32_t matrix_type;
+ uint32_t matrix_data_off;
+ void *matrix_data;
+ uint32_t matrix_element_size;
+
+ /* Pointer and type of copied data */
+ matrix_type_t matrix_decoded_type;
+ void *matrix_decoded;
+
+ /* Help data to try to estimate element size */
+ uint32_t matrix_elements;
+ uint32_t matrix_used_space;
+ double matrix_estimated_element_size;
+
+} camf_entry_t;
+
+typedef struct camf_entry_table_s
+{
+ uint32_t size;
+ camf_entry_t *element;
+} camf_entry_table_t;
+
+typedef struct x3f_camf_typeN_s
+{
+ uint32_t val0;
+ uint32_t val1;
+ uint32_t val2;
+ uint32_t val3;
+} x3f_camf_typeN_t;
+
+typedef struct x3f_camf_type2_s
+{
+ uint32_t reserved;
+ uint32_t infotype;
+ uint32_t infotype_version;
+ uint32_t crypt_key;
+} x3f_camf_type2_t;
+
+typedef struct x3f_camf_type4_s
+{
+ uint32_t decoded_data_size;
+ uint32_t decode_bias;
+ uint32_t block_size;
+ uint32_t block_count;
+} x3f_camf_type4_t;
+
+typedef struct x3f_camf_type5_s
+{
+ uint32_t decoded_data_size;
+ uint32_t decode_bias;
+ uint32_t unknown2;
+ uint32_t unknown3;
+} x3f_camf_type5_t;
+
+typedef struct x3f_camf_s
+{
+
+ /* Header info */
+ uint32_t type;
+ union {
+ x3f_camf_typeN_t tN;
+ x3f_camf_type2_t t2;
+ x3f_camf_type4_t t4;
+ x3f_camf_type5_t t5;
+ };
+
+ /* The encrypted raw data */
+ void *data;
+ uint32_t data_size;
+
+ /* Help data for type 4 Huffman compression */
+ x3f_true_huffman_t table;
+ x3f_hufftree_t tree;
+ uint8_t *decoding_start;
+ uint32_t decoding_size;
+
+ /* The decrypted data */
+ void *decoded_data;
+ uint32_t decoded_data_size;
+
+ /* Pointers into the decrypted data */
+ camf_entry_table_t entry_table;
+} x3f_camf_t;
+
+typedef struct x3f_directory_entry_header_s
+{
+ uint32_t identifier; /* Should be ´SECp´, "SECi", ... */
+ uint32_t version; /* 0x00020001 is version 2.1 */
+ union {
+ x3f_property_list_t property_list;
+ x3f_image_data_t image_data;
+ x3f_camf_t camf;
+ } data_subsection;
+} x3f_directory_entry_header_t;
+
+typedef struct x3f_directory_entry_s
+{
+ struct
+ {
+ uint32_t offset;
+ uint32_t size;
+ } input, output;
+
+ uint32_t type;
+
+ x3f_directory_entry_header_t header;
+} x3f_directory_entry_t;
+
+typedef struct x3f_directory_section_s
+{
+ uint32_t identifier; /* Should be ´SECd´ */
+ uint32_t version; /* 0x00020001 is version 2.1 */
+
+ /* 2.0 Fields */
+ uint32_t num_directory_entries;
+ x3f_directory_entry_t *directory_entry;
+} x3f_directory_section_t;
+
+typedef struct x3f_header_s
+{
+ /* 2.0 Fields */
+ uint32_t identifier; /* Should be ´FOVb´ */
+ uint32_t version; /* 0x00020001 means 2.1 */
+ uint8_t unique_identifier[SIZE_UNIQUE_IDENTIFIER];
+ uint32_t mark_bits;
+ uint32_t columns; /* Columns and rows ... */
+ uint32_t rows; /* ... before rotation */
+ uint32_t rotation; /* 0, 90, 180, 270 */
+
+ char white_balance[SIZE_WHITE_BALANCE]; /* Introduced in 2.1 */
+ char color_mode[SIZE_COLOR_MODE]; /* Introduced in 2.3 */
+
+ /* Introduced in 2.1 and extended from 32 to 64 in 3.0 */
+ uint8_t extended_types[NUM_EXT_DATA]; /* x3f_extended_types_t */
+ float extended_data[NUM_EXT_DATA]; /* 32 bits, but do type differ? */
+} x3f_header_t;
+
+typedef struct x3f_info_s
+{
+ char *error;
+ struct
+ {
+ LibRaw_abstract_datastream *file; /* Use if more data is needed */
+ } input, output;
+} x3f_info_t;
+
+typedef struct x3f_s
+{
+ x3f_info_t info;
+ x3f_header_t header;
+ x3f_directory_section_t directory_section;
+} x3f_t;
+
+typedef enum x3f_return_e
+{
+ X3F_OK = 0,
+ X3F_ARGUMENT_ERROR = 1,
+ X3F_INFILE_ERROR = 2,
+ X3F_OUTFILE_ERROR = 3,
+ X3F_INTERNAL_ERROR = 4
+} x3f_return_t;
+
+x3f_return_t x3f_delete(x3f_t *x3f);
+
+/* Hacky external flags */
+/* --------------------------------------------------------------------- */
+
+extern int legacy_offset;
+extern bool_t auto_legacy_offset;
+
+/* --------------------------------------------------------------------- */
+/* Huffman Decode Macros */
+/* --------------------------------------------------------------------- */
+
+#define HUF_TREE_MAX_LENGTH 27
+#define HUF_TREE_MAX_NODES(_leaves) ((HUF_TREE_MAX_LENGTH + 1) * (_leaves))
+#define HUF_TREE_GET_LENGTH(_v) (((_v) >> 27) & 0x1f)
+#define HUF_TREE_GET_CODE(_v) ((_v)&0x07ffffff)
+
+x3f_t *x3f_new_from_file(LibRaw_abstract_datastream *infile);
+x3f_return_t x3f_delete(x3f_t *x3f);
+x3f_directory_entry_t *x3f_get_raw(x3f_t *x3f);
+x3f_directory_entry_t *x3f_get_thumb_plain(x3f_t *x3f);
+x3f_return_t x3f_load_data(x3f_t *x3f, x3f_directory_entry_t *DE);
+x3f_directory_entry_t *x3f_get_thumb_huffman(x3f_t *x3f);
+x3f_directory_entry_t *x3f_get_thumb_jpeg(x3f_t *x3f);
+x3f_directory_entry_t *x3f_get_camf(x3f_t *x3f);
+x3f_directory_entry_t *x3f_get_prop(x3f_t *x3f);
+/* extern */ int64_t x3f_load_data_size(x3f_t *x3f, x3f_directory_entry_t *DE);
+
+#endif
diff --git a/libkdcraw/libraw/libraw/libraw.h b/libkdcraw/libraw/libraw/libraw.h
index 8e64345..50d4276 100644
--- a/libkdcraw/libraw/libraw/libraw.h
+++ b/libkdcraw/libraw/libraw/libraw.h
@@ -1,38 +1,83 @@
-/*
+/* -*- C++ -*-
* File: libraw.h
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
- * Created: Sat Mar 8, 2008
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Sat Mar 8, 2008
*
* LibRaw C++ interface
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
+
+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).
+
+*/
#ifndef _LIBRAW_CLASS_H
#define _LIBRAW_CLASS_H
-#ifdef HAVE_CONFIG_H
-#include "config.h"
+#ifdef __linux__
+#define _FILE_OFFSET_BITS 64
+#endif
+
+// Enable use old cinema cameras if USE_OLD_VIDEOCAMS defined
+#ifdef USE_OLD_VIDEOCAMS
+#define LIBRAW_OLD_VIDEO_SUPPORT
+#endif
+
+#ifndef LIBRAW_USE_DEPRECATED_IOSTREAMS_DATASTREAM
+#define LIBRAW_NO_IOSTREAMS_DATASTREAM
+#endif
+
+#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
+/* maximum file size to use LibRaw_file_datastream (fully buffered) I/O */
+#define LIBRAW_USE_STREAMS_DATASTREAM_MAXSIZE (250 * 1024L * 1024L)
#endif
#include <limits.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
+#include <math.h>
+
+/* better WIN32 defines */
+
+/* better WIN32 defines */
+
+#if defined(WIN32) || defined(_WIN32)
+
+/* Win32 API */
+# ifndef LIBRAW_WIN32_CALLS
+# define LIBRAW_WIN32_CALLS
+# endif
+/* DLLs: Microsoft or Intel compiler */
+# if defined(_MSC_VER) || defined(__INTEL_COMPILER)
+# ifndef LIBRAW_WIN32_DLLDEFS
+# define LIBRAW_WIN32_DLLDEFS
+# endif
+#endif
+
+/* wchar_t* API for std::filebuf */
+# if (defined(_MSC_VER) && (_MSC_VER > 1310)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 910))
+# ifndef LIBRAW_WIN32_UNICODEPATHS
+# define LIBRAW_WIN32_UNICODEPATHS
+# endif
+# elif _GLIBCXX_HAVE__WFOPEN && _GLIBCXX_USE_WCHAR_T
+# ifndef LIBRAW_WIN32_UNICODEPATHS
+# define LIBRAW_WIN32_UNICODEPATHS
+# endif
+# elif defined(_LIBCPP_HAS_OPEN_WITH_WCHAR)
+# ifndef LIBRAW_WIN32_UNICODEPATHS
+# define LIBRAW_WIN32_UNICODEPATHS
+# endif
+# endif
+
+#endif
#include "libraw_datastream.h"
#include "libraw_types.h"
@@ -40,194 +85,450 @@
#include "libraw_internal.h"
#include "libraw_alloc.h"
-//#define DCRAW_VERBOSE
-
#ifdef __cplusplus
-extern "C"
+extern "C"
{
#endif
-DllDef const char *libraw_strerror(int errorcode);
-DllDef const char *libraw_strprogress(enum LibRaw_progress);
- // LibRaw C API
-DllDef libraw_data_t *libraw_init(unsigned int flags);
-DllDef int libraw_open_file(libraw_data_t*, const char *);
-DllDef int libraw_open_buffer(libraw_data_t*, void * buffer, size_t size);
-DllDef int libraw_unpack(libraw_data_t*);
-DllDef int libraw_unpack_thumb(libraw_data_t*);
-DllDef void libraw_recycle(libraw_data_t*);
-DllDef void libraw_close(libraw_data_t*);
- // version helpers
-DllDef const char* libraw_version();
-DllDef int libraw_versionNumber();
- // Camera list
-DllDef const char** libraw_cameraList();
-DllDef int libraw_cameraCount();
-
-DllDef void libraw_set_memerror_handler(libraw_data_t*, memory_callback cb, void *datap);
-DllDef void libraw_set_dataerror_handler(libraw_data_t*,data_callback func,void *datap);
-DllDef void libraw_set_progress_handler(libraw_data_t*,progress_callback cb,void *datap);
-DllDef int libraw_add_masked_borders_to_bitmap(libraw_data_t* lr);
-DllDef const char * libraw_unpack_function_name(libraw_data_t* lr);
-DllDef int libraw_rotate_fuji_raw(libraw_data_t* lr);
-
- // DCRAW compatibility
-DllDef int libraw_adjust_sizes_info_only(libraw_data_t*);
-DllDef int libraw_dcraw_document_mode_processing(libraw_data_t*);
-DllDef int libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename);
-DllDef int libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname);
-DllDef int libraw_dcraw_process(libraw_data_t* lr);
-DllDef libraw_processed_image_t* dcraw_make_mem_image(libraw_data_t* lr, int *errc);
-DllDef libraw_processed_image_t* dcraw_make_mem_thumb(libraw_data_t* lr, int *errc);
+ DllDef const char *libraw_strerror(int errorcode);
+ DllDef const char *libraw_strprogress(enum LibRaw_progress);
+ /* LibRaw C API */
+ DllDef libraw_data_t *libraw_init(unsigned int flags);
+ DllDef int libraw_open_file(libraw_data_t *, const char *);
+#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
+ DllDef int libraw_open_file_ex(libraw_data_t *, const char *,
+ INT64 max_buff_sz);
+#endif
+#if defined(_WIN32) || defined(WIN32)
+ DllDef int libraw_open_wfile(libraw_data_t *, const wchar_t *);
+#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
+ DllDef int libraw_open_wfile_ex(libraw_data_t *, const wchar_t *,
+ INT64 max_buff_sz);
+#endif
+#endif
+
+ DllDef int libraw_open_buffer(libraw_data_t *, const void *buffer, size_t size);
+ DllDef int libraw_open_bayer(libraw_data_t *lr, unsigned char *data,
+ unsigned datalen, ushort _raw_width,
+ ushort _raw_height, ushort _left_margin,
+ ushort _top_margin, ushort _right_margin,
+ ushort _bottom_margin, unsigned char procflags,
+ unsigned char bayer_battern,
+ unsigned unused_bits, unsigned otherflags,
+ unsigned black_level);
+ DllDef int libraw_unpack(libraw_data_t *);
+ DllDef int libraw_unpack_thumb(libraw_data_t *);
+ DllDef int libraw_unpack_thumb_ex(libraw_data_t *,int);
+ DllDef void libraw_recycle_datastream(libraw_data_t *);
+ DllDef void libraw_recycle(libraw_data_t *);
+ DllDef void libraw_close(libraw_data_t *);
+ DllDef void libraw_subtract_black(libraw_data_t *);
+ DllDef int libraw_raw2image(libraw_data_t *);
+ DllDef void libraw_free_image(libraw_data_t *);
+ /* version helpers */
+ DllDef const char *libraw_version();
+ DllDef int libraw_versionNumber();
+ /* Camera list */
+ DllDef const char **libraw_cameraList();
+ DllDef int libraw_cameraCount();
+
+ /* helpers */
+ DllDef void libraw_set_exifparser_handler(libraw_data_t *,
+ exif_parser_callback cb,
+ void *datap);
+ DllDef void libraw_set_dataerror_handler(libraw_data_t *, data_callback func,
+ void *datap);
+ DllDef void libraw_set_progress_handler(libraw_data_t *, progress_callback cb,
+ void *datap);
+ DllDef const char *libraw_unpack_function_name(libraw_data_t *lr);
+ DllDef int libraw_get_decoder_info(libraw_data_t *lr,
+ libraw_decoder_info_t *d);
+ DllDef int libraw_COLOR(libraw_data_t *, int row, int col);
+ DllDef unsigned libraw_capabilities();
+
+ /* DCRAW compatibility */
+ DllDef int libraw_adjust_sizes_info_only(libraw_data_t *);
+ DllDef int libraw_dcraw_ppm_tiff_writer(libraw_data_t *lr,
+ const char *filename);
+ DllDef int libraw_dcraw_thumb_writer(libraw_data_t *lr, const char *fname);
+ DllDef int libraw_dcraw_process(libraw_data_t *lr);
+ DllDef libraw_processed_image_t *
+ libraw_dcraw_make_mem_image(libraw_data_t *lr, int *errc);
+ DllDef libraw_processed_image_t *
+ libraw_dcraw_make_mem_thumb(libraw_data_t *lr, int *errc);
+ DllDef void libraw_dcraw_clear_mem(libraw_processed_image_t *);
+ /* getters/setters used by 3DLut Creator */
+ DllDef void libraw_set_demosaic(libraw_data_t *lr, int value);
+ DllDef void libraw_set_output_color(libraw_data_t *lr, int value);
+ DllDef void libraw_set_adjust_maximum_thr(libraw_data_t *lr, float value);
+ DllDef void libraw_set_user_mul(libraw_data_t *lr, int index, float val);
+ DllDef void libraw_set_output_bps(libraw_data_t *lr, int value);
+ DllDef void libraw_set_gamma(libraw_data_t *lr, int index, float value);
+ DllDef void libraw_set_no_auto_bright(libraw_data_t *lr, int value);
+ DllDef void libraw_set_bright(libraw_data_t *lr, float value);
+ DllDef void libraw_set_highlight(libraw_data_t *lr, int value);
+ DllDef void libraw_set_fbdd_noiserd(libraw_data_t *lr, int value);
+ DllDef int libraw_get_raw_height(libraw_data_t *lr);
+ DllDef int libraw_get_raw_width(libraw_data_t *lr);
+ DllDef int libraw_get_iheight(libraw_data_t *lr);
+ DllDef int libraw_get_iwidth(libraw_data_t *lr);
+ DllDef float libraw_get_cam_mul(libraw_data_t *lr, int index);
+ DllDef float libraw_get_pre_mul(libraw_data_t *lr, int index);
+ DllDef float libraw_get_rgb_cam(libraw_data_t *lr, int index1, int index2);
+ DllDef int libraw_get_color_maximum(libraw_data_t *lr);
+ DllDef void libraw_set_output_tif(libraw_data_t *lr, int value);
+ DllDef libraw_iparams_t *libraw_get_iparams(libraw_data_t *lr);
+ DllDef libraw_lensinfo_t *libraw_get_lensinfo(libraw_data_t *lr);
+ DllDef libraw_imgother_t *libraw_get_imgother(libraw_data_t *lr);
#ifdef __cplusplus
}
#endif
-
#ifdef __cplusplus
class DllDef LibRaw
{
- public:
- libraw_data_t imgdata;
- int verbose;
-
- LibRaw(unsigned int flags = LIBRAW_OPTIONS_NONE);
-
- libraw_output_params_t* output_params_ptr() { return &imgdata.params;}
- int open_file(const char *fname);
- int open_buffer(void *buffer, size_t size);
- int open_datastream(LibRaw_abstract_datastream *);
- int unpack(void);
- int unpack_thumb(void);
-
- int adjust_sizes_info_only(void);
- void set_memerror_handler( memory_callback cb,void *data) {callbacks.memcb_data = data; callbacks.mem_cb = cb; }
- void set_dataerror_handler(data_callback func, void *data) { callbacks.datacb_data = data; callbacks.data_cb = func;}
- void set_progress_handler(progress_callback pcb, void *data) { callbacks.progresscb_data = data; callbacks.progress_cb = pcb;}
-
- // helpers
- static const char* version() { return LIBRAW_VERSION_STR;}
- static int versionNumber() { return LIBRAW_VERSION; }
- static const char** cameraList();
- static int cameraCount();
- static const char* strprogress(enum LibRaw_progress);
- static const char* strerror(int p) { return libraw_strerror(p);}
- // dcraw emulation
- int dcraw_document_mode_processing();
- int dcraw_ppm_tiff_writer(const char *filename);
- int dcraw_thumb_writer(const char *fname);
- int dcraw_process(void);
- // memory writers
- libraw_processed_image_t* dcraw_make_mem_image(int *errcode=NULL);
- libraw_processed_image_t* dcraw_make_mem_thumb(int *errcode=NULL);
-
- // free all internal data structures
- void recycle();
- ~LibRaw(void) { recycle(); delete tls; }
-
- int FC(int row,int col) { return (imgdata.idata.filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3);}
- int fc (int row, int col);
- int add_masked_borders_to_bitmap();
-
- const char *unpack_function_name();
- int rotate_fuji_raw();
-
- private:
- void* malloc(size_t t);
- void* calloc(size_t n,size_t t);
- void free(void *p);
- void merror (void *ptr, const char *where);
- void derror();
-
-// data
-
- LibRaw_TLS *tls;
- libraw_internal_data_t libraw_internal_data;
- decode first_decode[2048], *second_decode, *free_decode;
- tiff_ifd_t tiff_ifd[10];
- libraw_memmgr memmgr;
- libraw_callbacks_t callbacks;
-
- LibRaw_constants rgb_constants;
- void (LibRaw:: *write_thumb)(FILE *),
- (LibRaw:: *write_fun)(FILE *);
- void (LibRaw:: *load_raw)(),
- (LibRaw:: *thumb_load_raw)();
-
- void kodak_thumb_loader();
- void write_thumb_ppm_tiff(FILE *); // kodak
- void foveon_thumb_loader (void); //Sigma
-
-
- // moved from implementation level to private: visibility
- void init_masked_ptrs();
- ushort *get_masked_pointer(int row, int col);
-
- int own_filtering_supported(){ return 0;}
- void identify();
- void write_ppm_tiff (FILE *ofp);
- void convert_to_rgb();
- void kodak_ycbcr_load_raw();
- void remove_zeroes();
+public:
+ libraw_data_t imgdata;
+
+ LibRaw(unsigned int flags = LIBRAW_OPTIONS_NONE);
+ libraw_output_params_t *output_params_ptr() { return &imgdata.params; }
+#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
+ int open_file(const char *fname,
+ INT64 max_buffered_sz = LIBRAW_USE_STREAMS_DATASTREAM_MAXSIZE);
+#if defined(_WIN32) || defined(WIN32)
+ int open_file(const wchar_t *fname,
+ INT64 max_buffered_sz = LIBRAW_USE_STREAMS_DATASTREAM_MAXSIZE);
+#endif
+#else
+ int open_file(const char *fname);
+#if defined(_WIN32) || defined(WIN32)
+ int open_file(const wchar_t *fname);
+#endif
+
+#endif
+ int open_buffer(const void *buffer, size_t size);
+ virtual int open_datastream(LibRaw_abstract_datastream *);
+ virtual int open_bayer(const unsigned char *data, unsigned datalen,
+ ushort _raw_width, ushort _raw_height,
+ ushort _left_margin, ushort _top_margin,
+ ushort _right_margin, ushort _bottom_margin,
+ unsigned char procflags, unsigned char bayer_pattern,
+ unsigned unused_bits, unsigned otherflags,
+ unsigned black_level);
+ int error_count() { return libraw_internal_data.unpacker_data.data_error; }
+ void recycle_datastream();
+ int unpack(void);
+ int unpack_thumb(void);
+ int unpack_thumb_ex(int);
+ int thumbOK(INT64 maxsz = -1);
+ int adjust_sizes_info_only(void);
+ int subtract_black();
+ int subtract_black_internal();
+ int raw2image();
+ int raw2image_ex(int do_subtract_black);
+ void raw2image_start();
+ void free_image();
+ int adjust_maximum();
+ int adjust_to_raw_inset_crop(unsigned mask, float maxcrop = 0.55f);
+ void set_exifparser_handler(exif_parser_callback cb, void *data)
+ {
+ callbacks.exifparser_data = data;
+ callbacks.exif_cb = cb;
+ }
+ void set_dataerror_handler(data_callback func, void *data)
+ {
+ callbacks.datacb_data = data;
+ callbacks.data_cb = func;
+ }
+ void set_progress_handler(progress_callback pcb, void *data)
+ {
+ callbacks.progresscb_data = data;
+ callbacks.progress_cb = pcb;
+ }
+
+ static const char* cameramakeridx2maker(unsigned maker);
+ int setMakeFromIndex(unsigned index);
+
+ void convertFloatToInt(float dmin = 4096.f, float dmax = 32767.f,
+ float dtarget = 16383.f);
+ /* helpers */
+ static unsigned capabilities();
+ static const char *version();
+ static int versionNumber();
+ static const char **cameraList();
+ static int cameraCount();
+ static const char *strprogress(enum LibRaw_progress);
+ static const char *strerror(int p);
+ /* dcraw emulation */
+ int dcraw_ppm_tiff_writer(const char *filename);
+ int dcraw_thumb_writer(const char *fname);
+ int dcraw_process(void);
+ /* information calls */
+ int is_fuji_rotated()
+ {
+ return libraw_internal_data.internal_output_params.fuji_width;
+ }
+ int is_sraw();
+ int sraw_midpoint();
+ int is_nikon_sraw();
+ int is_coolscan_nef();
+ int is_jpeg_thumb();
+ int is_floating_point();
+ int have_fpdata();
+ /* memory writers */
+ virtual libraw_processed_image_t *dcraw_make_mem_image(int *errcode = NULL);
+ virtual libraw_processed_image_t *dcraw_make_mem_thumb(int *errcode = NULL);
+ static void dcraw_clear_mem(libraw_processed_image_t *);
+
+ /* Additional calls for make_mem_image */
+ void get_mem_image_format(int *width, int *height, int *colors,
+ int *bps) const;
+ int copy_mem_image(void *scan0, int stride, int bgr);
+
+ /* free all internal data structures */
+ void recycle();
+ virtual ~LibRaw(void);
+
+ int COLOR(int row, int col)
+ {
+ if (!imgdata.idata.filters)
+ return 6; /* Special value 0+1+2+3 */
+ if (imgdata.idata.filters < 1000)
+ return fcol(row, col);
+ return libraw_internal_data.internal_output_params.fuji_width
+ ? FCF(row, col)
+ : FC(row, col);
+ }
+
+ int FC(int row, int col)
+ {
+ return (imgdata.idata.filters >> (((row << 1 & 14) | (col & 1)) << 1) & 3);
+ }
+ int fcol(int row, int col);
+
+ const char *unpack_function_name();
+ virtual int get_decoder_info(libraw_decoder_info_t *d_info);
+ libraw_internal_data_t *get_internal_data_pointer()
+ {
+ return &libraw_internal_data;
+ }
+
+ static float powf_lim(float a, float b, float limup)
+ {
+ return (b > limup || b < -limup) ? 0.f : powf(a, b);
+ }
+ static float libraw_powf64l(float a, float b) { return powf_lim(a, b, 64.f); }
+
+ static unsigned sgetn(int n, uchar *s)
+ {
+ unsigned result = 0;
+ while (n-- > 0)
+ result = (result << 8) | (*s++);
+ return result;
+ }
+
+ /* Phase one correction/subtractBL calls */
+ /* Returns libraw error code */
+
+ int phase_one_subtract_black(ushort *src, ushort *dest);
+ int phase_one_correct();
+
+ int set_rawspeed_camerafile(char *filename);
+ virtual void setCancelFlag();
+ virtual void clearCancelFlag();
+ virtual int adobe_coeff(unsigned, const char *, int internal_only = 0);
+
+ void set_dng_host(void *);
+
+protected:
+ static void *memmem(char *haystack, size_t haystacklen, char *needle,
+ size_t needlelen);
+ static char *strcasestr(char *h, const char *n);
+ static size_t strnlen(const char *s, size_t n);
+
+#ifdef LIBRAW_NO_IOSTREAMS_DATASTREAM
+ int libraw_openfile_tail(LibRaw_abstract_datastream *stream);
+#endif
+
+ int is_curve_linear();
+ void checkCancel();
+ void cam_xyz_coeff(float _rgb_cam[3][4], double cam_xyz[4][3]);
+ void phase_one_allocate_tempbuffer();
+ void phase_one_free_tempbuffer();
+ virtual int is_phaseone_compressed();
+ virtual int is_canon_600();
+ /* Hotspots */
+ virtual void copy_fuji_uncropped(unsigned short cblack[4],
+ unsigned short *dmaxp);
+ virtual void copy_bayer(unsigned short cblack[4], unsigned short *dmaxp);
+ virtual void fuji_rotate();
+ virtual void convert_to_rgb_loop(float out_cam[3][4]);
+ virtual void lin_interpolate_loop(int *code, int size);
+ virtual void scale_colors_loop(float scale_mul[4]);
+
+ /* Fujifilm compressed decoder public interface (to make parallel decoder) */
+ virtual void
+ fuji_decode_loop(struct fuji_compressed_params *common_info, int count,
+ INT64 *offsets, unsigned *sizes, uchar *q_bases);
+ void fuji_decode_strip(struct fuji_compressed_params *info_common,
+ int cur_block, INT64 raw_offset, unsigned size, uchar *q_bases);
+ /* CR3 decoder public interface to make parallel decoder */
+ virtual void crxLoadDecodeLoop(void *, int);
+ int crxDecodePlane(void *, uint32_t planeNumber);
+ virtual void crxLoadFinalizeLoopE3(void *, int);
+ void crxConvertPlaneLineDf(void *, int);
+
+ int FCF(int row, int col)
+ {
+ int rr, cc;
+ if (libraw_internal_data.unpacker_data.fuji_layout)
+ {
+ rr = libraw_internal_data.internal_output_params.fuji_width - 1 - col +
+ (row >> 1);
+ cc = col + ((row + 1) >> 1);
+ }
+ else
+ {
+ rr = libraw_internal_data.internal_output_params.fuji_width - 1 + row -
+ (col >> 1);
+ cc = row + ((col + 1) >> 1);
+ }
+ return FC(rr, cc);
+ }
+
+ void adjust_bl();
+ void *malloc(size_t t);
+ void *calloc(size_t n, size_t t);
+ void *realloc(void *p, size_t s);
+ void free(void *p);
+ void derror();
+
+ LibRaw_TLS *tls;
+ libraw_internal_data_t libraw_internal_data;
+ decode first_decode[2048], *second_decode, *free_decode;
+ tiff_ifd_t tiff_ifd[LIBRAW_IFD_MAXCOUNT];
+ libraw_memmgr memmgr;
+ libraw_callbacks_t callbacks;
+
+ //void (LibRaw::*write_thumb)();
+ void (LibRaw::*write_fun)();
+ void (LibRaw::*load_raw)();
+ //void (LibRaw::*thumb_load_raw)();
+ void (LibRaw::*pentax_component_load_raw)();
+
+ void kodak_thumb_loader();
+ void write_thumb_ppm_tiff(FILE *);
+#ifdef USE_X3FTOOLS
+ void x3f_thumb_loader();
+ INT64 x3f_thumb_size();
+#endif
+
+ int own_filtering_supported() { return 0; }
+ void identify();
+ void initdata();
+ unsigned parse_custom_cameras(unsigned limit, libraw_custom_camera_t table[],
+ char **list);
+ void write_ppm_tiff();
+ void convert_to_rgb();
+ void remove_zeroes();
+ void crop_masked_pixels();
#ifndef NO_LCMS
- void apply_profile(char*,char*);
-#endif
-// Iterpolators
- void pre_interpolate();
- void border_interpolate (int border);
- void lin_interpolate();
- void vng_interpolate();
- void ppg_interpolate();
- void ahd_interpolate();
-
-// Image filters
- void bad_pixels(char*);
- void subtract(char*);
- void hat_transform (float *temp, float *base, int st, int size, int sc);
- void wavelet_denoise();
- void scale_colors();
- void median_filter ();
- void blend_highlights();
- void recover_highlights();
-
- void fuji_rotate();
- void stretch();
-
-// Thmbnail functions
- void foveon_thumb (FILE *tfp);
- void jpeg_thumb_writer (FILE *tfp,char *thumb,int thumb_length);
- void jpeg_thumb (FILE *tfp);
- void ppm_thumb (FILE *tfp);
- void layer_thumb (FILE *tfp);
- void rollei_thumb (FILE *tfp);
- void kodak_thumb_load_raw();
-
- // utility for cut'n'pasted code
- void foveon_decoder (unsigned size, unsigned code);
- unsigned get4();
-
- int flip_index (int row, int col);
- void gamma_lut(ushort lut[0x10000]);
-
-
-// == internal functions
-
-#ifdef LIBRAW_LIBRARY_BUILD
+ void apply_profile(const char *, const char *);
+#endif
+ void pre_interpolate();
+ void border_interpolate(int border);
+ void lin_interpolate();
+ void vng_interpolate();
+ void ppg_interpolate();
+ void cielab(ushort rgb[3], short lab[3]);
+ void xtrans_interpolate(int);
+ void ahd_interpolate();
+ void dht_interpolate();
+ void aahd_interpolate();
+
+ void dcb(int iterations, int dcb_enhance);
+ void fbdd(int noiserd);
+ void exp_bef(float expos, float preser);
+
+ void bad_pixels(const char *);
+ void subtract(const char *);
+ void hat_transform(float *temp, float *base, int st, int size, int sc);
+ void wavelet_denoise();
+ void scale_colors();
+ void median_filter();
+ void blend_highlights();
+ void recover_highlights();
+ void green_matching();
+
+ void stretch();
+
+ void jpeg_thumb_writer(FILE *tfp, char *thumb, int thumb_length);
+#if 0
+ void jpeg_thumb();
+ void ppm_thumb();
+ void ppm16_thumb();
+ void layer_thumb();
+ void rollei_thumb();
+#endif
+ void kodak_thumb_load_raw();
+
+ unsigned get4();
+
+ int flip_index(int row, int col);
+ void gamma_curve(double pwr, double ts, int mode, int imax);
+ void cubic_spline(const int *x_, const int *y_, const int len);
+
+ /* RawSpeed data */
+ void *_rawspeed_camerameta;
+ void *_rawspeed_decoder;
+ void *_rawspeed3_handle;
+ void fix_after_rawspeed(int bl);
+ int try_rawspeed(); /* returns LIBRAW_SUCCESS on success */
+ /* Fast cancel flag */
+ long _exitflag;
+
+ /* DNG SDK data */
+ void *dnghost;
+ void *dngnegative;
+ void *dngimage;
+ int valid_for_dngsdk();
+ int try_dngsdk();
+ /* X3F data */
+ void *_x3f_data; /* keep it even if USE_X3FTOOLS is not defined to do not change sizeof(LibRaw)*/
+
+ int raw_was_read()
+ {
+ return imgdata.rawdata.raw_image || imgdata.rawdata.color4_image ||
+ imgdata.rawdata.color3_image || imgdata.rawdata.float_image ||
+ imgdata.rawdata.float3_image || imgdata.rawdata.float4_image;
+ }
+
+#ifdef LIBRAW_LIBRARY_BUILD
#include "internal/libraw_internal_funcs.h"
#endif
-
};
-#ifdef LIBRAW_LIBRARY_BUILD
-#define RUN_CALLBACK(stage,iter,expect) if(callbacks.progress_cb) { \
- int rr = (*callbacks.progress_cb)(callbacks.progresscb_data,stage,iter,expect); \
- if(rr!=0) throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; \
- }
+#ifdef LIBRAW_LIBRARY_BUILD
+ushort libraw_sget2_static(short _order, uchar *s);
+unsigned libraw_sget4_static(short _order, uchar *s);
+int libraw_tagtype_dataunit_bytes(int tagtype);
+double libraw_sgetreal_static(short _order, int type, uchar *s);
+float libraw_int_to_float (int i);
#endif
-#endif // __cplusplus
+#ifdef LIBRAW_LIBRARY_BUILD
+#define RUN_CALLBACK(stage, iter, expect) \
+ if (callbacks.progress_cb) \
+ { \
+ int rr = (*callbacks.progress_cb)(callbacks.progresscb_data, stage, iter, \
+ expect); \
+ if (rr != 0) \
+ throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; \
+ }
+#endif
+#endif /* __cplusplus */
-#endif // _LIBRAW_CLASS_H
+#endif /* _LIBRAW_CLASS_H */
diff --git a/libkdcraw/libraw/libraw/libraw_alloc.h b/libkdcraw/libraw/libraw/libraw_alloc.h
index cd15383..c22d995 100644
--- a/libkdcraw/libraw/libraw/libraw_alloc.h
+++ b/libkdcraw/libraw/libraw/libraw_alloc.h
@@ -1,24 +1,19 @@
-/*
+/* -*- C++ -*-
* File: libraw_alloc.h
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
- * Created: Sat Mar 22, 2008
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Sat Mar 22, 2008
*
* LibRaw C++ interface
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+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).
+
*/
#ifndef __LIBRAW_ALLOC_H
@@ -26,73 +21,128 @@
#include <stdlib.h>
#include <string.h>
-#ifdef WIN32
-#define bzero(p,sz) memset(p,0,sz)
-#endif
+#include "libraw_const.h"
#ifdef __cplusplus
-#define MSIZE 32
+#define LIBRAW_MSIZE 512
-class libraw_memmgr
+class DllDef libraw_memmgr
{
- public:
- libraw_memmgr()
- {
- bzero(mems,sizeof(mems));
- calloc_cnt=0;
- }
- void *malloc(size_t sz)
- {
- void *ptr = ::malloc(sz);
- mem_ptr(ptr);
- return ptr;
- }
- void *calloc(size_t n, size_t sz)
- {
- void *ptr = ::calloc(n,sz);
- mem_ptr(ptr);
- return ptr;
- }
- void free(void *ptr)
- {
- ::free(ptr);
- forget_ptr(ptr);
- }
- void cleanup(void)
- {
- for(int i = 0; i< MSIZE; i++)
- if(mems[i])
- {
-// fprintf(stderr,"Found lost fragment at 0x%x\n",mems[i]);
- free(mems[i]);
- mems[i] = NULL;
- }
- }
+public:
+ libraw_memmgr(unsigned ee) : extra_bytes(ee)
+ {
+ size_t alloc_sz = LIBRAW_MSIZE * sizeof(void *);
+ mems = (void **)::malloc(alloc_sz);
+ memset(mems, 0, alloc_sz);
+ }
+ ~libraw_memmgr()
+ {
+ cleanup();
+ ::free(mems);
+ }
+ void *malloc(size_t sz)
+ {
+#ifdef LIBRAW_USE_CALLOC_INSTEAD_OF_MALLOC
+ void *ptr = ::calloc(sz + extra_bytes, 1);
+#else
+ void *ptr = ::malloc(sz + extra_bytes);
+#endif
+ mem_ptr(ptr);
+ return ptr;
+ }
+ void *calloc(size_t n, size_t sz)
+ {
+ void *ptr = ::calloc(n + (extra_bytes + sz - 1) / (sz ? sz : 1), sz);
+ mem_ptr(ptr);
+ return ptr;
+ }
+ void *realloc(void *ptr, size_t newsz)
+ {
+ void *ret = ::realloc(ptr, newsz + extra_bytes);
+ forget_ptr(ptr);
+ mem_ptr(ret);
+ return ret;
+ }
+ void free(void *ptr)
+ {
+ forget_ptr(ptr);
+ ::free(ptr);
+ }
+ void cleanup(void)
+ {
+ for (int i = 0; i < LIBRAW_MSIZE; i++)
+ if (mems[i])
+ {
+ ::free(mems[i]);
+ mems[i] = NULL;
+ }
+ }
- private:
- void *mems[MSIZE];
- int calloc_cnt;
- void mem_ptr(void *ptr)
- {
- if(ptr)
- for(int i=0;i < MSIZE; i++)
- if(!mems[i])
- {
- mems[i] = ptr;
- break;
- }
- }
- void forget_ptr(void *ptr)
+private:
+ void **mems;
+ unsigned extra_bytes;
+ void mem_ptr(void *ptr)
+ {
+#if defined(LIBRAW_USE_OPENMP)
+ bool ok = false; /* do not return from critical section */
+#endif
+
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp critical
+ {
+#endif
+ if (ptr)
+ {
+ for (int i = 0; i < LIBRAW_MSIZE - 1; i++)
+ if (!mems[i])
+ {
+ mems[i] = ptr;
+#if defined(LIBRAW_USE_OPENMP)
+ ok = true;
+ break;
+#else
+ return;
+#endif
+ }
+#ifdef LIBRAW_MEMPOOL_CHECK
+#if !defined(LIBRAW_USE_OPENMP)
+ /* remember ptr in last mems item to be free'ed at cleanup */
+ if (!mems[LIBRAW_MSIZE - 1])
+ mems[LIBRAW_MSIZE - 1] = ptr;
+ throw LIBRAW_EXCEPTION_MEMPOOL;
+#endif
+#endif
+ }
+#if defined(LIBRAW_USE_OPENMP)
+ }
+ if(!ok)
+ {
+ if (!mems[LIBRAW_MSIZE - 1])
+ mems[LIBRAW_MSIZE - 1] = ptr;
+ throw LIBRAW_EXCEPTION_MEMPOOL;
+ }
+#endif
+ }
+ void forget_ptr(void *ptr)
+ {
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp critical
{
- if(ptr)
- for(int i=0;i < MSIZE; i++)
- if(mems[i] == ptr)
- mems[i] = NULL;
+#endif
+ if (ptr)
+ for (int i = 0; i < LIBRAW_MSIZE; i++)
+ if (mems[i] == ptr)
+ {
+ mems[i] = NULL;
+ break;
+ }
+#if defined(LIBRAW_USE_OPENMP)
}
-
+#endif
+ }
};
-#endif //C++
+#endif /* C++ */
#endif
diff --git a/libkdcraw/libraw/libraw/libraw_const.h b/libkdcraw/libraw/libraw/libraw_const.h
index 20f3430..599306b 100644
--- a/libkdcraw/libraw/libraw/libraw_const.h
+++ b/libkdcraw/libraw/libraw/libraw_const.h
@@ -1,159 +1,810 @@
-/*
+/* -*- C++ -*-
* File: libraw_const.h
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
* Created: Sat Mar 8 , 2008
- *
* LibRaw error codes
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+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).
+
*/
#ifndef _LIBRAW_ERRORS_H
#define _LIBRAW_ERRORS_H
-enum LibRaw_constructor_flags
+#define LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD 0.75f
+#define LIBRAW_DEFAULT_AUTO_BRIGHTNESS_THRESHOLD 0.01f
+/* limit allocation size, default is 2Gb */
+#ifndef LIBRAW_MAX_ALLOC_MB_DEFAULT
+#define LIBRAW_MAX_ALLOC_MB_DEFAULT 2048L
+#endif
+
+#ifndef LIBRAW_MAX_NONDNG_RAW_FILE_SIZE
+#define LIBRAW_MAX_NONDNG_RAW_FILE_SIZE 2147483647ULL
+#endif
+
+#ifndef LIBRAW_MAX_DNG_RAW_FILE_SIZE
+#ifdef USE_DNGSDK
+#define LIBRAW_MAX_DNG_RAW_FILE_SIZE 4294967295ULL
+#else
+#define LIBRAW_MAX_DNG_RAW_FILE_SIZE 2147483647ULL
+#endif
+#endif
+
+
+/* limit thumbnail size, default is 512Mb*/
+#ifndef LIBRAW_MAX_THUMBNAIL_MB
+#define LIBRAW_MAX_THUMBNAIL_MB 512L
+#endif
+
+/* Check if enough file space exists before tag read */
+#ifndef LIBRAW_NO_IOSPACE_CHECK
+#define LIBRAW_IOSPACE_CHECK
+#endif
+#ifndef LIBRAW_NO_CR3_MEMPOOL
+#define LIBRAW_CR3_MEMPOOL
+#endif
+
+
+
+/* LibRaw uses own memory pool management, with LIBRAW_MSIZE (512)
+entries. It is enough for parsing/decoding non-damaged files, but
+may overflow on specially crafted files (eg. with many string values
+like XMP blocks.
+LIBRAW_MEMPOOL_CHECK define will result in error on pool overflow */
+#ifndef LIBRAW_NO_MEMPOOL_CHECK
+#define LIBRAW_MEMPOOL_CHECK
+#endif
+
+#define LIBRAW_MAX_METADATA_BLOCKS 1024
+#define LIBRAW_CBLACK_SIZE 4104
+#define LIBRAW_IFD_MAXCOUNT 10
+#define LIBRAW_THUMBNAIL_MAXCOUNT 8
+#define LIBRAW_CRXTRACKS_MAXCOUNT 16
+#define LIBRAW_AFDATA_MAXCOUNT 4
+
+#define LIBRAW_AHD_TILE 512
+
+#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
+
+enum LibRaw_open_flags
{
- LIBRAW_OPTIONS_NONE =0,
- LIBRAW_OPIONS_NO_MEMERR_CALLBACK=1,
- LIBRAW_OPIONS_NO_DATAERR_CALLBACK=1<<1
+ LIBRAW_OPEN_BIGFILE=1,
+ LIBRAW_OPEN_FILE= 1<<1
};
+#endif
-enum LibRaw_warnings
+enum LibRaw_openbayer_patterns
{
- LIBRAW_WARN_NONE =0,
- LIBRAW_WARN_FOVEON_NOMATRIX =1,
- LIBRAW_WARN_FOVEON_INVALIDWB =1<<1,
- LIBRAW_WARN_BAD_CAMERA_WB =1<<2,
- LIBRAW_WARN_NO_METADATA =1<<3,
- LIBRAW_WARN_NO_JPEGLIB = 1<<4,
- LIBRAW_WARN_NO_EMBEDDED_PROFILE = 1<<5,
- LIBRAW_WARN_NO_INPUT_PROFILE = 1<<6,
- LIBRAW_WARN_BAD_OUTPUT_PROFILE= 1<<7,
- LIBRAW_WARN_NO_BADPIXELMAP=1<<8,
- LIBRAW_WARN_BAD_DARKFRAME_FILE=1<<9,
- LIBRAW_WARN_BAD_DARKFRAME_DIM=1<<10
+ LIBRAW_OPENBAYER_RGGB = 0x94,
+ LIBRAW_OPENBAYER_BGGR = 0x16,
+ LIBRAW_OPENBAYER_GRBG = 0x61,
+ LIBRAW_OPENBAYER_GBRG = 0x49
};
-enum LibRaw_exceptions
+enum LibRaw_dngfields_marks
+{
+ LIBRAW_DNGFM_FORWARDMATRIX = 1,
+ LIBRAW_DNGFM_ILLUMINANT = 1 << 1,
+ LIBRAW_DNGFM_COLORMATRIX = 1 << 2,
+ LIBRAW_DNGFM_CALIBRATION = 1 << 3,
+ LIBRAW_DNGFM_ANALOGBALANCE = 1 << 4,
+ LIBRAW_DNGFM_BLACK = 1 << 5,
+ LIBRAW_DNGFM_WHITE = 1 << 6,
+ LIBRAW_DNGFM_OPCODE2 = 1 << 7,
+ LIBRAW_DNGFM_LINTABLE = 1 << 8,
+ LIBRAW_DNGFM_CROPORIGIN = 1 << 9,
+ LIBRAW_DNGFM_CROPSIZE = 1 << 10,
+ LIBRAW_DNGFM_PREVIEWCS = 1 << 11,
+ LIBRAW_DNGFM_ASSHOTNEUTRAL = 1 << 12,
+ LIBRAW_DNGFM_BASELINEEXPOSURE = 1 << 13,
+ LIBRAW_DNGFM_LINEARRESPONSELIMIT = 1 << 14,
+ LIBRAW_DNGFM_USERCROP = 1 << 15,
+ LIBRAW_DNGFM_OPCODE1 = 1 << 16,
+ LIBRAW_DNGFM_OPCODE3 = 1 << 17,
+};
+
+enum LibRaw_As_Shot_WB_Applied_codes
+{
+ LIBRAW_ASWB_APPLIED = 1,
+ LIBRAW_ASWB_CANON = 2,
+ LIBRAW_ASWB_NIKON = 4,
+ LIBRAW_ASWB_NIKON_SRAW = 8,
+ LIBRAW_ASWB_PENTAX = 16
+};
+
+#define tagtypeIs(typex) (type == typex)
+enum LibRaw_ExifTagTypes {
+ LIBRAW_EXIFTAG_TYPE_UNKNOWN = 0,
+ LIBRAW_EXIFTAG_TYPE_BYTE = 1,
+ LIBRAW_EXIFTAG_TYPE_ASCII = 2,
+ LIBRAW_EXIFTAG_TYPE_SHORT = 3,
+ LIBRAW_EXIFTAG_TYPE_LONG = 4,
+ LIBRAW_EXIFTAG_TYPE_RATIONAL = 5,
+ LIBRAW_EXIFTAG_TYPE_SBYTE = 6,
+ LIBRAW_EXIFTAG_TYPE_UNDEFINED = 7,
+ LIBRAW_EXIFTAG_TYPE_SSHORT = 8,
+ LIBRAW_EXIFTAG_TYPE_SLONG = 9,
+ LIBRAW_EXIFTAG_TYPE_SRATIONAL = 10,
+ LIBRAW_EXIFTAG_TYPE_FLOAT = 11,
+ LIBRAW_EXIFTAG_TYPE_DOUBLE = 12,
+ LIBRAW_EXIFTAG_TYPE_IFD = 13,
+ LIBRAW_EXIFTAG_TYPE_UNICODE = 14,
+ LIBRAW_EXIFTAG_TYPE_COMPLEX = 15,
+ LIBRAW_EXIFTAG_TYPE_LONG8 = 16,
+ LIBRAW_EXIFTAG_TYPE_SLONG8 = 17,
+ LIBRAW_EXIFTAG_TYPE_IFD8 = 18
+};
+
+#define LIBRAW_EXIFTOOLTAGTYPE_int8u LIBRAW_EXIFTAG_TYPE_BYTE
+#define LIBRAW_EXIFTOOLTAGTYPE_string LIBRAW_EXIFTAG_TYPE_ASCII
+#define LIBRAW_EXIFTOOLTAGTYPE_int16u LIBRAW_EXIFTAG_TYPE_SHORT
+#define LIBRAW_EXIFTOOLTAGTYPE_int32u LIBRAW_EXIFTAG_TYPE_LONG
+#define LIBRAW_EXIFTOOLTAGTYPE_rational64u LIBRAW_EXIFTAG_TYPE_RATIONAL
+#define LIBRAW_EXIFTOOLTAGTYPE_int8s LIBRAW_EXIFTAG_TYPE_SBYTE
+#define LIBRAW_EXIFTOOLTAGTYPE_undef LIBRAW_EXIFTAG_TYPE_UNDEFINED
+#define LIBRAW_EXIFTOOLTAGTYPE_binary LIBRAW_EXIFTAG_TYPE_UNDEFINED
+#define LIBRAW_EXIFTOOLTAGTYPE_int16s LIBRAW_EXIFTAG_TYPE_SSHORT
+#define LIBRAW_EXIFTOOLTAGTYPE_int32s LIBRAW_EXIFTAG_TYPE_SLONG
+#define LIBRAW_EXIFTOOLTAGTYPE_rational64s LIBRAW_EXIFTAG_TYPE_SRATIONAL
+#define LIBRAW_EXIFTOOLTAGTYPE_float LIBRAW_EXIFTAG_TYPE_FLOAT
+#define LIBRAW_EXIFTOOLTAGTYPE_double LIBRAW_EXIFTAG_TYPE_DOUBLE
+#define LIBRAW_EXIFTOOLTAGTYPE_ifd LIBRAW_EXIFTAG_TYPE_IFD
+#define LIBRAW_EXIFTOOLTAGTYPE_unicode LIBRAW_EXIFTAG_TYPE_UNICODE
+#define LIBRAW_EXIFTOOLTAGTYPE_complex LIBRAW_EXIFTAG_TYPE_COMPLEX
+#define LIBRAW_EXIFTOOLTAGTYPE_int64u LIBRAW_EXIFTAG_TYPE_LONG8
+#define LIBRAW_EXIFTOOLTAGTYPE_int64s LIBRAW_EXIFTAG_TYPE_SLONG8
+#define LIBRAW_EXIFTOOLTAGTYPE_ifd64 LIBRAW_EXIFTAG_TYPE_IFD8
+
+#define LIBRAW_LENS_NOT_SET 0xffffffffffffffffULL
+
+enum LibRaw_whitebalance_code
+{
+// clang-format off
+ /*
+ EXIF light sources
+ 12 = FL-D; Daylight fluorescent (D 5700K – 7100K) (F1,F5)
+ 13 = FL-N; Day white fluorescent (N 4600K – 5400K) (F7,F8)
+ 14 = FL-W; Cool white fluorescent (W 3900K – 4500K) (F2,F6, office, store, warehouse)
+ 15 = FL-WW; White fluorescent (WW 3200K – 3700K) (F3, residential)
+ 16 = FL-L; Soft/Warm white fluorescent (L 2600K - 3250K) (F4, kitchen, bath)
+ */
+//clang-format on
+ LIBRAW_WBI_Unknown = 0,
+ LIBRAW_WBI_Daylight = 1,
+ LIBRAW_WBI_Fluorescent = 2,
+ LIBRAW_WBI_Tungsten = 3,
+ LIBRAW_WBI_Flash = 4,
+ LIBRAW_WBI_FineWeather = 9,
+ LIBRAW_WBI_Cloudy = 10,
+ LIBRAW_WBI_Shade = 11,
+ LIBRAW_WBI_FL_D = 12,
+ LIBRAW_WBI_FL_N = 13,
+ LIBRAW_WBI_FL_W = 14,
+ LIBRAW_WBI_FL_WW = 15,
+ LIBRAW_WBI_FL_L = 16,
+ LIBRAW_WBI_Ill_A = 17,
+ LIBRAW_WBI_Ill_B = 18,
+ LIBRAW_WBI_Ill_C = 19,
+ LIBRAW_WBI_D55 = 20,
+ LIBRAW_WBI_D65 = 21,
+ LIBRAW_WBI_D75 = 22,
+ LIBRAW_WBI_D50 = 23,
+ LIBRAW_WBI_StudioTungsten = 24,
+ LIBRAW_WBI_Sunset = 64,
+ LIBRAW_WBI_Underwater = 65,
+ LIBRAW_WBI_FluorescentHigh = 66,
+ LIBRAW_WBI_HT_Mercury = 67,
+ LIBRAW_WBI_AsShot = 81,
+ LIBRAW_WBI_Auto = 82,
+ LIBRAW_WBI_Custom = 83,
+ LIBRAW_WBI_Auto1 = 85,
+ LIBRAW_WBI_Auto2 = 86,
+ LIBRAW_WBI_Auto3 = 87,
+ LIBRAW_WBI_Auto4 = 88,
+ LIBRAW_WBI_Custom1 = 90,
+ LIBRAW_WBI_Custom2 = 91,
+ LIBRAW_WBI_Custom3 = 92,
+ LIBRAW_WBI_Custom4 = 93,
+ LIBRAW_WBI_Custom5 = 94,
+ LIBRAW_WBI_Custom6 = 95,
+ LIBRAW_WBI_PC_Set1 = 96,
+ LIBRAW_WBI_PC_Set2 = 97,
+ LIBRAW_WBI_PC_Set3 = 98,
+ LIBRAW_WBI_PC_Set4 = 99,
+ LIBRAW_WBI_PC_Set5 = 100,
+ LIBRAW_WBI_Measured = 110,
+ LIBRAW_WBI_BW = 120,
+ LIBRAW_WBI_Kelvin = 254,
+ LIBRAW_WBI_Other = 255,
+ LIBRAW_WBI_None = 0xffff
+};
+
+enum LibRaw_MultiExposure_related
+{
+ LIBRAW_ME_NONE = 0,
+ LIBRAW_ME_SIMPLE = 1,
+ LIBRAW_ME_OVERLAY = 2,
+ LIBRAW_ME_HDR = 3
+};
+
+enum LibRaw_dng_processing
+{
+ LIBRAW_DNG_NONE = 0,
+ LIBRAW_DNG_FLOAT = 1,
+ LIBRAW_DNG_LINEAR = 2,
+ LIBRAW_DNG_DEFLATE = 4,
+ LIBRAW_DNG_XTRANS = 8,
+ LIBRAW_DNG_OTHER = 16,
+ LIBRAW_DNG_8BIT = 32,
+ /*LIBRAW_DNG_LARGERANGE=64,*/ /* more than 16 bit integer */
+ LIBRAW_DNG_ALL =
+ LIBRAW_DNG_FLOAT | LIBRAW_DNG_LINEAR | LIBRAW_DNG_DEFLATE | LIBRAW_DNG_XTRANS |
+ LIBRAW_DNG_8BIT | LIBRAW_DNG_OTHER /* |LIBRAW_DNG_LARGERANGE */,
+ LIBRAW_DNG_DEFAULT = LIBRAW_DNG_FLOAT | LIBRAW_DNG_LINEAR |
+ LIBRAW_DNG_DEFLATE | LIBRAW_DNG_8BIT
+};
+
+enum LibRaw_output_flags
+{
+ LIBRAW_OUTPUT_FLAGS_NONE = 0,
+ LIBRAW_OUTPUT_FLAGS_PPMMETA = 1
+};
+
+enum LibRaw_runtime_capabilities
+{
+ LIBRAW_CAPS_RAWSPEED = 1,
+ LIBRAW_CAPS_DNGSDK = 1<<1,
+ LIBRAW_CAPS_GPRSDK = 1<<2,
+ LIBRAW_CAPS_UNICODEPATHS = 1<<3,
+ LIBRAW_CAPS_X3FTOOLS = 1<<4,
+ LIBRAW_CAPS_RPI6BY9 = 1<<5,
+ LIBRAW_CAPS_ZLIB = 1<<6,
+ LIBRAW_CAPS_JPEG = 1<<7,
+ LIBRAW_CAPS_RAWSPEED3 = 1<<8,
+ LIBRAW_CAPS_RAWSPEED_BITS = 1<<9,
+};
+
+enum LibRaw_colorspace {
+ LIBRAW_COLORSPACE_NotFound = 0,
+ LIBRAW_COLORSPACE_sRGB,
+ LIBRAW_COLORSPACE_AdobeRGB,
+ LIBRAW_COLORSPACE_WideGamutRGB,
+ LIBRAW_COLORSPACE_ProPhotoRGB,
+ LIBRAW_COLORSPACE_ICC,
+ LIBRAW_COLORSPACE_Uncalibrated, // Tag 0x0001 InteropIndex containing "R03" + LIBRAW_COLORSPACE_Uncalibrated = Adobe RGB
+ LIBRAW_COLORSPACE_CameraLinearUniWB,
+ LIBRAW_COLORSPACE_CameraLinear,
+ LIBRAW_COLORSPACE_CameraGammaUniWB,
+ LIBRAW_COLORSPACE_CameraGamma,
+ LIBRAW_COLORSPACE_MonochromeLinear,
+ LIBRAW_COLORSPACE_MonochromeGamma,
+ LIBRAW_COLORSPACE_Unknown = 255
+};
+
+enum LibRaw_cameramaker_index
+{
+ LIBRAW_CAMERAMAKER_Unknown = 0,
+ LIBRAW_CAMERAMAKER_Agfa,
+ LIBRAW_CAMERAMAKER_Alcatel,
+ LIBRAW_CAMERAMAKER_Apple,
+ LIBRAW_CAMERAMAKER_Aptina,
+ LIBRAW_CAMERAMAKER_AVT,
+ LIBRAW_CAMERAMAKER_Baumer,
+ LIBRAW_CAMERAMAKER_Broadcom,
+ LIBRAW_CAMERAMAKER_Canon,
+ LIBRAW_CAMERAMAKER_Casio,
+ LIBRAW_CAMERAMAKER_CINE,
+ LIBRAW_CAMERAMAKER_Clauss,
+ LIBRAW_CAMERAMAKER_Contax,
+ LIBRAW_CAMERAMAKER_Creative,
+ LIBRAW_CAMERAMAKER_DJI,
+ LIBRAW_CAMERAMAKER_DXO,
+ LIBRAW_CAMERAMAKER_Epson,
+ LIBRAW_CAMERAMAKER_Foculus,
+ LIBRAW_CAMERAMAKER_Fujifilm,
+ LIBRAW_CAMERAMAKER_Generic,
+ LIBRAW_CAMERAMAKER_Gione,
+ LIBRAW_CAMERAMAKER_GITUP,
+ LIBRAW_CAMERAMAKER_Google,
+ LIBRAW_CAMERAMAKER_GoPro,
+ LIBRAW_CAMERAMAKER_Hasselblad,
+ LIBRAW_CAMERAMAKER_HTC,
+ LIBRAW_CAMERAMAKER_I_Mobile,
+ LIBRAW_CAMERAMAKER_Imacon,
+ LIBRAW_CAMERAMAKER_JK_Imaging,
+ LIBRAW_CAMERAMAKER_Kodak,
+ LIBRAW_CAMERAMAKER_Konica,
+ LIBRAW_CAMERAMAKER_Leaf,
+ LIBRAW_CAMERAMAKER_Leica,
+ LIBRAW_CAMERAMAKER_Lenovo,
+ LIBRAW_CAMERAMAKER_LG,
+ LIBRAW_CAMERAMAKER_Logitech,
+ LIBRAW_CAMERAMAKER_Mamiya,
+ LIBRAW_CAMERAMAKER_Matrix,
+ LIBRAW_CAMERAMAKER_Meizu,
+ LIBRAW_CAMERAMAKER_Micron,
+ LIBRAW_CAMERAMAKER_Minolta,
+ LIBRAW_CAMERAMAKER_Motorola,
+ LIBRAW_CAMERAMAKER_NGM,
+ LIBRAW_CAMERAMAKER_Nikon,
+ LIBRAW_CAMERAMAKER_Nokia,
+ LIBRAW_CAMERAMAKER_Olympus,
+ LIBRAW_CAMERAMAKER_OmniVison,
+ LIBRAW_CAMERAMAKER_Panasonic,
+ LIBRAW_CAMERAMAKER_Parrot,
+ LIBRAW_CAMERAMAKER_Pentax,
+ LIBRAW_CAMERAMAKER_PhaseOne,
+ LIBRAW_CAMERAMAKER_PhotoControl,
+ LIBRAW_CAMERAMAKER_Photron,
+ LIBRAW_CAMERAMAKER_Pixelink,
+ LIBRAW_CAMERAMAKER_Polaroid,
+ LIBRAW_CAMERAMAKER_RED,
+ LIBRAW_CAMERAMAKER_Ricoh,
+ LIBRAW_CAMERAMAKER_Rollei,
+ LIBRAW_CAMERAMAKER_RoverShot,
+ LIBRAW_CAMERAMAKER_Samsung,
+ LIBRAW_CAMERAMAKER_Sigma,
+ LIBRAW_CAMERAMAKER_Sinar,
+ LIBRAW_CAMERAMAKER_SMaL,
+ LIBRAW_CAMERAMAKER_Sony,
+ LIBRAW_CAMERAMAKER_ST_Micro,
+ LIBRAW_CAMERAMAKER_THL,
+ LIBRAW_CAMERAMAKER_VLUU,
+ LIBRAW_CAMERAMAKER_Xiaomi,
+ LIBRAW_CAMERAMAKER_XIAOYI,
+ LIBRAW_CAMERAMAKER_YI,
+ LIBRAW_CAMERAMAKER_Yuneec,
+ LIBRAW_CAMERAMAKER_Zeiss,
+ LIBRAW_CAMERAMAKER_OnePlus,
+ LIBRAW_CAMERAMAKER_ISG,
+ LIBRAW_CAMERAMAKER_VIVO,
+ LIBRAW_CAMERAMAKER_HMD_Global,
+ LIBRAW_CAMERAMAKER_HUAWEI,
+ LIBRAW_CAMERAMAKER_RaspberryPi,
+ LIBRAW_CAMERAMAKER_OmDigital,
+
+ // Insert additional indexes here
+ LIBRAW_CAMERAMAKER_TheLastOne
+};
+
+enum LibRaw_camera_mounts
+{
+ LIBRAW_MOUNT_Unknown = 0,
+ LIBRAW_MOUNT_Alpa,
+ LIBRAW_MOUNT_C, /* C-mount */
+ LIBRAW_MOUNT_Canon_EF_M,
+ LIBRAW_MOUNT_Canon_EF_S,
+ LIBRAW_MOUNT_Canon_EF,
+ LIBRAW_MOUNT_Canon_RF,
+ LIBRAW_MOUNT_Contax_N,
+ LIBRAW_MOUNT_Contax645,
+ LIBRAW_MOUNT_FT, /* original 4/3 */
+ LIBRAW_MOUNT_mFT, /* micro 4/3 */
+ LIBRAW_MOUNT_Fuji_GF, /* Fujifilm GFX cameras, G mount */
+ LIBRAW_MOUNT_Fuji_GX, /* Fujifilm GX680 */
+ LIBRAW_MOUNT_Fuji_X,
+ LIBRAW_MOUNT_Hasselblad_H, /* Hasselblad Hn cameras, HC & HCD lenses */
+ LIBRAW_MOUNT_Hasselblad_V,
+ LIBRAW_MOUNT_Hasselblad_XCD, /* Hasselblad Xn cameras, XCD lenses */
+ LIBRAW_MOUNT_Leica_M, /* Leica rangefinder bayonet */
+ LIBRAW_MOUNT_Leica_R, /* Leica SLRs, 'R' for reflex */
+ LIBRAW_MOUNT_Leica_S, /* LIBRAW_FORMAT_LeicaS 'MF' */
+ LIBRAW_MOUNT_Leica_SL, /* lens, mounts on 'L' throat, FF */
+ LIBRAW_MOUNT_Leica_TL, /* lens, mounts on 'L' throat, APS-C */
+ LIBRAW_MOUNT_LPS_L, /* Leica/Panasonic/Sigma camera mount, takes L, SL and TL lenses */
+ LIBRAW_MOUNT_Mamiya67, /* Mamiya RB67, RZ67 */
+ LIBRAW_MOUNT_Mamiya645,
+ LIBRAW_MOUNT_Minolta_A,
+ LIBRAW_MOUNT_Nikon_CX, /* used in 'Nikon 1' series */
+ LIBRAW_MOUNT_Nikon_F,
+ LIBRAW_MOUNT_Nikon_Z,
+ LIBRAW_MOUNT_PhaseOne_iXM_MV,
+ LIBRAW_MOUNT_PhaseOne_iXM_RS,
+ LIBRAW_MOUNT_PhaseOne_iXM,
+ LIBRAW_MOUNT_Pentax_645,
+ LIBRAW_MOUNT_Pentax_K,
+ LIBRAW_MOUNT_Pentax_Q,
+ LIBRAW_MOUNT_RicohModule,
+ LIBRAW_MOUNT_Rollei_bayonet, /* Rollei Hy-6: Leaf AFi, Sinar Hy6- models */
+ LIBRAW_MOUNT_Samsung_NX_M,
+ LIBRAW_MOUNT_Samsung_NX,
+ LIBRAW_MOUNT_Sigma_X3F,
+ LIBRAW_MOUNT_Sony_E,
+ LIBRAW_MOUNT_LF,
+ LIBRAW_MOUNT_DigitalBack,
+ LIBRAW_MOUNT_FixedLens,
+ LIBRAW_MOUNT_IL_UM, /* Interchangeable lens, mount unknown */
+ LIBRAW_MOUNT_TheLastOne
+};
+
+enum LibRaw_camera_formats
+{
+ LIBRAW_FORMAT_Unknown = 0,
+ LIBRAW_FORMAT_APSC,
+ LIBRAW_FORMAT_FF,
+ LIBRAW_FORMAT_MF,
+ LIBRAW_FORMAT_APSH,
+ LIBRAW_FORMAT_1INCH,
+ LIBRAW_FORMAT_1div2p3INCH, /* 1/2.3" */
+ LIBRAW_FORMAT_1div1p7INCH, /* 1/1.7" */
+ LIBRAW_FORMAT_FT, /* sensor size in FT & mFT cameras */
+ LIBRAW_FORMAT_CROP645, /* 44x33mm */
+ LIBRAW_FORMAT_LeicaS, /* 'MF' Leicas */
+ LIBRAW_FORMAT_645,
+ LIBRAW_FORMAT_66,
+ LIBRAW_FORMAT_69,
+ LIBRAW_FORMAT_LF,
+ LIBRAW_FORMAT_Leica_DMR,
+ LIBRAW_FORMAT_67,
+ LIBRAW_FORMAT_SigmaAPSC, /* DP1, DP2, SD15, SD14, SD10, SD9 */
+ LIBRAW_FORMAT_SigmaMerrill, /* SD1, 'SD1 Merrill', 'DP1 Merrill', 'DP2 Merrill' */
+ LIBRAW_FORMAT_SigmaAPSH, /* 'sd Quattro H' */
+ LIBRAW_FORMAT_3648, /* DALSA FTF4052C (Mamiya ZD) */
+ LIBRAW_FORMAT_68, /* Fujifilm GX680 */
+ LIBRAW_FORMAT_TheLastOne
+};
+
+enum LibRawImageAspects
+{
+ LIBRAW_IMAGE_ASPECT_UNKNOWN = 0,
+ LIBRAW_IMAGE_ASPECT_OTHER = 1,
+ LIBRAW_IMAGE_ASPECT_MINIMAL_REAL_ASPECT_VALUE = 99, /* 1:10*/
+ LIBRAW_IMAGE_ASPECT_MAXIMAL_REAL_ASPECT_VALUE = 10000, /* 10: 1*/
+ // Value: width / height * 1000
+ LIBRAW_IMAGE_ASPECT_3to2 = (1000 * 3)/2,
+ LIBRAW_IMAGE_ASPECT_1to1 = 1000,
+ LIBRAW_IMAGE_ASPECT_4to3 = (1000 * 4)/ 3,
+ LIBRAW_IMAGE_ASPECT_16to9 = (1000 * 16) / 9,
+ //LIBRAW_IMAGE_ASPECT_6to6, // what is the difference with 1:1 ?
+ LIBRAW_IMAGE_ASPECT_5to4 = (1000 * 5) / 4,
+ LIBRAW_IMAGE_ASPECT_7to6 = (1000 * 7) / 6,
+ LIBRAW_IMAGE_ASPECT_6to5 = (1000 * 6) / 5,
+ LIBRAW_IMAGE_ASPECT_7to5 = (1000 * 7) / 5
+};
+
+enum LibRaw_lens_focal_types
+{
+ LIBRAW_FT_UNDEFINED = 0,
+ LIBRAW_FT_PRIME_LENS = 1,
+ LIBRAW_FT_ZOOM_LENS = 2,
+ LIBRAW_FT_ZOOM_LENS_CONSTANT_APERTURE = 3,
+ LIBRAW_FT_ZOOM_LENS_VARIABLE_APERTURE = 4
+};
+
+enum LibRaw_Canon_RecordModes {
+ LIBRAW_Canon_RecordMode_UNDEFINED = 0,
+ LIBRAW_Canon_RecordMode_JPEG,
+ LIBRAW_Canon_RecordMode_CRW_THM,
+ LIBRAW_Canon_RecordMode_AVI_THM,
+ LIBRAW_Canon_RecordMode_TIF,
+ LIBRAW_Canon_RecordMode_TIF_JPEG,
+ LIBRAW_Canon_RecordMode_CR2,
+ LIBRAW_Canon_RecordMode_CR2_JPEG,
+ LIBRAW_Canon_RecordMode_UNKNOWN,
+ LIBRAW_Canon_RecordMode_MOV,
+ LIBRAW_Canon_RecordMode_MP4,
+ LIBRAW_Canon_RecordMode_CRM,
+ LIBRAW_Canon_RecordMode_CR3,
+ LIBRAW_Canon_RecordMode_CR3_JPEG,
+ LIBRAW_Canon_RecordMode_HEIF,
+ LIBRAW_Canon_RecordMode_CR3_HEIF,
+ LIBRAW_Canon_RecordMode_TheLastOne
+};
+
+enum LibRaw_minolta_storagemethods
+{
+ LIBRAW_MINOLTA_UNPACKED = 0x52,
+ LIBRAW_MINOLTA_PACKED = 0x59
+};
+
+enum LibRaw_minolta_bayerpatterns
+{
+ LIBRAW_MINOLTA_RGGB = 0x01,
+ LIBRAW_MINOLTA_G2BRG1 = 0x04
+};
+
+enum LibRaw_sony_cameratypes
+{
+ LIBRAW_SONY_DSC = 1,
+ LIBRAW_SONY_DSLR = 2,
+ LIBRAW_SONY_NEX = 3,
+ LIBRAW_SONY_SLT = 4,
+ LIBRAW_SONY_ILCE = 5,
+ LIBRAW_SONY_ILCA = 6,
+ LIBRAW_SONY_CameraType_UNKNOWN = 0xffff
+};
+
+enum LibRaw_Sony_0x2010_Type {
+ LIBRAW_SONY_Tag2010None = 0,
+ LIBRAW_SONY_Tag2010a,
+ LIBRAW_SONY_Tag2010b,
+ LIBRAW_SONY_Tag2010c,
+ LIBRAW_SONY_Tag2010d,
+ LIBRAW_SONY_Tag2010e,
+ LIBRAW_SONY_Tag2010f,
+ LIBRAW_SONY_Tag2010g,
+ LIBRAW_SONY_Tag2010h,
+ LIBRAW_SONY_Tag2010i
+};
+enum LibRaw_Sony_0x9050_Type {
+ LIBRAW_SONY_Tag9050None = 0,
+ LIBRAW_SONY_Tag9050a,
+ LIBRAW_SONY_Tag9050b,
+ LIBRAW_SONY_Tag9050c
+};
+
+enum LIBRAW_SONY_FOCUSMODEmodes
{
- LIBRAW_EXCEPTION_NONE =0,
- LIBRAW_EXCEPTION_ALLOC =1,
- LIBRAW_EXCEPTION_DECODE_RAW =2,
- LIBRAW_EXCEPTION_DECODE_JPEG=3,
- LIBRAW_EXCEPTION_IO_EOF =4,
- LIBRAW_EXCEPTION_IO_CORRUPT =5,
- LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK=6
+ LIBRAW_SONY_FOCUSMODE_MF = 0,
+ LIBRAW_SONY_FOCUSMODE_AF_S = 2,
+ LIBRAW_SONY_FOCUSMODE_AF_C = 3,
+ LIBRAW_SONY_FOCUSMODE_AF_A = 4,
+ LIBRAW_SONY_FOCUSMODE_DMF = 6,
+ LIBRAW_SONY_FOCUSMODE_AF_D = 7,
+ LIBRAW_SONY_FOCUSMODE_AF = 101,
+ LIBRAW_SONY_FOCUSMODE_PERMANENT_AF = 104,
+ LIBRAW_SONY_FOCUSMODE_SEMI_MF = 105,
+ LIBRAW_SONY_FOCUSMODE_UNKNOWN = -1
};
+enum LibRaw_KodakSensors
+{
+ LIBRAW_Kodak_UnknownSensor = 0,
+ LIBRAW_Kodak_M1 = 1,
+ LIBRAW_Kodak_M15 = 2,
+ LIBRAW_Kodak_M16 = 3,
+ LIBRAW_Kodak_M17 = 4,
+ LIBRAW_Kodak_M2 = 5,
+ LIBRAW_Kodak_M23 = 6,
+ LIBRAW_Kodak_M24 = 7,
+ LIBRAW_Kodak_M3 = 8,
+ LIBRAW_Kodak_M5 = 9,
+ LIBRAW_Kodak_M6 = 10,
+ LIBRAW_Kodak_C14 = 11,
+ LIBRAW_Kodak_X14 = 12,
+ LIBRAW_Kodak_M11 = 13
+};
+
+enum LibRaw_HasselbladFormatCodes {
+ LIBRAW_HF_Unknown = 0,
+ LIBRAW_HF_3FR,
+ LIBRAW_HF_FFF,
+ LIBRAW_HF_Imacon,
+ LIBRAW_HF_HasselbladDNG,
+ LIBRAW_HF_AdobeDNG,
+ LIBRAW_HF_AdobeDNG_fromPhocusDNG
+};
+
+enum LibRaw_rawspecial_t
+{
+ LIBRAW_RAWSPECIAL_SONYARW2_NONE = 0,
+ LIBRAW_RAWSPECIAL_SONYARW2_BASEONLY = 1,
+ LIBRAW_RAWSPECIAL_SONYARW2_DELTAONLY = 1 << 1,
+ LIBRAW_RAWSPECIAL_SONYARW2_DELTAZEROBASE = 1 << 2,
+ LIBRAW_RAWSPECIAL_SONYARW2_DELTATOVALUE = 1 << 3,
+ LIBRAW_RAWSPECIAL_SONYARW2_ALLFLAGS =
+ LIBRAW_RAWSPECIAL_SONYARW2_BASEONLY +
+ LIBRAW_RAWSPECIAL_SONYARW2_DELTAONLY +
+ LIBRAW_RAWSPECIAL_SONYARW2_DELTAZEROBASE +
+ LIBRAW_RAWSPECIAL_SONYARW2_DELTATOVALUE,
+ LIBRAW_RAWSPECIAL_NODP2Q_INTERPOLATERG = 1<<4,
+ LIBRAW_RAWSPECIAL_NODP2Q_INTERPOLATEAF = 1 << 5,
+ LIBRAW_RAWSPECIAL_SRAW_NO_RGB = 1 << 6,
+ LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE = 1 << 7
+};
+
+enum LibRaw_rawspeed_bits_t
+{
+ LIBRAW_RAWSPEEDV1_USE = 1,
+ LIBRAW_RAWSPEEDV1_FAILONUNKNOWN = 1 << 1,
+ LIBRAW_RAWSPEEDV1_IGNOREERRORS = 1 << 2,
+ /* bits 3-7 are reserved*/
+ LIBRAW_RAWSPEEDV3_USE = 1 << 8,
+ LIBRAW_RAWSPEEDV3_FAILONUNKNOWN = 1 << 9,
+ LIBRAW_RAWSPEEDV3_IGNOREERRORS = 1 << 10,
+};
+
+enum LibRaw_processing_options
+{
+ LIBRAW_RAWOPTIONS_PENTAX_PS_ALLFRAMES = 1,
+ LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT = 1 << 1,
+ LIBRAW_RAWOPTIONS_ARQ_SKIP_CHANNEL_SWAP = 1 << 2,
+ LIBRAW_RAWOPTIONS_NO_ROTATE_FOR_KODAK_THUMBNAILS = 1 << 3,
+// LIBRAW_RAWOPTIONS_USE_DNG_DEFAULT_CROP = 1 << 4,
+ LIBRAW_RAWOPTIONS_USE_PPM16_THUMBS = 1 << 5,
+ LIBRAW_RAWOPTIONS_DONT_CHECK_DNG_ILLUMINANT = 1 << 6,
+ LIBRAW_RAWOPTIONS_DNGSDK_ZEROCOPY = 1 << 7,
+ LIBRAW_RAWOPTIONS_ZEROFILTERS_FOR_MONOCHROMETIFFS = 1 << 8,
+ LIBRAW_RAWOPTIONS_DNG_ADD_ENHANCED = 1 << 9,
+ LIBRAW_RAWOPTIONS_DNG_ADD_PREVIEWS = 1 << 10,
+ LIBRAW_RAWOPTIONS_DNG_PREFER_LARGEST_IMAGE = 1 << 11,
+ LIBRAW_RAWOPTIONS_DNG_STAGE2 = 1 << 12,
+ LIBRAW_RAWOPTIONS_DNG_STAGE3 = 1 << 13,
+ LIBRAW_RAWOPTIONS_DNG_ALLOWSIZECHANGE = 1 << 14,
+ LIBRAW_RAWOPTIONS_DNG_DISABLEWBADJUST = 1 << 15,
+ LIBRAW_RAWOPTIONS_PROVIDE_NONSTANDARD_WB = 1 << 16,
+ LIBRAW_RAWOPTIONS_CAMERAWB_FALLBACK_TO_DAYLIGHT = 1 << 17,
+ LIBRAW_RAWOPTIONS_CHECK_THUMBNAILS_KNOWN_VENDORS = 1 << 18,
+ LIBRAW_RAWOPTIONS_CHECK_THUMBNAILS_ALL_VENDORS = 1 << 19,
+ LIBRAW_RAWOPTIONS_DNG_STAGE2_IFPRESENT = 1 << 20,
+ LIBRAW_RAWOPTIONS_DNG_STAGE3_IFPRESENT = 1 << 21,
+ LIBRAW_RAWOPTIONS_DNG_ADD_MASKS = 1 << 22,
+ LIBRAW_RAWOPTIONS_CANON_IGNORE_MAKERNOTES_ROTATION = 1 << 23
+};
+
+enum LibRaw_decoder_flags
+{
+ LIBRAW_DECODER_HASCURVE = 1 << 4,
+ LIBRAW_DECODER_SONYARW2 = 1 << 5,
+ LIBRAW_DECODER_TRYRAWSPEED = 1 << 6,
+ LIBRAW_DECODER_OWNALLOC = 1 << 7,
+ LIBRAW_DECODER_FIXEDMAXC = 1 << 8,
+ LIBRAW_DECODER_ADOBECOPYPIXEL = 1 << 9,
+ LIBRAW_DECODER_LEGACY_WITH_MARGINS = 1 << 10,
+ LIBRAW_DECODER_3CHANNEL = 1 << 11,
+ LIBRAW_DECODER_SINAR4SHOT = 1 << 11,
+ LIBRAW_DECODER_FLATDATA = 1 << 12,
+ LIBRAW_DECODER_FLAT_BG2_SWAPPED = 1<<13,
+ LIBRAW_DECODER_UNSUPPORTED_FORMAT = 1 << 14,
+ LIBRAW_DECODER_NOTSET = 1 << 15,
+ LIBRAW_DECODER_TRYRAWSPEED3 = 1 << 16
+};
-enum LibRaw_colorstate
+#define LIBRAW_XTRANS 9
+
+enum LibRaw_constructor_flags
{
- LIBRAW_COLORSTATE_UNKNOWN =0,
- LIBRAW_COLORSTATE_INIT =1,
- LIBRAW_COLORSTATE_CONST =2,
- LIBRAW_COLORSTATE_LOADED =3,
- LIBRAW_COLORSTATE_CALCULATED=4,
- LIBRAW_COLORSTATE_RESERVED1 =5,
- LIBRAW_COLORSTATE_RESERVED2 =6,
- LIBRAW_COLORSTATE_RESERVED3 =7
+ LIBRAW_OPTIONS_NONE = 0,
+ LIBRAW_OPTIONS_NO_DATAERR_CALLBACK = 1 << 1,
+ /* Compatibility w/ years old typo */
+ LIBRAW_OPIONS_NO_DATAERR_CALLBACK = LIBRAW_OPTIONS_NO_DATAERR_CALLBACK
};
-enum LibRaw_filtering
+enum LibRaw_warnings
{
- LIBRAW_FILTERING_DEFAULT =0,
- LIBRAW_FILTERING_NOZEROES =1, // no remove zeroes
- LIBRAW_FILTERING_NOBLACKS =2, // no black subtraction
- LIBRAW_FILTERING_NORAWCURVE =4, // no raw data postprocessing (e.g. PhaseOne corrections etc)
- LIBRAW_FILTERING_NONE =7, // (_NOZEROES | _NOBLACKS | _NORAWCURVE)
- LIBRAW_FILTERING_LIBRAWOWN =(8 | LIBRAW_FILTERING_NONE), // NONE + 8
- LIBRAW_FILTERING_AUTOMATIC_BIT =16, // - restore automatic mode after processing
- LIBRAW_FILTERING_AUTOMATIC = (LIBRAW_FILTERING_LIBRAWOWN | LIBRAW_FILTERING_AUTOMATIC_BIT)
+ LIBRAW_WARN_NONE = 0,
+ LIBRAW_WARN_BAD_CAMERA_WB = 1 << 2,
+ LIBRAW_WARN_NO_METADATA = 1 << 3,
+ LIBRAW_WARN_NO_JPEGLIB = 1 << 4,
+ LIBRAW_WARN_NO_EMBEDDED_PROFILE = 1 << 5,
+ LIBRAW_WARN_NO_INPUT_PROFILE = 1 << 6,
+ LIBRAW_WARN_BAD_OUTPUT_PROFILE = 1 << 7,
+ LIBRAW_WARN_NO_BADPIXELMAP = 1 << 8,
+ LIBRAW_WARN_BAD_DARKFRAME_FILE = 1 << 9,
+ LIBRAW_WARN_BAD_DARKFRAME_DIM = 1 << 10,
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ LIBRAW_WARN_NO_JASPER = 1 << 11,
+#endif
+ LIBRAW_WARN_RAWSPEED_PROBLEM = 1 << 12,
+ LIBRAW_WARN_RAWSPEED_UNSUPPORTED = 1 << 13,
+ LIBRAW_WARN_RAWSPEED_PROCESSED = 1 << 14,
+ LIBRAW_WARN_FALLBACK_TO_AHD = 1 << 15,
+ LIBRAW_WARN_PARSEFUJI_PROCESSED = 1 << 16,
+ LIBRAW_WARN_DNGSDK_PROCESSED = 1 << 17,
+ LIBRAW_WARN_DNG_IMAGES_REORDERED = 1 << 18,
+ LIBRAW_WARN_DNG_STAGE2_APPLIED = 1 << 19,
+ LIBRAW_WARN_DNG_STAGE3_APPLIED = 1 << 20,
+ LIBRAW_WARN_RAWSPEED3_PROBLEM = 1 << 21,
+ LIBRAW_WARN_RAWSPEED3_UNSUPPORTED = 1 << 22,
+ LIBRAW_WARN_RAWSPEED3_PROCESSED = 1 << 23,
+ LIBRAW_WARN_RAWSPEED3_NOTLISTED = 1 << 24
};
+enum LibRaw_exceptions
+{
+ LIBRAW_EXCEPTION_NONE = 0,
+ LIBRAW_EXCEPTION_ALLOC = 1,
+ LIBRAW_EXCEPTION_DECODE_RAW = 2,
+ LIBRAW_EXCEPTION_DECODE_JPEG = 3,
+ LIBRAW_EXCEPTION_IO_EOF = 4,
+ LIBRAW_EXCEPTION_IO_CORRUPT = 5,
+ LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK = 6,
+ LIBRAW_EXCEPTION_BAD_CROP = 7,
+ LIBRAW_EXCEPTION_IO_BADFILE = 8,
+ LIBRAW_EXCEPTION_DECODE_JPEG2000 = 9,
+ LIBRAW_EXCEPTION_TOOBIG = 10,
+ LIBRAW_EXCEPTION_MEMPOOL = 11,
+ LIBRAW_EXCEPTION_UNSUPPORTED_FORMAT = 12
+};
enum LibRaw_progress
{
- LIBRAW_PROGRESS_START = 0,
- LIBRAW_PROGRESS_OPEN = 1,
- LIBRAW_PROGRESS_IDENTIFY = 1<<1,
- LIBRAW_PROGRESS_SIZE_ADJUST = 1<<2,
- LIBRAW_PROGRESS_LOAD_RAW = 1<<3,
- LIBRAW_PROGRESS_REMOVE_ZEROES = 1<<4,
- LIBRAW_PROGRESS_BAD_PIXELS = 1<<5,
- LIBRAW_PROGRESS_DARK_FRAME = 1<<6,
- LIBRAW_PROGRESS_FOVEON_INTERPOLATE = 1<<7,
- LIBRAW_PROGRESS_SCALE_COLORS = 1<<8,
- LIBRAW_PROGRESS_PRE_INTERPOLATE = 1<<9,
- LIBRAW_PROGRESS_INTERPOLATE = 1<<10,
- LIBRAW_PROGRESS_MIX_GREEN = 1<<11,
- LIBRAW_PROGRESS_MEDIAN_FILTER = 1<<12,
- LIBRAW_PROGRESS_HIGHLIGHTS = 1<<13,
- LIBRAW_PROGRESS_FUJI_ROTATE = 1<<14,
- LIBRAW_PROGRESS_FLIP = 1<<15,
- LIBRAW_PROGRESS_APPLY_PROFILE = 1<<16,
- LIBRAW_PROGRESS_CONVERT_RGB = 1<<17,
- LIBRAW_PROGRESS_STRETCH = 1<<18,
-// reserved
- LIBRAW_PROGRESS_STAGE19 = 1<<19,
- LIBRAW_PROGRESS_STAGE20 = 1<<20,
- LIBRAW_PROGRESS_STAGE21 = 1<<21,
- LIBRAW_PROGRESS_STAGE22 = 1<<22,
- LIBRAW_PROGRESS_STAGE23 = 1<<23,
- LIBRAW_PROGRESS_STAGE24 = 1<<24,
- LIBRAW_PROGRESS_STAGE25 = 1<<25,
- LIBRAW_PROGRESS_STAGE26 = 1<<26,
- LIBRAW_PROGRESS_STAGE27 = 1<<27,
-
- LIBRAW_PROGRESS_THUMB_LOAD = 1<<28,
- LIBRAW_PROGRESS_TRESERVED1 = 1<<29,
- LIBRAW_PROGRESS_TRESERVED2 = 1<<30
+ LIBRAW_PROGRESS_START = 0,
+ LIBRAW_PROGRESS_OPEN = 1,
+ LIBRAW_PROGRESS_IDENTIFY = 1 << 1,
+ LIBRAW_PROGRESS_SIZE_ADJUST = 1 << 2,
+ LIBRAW_PROGRESS_LOAD_RAW = 1 << 3,
+ LIBRAW_PROGRESS_RAW2_IMAGE = 1 << 4,
+ LIBRAW_PROGRESS_REMOVE_ZEROES = 1 << 5,
+ LIBRAW_PROGRESS_BAD_PIXELS = 1 << 6,
+ LIBRAW_PROGRESS_DARK_FRAME = 1 << 7,
+ LIBRAW_PROGRESS_FOVEON_INTERPOLATE = 1 << 8,
+ LIBRAW_PROGRESS_SCALE_COLORS = 1 << 9,
+ LIBRAW_PROGRESS_PRE_INTERPOLATE = 1 << 10,
+ LIBRAW_PROGRESS_INTERPOLATE = 1 << 11,
+ LIBRAW_PROGRESS_MIX_GREEN = 1 << 12,
+ LIBRAW_PROGRESS_MEDIAN_FILTER = 1 << 13,
+ LIBRAW_PROGRESS_HIGHLIGHTS = 1 << 14,
+ LIBRAW_PROGRESS_FUJI_ROTATE = 1 << 15,
+ LIBRAW_PROGRESS_FLIP = 1 << 16,
+ LIBRAW_PROGRESS_APPLY_PROFILE = 1 << 17,
+ LIBRAW_PROGRESS_CONVERT_RGB = 1 << 18,
+ LIBRAW_PROGRESS_STRETCH = 1 << 19,
+ /* reserved */
+ LIBRAW_PROGRESS_STAGE20 = 1 << 20,
+ LIBRAW_PROGRESS_STAGE21 = 1 << 21,
+ LIBRAW_PROGRESS_STAGE22 = 1 << 22,
+ LIBRAW_PROGRESS_STAGE23 = 1 << 23,
+ LIBRAW_PROGRESS_STAGE24 = 1 << 24,
+ LIBRAW_PROGRESS_STAGE25 = 1 << 25,
+ LIBRAW_PROGRESS_STAGE26 = 1 << 26,
+ LIBRAW_PROGRESS_STAGE27 = 1 << 27,
+
+ LIBRAW_PROGRESS_THUMB_LOAD = 1 << 28,
+ LIBRAW_PROGRESS_TRESERVED1 = 1 << 29,
+ LIBRAW_PROGRESS_TRESERVED2 = 1 << 30
};
#define LIBRAW_PROGRESS_THUMB_MASK 0x0fffffff
enum LibRaw_errors
{
- LIBRAW_SUCCESS = 0,
- LIBRAW_UNSPECIFIED_ERROR=-1,
- LIBRAW_FILE_UNSUPPORTED = -2,
- LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE=-3,
- LIBRAW_OUT_OF_ORDER_CALL=-4,
- LIBRAW_NO_THUMBNAIL=-5,
- LIBRAW_UNSUPPORTED_THUMBNAIL=-6,
- LIBRAW_CANNOT_ADDMASK=-7,
- LIBRAW_UNSUFFICIENT_MEMORY=-100007,
- LIBRAW_DATA_ERROR=-100008,
- LIBRAW_IO_ERROR=-100009,
- LIBRAW_CANCELLED_BY_CALLBACK=-100010
+ LIBRAW_SUCCESS = 0,
+ LIBRAW_UNSPECIFIED_ERROR = -1,
+ LIBRAW_FILE_UNSUPPORTED = -2,
+ LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE = -3,
+ LIBRAW_OUT_OF_ORDER_CALL = -4,
+ LIBRAW_NO_THUMBNAIL = -5,
+ LIBRAW_UNSUPPORTED_THUMBNAIL = -6,
+ LIBRAW_INPUT_CLOSED = -7,
+ LIBRAW_NOT_IMPLEMENTED = -8,
+ LIBRAW_REQUEST_FOR_NONEXISTENT_THUMBNAIL = -9,
+ LIBRAW_UNSUFFICIENT_MEMORY = -100007,
+ LIBRAW_DATA_ERROR = -100008,
+ LIBRAW_IO_ERROR = -100009,
+ LIBRAW_CANCELLED_BY_CALLBACK = -100010,
+ LIBRAW_BAD_CROP = -100011,
+ LIBRAW_TOO_BIG = -100012,
+ LIBRAW_MEMPOOL_OVERFLOW = -100013
+};
+
+#define LIBRAW_FATAL_ERROR(ec) ((ec) < -100000)
+
+enum LibRaw_internal_thumbnail_formats
+{
+ LIBRAW_INTERNAL_THUMBNAIL_UNKNOWN = 0,
+ LIBRAW_INTERNAL_THUMBNAIL_KODAK_THUMB = 1,
+ LIBRAW_INTERNAL_THUMBNAIL_KODAK_YCBCR = 2,
+ LIBRAW_INTERNAL_THUMBNAIL_KODAK_RGB = 3,
+ LIBRAW_INTERNAL_THUMBNAIL_JPEG = 4,
+ LIBRAW_INTERNAL_THUMBNAIL_LAYER,
+ LIBRAW_INTERNAL_THUMBNAIL_ROLLEI,
+ LIBRAW_INTERNAL_THUMBNAIL_PPM,
+ LIBRAW_INTERNAL_THUMBNAIL_PPM16,
+ LIBRAW_INTERNAL_THUMBNAIL_X3F,
};
-#define LIBRAW_FATAL_ERROR(ec) ((ec)<-100000)
enum LibRaw_thumbnail_formats
{
- LIBRAW_THUMBNAIL_UNKNOWN=0,
- LIBRAW_THUMBNAIL_JPEG=1,
- LIBRAW_THUMBNAIL_BITMAP=2,
- LIBRAW_THUMBNAIL_LAYER=4,
- LIBRAW_THUMBNAIL_ROLLEI=5
+ LIBRAW_THUMBNAIL_UNKNOWN = 0,
+ LIBRAW_THUMBNAIL_JPEG = 1,
+ LIBRAW_THUMBNAIL_BITMAP = 2,
+ LIBRAW_THUMBNAIL_BITMAP16 = 3,
+ LIBRAW_THUMBNAIL_LAYER = 4,
+ LIBRAW_THUMBNAIL_ROLLEI = 5,
+ LIBRAW_THUMBNAIL_H265 = 6
};
enum LibRaw_image_formats
{
- LIBRAW_IMAGE_BITMAP=1,
- LIBRAW_IMAGE_JPEG=2
+ LIBRAW_IMAGE_JPEG = 1,
+ LIBRAW_IMAGE_BITMAP = 2
};
#endif
diff --git a/libkdcraw/libraw/libraw/libraw_datastream.h b/libkdcraw/libraw/libraw/libraw_datastream.h
index d5709a0..0596e83 100644
--- a/libkdcraw/libraw/libraw/libraw_datastream.h
+++ b/libkdcraw/libraw/libraw/libraw_datastream.h
@@ -1,24 +1,19 @@
/* -*- C -*-
* File: libraw_datastream.h
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
* Created: Sun Jan 18 13:07:35 2009
*
* LibRaw Data stream interface
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+
+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).
+
*/
#ifndef __LIBRAW_DATASTREAM_H
@@ -31,273 +26,385 @@
#ifndef __cplusplus
-struct LibRaw_abstract_datastream;
-
-#else // __cplusplus
+#else /* __cplusplus */
+#if defined _WIN32
+#ifndef LIBRAW_NO_WINSOCK2
+#include <winsock2.h>
+#endif
+#endif
+/* No unique_ptr on Apple ?? */
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) || \
+ (defined(_MSC_VER) && _MSVC_LANG >= 201103L)
+/* OK - use unique_ptr unless LIBRAW_USE_AUTOPTR defined externally*/
+#else
+/* Force to use auto_ptr */
+#ifndef LIBRAW_USE_AUTOPTR
+#define LIBRAW_USE_AUTOPTR
+#endif
+#endif
#include "libraw_const.h"
+#include "libraw_types.h"
+#include <fstream>
+#include <memory>
+#include <vector>
+
+#if defined(_WIN32) && (_MSC_VER) >= 1500
+#define WIN32SECURECALLS
+#endif
+
+#ifdef USE_DNGSDK
+
+#if defined LIBRAW_WIN32_CALLS
+#define qWinOS 1
+#define qMacOS 0
+#elif defined(__APPLE__)
+#define qWinOS 0
+#define qMacOS 1
+#else
+/* define OS types for DNG here */
+#endif
+#define qDNGXMPDocOps 0
+#define qDNGUseLibJPEG 1
+#define qDNGXMPFiles 0
+#define qDNGExperimental 1
+#define qDNGThreadSafe 1
+#include "dng_stream.h"
+#endif /* DNGSDK */
+
+#define IOERROR() \
+ do \
+ { \
+ throw LIBRAW_EXCEPTION_IO_EOF; \
+ } while (0)
class LibRaw_buffer_datastream;
+class LibRaw_bit_buffer;
-class LibRaw_abstract_datastream
+class DllDef LibRaw_abstract_datastream
{
- public:
- LibRaw_abstract_datastream(){substream=0;};
- virtual ~LibRaw_abstract_datastream(void){if(substream) delete substream;}
- virtual int valid(){return 0;}
- // file input emulation
- virtual int read(void *,size_t, size_t ){ return -1;}
- virtual int seek(off_t o, int whence){return -1;}
- virtual int tell(){return -1;}
- virtual int get_char(){return -1;}
- virtual char* gets(char *, int){ return NULL;}
- virtual int scanf_one(const char *, void *){return -1;}
- virtual int eof(){return -1;}
-
- virtual const char* fname(){ return NULL;};
- virtual int subfile_open(const char*){ return EINVAL;}
- virtual void subfile_close(){}
- virtual int tempbuffer_open(void*, size_t);
- virtual void tempbuffer_close()
- {
- if(substream) delete substream;
- substream = NULL;
- }
-
- protected:
- LibRaw_abstract_datastream *substream;
+public:
+ LibRaw_abstract_datastream() { };
+ virtual ~LibRaw_abstract_datastream(void) { }
+ virtual int valid() = 0;
+ virtual int read(void *, size_t, size_t) = 0;
+ virtual int seek(INT64, int) = 0;
+ virtual INT64 tell() = 0;
+ virtual INT64 size() = 0;
+ virtual int get_char() = 0;
+ virtual char *gets(char *, int) = 0;
+ virtual int scanf_one(const char *, void *) = 0;
+ virtual int eof() = 0;
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ virtual void *make_jas_stream() = 0;
+#endif
+ virtual int jpeg_src(void *);
+ virtual void buffering_off() {}
+ /* reimplement in subclass to use parallel access in xtrans_load_raw() if
+ * OpenMP is not used */
+ virtual int lock() { return 1; } /* success */
+ virtual void unlock() {}
+ virtual const char *fname() { return NULL; };
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ virtual const wchar_t *wfname() { return NULL; };
+#endif
};
+#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
-class LibRaw_file_datastream : public LibRaw_abstract_datastream
-{
- public:
- LibRaw_file_datastream(const char *fname)
- {
- if(fname)
- {filename = fname; f = fopen(fname,"rb");}
- else
- {filename=0;f=0;}
- sav=0;
- }
+#ifdef LIBRAW_WIN32_DLLDEFS
+#ifdef LIBRAW_USE_AUTOPTR
+template class DllDef std::auto_ptr<std::streambuf>;
+#else
+template class DllDef std::unique_ptr<std::streambuf>;
+#endif
+#endif
- virtual ~LibRaw_file_datastream() {if(f)fclose(f); if(sav)fclose(sav);}
+class DllDef LibRaw_file_datastream : public LibRaw_abstract_datastream
+{
+protected:
+#ifdef LIBRAW_USE_AUTOPTR
+ std::auto_ptr<std::streambuf> f; /* will close() automatically through dtor */
+#else
+ std::unique_ptr<std::streambuf> f;
+#endif
+ std::string filename;
+ INT64 _fsize;
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ std::wstring wfilename;
+#endif
+ FILE *jas_file;
- virtual int valid() { return f?1:0;}
+public:
+ virtual ~LibRaw_file_datastream();
+ LibRaw_file_datastream(const char *fname);
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ LibRaw_file_datastream(const wchar_t *fname);
+#endif
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ virtual void *make_jas_stream();
+#endif
+ virtual int valid();
+ virtual int read(void *ptr, size_t size, size_t nmemb);
+ virtual int eof();
+ virtual int seek(INT64 o, int whence);
+ virtual INT64 tell();
+ virtual INT64 size() { return _fsize; }
+ virtual int get_char() {return f->sbumpc();}
+ virtual char *gets(char *str, int sz);
+ virtual int scanf_one(const char *fmt, void *val);
+ virtual const char *fname();
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ virtual const wchar_t *wfname();
+#endif
+};
+#endif
-#define CHK() do {if(!f) throw LIBRAW_EXCEPTION_IO_EOF;}while(0)
- virtual int read(void * ptr,size_t size, size_t nmemb)
- {
- CHK();
- return substream?substream->read(ptr,size,nmemb):int(fread(ptr,size,nmemb,f));
- }
- virtual int eof()
- {
- CHK();
- return substream?substream->eof():feof(f);
- }
- virtual int seek(off_t o, int whence)
- {
- CHK();
- return substream?substream->seek(o,whence):fseek(f,o,whence);
- }
- virtual int tell()
- {
- CHK();
- return substream?substream->tell():ftell(f);
- }
- virtual int get_char()
- {
- CHK();
- return substream?substream->get_char():fgetc(f);
- }
- virtual char* gets(char *str, int sz)
- {
- CHK();
- return substream?substream->gets(str,sz):fgets(str,sz,f);
- }
- virtual int scanf_one(const char *fmt, void*val)
- {
- CHK();
- return substream?substream->scanf_one(fmt,val):fscanf(f,fmt,val);
- }
+#if defined (LIBRAW_NO_IOSTREAMS_DATASTREAM) && defined (LIBRAW_WIN32_CALLS)
- virtual const char *fname() { return filename; }
+struct DllDef LibRaw_bufio_params
+{
+ static int bufsize;
+ static void set_bufsize(int bs);
+};
- // secondary
- virtual int subfile_open(const char *fn)
+class buffer_t : public std::vector<unsigned char>
+{
+public:
+ INT64 _bstart, _bend;
+ buffer_t() : std::vector<unsigned char>(LibRaw_bufio_params::bufsize), _bstart(0), _bend(0) {}
+ int charOReof(INT64 _fpos)
{
- if(sav) return EBUSY;
- sav = f;
- f = fopen(fn,"rb");
- if(!f)
- {
- f = sav;
- sav = NULL;
- return ENOENT;
- }
- else
- return 0;
+ if (_bstart < 0LL || _bend < 0LL || _bend < _bstart || _fpos < 0LL)
+ return -1;
+ if ((_bend - _bstart) > (INT64)size())
+ return -1;
+ if (_fpos >= _bstart && _fpos < _bend)
+ return data()[_fpos - _bstart];
+ return -1;
}
- virtual void subfile_close()
+ bool contains(INT64 _fpos, INT64& contains)
{
- if(!sav) return;
- fclose(f);
- f = sav;
- sav = 0;
+ if (_bstart < 0LL || _bend < 0LL || _bend < _bstart || _fpos < 0LL)
+ {
+ contains = 0;
+ return false;
+ }
+ if ((_bend - _bstart) > (INT64)size())
+ {
+ contains = 0;
+ return false;
+ }
+ if (_fpos >= _bstart && _fpos < _bend)
+ {
+ contains = _bend - _fpos;
+ return true;
+ }
+ contains = 0;
+ return false;
}
-
- private:
- FILE *f,*sav;
- const char *filename;
};
-#undef CHK
-class LibRaw_buffer_datastream : public LibRaw_abstract_datastream
+
+class DllDef LibRaw_bigfile_buffered_datastream : public LibRaw_abstract_datastream
{
- public:
- LibRaw_buffer_datastream(void *buffer, size_t bsize)
+public:
+ LibRaw_bigfile_buffered_datastream(const char *fname);
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ LibRaw_bigfile_buffered_datastream(const wchar_t *fname);
+#endif
+ virtual ~LibRaw_bigfile_buffered_datastream();
+ virtual int valid();
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ virtual void *make_jas_stream();
+#endif
+ virtual void buffering_off() { buffered = 0; }
+ virtual int read(void *ptr, size_t size, size_t nmemb);
+ virtual int eof();
+ virtual int seek(INT64 o, int whence);
+ virtual INT64 tell();
+ virtual INT64 size() { return _fsize; }
+ virtual char *gets(char *str, int sz);
+ virtual int scanf_one(const char *fmt, void *val);
+ virtual const char *fname();
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ virtual const wchar_t *wfname();
+#endif
+ virtual int get_char()
+ {
+ int r = iobuffers[0].charOReof(_fpos);
+ if (r >= 0)
{
- buf = (unsigned char*)buffer; streampos = 0; streamsize = bsize;
+ _fpos++;
+ return r;
}
- virtual ~LibRaw_buffer_datastream(){}
- virtual int valid() { return buf?1:0;}
- virtual int read(void * ptr,size_t sz, size_t nmemb)
- {
- if(substream) return substream->read(ptr,sz,nmemb);
- size_t to_read = sz*nmemb;
- if(to_read > streamsize - streampos)
- to_read = streamsize-streampos;
- if(to_read<1)
- return 0;
- memmove(ptr,buf+streampos,to_read);
- streampos+=to_read;
- return int((to_read+sz-1)/sz);
+ unsigned char c;
+ r = read(&c, 1, 1);
+ return r > 0 ? c : r;
}
- virtual int eof()
- {
- if(substream) return substream->eof();
- return streampos >= streamsize;
- }
+protected:
+ INT64 readAt(void *ptr, size_t size, INT64 off);
+ bool fillBufferAt(int buf, INT64 off);
+ int selectStringBuffer(INT64 len, INT64& contains);
+ HANDLE fhandle;
+ INT64 _fsize;
+ INT64 _fpos; /* current file position; current buffer start position */
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ std::wstring wfilename;
+#endif
+ std::string filename;
+ buffer_t iobuffers[2];
+ int buffered;
+};
- virtual int seek(off_t o, int whence)
- {
- if(substream) return substream->seek(o,whence);
- switch(whence)
- {
- case SEEK_SET:
- if(o<0)
- streampos = 0;
- else if (size_t(o) > streamsize)
- streampos = streamsize;
- else
- streampos = size_t(o);
- return 0;
- case SEEK_CUR:
- if(o<0)
- {
- if(size_t(-o) >= streampos)
- streampos = 0;
- else
- streampos += o;
- }
- else if (o>0)
- {
- if(o+streampos> streamsize)
- streampos = streamsize;
- else
- streampos += o;
- }
- return 0;
- case SEEK_END:
- if(o>0)
- streampos = streamsize;
- else if ( size_t(-o) > streamsize)
- streampos = 0;
- else
- streampos = streamsize+o;
- return 0;
- default:
- return 0;
- }
- }
-
- virtual int tell()
- {
- if(substream) return substream->tell();
- return int(streampos);
- }
+#endif
- virtual int get_char()
- {
- if(substream) return substream->get_char();
- if(streampos>=streamsize)
- return -1;
- return buf[streampos++];
- }
- virtual char* gets(char *s, int sz)
- {
- if (substream) return substream->gets(s,sz);
- unsigned char *psrc,*pdest,*str;
- str = (unsigned char *)s;
- psrc = buf+streampos;
- pdest = str;
- while ( (size_t(psrc - buf) < streamsize)
- &&
- ((pdest-str)<sz)
- )
- {
- *pdest = *psrc;
- if(*psrc == '\n')
- break;
- psrc++;
- pdest++;
- }
- if(size_t(psrc-buf) < streamsize)
- psrc++;
- if((pdest-str)<sz)
- *(++pdest)=0;
- streampos = psrc - buf;
- return s;
- }
- virtual int scanf_one(const char *fmt, void* val)
- {
- if(substream) return substream->scanf_one(fmt,val);
- int scanf_res;
- if(streampos>streamsize) return 0;
- scanf_res = sscanf((char*)(buf+streampos),fmt,val);
- if(scanf_res>0)
- {
- int xcnt=0;
- while(streampos<streamsize)
- {
- streampos++;
- xcnt++;
- if(buf[streampos] == 0
- || buf[streampos]==' '
- || buf[streampos]=='\t'
- || buf[streampos]=='\n'
- || xcnt>24)
- break;
- }
- }
- return scanf_res;
- }
- private:
- unsigned char *buf;
- size_t streampos,streamsize;
+class DllDef LibRaw_buffer_datastream : public LibRaw_abstract_datastream
+{
+public:
+ LibRaw_buffer_datastream(const void *buffer, size_t bsize);
+ virtual ~LibRaw_buffer_datastream();
+ virtual int valid();
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ virtual void *make_jas_stream();
+#endif
+ virtual int jpeg_src(void *jpegdata);
+ virtual int read(void *ptr, size_t sz, size_t nmemb);
+ virtual int eof();
+ virtual int seek(INT64 o, int whence);
+ virtual INT64 tell();
+ virtual INT64 size() { return streamsize; }
+ virtual char *gets(char *s, int sz);
+ virtual int scanf_one(const char *fmt, void *val);
+ virtual int get_char()
+ {
+ if (streampos >= streamsize) return -1;
+ return buf[streampos++];
+ }
+
+private:
+ unsigned char *buf;
+ size_t streampos, streamsize;
};
-inline int LibRaw_abstract_datastream::tempbuffer_open(void *buf, size_t size)
+class DllDef LibRaw_bigfile_datastream : public LibRaw_abstract_datastream
{
- if(substream) return EBUSY;
- substream = new LibRaw_buffer_datastream(buf,size);
- return substream?0:EINVAL;
-}
+public:
+ LibRaw_bigfile_datastream(const char *fname);
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ LibRaw_bigfile_datastream(const wchar_t *fname);
+#endif
+ virtual ~LibRaw_bigfile_datastream();
+ virtual int valid();
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ virtual void *make_jas_stream();
+#endif
+ virtual int read(void *ptr, size_t size, size_t nmemb);
+ virtual int eof();
+ virtual int seek(INT64 o, int whence);
+ virtual INT64 tell();
+ virtual INT64 size() { return _fsize; }
+ virtual char *gets(char *str, int sz);
+ virtual int scanf_one(const char *fmt, void *val);
+ virtual const char *fname();
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ virtual const wchar_t *wfname();
+#endif
+ virtual int get_char()
+ {
+#ifndef LIBRAW_WIN32_CALLS
+ return getc_unlocked(f);
+#else
+ return fgetc(f);
+#endif
+ }
+protected:
+ FILE *f;
+ std::string filename;
+ INT64 _fsize;
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ std::wstring wfilename;
#endif
+};
+
+#ifdef LIBRAW_WIN32_CALLS
+class DllDef LibRaw_windows_datastream : public LibRaw_buffer_datastream
+{
+public:
+ /* ctor: high level constructor opens a file by name */
+ LibRaw_windows_datastream(const TCHAR *sFile);
+ /* ctor: construct with a file handle - caller is responsible for closing the
+ * file handle */
+ LibRaw_windows_datastream(HANDLE hFile);
+ /* dtor: unmap and close the mapping handle */
+ virtual ~LibRaw_windows_datastream();
+ virtual INT64 size() { return cbView_; }
+
+protected:
+ void Open(HANDLE hFile);
+ inline void reconstruct_base()
+ {
+ /* this subterfuge is to overcome the private-ness of
+ * LibRaw_buffer_datastream */
+ (LibRaw_buffer_datastream &)*this =
+ LibRaw_buffer_datastream(pView_, (size_t)cbView_);
+ }
+
+ HANDLE hMap_; /* handle of the file mapping */
+ void *pView_; /* pointer to the mapped memory */
+ __int64 cbView_; /* size of the mapping in bytes */
+};
#endif
+#ifdef USE_DNGSDK
+
+class libraw_dng_stream : public dng_stream
+{
+public:
+ libraw_dng_stream(LibRaw_abstract_datastream *p)
+ : dng_stream((dng_abort_sniffer *)NULL, kBigBufferSize, 0),
+ parent_stream(p)
+ {
+ if (parent_stream)
+ {
+ parent_stream->buffering_off();
+ off = parent_stream->tell();
+ parent_stream->seek(0UL, SEEK_SET); /* seek to start */
+ }
+ }
+ ~libraw_dng_stream()
+ {
+ if (parent_stream)
+ parent_stream->seek(off, SEEK_SET);
+ }
+ virtual uint64 DoGetLength()
+ {
+ if (parent_stream)
+ return parent_stream->size();
+ return 0;
+ }
+ virtual void DoRead(void *data, uint32 count, uint64 offset)
+ {
+ if (parent_stream)
+ {
+ parent_stream->seek(offset, SEEK_SET);
+ parent_stream->read(data, 1, count);
+ }
+ }
+
+private:
+ libraw_dng_stream(const libraw_dng_stream &stream);
+ libraw_dng_stream &operator=(const libraw_dng_stream &stream);
+ LibRaw_abstract_datastream *parent_stream;
+ INT64 off;
+};
+
+#endif
+
+#endif /* cplusplus */
+
+#endif
diff --git a/libkdcraw/libraw/libraw/libraw_internal.h b/libkdcraw/libraw/libraw/libraw_internal.h
index 6bdea0c..9ed3a17 100644
--- a/libkdcraw/libraw/libraw/libraw_internal.h
+++ b/libkdcraw/libraw/libraw/libraw_internal.h
@@ -1,240 +1,340 @@
-/*
+/* -*- C++ -*-
* File: libraw_internal.h
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
* Created: Sat Mar 8 , 2008
*
* LibRaw internal data structures (not visible outside)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#ifndef _LIBRAW_INTERNAL_TYPES_H
-#define _LIBRAW_INTERNAL_TYPES_H
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of two licenses as you choose:
-#include <stdio.h>
-#ifdef __cplusplus
+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).
-#ifndef CLASS
-#define CLASS LibRaw::
-#endif
+ */
-#else
-// C build
-#ifndef CLASS
-#define CLASS
-#endif
-#endif
+#ifndef _LIBRAW_INTERNAL_TYPES_H
+#define _LIBRAW_INTERNAL_TYPES_H
+#include <stdio.h>
#ifdef __cplusplus
#include "libraw_datastream.h"
+#include "libraw_types.h"
class LibRaw_TLS
{
public:
- struct
- {
- unsigned bitbuf;
- int vbits, reset;
- }getbits;
- struct
- {
- UINT64 bitbuf;
- int vbits;
-
- }ph1_bits;
- int make_decoder_leaf;
- struct
- {
- struct decode *dstart[18], *dindex;
- const int *s;
- }radc_token;
- struct
- {
- unsigned pad[128], p;
- }sony_decrypt;
- unsigned foveon_decoder_huff[1024];
- uchar jpeg_buffer[4096];
- struct
- {
- uchar buf[0x4000];
- int vbits, padding;
- }pana_bits;
-
- // init - should use in constructor/recycle
- void init()
- {
- getbits.bitbuf = 0; getbits.vbits = getbits.reset = 0;
- ph1_bits.bitbuf = 0; ph1_bits.vbits = 0;
- pana_bits.vbits = 0;
- }
+ struct
+ {
+ unsigned bitbuf;
+ int vbits, reset;
+ } getbits;
+ struct
+ {
+ UINT64 bitbuf;
+ int vbits;
+
+ } ph1_bits;
+ struct
+ {
+ unsigned pad[128], p;
+ } sony_decrypt;
+ struct
+ {
+ uchar buf[0x4002];
+ int vpos, padding;
+ } pana_data;
+ uchar jpeg_buffer[4096];
+ struct
+ {
+ float cbrt[0x10000], xyz_cam[3][4];
+ } ahd_data;
+ void init()
+ {
+ getbits.bitbuf = 0;
+ getbits.vbits = getbits.reset = 0;
+ ph1_bits.bitbuf = 0;
+ ph1_bits.vbits = 0;
+ pana_data.vpos = 0;
+ ahd_data.cbrt[0] = -2.0f;
+ }
};
-
class LibRaw_constants
{
- public:
- static const float d65_white[3];
- static const double xyz_rgb[3][3];
+public:
+ static const float d65_white[3];
+ static const double xyz_rgb[3][3];
+ static const double xyzd50_srgb[3][3];
+ static const double rgb_rgb[3][3];
+ static const double adobe_rgb[3][3];
+ static const double wide_rgb[3][3];
+ static const double prophoto_rgb[3][3];
+ static const double aces_rgb[3][3];
+ static const double dcip3d65_rgb[3][3];
+ static const double rec2020_rgb[3][3];
};
-#endif // __cplusplus
-
-#ifdef WIN32
-typedef long off_t;
-#endif
+#endif /* __cplusplus */
typedef struct
{
#ifndef __cplusplus
- struct
+ struct
#endif
- LibRaw_abstract_datastream *input;
- int input_internal;
-// char *ifname;
- char *meta_data;
- off_t profile_offset;
- off_t toffset;
+ LibRaw_abstract_datastream *input;
+ FILE *output;
+ int input_internal;
+ char *meta_data;
+ INT64 profile_offset;
+ INT64 toffset;
+ unsigned pana_black[4];
} internal_data_t;
-typedef struct
-{
- unsigned mix_green;
- unsigned raw_color;
- unsigned use_gamma;
- unsigned zero_is_bad;
- ushort shrink;
- ushort fuji_width;
- ushort fwidth,fheight;
-} internal_output_params_t;
-
#define LIBRAW_HISTOGRAM_SIZE 0x2000
typedef struct
{
- int (*histogram)[LIBRAW_HISTOGRAM_SIZE];
- unsigned *oprof;
+ int (*histogram)[LIBRAW_HISTOGRAM_SIZE];
+ unsigned *oprof;
} output_data_t;
typedef struct
{
- unsigned olympus_exif_cfa;
- unsigned unique_id;
- unsigned tiff_nifds;
- int tiff_flip;
-}identify_data_t;
+ unsigned olympus_exif_cfa;
+ unsigned long long unique_id;
+ unsigned long long OlyID;
+ unsigned tiff_nifds;
+ int tiff_flip;
+ int metadata_blocks;
+} identify_data_t;
typedef struct
{
- short order; // II* / MM* - file word byte order
- ushort sraw_mul[4],cr2_slice[3];
- unsigned kodak_cbpp;
- off_t strip_offset, data_offset;
- off_t meta_offset;
- unsigned meta_length;
- unsigned thumb_misc;
- unsigned fuji_layout;
- unsigned tiff_samples;
- unsigned tiff_bps;
- unsigned tiff_compress;
- unsigned zero_after_ff;
- unsigned tile_width, tile_length,load_flags;
- unsigned data_error;
-}unpacker_data_t;
+ uint32_t first;
+ uint32_t count;
+ uint32_t id;
+} crx_sample_to_chunk_t;
+// contents of tag CMP1 for relevant track in CR3 file
+typedef struct
+{
+ int32_t version;
+ int32_t f_width;
+ int32_t f_height;
+ int32_t tileWidth;
+ int32_t tileHeight;
+ int32_t nBits;
+ int32_t nPlanes;
+ int32_t cfaLayout;
+ int32_t encType;
+ int32_t imageLevels;
+ int32_t hasTileCols;
+ int32_t hasTileRows;
+ int32_t mdatHdrSize;
+ int32_t medianBits;
+ // Not from header, but from datastream
+ uint32_t MediaSize;
+ INT64 MediaOffset;
+ uint32_t MediaType; /* 1 -> /C/RAW, 2-> JPEG, 3-> CTMD metadata*/
+ crx_sample_to_chunk_t * stsc_data; /* samples to chunk */
+ uint32_t stsc_count;
+ uint32_t sample_count;
+ uint32_t sample_size; /* zero if not fixed sample size */
+ int32_t *sample_sizes;
+ uint32_t chunk_count;
+ INT64 *chunk_offsets;
+} crx_data_header_t;
+typedef struct
+{
+ short order;
+ ushort sraw_mul[4], cr2_slice[3];
+ unsigned kodak_cbpp;
+ INT64 strip_offset, data_offset;
+ INT64 meta_offset;
+ INT64 exif_offset, exif_subdir_offset, ifd0_offset;
+ unsigned data_size;
+ unsigned meta_length;
+ unsigned cr3_exif_length, cr3_ifd0_length;
+ unsigned thumb_misc;
+ enum LibRaw_internal_thumbnail_formats thumb_format;
+ unsigned fuji_layout;
+ unsigned tiff_samples;
+ unsigned tiff_bps;
+ unsigned tiff_compress;
+ unsigned tiff_sampleformat;
+ unsigned zero_after_ff;
+ unsigned tile_width, tile_length, load_flags;
+ unsigned data_error;
+ int hasselblad_parser_flag;
+ long long posRAFData;
+ unsigned lenRAFData;
+ int fuji_total_lines, fuji_total_blocks, fuji_block_width, fuji_bits,
+ fuji_raw_type, fuji_lossless;
+ int pana_encoding, pana_bpp;
+ crx_data_header_t crx_header[LIBRAW_CRXTRACKS_MAXCOUNT];
+ int crx_track_selected;
+ int crx_track_count;
+ short CR3_CTMDtag;
+ short CR3_Version;
+ int CM_found;
+ unsigned is_NikonTransfer;
+ unsigned is_Olympus;
+ int OlympusDNG_SubDirOffsetValid;
+ unsigned is_Sony;
+ unsigned is_pana_raw;
+ unsigned is_PentaxRicohMakernotes; /* =1 for Ricoh software by Pentax, Camera DNG */
+
+ unsigned dng_frames[LIBRAW_IFD_MAXCOUNT*2]; /* bits: 0-7: shot_select, 8-15: IFD#, 16-31: low 16 bit of newsubfile type */
+ unsigned short raw_stride;
+} unpacker_data_t;
typedef struct
{
- internal_data_t internal_data;
- internal_output_params_t internal_output_params;
- output_data_t output_data;
- identify_data_t identify_data;
- unpacker_data_t unpacker_data;
-// callbacks_t callbacks;
+ internal_data_t internal_data;
+ libraw_internal_output_params_t internal_output_params;
+ output_data_t output_data;
+ identify_data_t identify_data;
+ unpacker_data_t unpacker_data;
} libraw_internal_data_t;
-
-struct decode
+struct decode
{
- struct decode *branch[2];
- int leaf;
+ struct decode *branch[2];
+ int leaf;
};
-struct tiff_ifd_t
+struct tiff_ifd_t
{
- int t_width, t_height, bps, comp, phint, offset, t_flip, samples, bytes;
+ int t_width, t_height, bps, comp, phint, offset, t_flip, samples, bytes, extrasamples;
+ int t_tile_width, t_tile_length, sample_format, predictor;
+ int rows_per_strip;
+ int *strip_offsets, strip_offsets_count;
+ int *strip_byte_counts, strip_byte_counts_count;
+ unsigned t_filters;
+ int t_vwidth, t_vheight, t_lm,t_tm;
+ int t_fuji_width;
+ float t_shutter;
+ /* Per-IFD DNG fields */
+ INT64 opcode2_offset;
+ INT64 lineartable_offset;
+ int lineartable_len;
+ libraw_dng_color_t dng_color[2];
+ libraw_dng_levels_t dng_levels;
+ int newsubfiletype;
};
-
-struct jhead {
- int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
- struct decode *huff[6];
- ushort *row;
+struct jhead
+{
+ int algo, bits, high, wide, clrs, sraw, psv, restart, vpred[6];
+ ushort quant[64], idct[64], *huff[20], *free[20], *row;
};
-struct tiff_tag {
+
+struct libraw_tiff_tag
+{
ushort tag, type;
int count;
- union { char c[4]; short s[2]; int i; } val;
+ union {
+ char c[4];
+ short s[2];
+ int i;
+ } val;
};
-struct tiff_hdr {
+struct tiff_hdr
+{
ushort t_order, magic;
int ifd;
ushort pad, ntag;
- struct tiff_tag tag[23];
+ struct libraw_tiff_tag tag[23];
int nextifd;
ushort pad2, nexif;
- struct tiff_tag exif[4];
+ struct libraw_tiff_tag exif[4];
ushort pad3, ngps;
- struct tiff_tag gpst[10];
+ struct libraw_tiff_tag gpst[10];
short bps[4];
int rat[10];
unsigned gps[26];
char t_desc[512], t_make[64], t_model[64], soft[32], date[20], t_artist[64];
};
-
-
#ifdef DEBUG_STAGE_CHECKS
-#define CHECK_ORDER_HIGH(expected_stage) \
- do { if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) {fprintf(stderr,"CHECK_HIGH: check %d >= %d\n",imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK,expected_stage);return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
-
-#define CHECK_ORDER_LOW(expected_stage) \
- do { printf("Checking LOW %d/%d : %d\n",imgdata.progress_flags,expected_stage,imgdata.progress_flags<expected_stage); if( (imgdata.progress_flags&LIBRAW_PROGRESS_THUMB_MASK) < expected_stage ) { printf("failed!\n"); return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
-#define CHECK_ORDER_BIT(expected_stage) \
- do { if(imgdata.progress_flags & expected_stage) return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
-
-#define SET_PROC_FLAG(stage) do {imgdata.progress_flags |= stage; fprintf(stderr,"SET_FLAG: %d\n",stage); } while (0)
+#define CHECK_ORDER_HIGH(expected_stage) \
+ do \
+ { \
+ if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= \
+ expected_stage) \
+ { \
+ fprintf(stderr, "CHECK_HIGH: check %d >= %d\n", \
+ imgdata.progress_flags &LIBRAW_PROGRESS_THUMB_MASK, \
+ expected_stage); \
+ return LIBRAW_OUT_OF_ORDER_CALL; \
+ } \
+ } while (0)
+
+#define CHECK_ORDER_LOW(expected_stage) \
+ do \
+ { \
+ printf("Checking LOW %d/%d : %d\n", imgdata.progress_flags, \
+ expected_stage, imgdata.progress_flags < expected_stage); \
+ if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < \
+ expected_stage) \
+ { \
+ printf("failed!\n"); \
+ return LIBRAW_OUT_OF_ORDER_CALL; \
+ } \
+ } while (0)
+#define CHECK_ORDER_BIT(expected_stage) \
+ do \
+ { \
+ if (imgdata.progress_flags & expected_stage) \
+ return LIBRAW_OUT_OF_ORDER_CALL; \
+ } while (0)
+
+#define SET_PROC_FLAG(stage) \
+ do \
+ { \
+ imgdata.progress_flags |= stage; \
+ fprintf(stderr, "SET_FLAG: %d\n", stage); \
+ } while (0)
#else
-#define CHECK_ORDER_HIGH(expected_stage) \
- do { if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) \
- {return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
-
-#define CHECK_ORDER_LOW(expected_stage) \
- do { if((imgdata.progress_flags&LIBRAW_PROGRESS_THUMB_MASK) < expected_stage) \
- return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
-
-#define CHECK_ORDER_BIT(expected_stage) \
- do { if(imgdata.progress_flags & expected_stage) return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
-
-#define SET_PROC_FLAG(stage) do {imgdata.progress_flags |= stage;} while (0)
+#define CHECK_ORDER_HIGH(expected_stage) \
+ do \
+ { \
+ if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= \
+ expected_stage) \
+ { \
+ return LIBRAW_OUT_OF_ORDER_CALL; \
+ } \
+ } while (0)
+
+#define CHECK_ORDER_LOW(expected_stage) \
+ do \
+ { \
+ if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < \
+ expected_stage) \
+ return LIBRAW_OUT_OF_ORDER_CALL; \
+ } while (0)
+
+#define CHECK_ORDER_BIT(expected_stage) \
+ do \
+ { \
+ if (imgdata.progress_flags & expected_stage) \
+ return LIBRAW_OUT_OF_ORDER_CALL; \
+ } while (0)
+
+#define SET_PROC_FLAG(stage) \
+ do \
+ { \
+ imgdata.progress_flags |= stage; \
+ } while (0)
#endif
diff --git a/libkdcraw/libraw/libraw/libraw_types.h b/libkdcraw/libraw/libraw/libraw_types.h
index 00e3f26..ec413b6 100644
--- a/libkdcraw/libraw/libraw/libraw_types.h
+++ b/libkdcraw/libraw/libraw/libraw_types.h
@@ -1,285 +1,1175 @@
-/*
+/* -*- C++ -*-
* File: libraw_types.h
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
* Created: Sat Mar 8 , 2008
*
* LibRaw C data structures
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+
+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).
+
*/
#ifndef _LIBRAW_TYPES_H
#define _LIBRAW_TYPES_H
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifndef WIN32
+#include <sys/types.h>
+#ifndef _WIN32
#include <sys/time.h>
#endif
+
#include <stdio.h>
-#ifdef _OPENMP
-#include <omp.h>
+
+#if defined(_WIN32)
+#if defined(_MSC_VER) && (_MSC_VER <= 1500)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else /* WIN32, but not old MSVC */
+#include <stdint.h>
+#endif /* _WIN32 */
+#include <sys/types.h>
+#else
+#include <inttypes.h>
+#endif
+
+#if defined(_OPENMP)
+
+#if defined(LIBRAW_FORCE_OPENMP)
+#define LIBRAW_USE_OPENMP
+#else
+#if defined(_WIN32)
+#if defined(_MSC_VER) && \
+ (_MSC_VER >= 1600 || (_MSC_VER == 1500 && _MSC_FULL_VER >= 150030729))
+/* VS2010+ : OpenMP works OK, VS2008: have tested by cgilles */
+#define LIBRAW_USE_OPENMP
+#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 910)
+/* Have not tested on 9.x and 10.x, but Intel documentation claims OpenMP 2.5
+ * support in 9.1 */
+#define LIBRAW_USE_OPENMP
+#else
+#undef LIBRAW_USE_OPENMP
+#endif
+/* Not Win32 */
+#elif (defined(__APPLE__) || defined(__MACOSX__)) && defined(_REENTRANT)
+/* Latest XCode works with OpenMP, need to recheck here */
+#undef LIBRAW_USE_OPENMP
+#else
+#define LIBRAW_USE_OPENMP
+#endif
+#endif
#endif
+#ifdef LIBRAW_USE_OPENMP
+#include <omp.h>
+#endif
#ifdef __cplusplus
-extern "C" {
+extern "C"
+{
#endif
-#ifndef USE_LCMS
+#if defined(USE_LCMS)
+#include <lcms.h>
+#elif defined(USE_LCMS2)
+#include <lcms2.h>
+#else
#define NO_LCMS
#endif
#include "libraw_const.h"
#include "libraw_version.h"
+#ifdef _WIN32
+ typedef __int64 INT64;
+ typedef unsigned __int64 UINT64;
+#else
typedef long long INT64;
typedef unsigned long long UINT64;
-//#define ushort UshORt
-typedef unsigned char uchar;
-typedef unsigned short ushort;
+#endif
-#ifdef WIN32
+ typedef unsigned char uchar;
+ typedef unsigned short ushort;
+
+#ifdef LIBRAW_WIN32_DLLDEFS
#ifdef LIBRAW_NODLL
-# define DllDef
+#define DllDef
+#else
+#ifdef LIBRAW_BUILDLIB
+#define DllDef __declspec(dllexport)
#else
-# ifdef LIBRAW_BUILDLIB
-# define DllDef __declspec( dllexport )
-# else
-# define DllDef __declspec( dllimport )
-# endif
+#define DllDef __declspec(dllimport)
+#endif
#endif
-// NO Win32
#else
-# define DllDef
+#define DllDef
#endif
+ typedef struct
+ {
+ const char *decoder_name;
+ unsigned decoder_flags;
+ } libraw_decoder_info_t;
-//class LibRaw;
+ typedef struct
+ {
+ unsigned mix_green;
+ unsigned raw_color;
+ unsigned zero_is_bad;
+ ushort shrink;
+ ushort fuji_width;
+ } libraw_internal_output_params_t;
-typedef void (* memory_callback)(void * data, const char *file, const char *where);
+ typedef void (*memory_callback)(void *data, const char *file,
+ const char *where);
+ typedef void (*exif_parser_callback)(void *context, int tag, int type,
+ int len, unsigned int ord, void *ifp,
+ INT64 base);
-DllDef void default_memory_callback(void *data,const char *file, const char *where);
+ typedef void (*data_callback)(void *data, const char *file, const int offset);
-typedef void (*data_callback)(void *data,const char *file, const int offset);
+ DllDef void default_data_callback(void *data, const char *file,
+ const int offset);
-DllDef void default_data_callback(void *data,const char *file, const int offset);
-
-typedef int (* progress_callback) (void *data,enum LibRaw_progress stage, int iteration,int expected);
-
-typedef struct
-{
- memory_callback mem_cb;
- void* memcb_data;
+ typedef int (*progress_callback)(void *data, enum LibRaw_progress stage,
+ int iteration, int expected);
+ typedef int (*pre_identify_callback)(void *ctx);
+ typedef void (*post_identify_callback)(void *ctx);
+ typedef void (*process_step_callback)(void *ctx);
+ typedef struct
+ {
data_callback data_cb;
- void* datacb_data;
+ void *datacb_data;
progress_callback progress_cb;
void *progresscb_data;
-} libraw_callbacks_t;
-// Output bitmap type
+ exif_parser_callback exif_cb;
+ void *exifparser_data;
+ pre_identify_callback pre_identify_cb;
+ post_identify_callback post_identify_cb;
+ process_step_callback pre_subtractblack_cb, pre_scalecolors_cb,
+ pre_preinterpolate_cb, pre_interpolate_cb, interpolate_bayer_cb,
+ interpolate_xtrans_cb, post_interpolate_cb, pre_converttorgb_cb,
+ post_converttorgb_cb;
+ } libraw_callbacks_t;
-typedef struct
-{
- enum LibRaw_image_formats type;
- ushort height,
- width,
- colors,
- bits,
- gamma_corrected;
- unsigned int data_size; // ������ ���� ������ � ������
- unsigned char data[1]; // we'll allocate more!
-}libraw_processed_image_t;
-
-
-//Decoded from exif and used in calculations
-typedef struct
-{
- char make[64];
- char model[64];
+ typedef struct
+ {
+ enum LibRaw_image_formats type;
+ ushort height, width, colors, bits;
+ unsigned int data_size;
+ unsigned char data[1];
+ } libraw_processed_image_t;
- unsigned raw_count;
- unsigned dng_version;
- unsigned is_foveon;
- int colors;
+ typedef struct
+ {
+ char guard[4];
+ char make[64];
+ char model[64];
+ char software[64];
+ char normalized_make[64];
+ char normalized_model[64];
+ unsigned maker_index;
+ unsigned raw_count;
+ unsigned dng_version;
+ unsigned is_foveon;
+ int colors;
+ unsigned filters;
+ char xtrans[6][6];
+ char xtrans_abs[6][6];
+ char cdesc[5];
+ unsigned xmplen;
+ char *xmpdata;
- unsigned filters; // camera CFA pattern mask
- char cdesc[5];
+ } libraw_iparams_t;
-}libraw_iparams_t;
+ typedef struct
+ {
+ ushort cleft, ctop, cwidth, cheight;
+ } libraw_raw_inset_crop_t;
-typedef struct
-{
- ushort raw_height,
- raw_width,
- height,
- width,
- top_margin,
- left_margin;
- ushort iheight,
- iwidth;
- double pixel_aspect;
- int flip;
-
- // masked border sizes
- ushort right_margin,bottom_margin; // right masked width and bottom height, inited after idendify()
-
-} libraw_image_sizes_t;
-
-//Phase One data
-struct ph1_t
-{
- int format, key_off, t_black, black_off, split_col, tag_21a;
+ typedef struct
+ {
+ ushort raw_height, raw_width, height, width, top_margin, left_margin;
+ ushort iheight, iwidth;
+ unsigned raw_pitch;
+ double pixel_aspect;
+ int flip;
+ int mask[8][4];
+ ushort raw_aspect;
+ libraw_raw_inset_crop_t raw_inset_crops[2];
+ } libraw_image_sizes_t;
+
+ typedef struct
+ {
+ short t,l,b,r; // top, left, bottom, right pixel coordinates, (0,0) is top left pixel;
+ } libraw_area_t;
+
+ struct ph1_t
+ {
+ int format, key_off, tag_21a;
+ int t_black, split_col, black_col, split_row, black_row;
float tag_210;
-};
+ };
+ typedef struct
+ {
+ unsigned parsedfields;
+ ushort illuminant;
+ float calibration[4][4];
+ float colormatrix[4][3];
+ float forwardmatrix[3][4];
+ } libraw_dng_color_t;
-typedef struct
-{
- // 32 bits total
- unsigned curve_state : 3;
- unsigned rgb_cam_state : 3;
- unsigned cmatrix_state : 3;
- unsigned pre_mul_state : 3;
- unsigned cam_mul_state : 3;
- unsigned filler : 17;
-} color_data_state_t;
-
-typedef struct
-{
- color_data_state_t color_flags;
- ushort white[8][8]; // white block extracted from ciff/CRW
- float cam_mul[4]; // camera white balance (from RAW)
- float pre_mul[4]; // either set in identify() or calculated. Used on output
- float cmatrix[3][4]; // camera color matrix
- float rgb_cam[3][4]; // another way to set color matrix
- float cam_xyz[4][3]; // Camera to XYZ matrix (DNG coeffs)
- ushort curve[0x4001]; // camera tone curve/ljpeg curve
- unsigned black;
- unsigned maximum;
- struct ph1_t phase_one_data;
- float flash_used; // canon/CRW only
- float canon_ev; // canon/CRW only
- char model2[64];
- // profile
- void *profile;
- unsigned profile_length;
-}libraw_colordata_t;
-
-typedef struct
-{
- enum LibRaw_thumbnail_formats tformat;
- ushort twidth,
- theight;
- unsigned tlength;
- int tcolors;
+ typedef struct
+ {
+ unsigned parsedfields;
+ unsigned dng_cblack[LIBRAW_CBLACK_SIZE];
+ unsigned dng_black;
+ float dng_fcblack[LIBRAW_CBLACK_SIZE];
+ float dng_fblack;
+ unsigned dng_whitelevel[4];
+ ushort default_crop[4]; /* Origin and size */
+ float user_crop[4]; // top-left-bottom-right relative to default_crop
+ unsigned preview_colorspace;
+ float analogbalance[4];
+ float asshotneutral[4];
+ float baseline_exposure;
+ float LinearResponseLimit;
+ } libraw_dng_levels_t;
+
+ typedef struct
+ {
+ float romm_cam[9];
+ } libraw_P1_color_t;
+
+ typedef struct
+ {
+ int ColorDataVer;
+ int ColorDataSubVer;
+ int SpecularWhiteLevel;
+ int NormalWhiteLevel;
+ int ChannelBlackLevel[4];
+ int AverageBlackLevel;
+ /* multishot */
+ unsigned int multishot[4];
+ /* metering */
+ short MeteringMode;
+ short SpotMeteringMode;
+ uchar FlashMeteringMode;
+ short FlashExposureLock;
+ short ExposureMode;
+ short AESetting;
+ /* stabilization */
+ short ImageStabilization;
+ /* flash */
+ short FlashMode;
+ short FlashActivity;
+ short FlashBits;
+ short ManualFlashOutput;
+ short FlashOutput;
+ short FlashGuideNumber;
+ /* drive */
+ short ContinuousDrive;
+ /* sensor */
+ short SensorWidth;
+ short SensorHeight;
+
+ int AFMicroAdjMode;
+ float AFMicroAdjValue;
+ short MakernotesFlip;
+ short RecordMode;
+ short SRAWQuality;
+ unsigned wbi;
+ short RF_lensID;
+ int AutoLightingOptimizer;
+ int HighlightTonePriority;
+
+ /* -1 = n/a 1 = Economy
+ 2 = Normal 3 = Fine
+ 4 = RAW 5 = Superfine
+ 7 = CRAW 130 = Normal Movie, CRM LightRaw
+ 131 = CRM StandardRaw */
+ short Quality;
+ /* data compression curve
+ 0 = OFF 1 = CLogV1 2 = CLogV2? 3 = CLogV3 */
+ int CanonLog;
+
+ libraw_area_t DefaultCropAbsolute;
+ libraw_area_t RecommendedImageArea; // contains the image in proper aspect ratio?
+ libraw_area_t LeftOpticalBlack; // use this, when present, to estimate black levels?
+ libraw_area_t UpperOpticalBlack;
+ libraw_area_t ActiveArea;
- // thumbnail buffer
- char *thumb;
-}libraw_thumbnail_t;
+ short ISOgain[2]; // AutoISO & BaseISO per ExifTool
+ } libraw_canon_makernotes_t;
-// Decoded from exif/raw, but not used in real calculations
-typedef struct
-{
- float iso_speed;
- float shutter;
- float aperture;
- float focal_len;
- time_t timestamp;
- unsigned shot_order;
- unsigned gpsdata[32];
- // string variables
- char desc[512],
- artist[64];
-} libraw_imgother_t;
-
-typedef struct
-{
- unsigned greybox[4]; /* -A x1 y1 x2 y2 */
- double aber[4]; /* -C */
- double gamm[5]; /* -g */
- float user_mul[4]; /* -r mul0 mul1 mul2 mul3 */
- unsigned shot_select; /* -s */
- float bright; /* -b */
- float threshold; /* -n */
- int half_size; /* -h */
- int four_color_rgb; /* -f */
- int document_mode; /* -d/-D */
- int highlight; /* -H */
-// int verbose; /* -v */
- int use_auto_wb; /* -a */
- int use_camera_wb; /* -w */
- int use_camera_matrix; /* +M/-M */
- int output_color; /* -o */
- char *output_profile; /* -o */
- char *camera_profile; /* -p */
- char *bad_pixels; /* -P */
- char *dark_frame; /* -K */
- int output_bps; /* -4 */
- int gamma_16bit; /* -1 */
- int output_tiff; /* -T */
- int user_flip; /* -t */
- int user_qual; /* -q */
- int user_black; /* -k */
- int user_sat; /* -S */
-
- int med_passes; /* -m */
- float auto_bright_thr;
- int no_auto_bright; /* -W */
- int use_fuji_rotate;/* -j */
- enum LibRaw_filtering filtering_mode;
-}libraw_output_params_t;
-
-typedef struct
-{
- ushort *buffer; // actual pixel buffer size=(raw_width*raw_height - width*height)
- ushort *tl; // top left size=(top_margin*left_margin)
- ushort *top; // top size=(top_margin*width)
- ushort *tr; // top right size=((raw_width-width-left_margin)*top_margin)
- ushort *left; // left size=(left_margin*height)
- ushort *right; // right size=(raw_width-width-left_margin)*height;
- ushort *bl; // bottom left size=(raw_height-height-top_margin)*left_margin
- ushort *bottom; // bottom size=(raw_height-height-top_margin)*width
- ushort *br; // bottom right size=(raw_height-height-top_margin)*
- ushort (*ph1_black)[2]; // Phase One black
-}libraw_masked_t;
-
-typedef struct
-{
- unsigned int progress_flags;
- unsigned int process_warnings;
- libraw_iparams_t idata;
- libraw_image_sizes_t sizes;
- libraw_colordata_t color;
- libraw_imgother_t other;
- libraw_thumbnail_t thumbnail;
- libraw_masked_t masked_pixels;
- ushort (*image)[4] ;
- libraw_output_params_t params;
- // pointer to LibRaw class for use in C calls
- void *parent_class;
-} libraw_data_t;
+ typedef struct
+ {
+ int BaseISO;
+ double Gain;
+ char Sensor[8];
+ char SensorUnit[64]; // SU
+ char HostBody[64]; // HB
+ int SensorCode;
+ int SensorSubCode;
+ int CoatingCode;
+ int uncropped;
+
+/* CaptureSequenceInitiator is based on the content of the 'model' tag
+ - values like 'Pinhole', 'Flash Sync', '500 Mech.' etc in .3FR 'model' tag
+ come from MAIN MENU > SETTINGS > Camera;
+ - otherwise 'model' contains:
+ 1. if CF/CFV/CFH, SU enclosure, can be with SU type if '-' is present
+ 2. else if '-' is present, HB + SU type;
+ 3. HB;
+*/
+ char CaptureSequenceInitiator[32];
+
+/* SensorUnitConnector, makernotes 0x0015 tag:
+ - in .3FR - SU side
+ - in .FFF - HB side
+*/
+ char SensorUnitConnector[64];
+
+ int format; // 3FR, FFF, Imacon (H3D-39 and maybe others), Hasselblad/Phocus DNG, Adobe DNG
+ int nIFD_CM[2]; // number of IFD containing CM
+ int RecommendedCrop[2];
+
+/* mnColorMatrix is in makernotes tag 0x002a;
+ not present in .3FR files and Imacon/H3D-39 .FFF files;
+ when present in .FFF and Phocus .DNG files, it is a copy of CM1 from .3FR;
+ available samples contain all '1's in the first 3 elements
+*/
+ double mnColorMatrix[4][3];
+
+ } libraw_hasselblad_makernotes_t;
+
+ typedef struct
+ {
+ float ExpoMidPointShift;
+ ushort DynamicRange;
+ ushort FilmMode;
+ ushort DynamicRangeSetting;
+ ushort DevelopmentDynamicRange;
+ ushort AutoDynamicRange;
+ ushort DRangePriority;
+ ushort DRangePriorityAuto;
+ ushort DRangePriorityFixed;
+
+ /*
+ tag 0x9200, converted to BrightnessCompensation
+ F700, S3Pro, S5Pro, S20Pro, S200EXR
+ E550, E900, F810, S5600, S6500fd, S9000, S9500, S100FS
+ */
+ float BrightnessCompensation; /* in EV, if =4, raw data * 2^4 */
+ ushort FocusMode;
+ ushort AFMode;
+ ushort FocusPixel[2];
+ ushort PrioritySettings;
+ unsigned FocusSettings;
+ unsigned AF_C_Settings;
+ ushort FocusWarning;
+ ushort ImageStabilization[3];
+ ushort FlashMode;
+ ushort WB_Preset;
+
+ /* ShutterType:
+ 0 - mechanical
+ 1 = electronic
+ 2 = electronic, long shutter speed
+ 3 = electronic, front curtain
+ */
+ ushort ShutterType;
+ ushort ExrMode;
+ ushort Macro;
+ unsigned Rating;
+
+ /* CropMode:
+ 1 - FF on GFX,
+ 2 - sports finder (mechanical shutter),
+ 4 - 1.25x crop (electronic shutter, continuous high)
+ */
+ ushort CropMode;
+ char SerialSignature[0x0c + 1];
+ char SensorID[4 + 1];
+ char RAFVersion[4 + 1];
+ int RAFDataGeneration; // 0 (none), 1..4, 4096
+ ushort RAFDataVersion;
+ int isTSNERDTS;
+
+ /* DriveMode:
+ 0 - single frame
+ 1 - continuous low
+ 2 - continuous high
+ */
+ short DriveMode;
+
+ /*
+ tag 0x4000 BlackLevel:
+ S9100, S9000, S7000, S6000fd, S5200, S5100, S5000,
+ S5Pro, S3Pro, S2Pro, S20Pro,
+ S200EXR, S100FS,
+ F810, F700,
+ E900, E550,
+ DBP, and aliases for all of the above
+ */
+ ushort BlackLevel[9];
+ unsigned RAFData_ImageSizeTable[32];
+ int AutoBracketing;
+ int SequenceNumber;
+ int SeriesLength;
+ float PixelShiftOffset[2];
+ int ImageCount;
+ } libraw_fuji_info_t;
+
+ typedef struct
+ {
+ ushort cleft, ctop, cwidth, cheight;
+ } libraw_sensor_highspeed_crop_t;
+
+ typedef struct
+ {
+ double ExposureBracketValue;
+ ushort ActiveDLighting;
+ ushort ShootingMode;
+ /* stabilization */
+ uchar ImageStabilization[7];
+ uchar VibrationReduction;
+ uchar VRMode;
+ /* flash */
+ char FlashSetting[13];
+ char FlashType[20];
+ uchar FlashExposureCompensation[4];
+ uchar ExternalFlashExposureComp[4];
+ uchar FlashExposureBracketValue[4];
+ uchar FlashMode;
+ signed char FlashExposureCompensation2;
+ signed char FlashExposureCompensation3;
+ signed char FlashExposureCompensation4;
+ uchar FlashSource;
+ uchar FlashFirmware[2];
+ uchar ExternalFlashFlags;
+ uchar FlashControlCommanderMode;
+ uchar FlashOutputAndCompensation;
+ uchar FlashFocalLength;
+ uchar FlashGNDistance;
+ uchar FlashGroupControlMode[4];
+ uchar FlashGroupOutputAndCompensation[4];
+ uchar FlashColorFilter;
+
+/* NEF compression, comments follow those for ExifTool tag 0x0093:
+ 1: Lossy (type 1)
+ 2: Uncompressed
+ 3: Lossless
+ 4: Lossy (type 2)
+ 5: Striped packed 12-bit
+ 6: Uncompressed (14-bit reduced to 12-bit)
+ 7: Unpacked 12-bit
+ 8: Small raw
+ 9: Packed 12-bit
+ 10: Packed 14-bit
+ 13: High Efficiency (HE)
+ 14: High Efficiency* (HE*)
+*/
+ ushort NEFCompression;
+
+ int ExposureMode;
+ int ExposureProgram;
+ int nMEshots;
+ int MEgainOn;
+ double ME_WB[4];
+ uchar AFFineTune;
+ uchar AFFineTuneIndex;
+ int8_t AFFineTuneAdj;
+ unsigned LensDataVersion;
+ unsigned FlashInfoVersion;
+ unsigned ColorBalanceVersion;
+ uchar key;
+ ushort NEFBitDepth[4];
+ ushort HighSpeedCropFormat; /* 1 -> 1.3x; 2 -> DX; 3 -> 5:4; 4 -> 3:2; 6 ->
+ 16:9; 11 -> FX uncropped; 12 -> DX uncropped;
+ 17 -> 1:1 */
+ libraw_sensor_highspeed_crop_t SensorHighSpeedCrop;
+ ushort SensorWidth;
+ ushort SensorHeight;
+ ushort Active_D_Lighting;
+ unsigned ShotInfoVersion;
+ short MakernotesFlip;
+ double RollAngle; // positive is clockwise, CW
+ double PitchAngle; // positive is upwords
+ double YawAngle; // positive is to the right
+ } libraw_nikon_makernotes_t;
+
+ typedef struct
+ {
+ char CameraType2[6];
+ ushort ValidBits;
+ int SensorCalibration[2];
+ ushort DriveMode[5];
+ ushort ColorSpace;
+ ushort FocusMode[2];
+ ushort AutoFocus;
+ ushort AFPoint;
+ unsigned AFAreas[64];
+ double AFPointSelected[5];
+ ushort AFResult;
+ uchar AFFineTune;
+ short AFFineTuneAdj[3];
+ unsigned SpecialMode[3];
+ ushort ZoomStepCount;
+ ushort FocusStepCount;
+ ushort FocusStepInfinity;
+ ushort FocusStepNear;
+ double FocusDistance;
+ ushort AspectFrame[4]; // left, top, width, height
+ unsigned StackedImage[2];
+ uchar isLiveND;
+ unsigned LiveNDfactor;
+ ushort Panorama_mode;
+ ushort Panorama_frameNum;
+ } libraw_olympus_makernotes_t;
+
+ typedef struct
+ {
+ /* Compression:
+ 34826 (Panasonic RAW 2): LEICA DIGILUX 2;
+ 34828 (Panasonic RAW 3): LEICA D-LUX 3; LEICA V-LUX 1; Panasonic DMC-LX1;
+ Panasonic DMC-LX2; Panasonic DMC-FZ30; Panasonic DMC-FZ50; 34830 (not in
+ exiftool): LEICA DIGILUX 3; Panasonic DMC-L1; 34316 (Panasonic RAW 1):
+ others (LEICA, Panasonic, YUNEEC);
+ */
+ ushort Compression;
+ ushort BlackLevelDim;
+ float BlackLevel[8];
+ unsigned Multishot; /* 0 is Off, 65536 is Pixel Shift */
+ float gamma;
+ int HighISOMultiplier[3]; /* 0->R, 1->G, 2->B */
+ short FocusStepNear;
+ short FocusStepCount;
+ unsigned ZoomPosition;
+ unsigned LensManufacturer;
+ } libraw_panasonic_makernotes_t;
+
+ typedef struct
+ {
+ uchar DriveMode[4];
+ ushort FocusMode[2];
+ ushort AFPointSelected[2];
+ ushort AFPointSelected_Area;
+ int AFPointsInFocus_version;
+ unsigned AFPointsInFocus;
+ ushort FocusPosition;
+ short AFAdjustment;
+ uchar AFPointMode;
+ uchar MultiExposure; /* last bit is not "1" if ME is not used */
+ ushort Quality; /* 4 is raw, 7 is raw w/ pixel shift, 8 is raw w/ dynamic
+ pixel shift */
+ } libraw_pentax_makernotes_t;
+
+ typedef struct
+ {
+ ushort AFStatus;
+ unsigned AFAreaXPosition[2];
+ unsigned AFAreaYPosition[2];
+ ushort AFAreaMode;
+ unsigned SensorWidth;
+ unsigned SensorHeight;
+ unsigned CroppedImageWidth;
+ unsigned CroppedImageHeight;
+ ushort WideAdapter;
+ ushort CropMode;
+ ushort NDFilter;
+ ushort AutoBracketing;
+ ushort MacroMode;
+ ushort FlashMode;
+ double FlashExposureComp;
+ double ManualFlashOutput;
+ } libraw_ricoh_makernotes_t;
+
+ typedef struct
+ {
+ unsigned ImageSizeFull[4];
+ unsigned ImageSizeCrop[4];
+ int ColorSpace[2];
+ unsigned key[11];
+ double DigitalGain; /* PostAEGain, digital stretch */
+ int DeviceType;
+ char LensFirmware[32];
+ } libraw_samsung_makernotes_t;
+
+ typedef struct
+ {
+ ushort BlackLevelTop;
+ ushort BlackLevelBottom;
+ short offset_left, offset_top; /* KDC files, negative values or zeros */
+ ushort clipBlack, clipWhite; /* valid for P712, P850, P880 */
+ float romm_camDaylight[3][3];
+ float romm_camTungsten[3][3];
+ float romm_camFluorescent[3][3];
+ float romm_camFlash[3][3];
+ float romm_camCustom[3][3];
+ float romm_camAuto[3][3];
+ ushort val018percent, val100percent, val170percent;
+ short MakerNoteKodak8a;
+ float ISOCalibrationGain;
+ float AnalogISO;
+ } libraw_kodak_makernotes_t;
+
+ typedef struct {
+ char Software[64]; // tag 0x0203
+ char SystemType[64]; // tag 0x0204
+ char FirmwareString[256]; // tag 0x0301
+ char SystemModel[64];
+ } libraw_p1_makernotes_t;
+
+ typedef struct
+ {
+/* afdata:
+ 0x0010 CameraInfo
+ 0x2020 AFPointsUsed
+ 0x2022 FocalPlaneAFPointsUsed
+ 0x202a Tag202a
+ 0x940e AFInfo
+*/
+ ushort CameraType; // init in 0xffff
+ uchar Sony0x9400_version; /* 0 if not found/deciphered,
+ 0xa, 0xb, 0xc following exiftool convention */
+ uchar Sony0x9400_ReleaseMode2;
+ unsigned Sony0x9400_SequenceImageNumber;
+ uchar Sony0x9400_SequenceLength1;
+ unsigned Sony0x9400_SequenceFileNumber;
+ uchar Sony0x9400_SequenceLength2;
+ uint8_t AFAreaModeSetting; // init in 0xff; +
+ uint16_t AFAreaMode; // init in 0xffff; +
+ ushort FlexibleSpotPosition[2]; // init in (0xffff, 0xffff)
+ uint8_t AFPointSelected; // init in 0xff
+ uint8_t AFPointSelected_0x201e; // init in 0xff
+ short nAFPointsUsed;
+ uint8_t AFPointsUsed[10];
+ uint8_t AFTracking; // init in 0xff
+ uint8_t AFType;
+ ushort FocusLocation[4];
+ ushort FocusPosition; // init in 0xffff
+ int8_t AFMicroAdjValue; // init in 0x7f
+ int8_t AFMicroAdjOn; // init in -1
+ uchar AFMicroAdjRegisteredLenses; // init in 0xff
+ ushort VariableLowPassFilter;
+ unsigned LongExposureNoiseReduction; // init in 0xffffffff
+ ushort HighISONoiseReduction; // init in 0xffff
+ ushort HDR[2];
+ ushort group2010;
+ ushort group9050;
+ ushort real_iso_offset; // init in 0xffff
+ ushort MeteringMode_offset;
+ ushort ExposureProgram_offset;
+ ushort ReleaseMode2_offset;
+ unsigned MinoltaCamID; // init in 0xffffffff
+ float firmware;
+ ushort ImageCount3_offset; // init in 0xffff
+ unsigned ImageCount3;
+ unsigned ElectronicFrontCurtainShutter; // init in 0xffffffff
+ ushort MeteringMode2;
+ char SonyDateTime[20];
+ unsigned ShotNumberSincePowerUp;
+ ushort PixelShiftGroupPrefix;
+ unsigned PixelShiftGroupID;
+ char nShotsInPixelShiftGroup;
+ char numInPixelShiftGroup; /* '0' if ARQ, first shot in the group has '1'
+ here */
+ ushort prd_ImageHeight, prd_ImageWidth;
+ ushort prd_Total_bps;
+ ushort prd_Active_bps;
+ ushort prd_StorageMethod; /* 82 -> Padded; 89 -> Linear */
+ ushort prd_BayerPattern; /* 0 -> not valid; 1 -> RGGB; 4 -> GBRG */
+
+ ushort SonyRawFileType; /* init in 0xffff
+ valid for ARW 2.0 and up (FileFormat >= 3000)
+ takes precedence over RAWFileType and Quality:
+ 0 for uncompressed 14-bit raw
+ 1 for uncompressed 12-bit raw
+ 2 for compressed raw (lossy)
+ 3 for lossless compressed raw
+ 4 for lossless compressed raw v.2 (ILCE-1)
+ */
+ ushort RAWFileType; /* init in 0xffff
+ takes precedence over Quality
+ 0 for compressed raw,
+ 1 for uncompressed;
+ 2 lossless compressed raw v.2
+ */
+ ushort RawSizeType; /* init in 0xffff
+ 1 - large,
+ 2 - small,
+ 3 - medium
+ */
+ unsigned Quality; /* init in 0xffffffff
+ 0 or 6 for raw, 7 or 8 for compressed raw */
+ ushort FileFormat; /* 1000 SR2
+ 2000 ARW 1.0
+ 3000 ARW 2.0
+ 3100 ARW 2.1
+ 3200 ARW 2.2
+ 3300 ARW 2.3
+ 3310 ARW 2.3.1
+ 3320 ARW 2.3.2
+ 3330 ARW 2.3.3
+ 3350 ARW 2.3.5
+ 4000 ARW 4.0
+ */
+ char MetaVersion [16];
+ } libraw_sony_info_t;
+
+ typedef struct
+ {
+ ushort curve[0x10000];
+ unsigned cblack[LIBRAW_CBLACK_SIZE];
+ unsigned black;
+ unsigned data_maximum;
+ unsigned maximum;
+
+// Canon (SpecularWhiteLevel)
+// Kodak (14N, 14nx, SLR/c/n, DCS720X, DCS760C, DCS760M, ProBack, ProBack645, P712, P880, P850)
+// Olympus, except:
+// C5050Z, C5060WZ, C7070WZ, C8080WZ
+// SP350, SP500UZ, SP510UZ, SP565UZ
+// E-10, E-20
+// E-300, E-330, E-400, E-410, E-420, E-450, E-500, E-510, E-520
+// E-1, E-3
+// XZ-1
+// Panasonic
+// Pentax
+// Sony
+// and aliases of the above
+// DNG
+ long linear_max[4];
+
+ float fmaximum;
+ float fnorm;
+ ushort white[8][8];
+ float cam_mul[4];
+ float pre_mul[4];
+ float cmatrix[3][4];
+ float ccm[3][4];
+ float rgb_cam[3][4];
+ float cam_xyz[4][3];
+ struct ph1_t phase_one_data;
+ float flash_used;
+ float canon_ev;
+ char model2[64];
+ char UniqueCameraModel[64];
+ char LocalizedCameraModel[64];
+ char ImageUniqueID[64];
+ char RawDataUniqueID[17];
+ char OriginalRawFileName[64];
+ void *profile;
+ unsigned profile_length;
+ unsigned black_stat[8];
+ libraw_dng_color_t dng_color[2];
+ libraw_dng_levels_t dng_levels;
+ int WB_Coeffs[256][4]; /* R, G1, B, G2 coeffs */
+ float WBCT_Coeffs[64][5]; /* CCT, than R, G1, B, G2 coeffs */
+ int as_shot_wb_applied;
+ libraw_P1_color_t P1_color[2];
+ unsigned raw_bps; /* for Phase One: raw format; For other cameras: bits per pixel (copy of tiff_bps in most cases) */
+ /* Phase One raw format values, makernotes tag 0x010e:
+ 0 Name unknown
+ 1 "RAW 1"
+ 2 "RAW 2"
+ 3 "IIQ L" (IIQ L14)
+ 4 Never seen
+ 5 "IIQ S"
+ 6 "IIQ Sv2" (S14 / S14+)
+ 7 Never seen
+ 8 "IIQ L16" (IIQ L16EX / IIQ L16)
+ */
+ int ExifColorSpace;
+ } libraw_colordata_t;
+
+ typedef struct
+ {
+ enum LibRaw_thumbnail_formats tformat;
+ ushort twidth, theight;
+ unsigned tlength;
+ int tcolors;
+ char *thumb;
+ } libraw_thumbnail_t;
+
+ typedef struct
+ {
+ enum LibRaw_internal_thumbnail_formats tformat;
+ ushort twidth, theight, tflip;
+ unsigned tlength;
+ unsigned tmisc;
+ INT64 toffset;
+ }libraw_thumbnail_item_t;
+
+ typedef struct
+ {
+ int thumbcount;
+ libraw_thumbnail_item_t thumblist[LIBRAW_THUMBNAIL_MAXCOUNT];
+ } libraw_thumbnail_list_t;
+
+ typedef struct
+ {
+ float latitude[3]; /* Deg,min,sec */
+ float longitude[3]; /* Deg,min,sec */
+ float gpstimestamp[3]; /* Deg,min,sec */
+ float altitude;
+ char altref, latref, longref, gpsstatus;
+ char gpsparsed;
+ } libraw_gps_info_t;
+
+ typedef struct
+ {
+ float iso_speed;
+ float shutter;
+ float aperture;
+ float focal_len;
+ time_t timestamp;
+ unsigned shot_order;
+ unsigned gpsdata[32];
+ libraw_gps_info_t parsed_gps;
+ char desc[512], artist[64];
+ float analogbalance[4];
+ } libraw_imgother_t;
+
+ typedef struct
+ {
+ unsigned AFInfoData_tag;
+ short AFInfoData_order;
+ unsigned AFInfoData_version;
+ unsigned AFInfoData_length;
+ uchar *AFInfoData;
+ } libraw_afinfo_item_t;
+
+ typedef struct {
+ float FlashEC;
+ float FlashGN;
+ float CameraTemperature;
+ float SensorTemperature;
+ float SensorTemperature2;
+ float LensTemperature;
+ float AmbientTemperature;
+ float BatteryTemperature;
+ float exifAmbientTemperature;
+ float exifHumidity;
+ float exifPressure;
+ float exifWaterDepth;
+ float exifAcceleration;
+ float exifCameraElevationAngle;
+ float real_ISO;
+ float exifExposureIndex;
+ ushort ColorSpace;
+ char firmware[128];
+ float ExposureCalibrationShift;
+ libraw_afinfo_item_t afdata[LIBRAW_AFDATA_MAXCOUNT];
+ int afcount;
+ } libraw_metadata_common_t;
+
+ typedef struct
+ {
+ unsigned greybox[4]; /* -A x1 y1 x2 y2 */
+ unsigned cropbox[4]; /* -B x1 y1 x2 y2 */
+ double aber[4]; /* -C */
+ double gamm[6]; /* -g */
+ float user_mul[4]; /* -r mul0 mul1 mul2 mul3 */
+ float bright; /* -b */
+ float threshold; /* -n */
+ int half_size; /* -h */
+ int four_color_rgb; /* -f */
+ int highlight; /* -H */
+ int use_auto_wb; /* -a */
+ int use_camera_wb; /* -w */
+ int use_camera_matrix; /* +M/-M */
+ int output_color; /* -o */
+ char *output_profile; /* -o */
+ char *camera_profile; /* -p */
+ char *bad_pixels; /* -P */
+ char *dark_frame; /* -K */
+ int output_bps; /* -4 */
+ int output_tiff; /* -T */
+ int output_flags;
+ int user_flip; /* -t */
+ int user_qual; /* -q */
+ int user_black; /* -k */
+ int user_cblack[4];
+ int user_sat; /* -S */
+ int med_passes; /* -m */
+ float auto_bright_thr;
+ float adjust_maximum_thr;
+ int no_auto_bright; /* -W */
+ int use_fuji_rotate; /* -j */
+ int green_matching;
+ /* DCB parameters */
+ int dcb_iterations;
+ int dcb_enhance_fl;
+ int fbdd_noiserd;
+ int exp_correc;
+ float exp_shift;
+ float exp_preser;
+ /* Disable Auto-scale */
+ int no_auto_scale;
+ /* Disable intepolation */
+ int no_interpolation;
+ } libraw_output_params_t;
+
+ typedef struct
+ {
+ /* Raw speed */
+ int use_rawspeed;
+ /* DNG SDK */
+ int use_dngsdk;
+ unsigned options;
+ unsigned shot_select; /* -s */
+ unsigned specials;
+ unsigned max_raw_memory_mb;
+ int sony_arw2_posterization_thr;
+ /* Nikon Coolscan */
+ float coolscan_nef_gamma;
+ char p4shot_order[5];
+ /* Custom camera list */
+ char **custom_camera_strings;
+ }libraw_raw_unpack_params_t;
+
+ typedef struct
+ {
+ /* really allocated bitmap */
+ void *raw_alloc;
+ /* alias to single_channel variant */
+ ushort *raw_image;
+ /* alias to 4-channel variant */
+ ushort (*color4_image)[4];
+ /* alias to 3-color variand decoded by RawSpeed */
+ ushort (*color3_image)[3];
+ /* float bayer */
+ float *float_image;
+ /* float 3-component */
+ float (*float3_image)[3];
+ /* float 4-component */
+ float (*float4_image)[4];
+
+ /* Phase One black level data; */
+ short (*ph1_cblack)[2];
+ short (*ph1_rblack)[2];
+ /* save color and sizes here, too.... */
+ libraw_iparams_t iparams;
+ libraw_image_sizes_t sizes;
+ libraw_internal_output_params_t ioparams;
+ libraw_colordata_t color;
+ } libraw_rawdata_t;
+
+ typedef struct
+ {
+ unsigned long long LensID;
+ char Lens[128];
+ ushort LensFormat; /* to characterize the image circle the lens covers */
+ ushort LensMount; /* 'male', lens itself */
+ unsigned long long CamID;
+ ushort CameraFormat; /* some of the sensor formats */
+ ushort CameraMount; /* 'female', body throat */
+ char body[64];
+ short FocalType; /* -1/0 is unknown; 1 is fixed focal; 2 is zoom */
+ char LensFeatures_pre[16], LensFeatures_suf[16];
+ float MinFocal, MaxFocal;
+ float MaxAp4MinFocal, MaxAp4MaxFocal, MinAp4MinFocal, MinAp4MaxFocal;
+ float MaxAp, MinAp;
+ float CurFocal, CurAp;
+ float MaxAp4CurFocal, MinAp4CurFocal;
+ float MinFocusDistance;
+ float FocusRangeIndex;
+ float LensFStops;
+ unsigned long long TeleconverterID;
+ char Teleconverter[128];
+ unsigned long long AdapterID;
+ char Adapter[128];
+ unsigned long long AttachmentID;
+ char Attachment[128];
+ ushort FocalUnits;
+ float FocalLengthIn35mmFormat;
+ } libraw_makernotes_lens_t;
+
+ typedef struct
+ {
+ float EffectiveMaxAp;
+ uchar LensIDNumber, LensFStops, MCUVersion, LensType;
+ } libraw_nikonlens_t;
+
+ typedef struct
+ {
+ float MinFocal, MaxFocal, MaxAp4MinFocal, MaxAp4MaxFocal;
+ } libraw_dnglens_t;
+
+ typedef struct
+ {
+ float MinFocal, MaxFocal, MaxAp4MinFocal, MaxAp4MaxFocal, EXIF_MaxAp;
+ char LensMake[128], Lens[128], LensSerial[128], InternalLensSerial[128];
+ ushort FocalLengthIn35mmFormat;
+ libraw_nikonlens_t nikon;
+ libraw_dnglens_t dng;
+ libraw_makernotes_lens_t makernotes;
+ } libraw_lensinfo_t;
+
+ typedef struct
+ {
+ libraw_canon_makernotes_t canon;
+ libraw_nikon_makernotes_t nikon;
+ libraw_hasselblad_makernotes_t hasselblad;
+ libraw_fuji_info_t fuji;
+ libraw_olympus_makernotes_t olympus;
+ libraw_sony_info_t sony;
+ libraw_kodak_makernotes_t kodak;
+ libraw_panasonic_makernotes_t panasonic;
+ libraw_pentax_makernotes_t pentax;
+ libraw_p1_makernotes_t phaseone;
+ libraw_ricoh_makernotes_t ricoh;
+ libraw_samsung_makernotes_t samsung;
+ libraw_metadata_common_t common;
+ } libraw_makernotes_t;
+
+ typedef struct
+ {
+ short DriveMode;
+ short FocusMode;
+ short MeteringMode;
+ short AFPoint;
+ short ExposureMode;
+ short ExposureProgram;
+ short ImageStabilization;
+ char BodySerial[64];
+ char InternalBodySerial[64]; /* this may be PCB or sensor serial, depends on
+ make/model */
+ } libraw_shootinginfo_t;
+
+ typedef struct
+ {
+ unsigned fsize;
+ ushort rw, rh;
+ uchar lm, tm, rm, bm;
+ ushort lf;
+ uchar cf, max, flags;
+ char t_make[10], t_model[20];
+ ushort offset;
+ } libraw_custom_camera_t;
+
+ typedef struct
+ {
+ ushort (*image)[4];
+ libraw_image_sizes_t sizes;
+ libraw_iparams_t idata;
+ libraw_lensinfo_t lens;
+ libraw_makernotes_t makernotes;
+ libraw_shootinginfo_t shootinginfo;
+ libraw_output_params_t params;
+ libraw_raw_unpack_params_t rawparams;
+ unsigned int progress_flags;
+ unsigned int process_warnings;
+ libraw_colordata_t color;
+ libraw_imgother_t other;
+ libraw_thumbnail_t thumbnail;
+ libraw_thumbnail_list_t thumbs_list;
+ libraw_rawdata_t rawdata;
+ void *parent_class;
+ } libraw_data_t;
+
+ struct fuji_q_table
+ {
+ int8_t *q_table; /* quantization table */
+ int raw_bits;
+ int total_values;
+ int max_grad; // sdp val
+ int q_grad_mult; // quant_gradient multiplier
+ int q_base;
+ };
+
+ struct fuji_compressed_params
+ {
+ struct fuji_q_table qt[4];
+ void *buf;
+ int max_bits;
+ int min_value;
+ int max_value; // q_point[4]
+ ushort line_width;
+ };
#ifdef __cplusplus
}
#endif
+#if defined (LIBRAW_LIBRARY_BUILD) && defined(__cplusplus)
+
+class libraw_static_table_t
+{
+public:
+ libraw_static_table_t(const int *a, const unsigned s): data(a),_size(s) {}
+ libraw_static_table_t(): data(0),_size(0){}
+ libraw_static_table_t(const libraw_static_table_t& s) : data(s.data), _size(s._size) {}
+ unsigned size() const { return _size; }
+ libraw_static_table_t& operator = (const libraw_static_table_t& s)
+ {
+ _size = s._size;
+ data = s.data;
+ return *this;
+ }
+ int operator [] (unsigned idx) const
+ {
+ if (idx < _size) return data[idx];
+ if(_size>0 && data) return data[0];
+ return 0;
+ }
+private:
+ const int *data;
+ unsigned _size;
+};
+
+#endif
+
+
+/* Byte order */
+#if defined(__POWERPC__)
+#define LibRawBigEndian 1
+
+#elif defined(__INTEL__)
+#define LibRawBigEndian 0
+
+#elif defined(_M_IX86) || defined(__i386__)
+#define LibRawBigEndian 0
+
+#elif defined(_M_X64) || defined(__amd64__) || defined(__x86_64__)
+#define LibRawBigEndian 0
+
+#elif defined(__LITTLE_ENDIAN__)
+#define LibRawBigEndian 0
+
+#elif defined(__BIG_ENDIAN__)
+#define LibRawBigEndian 1
+#elif defined(_ARM_)
+#define LibRawBigEndian 0
+
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define LibRawBigEndian 0
+
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define LibRawBigEndian 1
+#else
+#ifndef qXCodeRez
+#error Unable to figure out byte order.
+#endif
+#endif
+
#endif
diff --git a/libkdcraw/libraw/libraw/libraw_version.h b/libkdcraw/libraw/libraw/libraw_version.h
index 1b00731..3845a5e 100644
--- a/libkdcraw/libraw/libraw/libraw_version.h
+++ b/libkdcraw/libraw/libraw/libraw_version.h
@@ -1,47 +1,63 @@
-/*
+/* -*- C++ -*-
* File: libraw_version.h
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
- * Created: Mon Sept 8, 2008
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Mon Sept 8, 2008
*
* LibRaw C++ interface
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+
+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 the file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+(See the file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
*/
#ifndef __VERSION_H
#define __VERSION_H
-#define LIBRAW_MAJOR_VERSION 0
-#define LIBRAW_MINOR_VERSION 7
-#define LIBRAW_PATCH_VERSION 2
-#define LIBRAW_VERSION_TAIL Release
+#define LIBRAW_MAJOR_VERSION 0
+#define LIBRAW_MINOR_VERSION 21
+#define LIBRAW_PATCH_VERSION 1
+#define LIBRAW_VERSION_TAIL Release
+
+#define LIBRAW_SHLIB_CURRENT 23
+#define LIBRAW_SHLIB_REVISION 0
+#define LIBRAW_SHLIB_AGE 0
+
+#define _LIBRAW_VERSION_MAKE(a, b, c, d) #a "." #b "." #c "-" #d
+#define LIBRAW_VERSION_MAKE(a, b, c, d) _LIBRAW_VERSION_MAKE(a, b, c, d)
+
+#define LIBRAW_VERSION_STR \
+ LIBRAW_VERSION_MAKE(LIBRAW_MAJOR_VERSION, LIBRAW_MINOR_VERSION, \
+ LIBRAW_PATCH_VERSION, LIBRAW_VERSION_TAIL)
+
+#define LIBRAW_MAKE_VERSION(major, minor, patch) \
+ (((major) << 16) | ((minor) << 8) | (patch))
-#define _LIBRAW_VERSION_MAKE(a,b,c,d) #a"."#b"."#c"-"#d
-#define LIBRAW_VERSION_MAKE(a,b,c,d) _LIBRAW_VERSION_MAKE(a,b,c,d)
+#define LIBRAW_VERSION \
+ LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION, LIBRAW_MINOR_VERSION, \
+ LIBRAW_PATCH_VERSION)
-#define LIBRAW_VERSION_STR LIBRAW_VERSION_MAKE(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,LIBRAW_PATCH_VERSION,LIBRAW_VERSION_TAIL)
+#define LIBRAW_CHECK_VERSION(major, minor, patch) \
+ (LibRaw::versionNumber() >= LIBRAW_MAKE_VERSION(major, minor, patch))
-#define LIBRAW_MAKE_VERSION(major,minor,patch) \
- (((major) << 16) | ((minor) << 8) | (patch))
+#define LIBRAW_RUNTIME_CHECK_VERSION_EXACT() \
+ ((LibRaw::versionNumber() & 0xffff00) == \
+ LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION, LIBRAW_MINOR_VERSION, 0))
-#define LIBRAW_VERSION \
- LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,LIBRAW_PATCH_VERSION)
+#define LIBRAW_RUNTIME_CHECK_VERSION_NOTLESS() \
+ ((LibRaw::versionNumber() & 0xffff00) >= \
+ LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION, LIBRAW_MINOR_VERSION, 0))
-#define LIBRAW_CHECK_VERSION(major,minor,patch) \
- ( LibRaw::versionNumber() >= LIBRAW_MAKE_VERSION(major,minor,patch) )
+#define LIBRAW_COMPILE_CHECK_VERSION(major, minor) \
+ (LIBRAW_MAKE_VERSION(major, minor, 0) == (LIBRAW_VERSION & 0xffff00))
+#define LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(major, minor) \
+ (LIBRAW_MAKE_VERSION(major, minor, 0) <= (LIBRAW_VERSION & 0xffff00))
#endif
diff --git a/libkdcraw/libraw/samples/4channels.cpp b/libkdcraw/libraw/samples/4channels.cpp
index 1bf6be1..82d40f4 100644
--- a/libkdcraw/libraw/samples/4channels.cpp
+++ b/libkdcraw/libraw/samples/4channels.cpp
@@ -1,187 +1,174 @@
-/*
+/* -*- C++ -*-
* File: 4channels.cpp
- * Copyright 2009 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
* Created: Mon Feb 09, 2009
*
* LibRaw sample
* Generates 4 TIFF file from RAW data, one file per channel
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+
+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 <stdio.h>
#include <string.h>
#include <math.h>
-#ifndef WIN32
+#include "libraw/libraw.h"
+
+#ifndef LIBRAW_WIN32_CALLS
#include <netinet/in.h>
#else
#include <winsock2.h>
#endif
-#include "libraw/libraw.h"
-
-#ifdef WIN32
+#ifdef LIBRAW_WIN32_CALLS
#define snprintf _snprintf
#endif
int main(int ac, char *av[])
{
- int i, ret;
- int autoscale=0,filtering_mode=LIBRAW_FILTERING_DEFAULT,black_subtraction=1;
- char outfn[1024],thumbfn[1024];
-
- LibRaw RawProcessor;
- if(ac<2)
- {
- usage:
- printf(
- "4channeld - LibRaw %s sample. %d cameras supported\n"
- "Usage: %s [-s N] [-g] [-A] [-B] [-N] raw-files....\n"
- "\t-s N - select Nth image in file (default=0)\n"
- "\t-g - use gamma correction with gamma 2.2 (not precise,use for visual inspection only)\n"
- "\t-A - autoscaling (by integer factor)\n"
- "\t-B - no black subtraction\n"
- "\t-N - no raw curve\n"
- ,LibRaw::version(),
- LibRaw::cameraCount(),
- av[0]);
- return 0;
- }
-
+ int i, ret;
+ int autoscale = 0, black_subtraction = 1, use_gamma = 0;
+ char outfn[1024];
+
+ LibRaw RawProcessor;
+ if (ac < 2)
+ {
+ usage:
+ printf("4channels - LibRaw %s sample. %d cameras supported\n"
+ "Usage: %s [-s N] [-g] [-A] [-B] [-N] raw-files....\n"
+ "\t-s N - select Nth image in file (default=0)\n"
+ "\t-g - use gamma correction with gamma 2.2 (not precise,use for "
+ "visual inspection only)\n"
+ "\t-A - autoscaling (by integer factor)\n"
+ "\t-B - no black subtraction\n",
+ LibRaw::version(), LibRaw::cameraCount(), av[0]);
+ return 0;
+ }
+
#define P1 RawProcessor.imgdata.idata
#define S RawProcessor.imgdata.sizes
#define C RawProcessor.imgdata.color
#define T RawProcessor.imgdata.thumbnail
#define P2 RawProcessor.imgdata.other
#define OUT RawProcessor.imgdata.params
+#define OUTR RawProcessor.imgdata.rawparams
- OUT.document_mode=2;
- OUT.output_bps=16;
- OUT.output_tiff=1;
- OUT.user_flip=0;
- OUT.no_auto_bright = 1;
- OUT.half_size=1;
- OUT.filtering_mode= LIBRAW_FILTERING_AUTOMATIC;
-
- for (i=1;i<ac;i++)
- {
- if(av[i][0]=='-')
- {
- if(av[i][1]=='s' && av[i][2]==0)
- {
- i++;
- OUT.shot_select=atoi(av[i]);
- }
- else if(av[i][1]=='g' && av[i][2]==0)
- OUT.gamma_16bit=1;
- else if(av[i][1]=='A' && av[i][2]==0)
- autoscale=1;
- else if(av[i][1]=='B' && av[i][2]==0)
- {
- filtering_mode |= (LIBRAW_FILTERING_NOZEROES | LIBRAW_FILTERING_NOBLACKS);
- black_subtraction=0;
- }
- else if(av[i][1]=='N' && av[i][2]==0)
- filtering_mode |= LIBRAW_FILTERING_NORAWCURVE;
- else
- goto usage;
- continue;
- }
- if(filtering_mode)
- OUT.filtering_mode = (LibRaw_filtering) filtering_mode;
- int r,c;
- printf("Processing file %s\n",av[i]);
- if( (ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot open %s: %s\n",av[i],libraw_strerror(ret));
- continue; // no recycle b/c open file will recycle itself
- }
- if(P1.is_foveon)
- {
- printf("Cannot process foveon image %s\n",av[i]);
- continue ;
- }
- if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot unpack %s: %s\n",av[i],libraw_strerror(ret));
- continue;
- }
- if(black_subtraction && C.black>0)
- {
- for(int j=0; j<S.iheight*S.iwidth; j++)
- for(int c = 0; c< 4; c++)
- if(RawProcessor.imgdata.image[j][c]>C.black)
- RawProcessor.imgdata.image[j][c]-=C.black;
- else
- RawProcessor.imgdata.image[j][c]=0;
- }
-
- if(autoscale)
- {
- unsigned max=0,scale;
- for(int j=0; j<S.iheight*S.iwidth; j++)
- for(int c = 0; c< 4; c++)
- if(max < RawProcessor.imgdata.image[j][c])
- max = RawProcessor.imgdata.image[j][c];
- if (max >0 && max< 1<<15)
- {
- scale = (1<<16)/max;
- printf("Scaling with multiplier=%d (max=%d)\n",scale,max);
- for(int j=0; j<S.iheight*S.iwidth; j++)
- for(c=0;c<4;c++)
- RawProcessor.imgdata.image[j][c] *= scale;
- }
- printf("Black level (scaled)=%d\n",C.black*scale);
- }
- else
- printf("Black level (unscaled)=%d\n",C.black);
-
-
- // hack to make dcraw tiff writer happy
- int isrgb=(P1.colors==4?0:1);
- P1.colors = 1;
- S.width = S.iwidth;
- S.height = S.iheight;
-
- for (int layer=0;layer<4;layer++)
- {
- if(layer>0)
- {
- for (int rc = 0; rc < S.iheight*S.iwidth; rc++)
- RawProcessor.imgdata.image[rc][0] = RawProcessor.imgdata.image[rc][layer];
- }
- char lname[8];
- if(isrgb)
- {
- snprintf(lname,7,"%c",(char*)("RGBG")[layer]);
- if(layer==3)
- strcat(lname,"2");
- }
- else
- snprintf(lname,7,"%c",(char*)("GCMY")[layer]);
-
- if(OUT.shot_select)
- snprintf(outfn,sizeof(outfn),"%s-%d.%s.tiff",av[i],OUT.shot_select,lname);
- else
- snprintf(outfn,sizeof(outfn),"%s.%s.tiff",av[i],lname);
-
- printf("Writing file %s\n",outfn);
- if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
- fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret));
- }
-
- }
- return 0;
+ OUT.output_bps = 16;
+ OUT.output_tiff = 1;
+ OUT.user_flip = 0;
+ OUT.no_auto_bright = 1;
+ OUT.half_size = 1;
+
+ for (i = 1; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ if (av[i][1] == 's' && av[i][2] == 0)
+ {
+ i++;
+ OUTR.shot_select = av[i] ? atoi(av[i]) : 0;
+ }
+ else if (av[i][1] == 'g' && av[i][2] == 0)
+ use_gamma = 1;
+ else if (av[i][1] == 'A' && av[i][2] == 0)
+ autoscale = 1;
+ else if (av[i][1] == 'B' && av[i][2] == 0)
+ {
+ black_subtraction = 0;
+ }
+ else
+ goto usage;
+ continue;
+ }
+ if (!use_gamma)
+ OUT.gamm[0] = OUT.gamm[1] = 1;
+
+ int c;
+ printf("Processing file %s\n", av[i]);
+ if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret));
+ continue; // no recycle b/c open file will recycle itself
+ }
+ if (P1.is_foveon)
+ {
+ printf("Cannot process Foveon image %s\n", av[i]);
+ continue;
+ }
+ if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
+ continue;
+ }
+ RawProcessor.raw2image();
+ if (black_subtraction)
+ {
+ RawProcessor.subtract_black();
+ }
+
+ if (autoscale)
+ {
+ unsigned max = 0, scale = 1;
+ for (int j = 0; j < S.iheight * S.iwidth; j++)
+ for (int c = 0; c < 4; c++)
+ if (max < RawProcessor.imgdata.image[j][c])
+ max = RawProcessor.imgdata.image[j][c];
+ if (max > 0 && max < 1 << 15)
+ {
+ scale = (1 << 16) / max;
+ printf("Scaling with multiplier=%d (max=%d)\n", scale, max);
+ for (int j = 0; j < S.iheight * S.iwidth; j++)
+ for (c = 0; c < 4; c++)
+ RawProcessor.imgdata.image[j][c] *= scale;
+ }
+ printf("Black level (scaled)=%d\n", C.black * scale);
+ }
+ else
+ printf("Black level (unscaled)=%d\n", C.black);
+
+ // hack to make dcraw tiff writer happy
+ int isrgb = (P1.colors == 4 ? 0 : 1);
+ P1.colors = 1;
+ S.width = S.iwidth;
+ S.height = S.iheight;
+
+ for (int layer = 0; layer < 4; layer++)
+ {
+ if (layer > 0)
+ {
+ for (int rc = 0; rc < S.iheight * S.iwidth; rc++)
+ RawProcessor.imgdata.image[rc][0] =
+ RawProcessor.imgdata.image[rc][layer];
+ }
+ char lname[8];
+ if (isrgb)
+ {
+ snprintf(lname, 7, "%c", ((char *)("RGBG"))[layer]);
+ if (layer == 3)
+ strcat(lname, "2");
+ }
+ else
+ snprintf(lname, 7, "%c", ((char *)("GCMY"))[layer]);
+
+ if (OUTR.shot_select)
+ snprintf(outfn, sizeof(outfn), "%s-%d.%s.tiff", av[i], OUTR.shot_select,
+ lname);
+ else
+ snprintf(outfn, sizeof(outfn), "%s.%s.tiff", av[i], lname);
+
+ printf("Writing file %s\n", outfn);
+ if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
+ fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret));
+ }
+ }
+ return 0;
}
diff --git a/libkdcraw/libraw/samples/Makefile b/libkdcraw/libraw/samples/Makefile
new file mode 100644
index 0000000..be880e8
--- /dev/null
+++ b/libkdcraw/libraw/samples/Makefile
@@ -0,0 +1,2 @@
+all:
+ (cd ..; make all_samples)
diff --git a/libkdcraw/libraw/samples/dcraw_emu.cpp b/libkdcraw/libraw/samples/dcraw_emu.cpp
index f882805..1af82ff 100644
--- a/libkdcraw/libraw/samples/dcraw_emu.cpp
+++ b/libkdcraw/libraw/samples/dcraw_emu.cpp
@@ -1,27 +1,25 @@
-/*
+/* -*- C++ -*-
* File: dcraw_emu.cpp
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
* Created: Sun Mar 23, 2008
*
- * LibRaw simple C++ API (almost complete dcraw emulator)
+ * LibRaw simple C++ API sample: almost complete dcraw emulator
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+
+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).
+
+
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
+#ifdef _MSC_VER
+// suppress sprintf-related warning. sprintf() is permitted in sample code
+#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
@@ -29,260 +27,644 @@
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
-#ifndef WIN32
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/stat.h>
+
+#include "libraw/libraw.h"
+
+#ifndef LIBRAW_WIN32_CALLS
#include <sys/mman.h>
+#include <sys/time.h>
+#include <unistd.h>
+#else
+#include <io.h>
#endif
+#include <fcntl.h>
+#include <sys/stat.h>
-#include "libraw/libraw.h"
-#ifdef WIN32
+#ifdef LIBRAW_WIN32_CALLS
#define snprintf _snprintf
+#include <windows.h>
+#else
+#define O_BINARY 0
#endif
-#ifdef _OPENMP
-#include <omp.h>
+#ifdef USE_DNGSDK
+#include "dng_host.h"
+#include "dng_negative.h"
+#include "dng_simple_image.h"
+#include "dng_info.h"
#endif
void usage(const char *prog)
{
- printf("dcraw_emu: almost complete dcraw emulator\n");
- printf("Usage: %s [OPTION]... [FILE]...\n", prog);
- printf(
-"-v Verbose: print progress messages (repeated -v will add verbosity)\n"
-"-w Use camera white balance, if possible\n"
-"-a Average the whole image for white balance\n"
-"-A <x y w h> Average a grey box for white balance\n"
-"-r <r g b g> Set custom white balance\n"
-"+M/-M Use/don't use an embedded color matrix\n"
-"-C <r b> Correct chromatic aberration\n"
-"-P <file> Fix the dead pixels listed in this file\n"
-"-K <file> Subtract dark frame (16-bit raw PGM)\n"
-"-k <num> Set the darkness level\n"
-"-S <num> Set the saturation level\n"
-"-n <num> Set threshold for wavelet denoising\n"
-"-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)\n"
-"-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)\n"
-"-o [0-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)\n"
+ printf("dcraw_emu: almost complete dcraw emulator\n");
+ printf("Usage: %s [OPTION]... [FILE]...\n", prog);
+ printf("-c float-num Set adjust maximum threshold (default 0.75)\n"
+ "-v Verbose: print progress messages (repeated -v will add "
+ "verbosity)\n"
+ "-w Use camera white balance, if possible\n"
+ "-a Average the whole image for white balance\n"
+ "-A <x y w h> Average a grey box for white balance\n"
+ "-r <r g b g> Set custom white balance\n"
+ "+M/-M Use/don't use an embedded color matrix\n"
+ "-C <r b> Correct chromatic aberration\n"
+ "-P <file> Fix the dead pixels listed in this file\n"
+ "-K <file> Subtract dark frame (16-bit raw PGM)\n"
+ "-k <num> Set the darkness level\n"
+ "-S <num> Set the saturation level\n"
+ "-R <num> Set raw processing options to num\n"
+ "-n <num> Set threshold for wavelet denoising\n"
+ "-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)\n"
+ "-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)\n"
+ "-o [0-8] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ,ACES,\n"
+ " DCI-P3,Rec2020)\n"
#ifndef NO_LCMS
-"-o file Output ICC profile\n"
-"-p file Camera input profile (use \'embed\' for embedded profile)\n"
+ "-o file Output ICC profile\n"
+ "-p file Camera input profile (use \'embed\' for embedded profile)\n"
+#endif
+ "-j Don't stretch or rotate raw pixels\n"
+ "-W Don't automatically brighten the image\n"
+ "-b <num> Adjust brightness (default = 1.0)\n"
+ "-q N Set the interpolation quality:\n"
+ " 0 - linear, 1 - VNG, 2 - PPG, 3 - AHD, 4 - DCB\n"
+ " 11 - DHT, 12 - AAHD\n"
+ "-h Half-size color image (twice as fast as \"-q 0\")\n"
+ "-f Interpolate RGGB as four colors\n"
+ "-m <num> Apply a 3x3 median filter to R-G and B-G\n"
+ "-s [0..N-1] Select one raw image from input file\n"
+ "-4 Linear 16-bit, same as \"-6 -W -g 1 1\n"
+ "-6 Write 16-bit output\n"
+ "-g pow ts Set gamma curve to gamma pow and toe slope ts (default = "
+ "2.222 4.5)\n"
+ "-T Write TIFF instead of PPM\n"
+ "-G Use green_matching() filter\n"
+ "-B <x y w h> use cropbox\n"
+ "-F Use FILE I/O instead of streambuf API\n"
+ "-Z <suf> Output filename generation rules\n"
+ " .suf => append .suf to input name, keeping existing suffix "
+ "too\n"
+ " suf => replace input filename last extension\n"
+ " - => output to stdout\n"
+ " filename.suf => output to filename.suf\n"
+ "-timing Detailed timing report\n"
+ "-fbdd N 0 - disable FBDD noise reduction (default), 1 - light "
+ "FBDD, 2 - full\n"
+ "-dcbi N Number of extra DCD iterations (default - 0)\n"
+ "-dcbe DCB color enhance\n"
+ "-aexpo <e p> exposure correction\n"
+ "-apentax4shot enables merge of 4-shot pentax files\n"
+ "-apentax4shotorder 3102 sets pentax 4-shot alignment order\n"
+#ifdef USE_RAWSPEED_BITS
+ "-arsbits V Set use_rawspeed to V\n"
#endif
-"-j Don't stretch or rotate raw pixels\n"
-"-W Don't automatically brighten the image\n"
-"-b <num> Adjust brightness (default = 1.0)\n"
-"-q [0-3] Set the interpolation quality\n"
-"-h Half-size color image (twice as fast as \"-q 0\")\n"
-"-f Interpolate RGGB as four colors\n"
-"-m <num> Apply a 3x3 median filter to R-G and B-G\n"
-"-s [0..N-1] Select one raw image from input file\n"
-"-4 Write 16-bit linear instead of 8-bit with gamma\n"
-"-g pow ts Set gamma curve to gamma pow and toe slope ts (default = 2.222 4.5)\n"
-"-T Write TIFF instead of PPM\n"
-#ifndef WIN32
-"-B Use mmap()-ed buffer instead of plain FILE I/O\n"
+ "-mmap Use memory mmaped buffer instead of plain FILE I/O\n"
+ "-mem Use memory buffer instead of FILE I/O\n"
+ "-disars Do not use RawSpeed library\n"
+ "-disinterp Do not run interpolation step\n"
+ "-dsrawrgb1 Disable YCbCr to RGB conversion for sRAW (Cb/Cr "
+ "interpolation enabled)\n"
+ "-dsrawrgb2 Disable YCbCr to RGB conversion for sRAW (Cb/Cr "
+ "interpolation disabled)\n"
+#ifdef USE_DNGSDK
+ "-dngsdk Use Adobe DNG SDK for DNG decode\n"
+ "-dngflags N set DNG decoding options to value N\n"
#endif
- );
- exit(1);
+ "-doutputflags N set params.output_flags to N\n"
+ );
+ exit(1);
}
-static int verbosity=0;
+static int verbosity = 0;
+int cnt = 0;
+int my_progress_callback(void *d, enum LibRaw_progress p, int iteration,
+ int expected)
+{
+ char *passed = (char *)(d ? d : "default string"); // data passed to callback
+ // at set_callback stage
+
+ if (verbosity > 2) // verbosity set by repeat -v switches
+ {
+ printf("CB: %s pass %d of %d (data passed=%s)\n", libraw_strprogress(p),
+ iteration, expected, passed);
+ }
+ else if (iteration == 0) // 1st iteration of each step
+ printf("Starting %s (expecting %d iterations)\n", libraw_strprogress(p),
+ expected);
+ else if (iteration == expected - 1)
+ printf("%s finished\n", libraw_strprogress(p));
+
+ /// if(++cnt>10) return 1; // emulate user termination on 10-th callback
+ /// call
-int cnt=0;
-int my_progress_callback(void *d,enum LibRaw_progress p,int iteration, int expected)
+ return 0; // always return 0 to continue processing
+}
+
+// timer
+#ifndef LIBRAW_WIN32_CALLS
+static struct timeval start, end;
+void timerstart(void) { gettimeofday(&start, NULL); }
+void timerprint(const char *msg, const char *filename)
+{
+ gettimeofday(&end, NULL);
+ float msec = (end.tv_sec - start.tv_sec) * 1000.0f +
+ (end.tv_usec - start.tv_usec) / 1000.0f;
+ printf("Timing: %s/%s: %6.3f msec\n", filename, msg, msec);
+}
+#else
+LARGE_INTEGER start;
+void timerstart(void) { QueryPerformanceCounter(&start); }
+void timerprint(const char *msg, const char *filename)
{
- char *passed = (char*)(d?d:"default string"); // data passed to callback at set_callback stage
+ LARGE_INTEGER unit, end;
+ QueryPerformanceCounter(&end);
+ QueryPerformanceFrequency(&unit);
+ float msec = (float)(end.QuadPart - start.QuadPart);
+ msec /= (float)unit.QuadPart / 1000.0f;
+ printf("Timing: %s/%s: %6.3f msec\n", filename, msg, msec);
+}
- if(verbosity>2) // verbosity set by repeat -v switches
- {
- printf("CB: %s pass %d of %d (data passed=%s)\n",libraw_strprogress(p),iteration,expected,passed);
- }
- else if (iteration == 0) // 1st iteration of each step
- printf("Starting %s (expecting %d iterations)\n", libraw_strprogress(p),expected);
- else if (iteration == expected-1)
- printf("%s finished\n",libraw_strprogress(p));
+#endif
+
+struct file_mapping
+{
+ void *map;
+ INT64 fsize;
+#ifdef LIBRAW_WIN32_CALLS
+ HANDLE fd, fd_map;
+ file_mapping() : map(0), fsize(0), fd(INVALID_HANDLE_VALUE), fd_map(INVALID_HANDLE_VALUE){}
+#else
+ int fd;
+ file_mapping() : map(0), fsize(0), fd(-1){}
+#endif
+};
-/// if(++cnt>10) return 1; // emulate user termination on 10-th callback call
+void create_mapping(struct file_mapping& data, const std::string& fn)
+{
+#ifdef LIBRAW_WIN32_CALLS
+ std::wstring fpath(fn.begin(), fn.end());
+ if ((data.fd = CreateFileW(fpath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) return;
+ LARGE_INTEGER fs;
+ if (!GetFileSizeEx(data.fd, &fs)) return;
+ data.fsize = fs.QuadPart;
+ if ((data.fd_map = ::CreateFileMapping(data.fd, 0, PAGE_READONLY, fs.HighPart, fs.LowPart, 0)) == INVALID_HANDLE_VALUE) return;
+ data.map = MapViewOfFile(data.fd_map, FILE_MAP_READ, 0, 0, data.fsize);
+#else
+ struct stat stt;
+ if ((data.fd = open(fn.c_str(), O_RDONLY)) < 0) return;
+ if (fstat(data.fd, &stt) != 0) return;
+ data.fsize = stt.st_size;
+ data.map = mmap(0, data.fsize, PROT_READ | PROT_WRITE, MAP_PRIVATE, data.fd, 0);
+ return;
+#endif
+}
- return 0; // always return 0 to continue processing
+void close_mapping(struct file_mapping& data)
+{
+#ifdef LIBRAW_WIN32_CALLS
+ if (data.map) UnmapViewOfFile(data.map);
+ if (data.fd_map != INVALID_HANDLE_VALUE) CloseHandle(data.fd_map);
+ if (data.fd != INVALID_HANDLE_VALUE) CloseHandle(data.fd);
+ data.map = 0;
+ data.fsize = 0;
+ data.fd = data.fd_map = INVALID_HANDLE_VALUE;
+#else
+ if (data.map)
+ munmap(data.map, data.fsize);
+ if (data.fd >= 0)
+ close(data.fd);
+ data.map = 0;
+ data.fsize = 0;
+ data.fd = -1;
+#endif
}
int main(int argc, char *argv[])
{
- if(argc==1) usage(argv[0]);
-
- LibRaw RawProcessor;
- int i,arg,c,ret;
- char opm,opt,*cp,*sp;
- int use_mmap=0, msize;
- void *iobuffer;
+ if (argc == 1)
+ usage(argv[0]);
+ LibRaw RawProcessor;
+ int i, arg, c, ret;
+ char opm, opt, *cp, *sp;
+ int use_timing = 0, use_mem = 0, use_mmap = 0;
+ char *outext = NULL;
+#ifdef USE_DNGSDK
+ dng_host *dnghost = NULL;
+#endif
+ struct file_mapping mapping;
+ void *iobuffer = 0;
+#ifdef OUT
+#undef OUT
+#endif
#define OUT RawProcessor.imgdata.params
-
- argv[argc] = "";
- for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; )
+#define OUTR RawProcessor.imgdata.rawparams
+
+ argv[argc] = (char *)"";
+ for (arg = 1; (((opm = argv[arg][0]) - 2) | 2) == '+';)
+ {
+ char *optstr = argv[arg];
+ opt = argv[arg++][1];
+ if ((cp = strchr(sp = (char *)"cnbrkStqmHABCgU", opt)) != 0)
+ for (i = 0; i < "111411111144221"[cp - sp] - '0'; i++)
+ if (!isdigit(argv[arg + i][0]) && !optstr[2])
+ {
+ fprintf(stderr, "Non-numeric argument to \"-%c\"\n", opt);
+ return 1;
+ }
+ if (!strchr("ftdeam", opt) && argv[arg - 1][2]) {
+ fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
+ continue;
+ }
+ switch (opt)
+ {
+ case 'v':
+ verbosity++;
+ break;
+ case 'G':
+ OUT.green_matching = 1;
+ break;
+ case 'c':
+ OUT.adjust_maximum_thr = (float)atof(argv[arg++]);
+ break;
+ case 'U':
+ OUT.auto_bright_thr = (float)atof(argv[arg++]);
+ break;
+ case 'n':
+ OUT.threshold = (float)atof(argv[arg++]);
+ break;
+ case 'b':
+ OUT.bright = (float)atof(argv[arg++]);
+ break;
+ case 'P':
+ OUT.bad_pixels = argv[arg++];
+ break;
+ case 'K':
+ OUT.dark_frame = argv[arg++];
+ break;
+ case 'r':
+ for (c = 0; c < 4; c++)
+ OUT.user_mul[c] = (float)atof(argv[arg++]);
+ break;
+ case 'C':
+ OUT.aber[0] = 1 / atof(argv[arg++]);
+ OUT.aber[2] = 1 / atof(argv[arg++]);
+ break;
+ case 'g':
+ OUT.gamm[0] = 1 / atof(argv[arg++]);
+ OUT.gamm[1] = atof(argv[arg++]);
+ break;
+ case 'k':
+ OUT.user_black = atoi(argv[arg++]);
+ break;
+ case 'S':
+ OUT.user_sat = atoi(argv[arg++]);
+ break;
+ case 'R':
+ OUTR.options = atoi(argv[arg++]);
+ break;
+ case 't':
+ if (!strcmp(optstr, "-timing"))
+ use_timing = 1;
+ else if (!argv[arg - 1][2])
+ OUT.user_flip = atoi(argv[arg++]);
+ else
+ fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
+ break;
+ case 'q':
+ OUT.user_qual = atoi(argv[arg++]);
+ break;
+ case 'm':
+ if (!strcmp(optstr, "-mmap"))
+ use_mmap = 1;
+ else
+ if (!strcmp(optstr, "-mem"))
+ use_mem = 1;
+ else
{
- opt = argv[arg++][1];
- if ((cp = strchr (sp="nbrkStqmHACgU", opt)))
- for (i=0; i < "11411111142"[cp-sp]-'0'; i++)
- if (!isdigit(argv[arg+i][0]))
- {
- fprintf (stderr,"Non-numeric argument to \"-%c\"\n", opt);
- return 1;
- }
- switch (opt)
- {
- case 'v': verbosity++; break;
-
- case 'U': OUT.auto_bright_thr = atof(argv[arg++]); break;
- case 'n': OUT.threshold = atof(argv[arg++]); break;
- case 'b': OUT.bright = atof(argv[arg++]); break;
- case 'P': OUT.bad_pixels = argv[arg++]; break;
- case 'K': OUT.dark_frame = argv[arg++]; break;
- case 'r':
- for(c=0;c<4;c++)
- OUT.user_mul[c] = atof(argv[arg++]);
- break;
- case 'C':
- OUT.aber[0] = 1 / atof(argv[arg++]);
- OUT.aber[2] = 1 / atof(argv[arg++]);
- break;
- case 'g':
- OUT.gamm[0] = 1 / atof(argv[arg++]);
- OUT.gamm[1] = atof(argv[arg++]);
- break;
- case 'k': OUT.user_black = atoi(argv[arg++]); break;
- case 'S': OUT.user_sat = atoi(argv[arg++]); break;
- case 't': OUT.user_flip = atoi(argv[arg++]); break;
- case 'q': OUT.user_qual = atoi(argv[arg++]); break;
- case 'm': OUT.med_passes = atoi(argv[arg++]); break;
- case 'H': OUT.highlight = atoi(argv[arg++]); break;
- case 's': OUT.shot_select = abs(atoi(argv[arg++])); break;
- case 'o':
- if(isdigit(argv[arg+1][0]) && !isdigit(argv[arg+1][1]))
- OUT.output_color = atoi(argv[arg++]);
+ if (!argv[arg - 1][2])
+ OUT.med_passes = atoi(argv[arg++]);
+ else
+ fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
+ }
+ break;
+ case 'H':
+ OUT.highlight = atoi(argv[arg++]);
+ break;
+ case 's':
+ OUTR.shot_select = abs(atoi(argv[arg++]));
+ break;
+ case 'o':
+ if (isdigit(argv[arg][0]) && !isdigit(argv[arg][1]))
+ OUT.output_color = atoi(argv[arg++]);
#ifndef NO_LCMS
- else
- OUT.output_profile = argv[arg++];
- break;
- case 'p': OUT.camera_profile = argv[arg++];
+ else
+ OUT.output_profile = argv[arg++];
+ break;
+ case 'p':
+ OUT.camera_profile = argv[arg++];
#endif
- break;
- case 'h': OUT.half_size = 1;
- // no break: "-h" implies "-f"
- case 'f':
- OUT.four_color_rgb = 1;
- break;
- case 'A': for(c=0; c<4;c++) OUT.greybox[c] = atoi(argv[arg++]);
- case 'a': OUT.use_auto_wb = 1; break;
- case 'w': OUT.use_camera_wb = 1; break;
- case 'M': OUT.use_camera_matrix = (opm == '+'); break;
- case 'j': OUT.use_fuji_rotate = 0; break;
- case 'W': OUT.no_auto_bright = 1; break;
- case 'T': OUT.output_tiff = 1; break;
- case '4': OUT.output_bps = 16; break;
- case '1': OUT.gamma_16bit = 1; break;
-#ifndef WIN32
- case 'B': use_mmap = 1; break;
+ break;
+ case 'h':
+ OUT.half_size = 1;
+ break;
+ case 'f':
+ if (!strcmp(optstr, "-fbdd"))
+ OUT.fbdd_noiserd = atoi(argv[arg++]);
+ else
+ {
+ if (!argv[arg - 1][2])
+ OUT.four_color_rgb = 1;
+ else
+ fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
+ }
+ break;
+ case 'A':
+ for (c = 0; c < 4; c++)
+ OUT.greybox[c] = atoi(argv[arg++]);
+ break;
+ case 'B':
+ for (c = 0; c < 4; c++)
+ OUT.cropbox[c] = atoi(argv[arg++]);
+ break;
+ case 'a':
+ if (!strcmp(optstr, "-aexpo"))
+ {
+ OUT.exp_correc = 1;
+ OUT.exp_shift = (float)atof(argv[arg++]);
+ OUT.exp_preser = (float)atof(argv[arg++]);
+ }
+#ifdef USE_RAWSPEED_BITS
+ else if (!strcmp(optstr, "-arsbits"))
+ {
+ OUTR.use_rawspeed = atoi(argv[arg++]);
+ }
#endif
- default:
- fprintf (stderr,"Unknown option \"-%c\".\n", opt);
- return 1;
- }
+ else if (!strcmp(optstr, "-apentax4shot"))
+ {
+ OUTR.options |= LIBRAW_RAWOPTIONS_PENTAX_PS_ALLFRAMES;
+ }
+ else if (!strcmp(optstr, "-apentax4shotorder"))
+ {
+ strncpy(OUTR.p4shot_order, argv[arg++], 5);
+ }
+ else if (!argv[arg - 1][2])
+ OUT.use_auto_wb = 1;
+ else
+ fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
+ break;
+ case 'w':
+ OUT.use_camera_wb = 1;
+ break;
+ case 'M':
+ OUT.use_camera_matrix = (opm == '+')?3:0;
+ break;
+ case 'j':
+ OUT.use_fuji_rotate = 0;
+ break;
+ case 'W':
+ OUT.no_auto_bright = 1;
+ break;
+ case 'T':
+ OUT.output_tiff = 1;
+ break;
+ case '4':
+ OUT.gamm[0] = OUT.gamm[1] = OUT.no_auto_bright = 1; /* no break here! */
+ case '6':
+ OUT.output_bps = 16;
+ break;
+ case 'Z':
+ outext = strdup(argv[arg++]);
+ break;
+ case 'd':
+ if (!strcmp(optstr, "-dcbi"))
+ OUT.dcb_iterations = atoi(argv[arg++]);
+ else if (!strcmp(optstr, "-doutputflags"))
+ OUT.output_flags = atoi(argv[arg++]);
+ else if (!strcmp(optstr, "-disars"))
+ OUTR.use_rawspeed = 0;
+ else if (!strcmp(optstr, "-disinterp"))
+ OUT.no_interpolation = 1;
+ else if (!strcmp(optstr, "-dcbe"))
+ OUT.dcb_enhance_fl = 1;
+ else if (!strcmp(optstr, "-dsrawrgb1"))
+ {
+ OUTR.specials |= LIBRAW_RAWSPECIAL_SRAW_NO_RGB;
+ OUTR.specials &= ~LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE;
+ }
+ else if (!strcmp(optstr, "-dsrawrgb2"))
+ {
+ OUTR.specials &= ~LIBRAW_RAWSPECIAL_SRAW_NO_RGB;
+ OUTR.specials |= LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE;
+ }
+#ifdef USE_DNGSDK
+ else if (!strcmp(optstr, "-dngsdk"))
+ {
+ dnghost = new dng_host;
+ RawProcessor.set_dng_host(dnghost);
+ }
+ else if (!strcmp(optstr, "-dngflags"))
+ {
+ OUTR.use_dngsdk = atoi(argv[arg++]);
}
- putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
- OUT.filtering_mode = LIBRAW_FILTERING_AUTOMATIC;
+#endif
+ else
+ fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
+ break;
+ default:
+ fprintf(stderr, "Unknown option \"-%c\".\n", opt);
+ break;
+ }
+ }
+#ifndef LIBRAW_WIN32_CALLS
+ putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
+#else
+ _putenv(
+ (char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
+#endif
#define P1 RawProcessor.imgdata.idata
#define S RawProcessor.imgdata.sizes
#define C RawProcessor.imgdata.color
#define T RawProcessor.imgdata.thumbnail
#define P2 RawProcessor.imgdata.other
- if(verbosity>1)
- RawProcessor.set_progress_handler(my_progress_callback,(void*)"Sample data passed");
-#ifdef _OPENMP
- if(verbosity)
- printf ("Using %d threads\n", omp_get_max_threads());
+ if (outext && !strcmp(outext, "-"))
+ use_timing = verbosity = 0;
+
+ if (verbosity > 1)
+ RawProcessor.set_progress_handler(my_progress_callback,
+ (void *)"Sample data passed");
+#ifdef LIBRAW_USE_OPENMP
+ if (verbosity)
+ printf("Using %d threads\n", omp_get_max_threads());
#endif
- for ( ; arg < argc; arg++)
+ int done = 0;
+ int total = argc - arg;
+ for (; arg < argc; arg++)
+ {
+ char outfn[1024];
+
+ if (verbosity)
+ printf("Processing file %s\n", argv[arg]);
+
+ timerstart();
+
+ if (use_mmap)
+ {
+ create_mapping(mapping, argv[arg]);
+ if (!mapping.map)
+ {
+ fprintf(stderr, "Cannot map %s\n", argv[arg]);
+ close_mapping(mapping);
+ continue;
+ }
+ if ((ret = RawProcessor.open_buffer(mapping.map,mapping.fsize) !=
+ LIBRAW_SUCCESS))
+ {
+ fprintf(stderr, "Cannot open_buffer %s: %s\n", argv[arg], libraw_strerror(ret));
+ close_mapping(mapping);
+ continue; // no recycle b/c open file will recycle itself
+ }
+ }
+ else if (use_mem)
+ {
+ int file = open(argv[arg], O_RDONLY | O_BINARY);
+ struct stat st;
+ if (file < 0)
+ {
+ fprintf(stderr, "Cannot open %s: %s\n", argv[arg], strerror(errno));
+ continue;
+ }
+ if (fstat(file, &st))
+ {
+ fprintf(stderr, "Cannot stat %s: %s\n", argv[arg], strerror(errno));
+ close(file);
+ continue;
+ }
+ if (!(iobuffer = malloc(st.st_size)))
+ {
+ fprintf(stderr, "Cannot allocate %d kbytes for memory buffer\n",
+ (int)(st.st_size / 1024));
+ close(file);
+ continue;
+ }
+ int rd;
+ if (st.st_size != (rd = read(file, iobuffer, st.st_size)))
+ {
+ fprintf(stderr,
+ "Cannot read %d bytes instead of %d to memory buffer\n",
+ (int)rd, (int)st.st_size);
+ close(file);
+ free(iobuffer);
+ continue;
+ }
+ close(file);
+ if ((ret = RawProcessor.open_buffer(iobuffer, st.st_size)) !=
+ LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot open_buffer %s: %s\n", argv[arg],
+ libraw_strerror(ret));
+ free(iobuffer);
+ continue; // no recycle b/c open file will recycle itself
+ }
+ }
+ else
+ {
+ ret = RawProcessor.open_file(argv[arg]);
+
+ if (ret != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot open %s: %s\n", argv[arg],
+ libraw_strerror(ret));
+ continue; // no recycle b/c open_file will recycle itself
+ }
+ }
+
+ if (use_timing)
+ timerprint("LibRaw::open_file()", argv[arg]);
+
+ timerstart();
+ if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack %s: %s\n", argv[arg],
+ libraw_strerror(ret));
+ continue;
+ }
+
+ if (use_timing)
+ timerprint("LibRaw::unpack()", argv[arg]);
+
+ timerstart();
+ if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_process()))
+ {
+ fprintf(stderr, "Cannot do postprocessing on %s: %s\n", argv[arg],
+ libraw_strerror(ret));
+ if (LIBRAW_FATAL_ERROR(ret))
+ continue;
+ }
+ if (use_timing)
+ timerprint("LibRaw::dcraw_process()", argv[arg]);
+
+ if (!outext)
+ snprintf(outfn, sizeof(outfn), "%s.%s", argv[arg],
+ OUT.output_tiff ? "tiff" : (P1.colors > 1 ? "ppm" : "pgm"));
+ else if (!strcmp(outext, "-"))
+ snprintf(outfn, sizeof(outfn), "-");
+ else
+ {
+ if (*outext == '.') // append
+ snprintf(outfn, sizeof(outfn), "%s%s", argv[arg], outext);
+ else if (strchr(outext, '.') && *outext != '.') // dot is not 1st char
+ strncpy(outfn, outext, sizeof(outfn));
+ else
+ {
+ strncpy(outfn, argv[arg], sizeof(outfn));
+ if (strlen(outfn) > 0)
{
- char outfn[1024];
-
- if(verbosity) printf("Processing file %s\n",argv[arg]);
-#ifndef WIN32
- if(use_mmap)
- {
- int file = open(argv[arg],O_RDONLY);
- struct stat st;
- if(file<0)
- {
- fprintf(stderr,"Cannot open %s: %s\n",argv[arg],strerror(errno));
- continue;
- }
- if(fstat(file,&st))
- {
- fprintf(stderr,"Cannot stat %s: %s\n",argv[arg],strerror(errno));
- close(file);
- continue;
- }
- int pgsz = getpagesize();
- msize = ((st.st_size+pgsz-1)/pgsz)*pgsz;
- iobuffer = mmap(NULL,msize,PROT_READ,MAP_PRIVATE,file,0);
- if(!iobuffer)
- {
- fprintf(stderr,"Cannot mmap %s: %s\n",argv[arg],strerror(errno));
- close(file);
- continue;
- }
- close(file);
- if( (ret = RawProcessor.open_buffer(iobuffer,st.st_size) != LIBRAW_SUCCESS))
- {
- fprintf(stderr,"Cannot open_buffer %s: %s\n",argv[arg],libraw_strerror(ret));
- continue; // no recycle b/c open file will recycle itself
- }
-
- }
- else
-#endif
- {
- if( (ret = RawProcessor.open_file(argv[arg])) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot open %s: %s\n",argv[arg],libraw_strerror(ret));
- continue; // no recycle b/c open_file will recycle itself
- }
- }
- if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot unpack %s: %s\n",argv[arg],libraw_strerror(ret));
- continue;
- }
- if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_process()))
- {
- fprintf(stderr,"Cannot do postpocessing on %s: %s\n",argv[arg],libraw_strerror(ret));
- if(LIBRAW_FATAL_ERROR(ret))
- continue;
- }
- snprintf(outfn,sizeof(outfn),
- "%s.%s",
- argv[arg], OUT.output_tiff ? "tiff" : (P1.colors>1?"ppm":"pgm"));
-
- if(verbosity) printf("Writing file %s\n",outfn);
-
- if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
- fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret));
-
-#ifndef WIN32
- if(use_mmap && iobuffer)
- {
- munmap(iobuffer,msize);
- iobuffer=0;
- }
-#endif
-
- RawProcessor.recycle(); // just for show this call
+ char *lastchar = outfn + strlen(outfn); // points to term 0
+ while (--lastchar > outfn)
+ {
+ if (*lastchar == '/' || *lastchar == '\\')
+ break;
+ if (*lastchar == '.')
+ {
+ *lastchar = 0;
+ break;
+ };
+ }
}
- return 0;
+ strncat(outfn, ".", sizeof(outfn) - strlen(outfn) - 1);
+ strncat(outfn, outext, sizeof(outfn) - strlen(outfn) - 1);
+ }
+ }
+
+ if (verbosity)
+ {
+ printf("Writing file %s\n", outfn);
+ }
+
+ if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
+ fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret));
+ else
+ done++;
+
+ RawProcessor.recycle(); // just for show this call
+
+ if (use_mmap && mapping.map)
+ close_mapping(mapping);
+ else if (use_mem && iobuffer)
+ {
+ free(iobuffer);
+ iobuffer = 0;
+ }
+ }
+#ifdef USE_DNGSDK
+ if (dnghost)
+ delete dnghost;
+#endif
+ if (total == 0)
+ return 1;
+ if (done < total)
+ return 2;
+ return 0;
}
diff --git a/libkdcraw/libraw/samples/dcraw_half.c b/libkdcraw/libraw/samples/dcraw_half.c
index 6b56e21..5fe56a5 100644
--- a/libkdcraw/libraw/samples/dcraw_half.c
+++ b/libkdcraw/libraw/samples/dcraw_half.c
@@ -1,24 +1,20 @@
-/*
+/* -*- C++ -*-
* File: dcraw_half.c
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
* Created: Sat Mar 8 , 2008
*
- * LibRaw C API sample (emulates call to "dcraw -h")
+ * LibRaw C API sample: emulates "dcraw -h"
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+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 <stdio.h>
#include <string.h>
@@ -27,57 +23,56 @@
#include "libraw/libraw.h"
+#define HANDLE_FATAL_ERROR(ret) \
+ if (ret) \
+ { \
+ fprintf(stderr, "%s: libraw %s\n", av[i], libraw_strerror(ret)); \
+ if (LIBRAW_FATAL_ERROR(ret)) \
+ exit(1); \
+ }
-#define HANDLE_FATAL_ERROR(ret)\
- if(ret)\
- {\
- fprintf(stderr,"%s: libraw %s\n",av[i],libraw_strerror(ret));\
- if(LIBRAW_FATAL_ERROR(ret))\
- exit(1); \
- }\
-
-#define HANDLE_ALL_ERRORS(ret)\
- if(ret)\
- {\
- fprintf(stderr,"%s: libraw %s\n",av[i],libraw_strerror(ret));\
- continue; \
- }\
-
+#define HANDLE_ALL_ERRORS(ret) \
+ if (ret) \
+ { \
+ fprintf(stderr, "%s: libraw %s\n", av[i], libraw_strerror(ret)); \
+ continue; \
+ }
int main(int ac, char *av[])
{
- int i;
- libraw_data_t *iprc = libraw_init(0);
-
- if(!iprc)
- {
- fprintf(stderr,"Cannot create libraw handle\n");
- exit(1);
- }
-
- iprc->params.half_size = 1; /* dcraw -h */
-
- for (i=1;i<ac;i++)
- {
- char outfn[1024];
- int ret = libraw_open_file(iprc,av[i]);
- HANDLE_ALL_ERRORS(ret);
-
- printf("Processing %s (%s %s)\n",av[i],iprc->idata.make,iprc->idata.model);
-
- ret = libraw_unpack(iprc);
- HANDLE_ALL_ERRORS(ret);
-
- ret = libraw_dcraw_process(iprc);
- HANDLE_ALL_ERRORS(ret);
-
- strcpy(outfn,av[i]);
- strcat(outfn,".ppm");
- printf("Writing to %s\n",outfn);
-
- ret = libraw_dcraw_ppm_tiff_writer(iprc,outfn);
- HANDLE_FATAL_ERROR(ret);
- }
- libraw_close(iprc);
- return 0;
+ int i;
+ libraw_data_t *iprc = libraw_init(0);
+
+ if (!iprc)
+ {
+ fprintf(stderr, "Cannot create libraw handle\n");
+ exit(1);
+ }
+
+ iprc->params.half_size = 1; /* dcraw -h */
+
+ for (i = 1; i < ac; i++)
+ {
+ char outfn[1024];
+ int ret = libraw_open_file(iprc, av[i]);
+ HANDLE_ALL_ERRORS(ret);
+
+ printf("Processing %s (%s %s)\n", av[i], iprc->idata.make,
+ iprc->idata.model);
+
+ ret = libraw_unpack(iprc);
+ HANDLE_ALL_ERRORS(ret);
+
+ ret = libraw_dcraw_process(iprc);
+ HANDLE_ALL_ERRORS(ret);
+
+ strcpy(outfn, av[i]);
+ strcat(outfn, ".ppm");
+ printf("Writing to %s\n", outfn);
+
+ ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn);
+ HANDLE_FATAL_ERROR(ret);
+ }
+ libraw_close(iprc);
+ return 0;
}
diff --git a/libkdcraw/libraw/samples/half_mt.c b/libkdcraw/libraw/samples/half_mt.c
index 8f91b8f..f46c83e 100644
--- a/libkdcraw/libraw/samples/half_mt.c
+++ b/libkdcraw/libraw/samples/half_mt.c
@@ -1,24 +1,22 @@
-/*
+/* -*- C++ -*-
* File: halt_mt.c
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
- * Created: Sat Mar 8 , 2008
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Sat Mar 8, 2008
*
- * LibRaw C API mutithreaded sample (emulates call to "dcraw -h [-w] [-a] [-v]")
+ * LibRaw C API mutithreaded sample: emulates call to "dcraw -h [-w] [-a]
+[-v]"
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+
+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 <stdio.h>
#include <string.h>
@@ -28,151 +26,153 @@
#include "libraw/libraw.h"
-#define HANDLE_ERRORS(ret) do { \
- if(ret) \
- { \
- fprintf(stderr,"%s: %s\n",fn,libraw_strerror(ret)); \
- if(LIBRAW_FATAL_ERROR(ret)) \
- { \
- libraw_close(iprc); \
- return -1; \
- } \
- } \
- }while(0)
-
-
-// global settings
-int verbose=0,use_camera_wb=0,use_auto_wb=0,tiff_mode=0;
+#define HANDLE_ERRORS(ret) \
+ do \
+ { \
+ if (ret) \
+ { \
+ fprintf(stderr, "%s: %s\n", fn, libraw_strerror(ret)); \
+ if (LIBRAW_FATAL_ERROR(ret)) \
+ { \
+ libraw_close(iprc); \
+ return NULL; \
+ } \
+ } \
+ } while (0)
+
+int verbose = 0, use_camera_wb = 0, use_auto_wb = 0, tiff_mode = 0;
-// global file queue
pthread_mutex_t qm;
-char **queue=NULL;
-size_t qsize=0,qptr=0;
+char **queue = NULL;
+size_t qsize = 0, qptr = 0;
char *get_next_file()
{
- char *ret;
- if(!queue) return NULL;
- if(qptr>=qsize) return NULL;
- pthread_mutex_lock(&qm);
- ret = queue[qptr++];
- pthread_mutex_unlock(&qm);
- return ret;
+ char *ret;
+ if (!queue)
+ return NULL;
+ if (qptr >= qsize)
+ return NULL;
+ pthread_mutex_lock(&qm);
+ ret = queue[qptr++];
+ pthread_mutex_unlock(&qm);
+ return ret;
}
-
-// thread routine
-int process_files(void *q)
+void *process_files(void *q)
{
- int ret;
- int count=0;
- char outfn[1024], *fn;
- libraw_data_t *iprc = libraw_init(0);
-
- if(!iprc)
- {
- fprintf(stderr,"Cannot create libraw handle\n");
- return -1;
- }
-
- while((fn = get_next_file()))
- {
-
- iprc->params.half_size = 1; /* dcraw -h */
- iprc->params.use_camera_wb = use_camera_wb;
- iprc->params.use_auto_wb = use_auto_wb;
- iprc->params.output_tiff = tiff_mode;
-
- ret = libraw_open_file(iprc,fn);
- if(verbose) fprintf(stderr,"%s: %s/%s\n",fn,iprc->idata.make,iprc->idata.model);
- HANDLE_ERRORS(ret);
-
- ret = libraw_unpack(iprc);
- HANDLE_ERRORS(ret);
-
- ret = libraw_dcraw_process(iprc);
- HANDLE_ERRORS(ret);
-
- snprintf(outfn,1023,"%s.ppm",fn);
-
- if(verbose) fprintf(stderr,"Writing file %s\n",outfn);
- ret = libraw_dcraw_ppm_tiff_writer(iprc,outfn);
- HANDLE_ERRORS(ret);
- count++;
- }
- libraw_close(iprc);
- return count;
+ int ret;
+ int count = 0;
+ char outfn[1024], *fn;
+ libraw_data_t *iprc = libraw_init(0);
+
+ if (!iprc)
+ {
+ fprintf(stderr, "Cannot create libraw handle\n");
+ return NULL;
+ }
+
+ while ((fn = get_next_file()))
+ {
+
+ iprc->params.half_size = 1; /* dcraw -h */
+ iprc->params.use_camera_wb = use_camera_wb;
+ iprc->params.use_auto_wb = use_auto_wb;
+ iprc->params.output_tiff = tiff_mode;
+
+ ret = libraw_open_file(iprc, fn);
+ if (verbose)
+ fprintf(stderr, "%s: %s/%s\n", fn, iprc->idata.make, iprc->idata.model);
+ HANDLE_ERRORS(ret);
+
+ ret = libraw_unpack(iprc);
+ HANDLE_ERRORS(ret);
+
+ ret = libraw_dcraw_process(iprc);
+ HANDLE_ERRORS(ret);
+
+ snprintf(outfn, 1023, "%s.%s", fn, tiff_mode ? "tiff" : "ppm");
+
+ if (verbose)
+ fprintf(stderr, "Writing file %s\n", outfn);
+ ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn);
+ HANDLE_ERRORS(ret);
+ count++;
+ }
+ libraw_close(iprc);
+ return NULL;
}
-void usage(const char*p)
+void usage(const char *p)
{
- printf("%s: Multi-threaded LibRaw sample app. Emulates dcraw -h [-w] [-a]\n",p);
- printf(
- "Options:\n"
- "-J n - set parrallel job coun (default 2)\n"
- "-v - verbose\n"
- "-w - use camera white balance\n"
- "-a - average image for white balance\n");
- exit(1);
+ printf("%s: Multi-threaded LibRaw sample app. Emulates dcraw -h [-w] [-a]\n",
+ p);
+ printf("Options:\n"
+ "-J n - set parallel job count (default 2)\n"
+ "-v - verbose\n"
+ "-w - use camera white balance\n"
+ "-a - average image for white balance\n");
+ exit(1);
}
int show_files(void *q)
{
- char *p;
- int cnt = 0;
- while(p = get_next_file())
- {
- printf("%s\n",p);
- cnt++;
- }
- return cnt;
-
+ char *p;
+ int cnt = 0;
+ while ((p = get_next_file()))
+ {
+ printf("%s\n", p);
+ cnt++;
+ }
+ return cnt;
}
int main(int ac, char *av[])
{
- int i, thread_count,max_threads = 2;
- pthread_t *threads;
- if(ac<2)
- usage(av[0]);
-
- queue = calloc(ac-1,sizeof(queue[0]));
-
- for (i=1;i<ac;i++)
- {
- if(av[i][0]=='-')
- {
- if(av[i][1]=='w') use_camera_wb = 1;
- if(av[i][1]=='a') use_auto_wb = 1;
- if(av[i][1]=='v') verbose = 1;
- if(av[i][1]=='T') tiff_mode = 1;
- if(av[i][1]=='J')
- {
- max_threads=atoi(av[++i]);
- if(max_threads<1)
- {
- fprintf(stderr,"Job count should be at least 1\n");
- exit(1);
- }
- }
- }
- else
- queue[qsize++] = av[i];
- }
- pthread_mutex_init(&qm,NULL);
- threads = calloc(max_threads,sizeof(threads[0]));
- for(i=0;i<max_threads;i++)
- pthread_create(&threads[i],NULL,process_files,NULL);
- for(i=0;i<max_threads;i++)
+ int i, max_threads = 2;
+ pthread_t *threads;
+ if (ac < 2)
+ usage(av[0]);
+
+ queue = calloc(ac - 1, sizeof(queue[0]));
+
+ for (i = 1; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ if (av[i][1] == 'w')
+ use_camera_wb = 1;
+ if (av[i][1] == 'a')
+ use_auto_wb = 1;
+ if (av[i][1] == 'v')
+ verbose = 1;
+ if (av[i][1] == 'T')
+ tiff_mode = 1;
+ if (av[i][1] == 'J')
+ {
+ max_threads = atoi(av[++i]);
+ if (max_threads < 1)
{
- int *iptr;
- if(threads[i])
- {
- pthread_join(threads[i],&iptr);
- if(iptr)
- printf("Thread %d : %d files\n",i,(int)iptr);
- }
+ fprintf(stderr, "Job count should be at least 1\n");
+ exit(1);
}
-
- return 0;
+ }
+ }
+ else
+ queue[qsize++] = av[i];
+ }
+ pthread_mutex_init(&qm, NULL);
+ threads = calloc(max_threads, sizeof(threads[0]));
+ for (i = 0; i < max_threads; i++)
+ pthread_create(&threads[i], NULL, process_files, NULL);
+ for (i = 0; i < max_threads; i++)
+ {
+ int *iptr;
+ if (threads[i])
+ {
+ pthread_join(threads[i], (void *)&iptr);
+ }
+ }
+
+ return 0;
}
diff --git a/libkdcraw/libraw/samples/half_mt_win32.c b/libkdcraw/libraw/samples/half_mt_win32.c
index a741e55..b8d3943 100644
--- a/libkdcraw/libraw/samples/half_mt_win32.c
+++ b/libkdcraw/libraw/samples/half_mt_win32.c
@@ -1,25 +1,22 @@
-/*
+/* -*- C++ -*-
* File: halt_mt_win32.c
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
- * Created: Sat Mar 8 , 2008
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Sat Mar 8, 2008
*
- * LibRaw C API mutithreaded sample (emulates call to "dcraw -h [-w] [-a] [-v]")
+ * LibRaw C API mutithreaded sample: emulates call to "dcraw -h [-w] [-a]
+[-v]"
* Win32 version
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+
+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 <stdio.h>
#include <string.h>
@@ -28,185 +25,188 @@
#include <windows.h>
#include "libraw/libraw.h"
-#ifdef WIN32
+#ifdef LIBRAW_WIN32_CALLS
#define snprintf _snprintf
#endif
-
-#define HANDLE_ERRORS(ret) do { \
- if(ret) \
- { \
- fprintf(stderr,"%s: %s\n",fn,libraw_strerror(ret)); \
- if(LIBRAW_FATAL_ERROR(ret)) \
- { \
- libraw_close(iprc); \
- return -1; \
- } \
- } \
- }while(0)
-
+#define HANDLE_ERRORS(ret) \
+ do \
+ { \
+ if (ret) \
+ { \
+ fprintf(stderr, "%s: %s\n", fn, libraw_strerror(ret)); \
+ if (LIBRAW_FATAL_ERROR(ret)) \
+ { \
+ libraw_close(iprc); \
+ return -1; \
+ } \
+ } \
+ } while (0)
// global settings
-int verbose=0,use_camera_wb=0,use_auto_wb=0,tiff_mode=0;
+int verbose = 0, use_camera_wb = 0, use_auto_wb = 0, tiff_mode = 0;
// global file queue
HANDLE qmutex;
-char **queue=NULL;
-size_t qsize=0,qptr=0;
+char **queue = NULL;
+size_t qsize = 0, qptr = 0;
char *get_next_file()
{
- char *ret;
- DWORD dwWaitResult;
- if(!queue) return NULL;
- if(qptr>=qsize) return NULL;
-
- dwWaitResult = WaitForSingleObject(
- qmutex, // handle to mutex
- INFINITE); // no time-out interval
- switch (dwWaitResult)
- {
- // The thread got ownership of the mutex
- case WAIT_OBJECT_0:
- ret = queue[qptr++];
- ReleaseMutex(qmutex);
- break;
- case WAIT_ABANDONED:
- return NULL; // cannot obtain the lock
- };
- return ret;
+ char *ret;
+ DWORD dwWaitResult;
+ if (!queue)
+ return NULL;
+ if (qptr >= qsize)
+ return NULL;
+
+ dwWaitResult = WaitForSingleObject(qmutex, // handle to mutex
+ INFINITE); // no time-out interval
+ switch (dwWaitResult)
+ {
+ // The thread got ownership of the mutex
+ case WAIT_OBJECT_0:
+ ret = queue[qptr++];
+ ReleaseMutex(qmutex);
+ break;
+ case WAIT_ABANDONED:
+ return NULL; // cannot obtain the lock
+ };
+ return ret;
}
-
// thread routine
int process_files(void *q)
{
- int ret;
- int count=0;
- char outfn[1024], *fn;
- libraw_data_t *iprc = libraw_init(0);
-
- if(!iprc)
- {
- fprintf(stderr,"Cannot create libraw handle\n");
- return -1;
- }
-
- while((fn = get_next_file()))
- {
-
- iprc->params.half_size = 1; /* dcraw -h */
- iprc->params.use_camera_wb = use_camera_wb;
- iprc->params.use_auto_wb = use_auto_wb;
- iprc->params.output_tiff = tiff_mode;
-
- ret = libraw_open_file(iprc,fn);
- if(verbose) fprintf(stderr,"%s: %s/%s\n",fn,iprc->idata.make,iprc->idata.model);
- HANDLE_ERRORS(ret);
-
- ret = libraw_unpack(iprc);
- HANDLE_ERRORS(ret);
-
- ret = libraw_dcraw_process(iprc);
- HANDLE_ERRORS(ret);
-
- snprintf(outfn,1023,"%s.%s",fn,tiff_mode?"tif":"ppm");
-
- if(verbose) fprintf(stderr,"Writing file %s\n",outfn);
- ret = libraw_dcraw_ppm_tiff_writer(iprc,outfn);
- HANDLE_ERRORS(ret);
- count++;
- }
- libraw_close(iprc);
- printf("Processed %d files\n",count);
- return 0;
+ int ret;
+ int count = 0;
+ char outfn[1024], *fn;
+ libraw_data_t *iprc = libraw_init(0);
+
+ if (!iprc)
+ {
+ fprintf(stderr, "Cannot create libraw handle\n");
+ return -1;
+ }
+
+ while ((fn = get_next_file()))
+ {
+
+ iprc->params.half_size = 1; /* dcraw -h */
+ iprc->params.use_camera_wb = use_camera_wb;
+ iprc->params.use_auto_wb = use_auto_wb;
+ iprc->params.output_tiff = tiff_mode;
+
+ ret = libraw_open_file(iprc, fn);
+ if (verbose)
+ fprintf(stderr, "%s: %s/%s\n", fn, iprc->idata.make, iprc->idata.model);
+ HANDLE_ERRORS(ret);
+
+ ret = libraw_unpack(iprc);
+ HANDLE_ERRORS(ret);
+
+ ret = libraw_dcraw_process(iprc);
+ HANDLE_ERRORS(ret);
+
+ snprintf(outfn, 1023, "%s.%s", fn, tiff_mode ? "tif" : "ppm");
+
+ if (verbose)
+ fprintf(stderr, "Writing file %s\n", outfn);
+ ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn);
+ HANDLE_ERRORS(ret);
+ count++;
+ }
+ libraw_close(iprc);
+ printf("Processed %d files\n", count);
+ return 0;
}
-void usage(const char*p)
+void usage(const char *p)
{
- printf(
- "Options:\n"
- "-J n - set parrallel job coun (default 2)\n"
- "-v - verbose\n"
- "-w - use camera white balance\n"
- "-T - output TIFF instead of PPM\n"
- "-a - average image for white balance\n");
- exit(1);
+ printf("Options:\n"
+ "-J n - set parallel job count (default 2)\n"
+ "-v - verbose\n"
+ "-w - use camera white balance\n"
+ "-T - output TIFF instead of PPM\n"
+ "-a - average image for white balance\n");
+ exit(1);
}
int show_files(void *q)
{
- char *p;
- int cnt = 0;
- while(p = get_next_file())
- {
- printf("%s\n",p);
- cnt++;
- }
- return cnt;
-
+ char *p;
+ int cnt = 0;
+ while (p = get_next_file())
+ {
+ printf("%s\n", p);
+ cnt++;
+ }
+ return cnt;
}
int main(int ac, char *av[])
{
- int i,max_threads = 2;
- HANDLE *threads;
- DWORD ThreadID;
-
- if(ac<2)
- usage(av[0]);
-
- queue = calloc(ac-1,sizeof(queue[0]));
-
- for (i=1;i<ac;i++)
- {
- if(av[i][0]=='-')
- {
- if(av[i][1]=='w') use_camera_wb = 1;
- if(av[i][1]=='a') use_auto_wb = 1;
- if(av[i][1]=='v') verbose = 1;
- if(av[i][1]=='T') tiff_mode = 1;
- if(av[i][1]=='J')
- {
- max_threads=atoi(av[++i]);
- if(max_threads<1)
- {
- fprintf(stderr,"Job count should be at least 1\n");
- exit(1);
- }
- }
- }
- else
- queue[qsize++] = av[i];
- }
- qmutex = CreateMutex(NULL,FALSE,NULL);
- threads = calloc(max_threads,sizeof(threads[0]));
- for(i=0;i<max_threads;i++)
- {
-
- if (NULL == (threads[i] = CreateThread(
- NULL, // default security attributes
- 0, // default stack size
- (LPTHREAD_START_ROUTINE) process_files,
- NULL, // no thread function arguments
- 0, // default creation flags
- &ThreadID) // receive thread identifier
- )
- )
+ int i, max_threads = 2;
+ HANDLE *threads;
+ DWORD ThreadID;
+
+ if (ac < 2)
+ usage(av[0]);
+
+ queue = calloc(ac - 1, sizeof(queue[0]));
+
+ for (i = 1; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ if (av[i][1] == 'w')
+ use_camera_wb = 1;
+ if (av[i][1] == 'a')
+ use_auto_wb = 1;
+ if (av[i][1] == 'v')
+ verbose = 1;
+ if (av[i][1] == 'T')
+ tiff_mode = 1;
+ if (av[i][1] == 'J')
+ {
+ max_threads = atoi(av[++i]);
+ if (max_threads < 1)
{
- printf("CreateThread error: %d\n", GetLastError());
- return 1;
+ fprintf(stderr, "Job count should be at least 1\n");
+ exit(1);
}
- }
-
- WaitForMultipleObjects(max_threads, threads, TRUE, INFINITE);
-
- // Close thread and mutex handles
-
- for( i=0; i < max_threads; i++ )
- CloseHandle(threads[i]);
-
- CloseHandle(qmutex);
-
- return 0;
+ }
+ }
+ else
+ queue[qsize++] = av[i];
+ }
+ qmutex = CreateMutex(NULL, FALSE, NULL);
+ threads = calloc(max_threads, sizeof(threads[0]));
+ for (i = 0; i < max_threads; i++)
+ {
+
+ if (NULL ==
+ (threads[i] = CreateThread(NULL, // default security attributes
+ 0, // default stack size
+ (LPTHREAD_START_ROUTINE)process_files,
+ NULL, // no thread function arguments
+ 0, // default creation flags
+ &ThreadID) // receive thread identifier
+ ))
+ {
+ printf("CreateThread error: %d\n", GetLastError());
+ return 1;
+ }
+ }
+
+ WaitForMultipleObjects(max_threads, threads, TRUE, INFINITE);
+
+ // Close thread and mutex handles
+
+ for (i = 0; i < max_threads; i++)
+ CloseHandle(threads[i]);
+
+ CloseHandle(qmutex);
+
+ return 0;
}
diff --git a/libkdcraw/libraw/samples/mem_image.cpp b/libkdcraw/libraw/samples/mem_image.cpp
index b1bbbed..1ce5b8c 100644
--- a/libkdcraw/libraw/samples/mem_image.cpp
+++ b/libkdcraw/libraw/samples/mem_image.cpp
@@ -1,25 +1,22 @@
-/*
+/* -*- C++ -*-
* File: mem_image.cpp
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
- * Created: Sat Mar 8 , 2008
- *
- * LibRaw mem_image/mem_thumb API test. Resuls should be same (bitwise) as in dcraw [-4] [-e]
- * Testing note: for ppm-thumbnails you should use dcraw -w -e for thumbnail extraction
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+ * LibRaw mem_image/mem_thumb API test. Results should be same (bitwise) to
+dcraw [-4] [-6] [-e]
+ * Testing note: for ppm-thumbnails you should use dcraw -w -e for thumbnail
+extraction
+
+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 <stdio.h>
#include <string.h>
@@ -27,7 +24,11 @@
#include "libraw/libraw.h"
-#ifdef WIN32
+#ifdef USE_JPEG
+#include "jpeglib.h"
+#endif
+
+#ifdef LIBRAW_WIN32_CALLS
#define snprintf _snprintf
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
@@ -35,83 +36,140 @@
#include <netinet/in.h>
#endif
+#ifdef USE_JPEG
+void write_jpeg(libraw_processed_image_t *img, const char *basename, int quality)
+{
+ char fn[1024];
+ if(img->colors != 1 && img->colors != 3)
+ {
+ printf("Only BW and 3-color images supported for JPEG output\n");
+ return;
+ }
+ snprintf(fn, 1024, "%s.jpg", basename);
+ FILE *f = fopen(fn, "wb");
+ if (!f)
+ return;
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
+ int row_stride; /* physical row width in image buffer */
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+ jpeg_stdio_dest(&cinfo, f);
+ cinfo.image_width = img->width; /* image width and height, in pixels */
+ cinfo.image_height = img->height;
+ cinfo.input_components = img->colors; /* # of color components per pixel */
+ cinfo.in_color_space = img->colors==3?JCS_RGB:JCS_GRAYSCALE; /* colorspace of input image */
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, quality, TRUE);
+ jpeg_start_compress(&cinfo, TRUE);
+ row_stride = img->width * img->colors; /* JSAMPLEs per row in image_buffer */
+ while (cinfo.next_scanline < cinfo.image_height) {
+ row_pointer[0] = &img->data[cinfo.next_scanline * row_stride];
+ (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+ jpeg_finish_compress(&cinfo);
+ fclose(f);
+ jpeg_destroy_compress(&cinfo);
+}
+
+#endif
// no error reporting, only params check
void write_ppm(libraw_processed_image_t *img, const char *basename)
{
- if(!img) return;
- // type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check
- if(img->type != LIBRAW_IMAGE_BITMAP) return;
- // only 3-color images supported...
- if(img->colors != 3) return;
+ if (!img)
+ return;
+ // type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check
+ if (img->type != LIBRAW_IMAGE_BITMAP)
+ return;
+ if (img->colors != 3 && img->colors != 1)
+ {
+ printf("Only monochrome and 3-color images supported for PPM output\n");
+ return;
+ }
- char fn[1024];
- snprintf(fn,1024,"%s.ppm",basename);
- FILE *f = fopen(fn,"wb");
- if(!f) return;
- fprintf (f, "P6\n%d %d\n%d\n", img->width, img->height, (1 << img->bits)-1);
+ char fn[1024];
+ snprintf(fn, 1024, "%s.p%cm", basename, img->colors==1?'g':'p');
+ FILE *f = fopen(fn, "wb");
+ if (!f)
+ return;
+ fprintf(f, "P%d\n%d %d\n%d\n", img->colors/2 + 5, img->width, img->height, (1 << img->bits) - 1);
/*
NOTE:
data in img->data is not converted to network byte order.
So, we should swap values on some architectures for dcraw compatibility
(unfortunately, xv cannot display 16-bit PPMs with network byte order data
*/
-#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
- if (img->bits == 16 && htons(0x55aa) != 0x55aa)
- for(int i=0; i< img->data_size; i+=2)
- SWAP(img->data[i],img->data[i+1]);
+#define SWAP(a, b) \
+ { \
+ a ^= b; \
+ a ^= (b ^= a); \
+ }
+ if (img->bits == 16 && htons(0x55aa) != 0x55aa)
+ for (unsigned i = 0; i < img->data_size-1; i += 2)
+ SWAP(img->data[i], img->data[i + 1]);
#undef SWAP
- fwrite(img->data,img->data_size,1,f);
- fclose(f);
+ fwrite(img->data, img->data_size, 1, f);
+ fclose(f);
}
void write_thumb(libraw_processed_image_t *img, const char *basename)
{
- if(!img) return;
+ if (!img)
+ return;
- if(img->type == LIBRAW_IMAGE_BITMAP)
- {
- char fnt[1024];
- snprintf(fnt,1024,"%s.thumb",basename);
- write_ppm(img,fnt);
- }
- else if (img->type == LIBRAW_IMAGE_JPEG)
- {
- char fn[1024];
- snprintf(fn,1024,"%s.thumb.jpg",basename);
- FILE *f = fopen(fn,"wb");
- if(!f) return;
- fwrite(img->data,img->data_size,1,f);
- fclose(f);
- }
+ if (img->type == LIBRAW_IMAGE_BITMAP)
+ {
+ char fnt[1024];
+ snprintf(fnt, 1024, "%s.thumb", basename);
+ write_ppm(img, fnt);
+ }
+ else if (img->type == LIBRAW_IMAGE_JPEG)
+ {
+ char fn[1024];
+ snprintf(fn, 1024, "%s.thumb.jpg", basename);
+ FILE *f = fopen(fn, "wb");
+ if (!f)
+ return;
+ fwrite(img->data, img->data_size, 1, f);
+ fclose(f);
+ }
}
-
-
int main(int ac, char *av[])
{
- int i, ret, verbose=0, output_thumbs=0;
+ int i, ret, output_thumbs = 0;
+#ifdef USE_JPEG
+ int output_jpeg = 0, jpgqual = 90;
+#endif
+ // don't use fixed size buffers in real apps!
- // don't use fixed size buffers in real apps!
- char outfn[1024],thumbfn[1024];
+ LibRaw RawProcessor;
- LibRaw RawProcessor;
-
- if(ac<2)
- {
- printf(
- "mem_image - LibRaw sample, to illustrate work for memory buffers. Emulates dcraw [-4] [-1] [-e]\n"
- "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n"
- "\t-4 - output 16-bit PPM\n"
- "\t-1 - gamma-correct 16-bit data\n"
- "\t-e - extract thumbnails (same as dcraw -e in separate run)\n",
- av[0]);
- return 0;
- }
+ if (ac < 2)
+ {
+ printf("mem_image - LibRaw sample, to illustrate work for memory buffers.\n"
+ "Emulates dcraw [-4] [-1] [-e] [-h]\n"
+#ifdef USE_JPEG
+ "Usage: %s [-D] [-j[nn]] [-T] [-v] [-e] raw-files....\n"
+#else
+ "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n"
+#endif
+ "\t-6 - output 16-bit PPM\n"
+ "\t-4 - linear 16-bit data\n"
+ "\t-e - extract thumbnails (same as dcraw -e in separate run)\n"
+#ifdef USE_JPEG
+ "\t-j[qual] - output JPEG with qual quality (e.g. -j90)\n"
+#endif
+ "\t-h - use half_size\n", av[0]);
+ return 0;
+ }
+
+ putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
- putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
-
#define P1 RawProcessor.imgdata.idata
#define S RawProcessor.imgdata.sizes
#define C RawProcessor.imgdata.color
@@ -119,80 +177,106 @@ int main(int ac, char *av[])
#define P2 RawProcessor.imgdata.other
#define OUT RawProcessor.imgdata.params
+ for (i = 1; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ if (av[i][1] == '6' && av[i][2] == 0)
+ OUT.output_bps = 16;
+ if (av[i][1] == '4' && av[i][2] == 0)
+ {
+ OUT.output_bps = 16;
+ OUT.gamm[0] = OUT.gamm[1] = OUT.no_auto_bright = 1;
+ }
+ if (av[i][1] == 'e' && av[i][2] == 0)
+ output_thumbs++;
+ if (av[i][1] == 'h' && av[i][2] == 0)
+ OUT.half_size = 1;
+#ifdef USE_JPEG
+ if (av[i][1] == 'j')
+ {
+ output_jpeg = 1;
+ if(av[i][2] != 0)
+ jpgqual = atoi(av[i]+2);
+ }
+#endif
+ continue;
+ }
+#ifdef USE_JPEG
+ if(output_jpeg && OUT.output_bps>8)
+ {
+ printf("JPEG is limited to 8 bit\n");
+ OUT.output_bps = 8;
+ }
+#endif
+ printf("Processing %s\n", av[i]);
+ if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret));
+ continue; // no recycle b/c open file will recycle itself
+ }
+
+ if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
+ continue;
+ }
+
+ // we should call dcraw_process before thumbnail extraction because for
+ // some cameras (i.e. Kodak ones) white balance for thumbnail should be set
+ // from main image settings
+
+ ret = RawProcessor.dcraw_process();
- for (i=1;i<ac;i++)
+ if (LIBRAW_SUCCESS != ret)
+ {
+ fprintf(stderr, "Cannot do postprocessing on %s: %s\n", av[i],
+ libraw_strerror(ret));
+ if (LIBRAW_FATAL_ERROR(ret))
+ continue;
+ }
+ libraw_processed_image_t *image = RawProcessor.dcraw_make_mem_image(&ret);
+ if (image)
+ {
+#ifdef USE_JPEG
+ if(output_jpeg)
+ write_jpeg(image, av[i], jpgqual);
+ else
+#endif
+ write_ppm(image, av[i]);
+ LibRaw::dcraw_clear_mem(image);
+ }
+ else
+ fprintf(stderr, "Cannot unpack %s to memory buffer: %s\n", av[i],
+ libraw_strerror(ret));
+
+ if (output_thumbs)
+ {
+
+ if ((ret = RawProcessor.unpack_thumb()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack_thumb %s: %s\n", av[i],
+ libraw_strerror(ret));
+ if (LIBRAW_FATAL_ERROR(ret))
+ continue; // skip to next file
+ }
+ else
+ {
+ libraw_processed_image_t *thumb =
+ RawProcessor.dcraw_make_mem_thumb(&ret);
+ if (thumb)
{
- if(av[i][0]=='-')
- {
- if(av[i][1]=='4' && av[i][2]==0)
- OUT.output_bps = 16;
- if(av[i][1]=='1' && av[i][2]==0)
- OUT.gamma_16bit = 1;
- if(av[i][1]=='e' && av[i][2]==0)
- output_thumbs++;
- continue;
- }
- printf("Processing %s\n",av[i]);
- if( (ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot open %s: %s\n",av[i],libraw_strerror(ret));
- continue; // no recycle b/c open file will recycle itself
- }
-
-
- if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot unpack %s: %s\n",av[i],libraw_strerror(ret));
- continue;
- }
-
- // we should call dcraw_process before thumbnail extraction because for
- // some cameras (i.e. Kodak ones) white balance for thumbnal should be set
- // from main image settings
-
-
- ret = RawProcessor.dcraw_process();
-
- if(LIBRAW_SUCCESS !=ret)
- {
- fprintf(stderr,"Cannot do postpocessing on %s: %s\n",
- av[i],libraw_strerror(ret));
- if(LIBRAW_FATAL_ERROR(ret))
- continue;
- }
- libraw_processed_image_t *image = RawProcessor.dcraw_make_mem_image(&ret);
- if(image)
- {
- write_ppm(image,av[i]);
- free(image);
- }
- else
- fprintf(stderr,"Cannot unpack %s to memory buffer: %s\n" , av[i],libraw_strerror(ret));
-
- if(output_thumbs)
- {
-
- if( (ret = RawProcessor.unpack_thumb() ) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot unpack_thumb %s: %s\n",av[i],libraw_strerror(ret));
- if(LIBRAW_FATAL_ERROR(ret))
- continue; // skip to next file
- }
- else
- {
- libraw_processed_image_t *thumb = RawProcessor.dcraw_make_mem_thumb(&ret);
- if(thumb)
- {
- write_thumb(thumb,av[i]);
- free(thumb);
- }
- else
- fprintf(stderr,"Cannot unpack thumbnail of %s to memory buffer: %s\n" , av[i],libraw_strerror(ret));
- }
-
- }
-
- RawProcessor.recycle(); // just for show this call
+ write_thumb(thumb, av[i]);
+ LibRaw::dcraw_clear_mem(thumb);
}
- return 0;
+ else
+ fprintf(stderr,
+ "Cannot unpack thumbnail of %s to memory buffer: %s\n", av[i],
+ libraw_strerror(ret));
+ }
+ }
+
+ RawProcessor.recycle(); // just for show this call
+ }
+ return 0;
}
diff --git a/libkdcraw/libraw/samples/mem_image_sample.cpp b/libkdcraw/libraw/samples/mem_image_sample.cpp
new file mode 100644
index 0000000..1ce5b8c
--- /dev/null
+++ b/libkdcraw/libraw/samples/mem_image_sample.cpp
@@ -0,0 +1,282 @@
+/* -*- C++ -*-
+ * File: mem_image.cpp
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ *
+ * LibRaw mem_image/mem_thumb API test. Results should be same (bitwise) to
+dcraw [-4] [-6] [-e]
+ * Testing note: for ppm-thumbnails you should use dcraw -w -e for thumbnail
+extraction
+
+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 <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "libraw/libraw.h"
+
+#ifdef USE_JPEG
+#include "jpeglib.h"
+#endif
+
+#ifdef LIBRAW_WIN32_CALLS
+#define snprintf _snprintf
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+#else
+#include <netinet/in.h>
+#endif
+
+#ifdef USE_JPEG
+void write_jpeg(libraw_processed_image_t *img, const char *basename, int quality)
+{
+ char fn[1024];
+ if(img->colors != 1 && img->colors != 3)
+ {
+ printf("Only BW and 3-color images supported for JPEG output\n");
+ return;
+ }
+ snprintf(fn, 1024, "%s.jpg", basename);
+ FILE *f = fopen(fn, "wb");
+ if (!f)
+ return;
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
+ int row_stride; /* physical row width in image buffer */
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+ jpeg_stdio_dest(&cinfo, f);
+ cinfo.image_width = img->width; /* image width and height, in pixels */
+ cinfo.image_height = img->height;
+ cinfo.input_components = img->colors; /* # of color components per pixel */
+ cinfo.in_color_space = img->colors==3?JCS_RGB:JCS_GRAYSCALE; /* colorspace of input image */
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, quality, TRUE);
+ jpeg_start_compress(&cinfo, TRUE);
+ row_stride = img->width * img->colors; /* JSAMPLEs per row in image_buffer */
+ while (cinfo.next_scanline < cinfo.image_height) {
+ row_pointer[0] = &img->data[cinfo.next_scanline * row_stride];
+ (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+ jpeg_finish_compress(&cinfo);
+ fclose(f);
+ jpeg_destroy_compress(&cinfo);
+}
+
+#endif
+
+// no error reporting, only params check
+void write_ppm(libraw_processed_image_t *img, const char *basename)
+{
+ if (!img)
+ return;
+ // type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check
+ if (img->type != LIBRAW_IMAGE_BITMAP)
+ return;
+ if (img->colors != 3 && img->colors != 1)
+ {
+ printf("Only monochrome and 3-color images supported for PPM output\n");
+ return;
+ }
+
+ char fn[1024];
+ snprintf(fn, 1024, "%s.p%cm", basename, img->colors==1?'g':'p');
+ FILE *f = fopen(fn, "wb");
+ if (!f)
+ return;
+ fprintf(f, "P%d\n%d %d\n%d\n", img->colors/2 + 5, img->width, img->height, (1 << img->bits) - 1);
+/*
+ NOTE:
+ data in img->data is not converted to network byte order.
+ So, we should swap values on some architectures for dcraw compatibility
+ (unfortunately, xv cannot display 16-bit PPMs with network byte order data
+*/
+#define SWAP(a, b) \
+ { \
+ a ^= b; \
+ a ^= (b ^= a); \
+ }
+ if (img->bits == 16 && htons(0x55aa) != 0x55aa)
+ for (unsigned i = 0; i < img->data_size-1; i += 2)
+ SWAP(img->data[i], img->data[i + 1]);
+#undef SWAP
+
+ fwrite(img->data, img->data_size, 1, f);
+ fclose(f);
+}
+
+void write_thumb(libraw_processed_image_t *img, const char *basename)
+{
+ if (!img)
+ return;
+
+ if (img->type == LIBRAW_IMAGE_BITMAP)
+ {
+ char fnt[1024];
+ snprintf(fnt, 1024, "%s.thumb", basename);
+ write_ppm(img, fnt);
+ }
+ else if (img->type == LIBRAW_IMAGE_JPEG)
+ {
+ char fn[1024];
+ snprintf(fn, 1024, "%s.thumb.jpg", basename);
+ FILE *f = fopen(fn, "wb");
+ if (!f)
+ return;
+ fwrite(img->data, img->data_size, 1, f);
+ fclose(f);
+ }
+}
+
+int main(int ac, char *av[])
+{
+ int i, ret, output_thumbs = 0;
+#ifdef USE_JPEG
+ int output_jpeg = 0, jpgqual = 90;
+#endif
+ // don't use fixed size buffers in real apps!
+
+ LibRaw RawProcessor;
+
+ if (ac < 2)
+ {
+ printf("mem_image - LibRaw sample, to illustrate work for memory buffers.\n"
+ "Emulates dcraw [-4] [-1] [-e] [-h]\n"
+#ifdef USE_JPEG
+ "Usage: %s [-D] [-j[nn]] [-T] [-v] [-e] raw-files....\n"
+#else
+ "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n"
+#endif
+ "\t-6 - output 16-bit PPM\n"
+ "\t-4 - linear 16-bit data\n"
+ "\t-e - extract thumbnails (same as dcraw -e in separate run)\n"
+#ifdef USE_JPEG
+ "\t-j[qual] - output JPEG with qual quality (e.g. -j90)\n"
+#endif
+ "\t-h - use half_size\n", av[0]);
+ return 0;
+ }
+
+ putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
+
+#define P1 RawProcessor.imgdata.idata
+#define S RawProcessor.imgdata.sizes
+#define C RawProcessor.imgdata.color
+#define T RawProcessor.imgdata.thumbnail
+#define P2 RawProcessor.imgdata.other
+#define OUT RawProcessor.imgdata.params
+
+ for (i = 1; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ if (av[i][1] == '6' && av[i][2] == 0)
+ OUT.output_bps = 16;
+ if (av[i][1] == '4' && av[i][2] == 0)
+ {
+ OUT.output_bps = 16;
+ OUT.gamm[0] = OUT.gamm[1] = OUT.no_auto_bright = 1;
+ }
+ if (av[i][1] == 'e' && av[i][2] == 0)
+ output_thumbs++;
+ if (av[i][1] == 'h' && av[i][2] == 0)
+ OUT.half_size = 1;
+#ifdef USE_JPEG
+ if (av[i][1] == 'j')
+ {
+ output_jpeg = 1;
+ if(av[i][2] != 0)
+ jpgqual = atoi(av[i]+2);
+ }
+#endif
+ continue;
+ }
+#ifdef USE_JPEG
+ if(output_jpeg && OUT.output_bps>8)
+ {
+ printf("JPEG is limited to 8 bit\n");
+ OUT.output_bps = 8;
+ }
+#endif
+ printf("Processing %s\n", av[i]);
+ if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret));
+ continue; // no recycle b/c open file will recycle itself
+ }
+
+ if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
+ continue;
+ }
+
+ // we should call dcraw_process before thumbnail extraction because for
+ // some cameras (i.e. Kodak ones) white balance for thumbnail should be set
+ // from main image settings
+
+ ret = RawProcessor.dcraw_process();
+
+ if (LIBRAW_SUCCESS != ret)
+ {
+ fprintf(stderr, "Cannot do postprocessing on %s: %s\n", av[i],
+ libraw_strerror(ret));
+ if (LIBRAW_FATAL_ERROR(ret))
+ continue;
+ }
+ libraw_processed_image_t *image = RawProcessor.dcraw_make_mem_image(&ret);
+ if (image)
+ {
+#ifdef USE_JPEG
+ if(output_jpeg)
+ write_jpeg(image, av[i], jpgqual);
+ else
+#endif
+ write_ppm(image, av[i]);
+ LibRaw::dcraw_clear_mem(image);
+ }
+ else
+ fprintf(stderr, "Cannot unpack %s to memory buffer: %s\n", av[i],
+ libraw_strerror(ret));
+
+ if (output_thumbs)
+ {
+
+ if ((ret = RawProcessor.unpack_thumb()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack_thumb %s: %s\n", av[i],
+ libraw_strerror(ret));
+ if (LIBRAW_FATAL_ERROR(ret))
+ continue; // skip to next file
+ }
+ else
+ {
+ libraw_processed_image_t *thumb =
+ RawProcessor.dcraw_make_mem_thumb(&ret);
+ if (thumb)
+ {
+ write_thumb(thumb, av[i]);
+ LibRaw::dcraw_clear_mem(thumb);
+ }
+ else
+ fprintf(stderr,
+ "Cannot unpack thumbnail of %s to memory buffer: %s\n", av[i],
+ libraw_strerror(ret));
+ }
+ }
+
+ RawProcessor.recycle(); // just for show this call
+ }
+ return 0;
+}
diff --git a/libkdcraw/libraw/samples/multirender_test.cpp b/libkdcraw/libraw/samples/multirender_test.cpp
new file mode 100644
index 0000000..06dcec5
--- /dev/null
+++ b/libkdcraw/libraw/samples/multirender_test.cpp
@@ -0,0 +1,107 @@
+/* -*- C++ -*-
+ * File: multirender_test.cpp
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Jul 10, 2011
+ *
+ * LibRaw simple C++ API: creates 8 different renderings from 1 source file.
+The 1st and 4th one should be identical
+
+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 <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "libraw/libraw.h"
+
+#ifndef LIBRAW_WIN32_CALLS
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#endif
+
+#ifdef LIBRAW_WIN32_CALLS
+#define snprintf _snprintf
+#endif
+
+int process_once(LibRaw &RawProcessor, int half_mode, int camera_wb,
+ int auto_wb, int suffix, int user_flip, char *fname)
+{
+ char outfn[1024];
+ RawProcessor.imgdata.params.half_size = half_mode;
+ RawProcessor.imgdata.params.use_camera_wb = camera_wb;
+ RawProcessor.imgdata.params.use_auto_wb = auto_wb;
+ RawProcessor.imgdata.params.user_flip = user_flip;
+
+ int ret = RawProcessor.dcraw_process();
+
+ if (LIBRAW_SUCCESS != ret)
+ {
+ fprintf(stderr, "Cannot do postprocessing on %s: %s\n", fname,
+ libraw_strerror(ret));
+ return ret;
+ }
+ snprintf(outfn, sizeof(outfn), "%s.%d.%s", fname, suffix,
+ (RawProcessor.imgdata.idata.colors > 1 ? "ppm" : "pgm"));
+
+ printf("Writing file %s\n", outfn);
+
+ if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
+ fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret));
+ return ret;
+}
+
+int main(int ac, char *av[])
+{
+ int i, ret;
+
+ LibRaw RawProcessor;
+ if (ac < 2)
+ {
+ printf("multirender_test - LibRaw %s sample. Performs 4 different "
+ "renderings of one file\n"
+ " %d cameras supported\n"
+ "Usage: %s raw-files....\n",
+ LibRaw::version(), LibRaw::cameraCount(), av[0]);
+ return 0;
+ }
+
+ for (i = 1; i < ac; i++)
+ {
+
+ printf("Processing file %s\n", av[i]);
+
+ if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot open_file %s: %s\n", av[i], libraw_strerror(ret));
+ continue; // no recycle b/c open file will recycle itself
+ }
+
+ if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
+ continue;
+ }
+ process_once(RawProcessor, 0, 0, 0, 1, -1, av[i]); // default flip
+ process_once(RawProcessor, 1, 0, 1, 2, -1, av[i]);
+ process_once(RawProcessor, 1, 1, 0, 3, -1, av[i]); // default flip
+ process_once(RawProcessor, 1, 1, 0, 4, 1, av[i]); // flip 1
+ process_once(RawProcessor, 1, 1, 0, 5, 3, av[i]); // flip 3
+ process_once(RawProcessor, 1, 1, 0, 6, 1, av[i]); // 1 again same as 4
+ process_once(RawProcessor, 1, 1, 0, 7, -1,
+ av[i]); // default again, same as 3
+ process_once(RawProcessor, 0, 0, 0, 8, -1, av[i]); // same as 1
+
+ RawProcessor.recycle(); // just for show this call
+ }
+ return 0;
+}
diff --git a/libkdcraw/libraw/samples/openbayer_sample.cpp b/libkdcraw/libraw/samples/openbayer_sample.cpp
new file mode 100644
index 0000000..c1e4659
--- /dev/null
+++ b/libkdcraw/libraw/samples/openbayer_sample.cpp
@@ -0,0 +1,65 @@
+/* -*- C++ -*-
+ * File: openvayer_sample.cpp
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Feb 11, 2020
+ *
+ * LibRaw simple C++ API: opens bayer data (Kodak KAI-0340 sensor) from buffer,
+dump as 8-bit tiff
+
+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 <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "libraw/libraw.h"
+
+#ifndef LIBRAW_WIN32_CALLS
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#endif
+
+int main(int ac, char *av[])
+{
+ if (ac != 2)
+ return 1;
+ FILE *in = fopen(av[1], "rb");
+ fseek(in, 0, SEEK_END);
+ unsigned fsz = ftell(in);
+ unsigned char *buffer = (unsigned char *)malloc(fsz);
+ if (!buffer)
+ return 2;
+ fseek(in, 0, SEEK_SET);
+ unsigned readb = fread(buffer, 1, fsz, in);
+ if (readb != fsz)
+ return 3;
+ LibRaw rp;
+ rp.imgdata.params.output_tiff = 1;
+ int ret = rp.open_bayer(buffer, fsz, 640, 480, 0, 0, 0, 0, 0,
+ LIBRAW_OPENBAYER_RGGB, 0, 0, 1400);
+ if (ret != LIBRAW_SUCCESS)
+ return 4;
+ if ((ret = rp.unpack()) != LIBRAW_SUCCESS)
+ printf("Unpack error: %d\n", ret);
+
+ if ((ret = rp.dcraw_process()) != LIBRAW_SUCCESS)
+ printf("Processing error: %d\n", ret);
+
+ char outfn[256];
+ sprintf(outfn, "%s.tif", av[1]);
+ if (LIBRAW_SUCCESS != (ret = rp.dcraw_ppm_tiff_writer(outfn)))
+ printf("Cannot write %s: %s\n", outfn, libraw_strerror(ret));
+ else
+ printf("Created %s\n", outfn);
+}
diff --git a/libkdcraw/libraw/samples/postprocessing_benchmark.cpp b/libkdcraw/libraw/samples/postprocessing_benchmark.cpp
new file mode 100644
index 0000000..703a7a3
--- /dev/null
+++ b/libkdcraw/libraw/samples/postprocessing_benchmark.cpp
@@ -0,0 +1,223 @@
+/* -*- C++ -*-
+ * File: postprocessing_benchmark.cpp
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Jul 13, 2011
+ *
+ * LibRaw simple C++ API: creates 8 different renderings from 1 source file.
+The 1st and 4th one should be identical
+
+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 <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "libraw/libraw.h"
+
+#ifndef LIBRAW_WIN32_CALLS
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include "libraw/libraw.h"
+
+void timerstart(void);
+float timerend(void);
+
+int main(int argc, char *argv[])
+{
+ int i, ret, rep = 1;
+ LibRaw RawProcessor;
+#ifdef OUT
+#undef OUT
+#endif
+#define OUT RawProcessor.imgdata.params
+#define OUTR RawProcessor.imgdata.rawparams
+#define S RawProcessor.imgdata.sizes
+
+ if (argc < 2)
+ {
+ printf(
+ "postprocessing benchmark: LibRaw %s sample, %d cameras supported\n"
+ "Measures postprocessing speed with different options\n"
+ "Usage: %s [-a] [-H N] [-q N] [-h] [-m N] [-n N] [-s N] [-B x y w h] "
+ "[-R N]\n"
+ "-a average image for white balance\n"
+ "-H <num> Highlight mode (0=clip, 1=unclip, 2=blend, "
+ "3+=rebuild)\n"
+ "-q <num> Set the interpolation quality\n"
+ "-h Half-size color image\n"
+ "-m <num> Apply a num-passes 3x3 median filter to R-G and B-G\n"
+ "-n <num> Set threshold for wavelet denoising\n"
+ "-s <num> Select one raw image from input file\n"
+ "-B <x y w h> Crop output image\n"
+ "-R <num> Number of repetitions\n"
+ "-c Do not use rawspeed\n",
+ LibRaw::version(), LibRaw::cameraCount(), argv[0]);
+ return 0;
+ }
+ char opm, opt, *cp, *sp;
+ int arg, c;
+ int shrink = 0;
+
+ argv[argc] = (char *)"";
+ for (arg = 1; (((opm = argv[arg][0]) - 2) | 2) == '+';)
+ {
+ char *optstr = argv[arg];
+ opt = argv[arg++][1];
+ if ((cp = strchr(sp = (char *)"HqmnsBR", opt)) != 0)
+ for (i = 0; i < "1111141"[cp - sp] - '0'; i++)
+ if (!isdigit(argv[arg + i][0]) && !optstr[2])
+ {
+ fprintf(stderr, "Non-numeric argument to \"-%c\"\n", opt);
+ return 1;
+ }
+ switch (opt)
+ {
+ case 'a':
+ OUT.use_auto_wb = 1;
+ break;
+ case 'H':
+ OUT.highlight = atoi(argv[arg++]);
+ break;
+ case 'q':
+ OUT.user_qual = atoi(argv[arg++]);
+ break;
+ case 'h':
+ OUT.half_size = 1;
+ OUT.four_color_rgb = 1;
+ shrink = 1;
+ break;
+ case 'm':
+ OUT.med_passes = atoi(argv[arg++]);
+ break;
+ case 'n':
+ OUT.threshold = (float)atof(argv[arg++]);
+ break;
+ case 's':
+ OUTR.shot_select = abs(atoi(argv[arg++]));
+ break;
+ case 'B':
+ for (c = 0; c < 4; c++)
+ OUT.cropbox[c] = atoi(argv[arg++]);
+ break;
+ case 'R':
+ rep = abs(atoi(argv[arg++]));
+ if (rep < 1)
+ rep = 1;
+ break;
+ case 'c':
+ RawProcessor.imgdata.rawparams.use_rawspeed = 0;
+ break;
+ default:
+ fprintf(stderr, "Unknown option \"-%c\".\n", opt);
+ return 1;
+ }
+ }
+ for (; arg < argc; arg++)
+ {
+ printf("Processing file %s\n", argv[arg]);
+ timerstart();
+ if ((ret = RawProcessor.open_file(argv[arg])) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot open_file %s: %s\n", argv[arg],
+ libraw_strerror(ret));
+ continue; // no recycle b/c open file will recycle itself
+ }
+
+ if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack %s: %s\n", argv[arg],
+ libraw_strerror(ret));
+ continue;
+ }
+ float qsec = timerend();
+ printf("\n%.1f msec for unpack\n", qsec);
+ float mpix, rmpix;
+ timerstart();
+ for (c = 0; c < rep; c++)
+ {
+ if ((ret = RawProcessor.dcraw_process()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot postprocess %s: %s\n", argv[arg],
+ libraw_strerror(ret));
+ break;
+ }
+ libraw_processed_image_t *p = RawProcessor.dcraw_make_mem_image();
+ if (p)
+ RawProcessor.dcraw_clear_mem(p);
+ RawProcessor.free_image();
+ }
+ float msec = timerend() / (float)rep;
+
+ if ((ret = RawProcessor.adjust_sizes_info_only()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot adjust sizes for %s: %s\n", argv[arg],
+ libraw_strerror(ret));
+ break;
+ }
+ rmpix = (S.iwidth * S.iheight) / 1000000.0f;
+
+ if (c == rep) // no failure
+ {
+ unsigned int crop[4];
+ for (int i = 0; i < 4; i++)
+ crop[i] = (OUT.cropbox[i]) >> shrink;
+ if (crop[0] + crop[2] > S.iwidth)
+ crop[2] = S.iwidth - crop[0];
+ if (crop[1] + crop[3] > S.iheight)
+ crop[3] = S.iheight - crop[1];
+
+ mpix = float(crop[2] * crop[3]) / 1000000.0f;
+ float mpixsec = mpix * 1000.0f / msec;
+
+ printf("Performance: %.2f Mpix/sec\n"
+ "File: %s, Frame: %d %.1f total Mpix, %.1f msec\n"
+ "Params: WB=%s Highlight=%d Qual=%d HalfSize=%s Median=%d "
+ "Wavelet=%.0f\n"
+ "Crop: %u-%u:%ux%u, active Mpix: %.2f, %.1f frames/sec\n",
+ mpixsec, argv[arg], OUTR.shot_select, rmpix, msec,
+ OUT.use_auto_wb ? "auto" : "default", OUT.highlight, OUT.user_qual,
+ OUT.half_size ? "YES" : "No", OUT.med_passes, OUT.threshold,
+ crop[0], crop[1], crop[2], crop[3], mpix, 1000.0f / msec);
+ }
+ }
+
+ return 0;
+}
+
+#ifndef LIBRAW_WIN32_CALLS
+static struct timeval start, end;
+void timerstart(void) { gettimeofday(&start, NULL); }
+float timerend(void)
+{
+ gettimeofday(&end, NULL);
+ float msec = (end.tv_sec - start.tv_sec) * 1000.0f +
+ (end.tv_usec - start.tv_usec) / 1000.0f;
+ return msec;
+}
+#else
+LARGE_INTEGER start;
+void timerstart(void) { QueryPerformanceCounter(&start); }
+float timerend()
+{
+ LARGE_INTEGER unit, end;
+ QueryPerformanceCounter(&end);
+ QueryPerformanceFrequency(&unit);
+ float msec = (float)(end.QuadPart - start.QuadPart);
+ msec /= (float)unit.QuadPart / 1000.0f;
+ return msec;
+}
+
+#endif
diff --git a/libkdcraw/libraw/samples/raw-identify.cpp b/libkdcraw/libraw/samples/raw-identify.cpp
new file mode 100644
index 0000000..ced5181
--- /dev/null
+++ b/libkdcraw/libraw/samples/raw-identify.cpp
@@ -0,0 +1,739 @@
+/* -*- C++ -*-
+ * File: identify.cpp
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Sat Mar 8, 2008
+ *
+ * LibRaw C++ demo: emulates dcraw -i [-v]
+ *
+
+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 <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <string>
+#include <list>
+
+#include "libraw/libraw.h"
+
+#ifdef LIBRAW_WIN32_CALLS
+#define snprintf _snprintf
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+#endif
+
+#ifndef LIBRAW_WIN32_CALLS
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#ifndef MAX_PATH
+#define MAX_PATH PATH_MAX
+#endif
+#endif
+
+#ifdef _MSC_VER
+#if _MSC_VER < 1800 /* below MSVC 2013 */
+float roundf(float f) { return floorf(f + 0.5); }
+
+#endif
+#endif
+
+#define P1 MyCoolRawProcessor.imgdata.idata
+#define P2 MyCoolRawProcessor.imgdata.other
+#define P3 MyCoolRawProcessor.imgdata.makernotes.common
+
+#define mnLens MyCoolRawProcessor.imgdata.lens.makernotes
+#define exifLens MyCoolRawProcessor.imgdata.lens
+#define ShootingInfo MyCoolRawProcessor.imgdata.shootinginfo
+
+#define S MyCoolRawProcessor.imgdata.sizes
+#define O MyCoolRawProcessor.imgdata.params
+#define C MyCoolRawProcessor.imgdata.color
+#define T MyCoolRawProcessor.imgdata.thumbnail
+
+void print_verbose(FILE *, LibRaw &MyCoolRawProcessor, std::string &fn);
+void print_wbfun(FILE *, LibRaw &MyCoolRawProcessor, std::string &fn);
+void print_szfun(FILE *, LibRaw &MyCoolRawProcessor, std::string &fn);
+void print_unpackfun(FILE *, LibRaw &MyCoolRawProcessor, int print_frame, std::string &fn);
+
+/*
+table of fluorescents:
+12 = FL-D; Daylight fluorescent (D 5700K – 7100K) (F1,F5)
+13 = FL-N; Day white fluorescent (N 4600K – 5400K) (F7,F8)
+14 = FL-W; Cool white fluorescent (W 3900K – 4500K) (F2,F6, office,
+store,warehouse) 15 = FL-WW; White fluorescent (WW 3200K – 3700K) (F3,
+residential) 16 = FL-L; Soft/Warm white fluorescent (L 2600K - 3250K) (F4,
+kitchen, bath)
+*/
+
+static const struct
+{
+ const int NumId;
+ const char *StrId;
+ const char *hrStrId; // human-readable
+ const int aux_setting;
+} WBToStr[] = {
+ {LIBRAW_WBI_Unknown, "WBI_Unknown", "Unknown", 0},
+ {LIBRAW_WBI_Daylight, "WBI_Daylight", "Daylight", 0},
+ {LIBRAW_WBI_Fluorescent, "WBI_Fluorescent", "Fluorescent", 0},
+ {LIBRAW_WBI_Tungsten, "WBI_Tungsten", "Tungsten (Incandescent)", 0},
+ {LIBRAW_WBI_Flash, "WBI_Flash", "Flash", 0},
+ {LIBRAW_WBI_FineWeather, "WBI_FineWeather", "Fine Weather", 0},
+ {LIBRAW_WBI_Cloudy, "WBI_Cloudy", "Cloudy", 0},
+ {LIBRAW_WBI_Shade, "WBI_Shade", "Shade", 0},
+ {LIBRAW_WBI_FL_D, "WBI_FL_D", "Daylight Fluorescent", 0},
+ {LIBRAW_WBI_FL_N, "WBI_FL_N", "Day White Fluorescent", 0},
+ {LIBRAW_WBI_FL_W, "WBI_FL_W", "Cool White Fluorescent", 0},
+ {LIBRAW_WBI_FL_WW, "WBI_FL_WW", "White Fluorescent", 0},
+ {LIBRAW_WBI_FL_L, "WBI_FL_L", "Warm White Fluorescent", 0},
+ {LIBRAW_WBI_Ill_A, "WBI_Ill_A", "Illuminant A", 0},
+ {LIBRAW_WBI_Ill_B, "WBI_Ill_B", "Illuminant B", 0},
+ {LIBRAW_WBI_Ill_C, "WBI_Ill_C", "Illuminant C", 0},
+ {LIBRAW_WBI_D55, "WBI_D55", "D55", 0},
+ {LIBRAW_WBI_D65, "WBI_D65", "D65", 0},
+ {LIBRAW_WBI_D75, "WBI_D75", "D75", 0},
+ {LIBRAW_WBI_D50, "WBI_D50", "D50", 0},
+ {LIBRAW_WBI_StudioTungsten, "WBI_StudioTungsten", "ISO Studio Tungsten", 0},
+ {LIBRAW_WBI_BW, "WBI_BW", "BW", 0},
+ {LIBRAW_WBI_Other, "WBI_Other", "Other", 0},
+ {LIBRAW_WBI_Sunset, "WBI_Sunset", "Sunset", 1},
+ {LIBRAW_WBI_Underwater, "WBI_Underwater", "Underwater", 1},
+ {LIBRAW_WBI_FluorescentHigh, "WBI_FluorescentHigh", "Fluorescent High", 1},
+ {LIBRAW_WBI_HT_Mercury, "WBI_HT_Mercury", "HT Mercury", 1},
+ {LIBRAW_WBI_AsShot, "WBI_AsShot", "As Shot", 1},
+ {LIBRAW_WBI_Measured, "WBI_Measured", "Camera Measured", 1},
+ {LIBRAW_WBI_Auto, "WBI_Auto", "Camera Auto", 1},
+ {LIBRAW_WBI_Auto1, "WBI_Auto1", "Camera Auto 1", 1},
+ {LIBRAW_WBI_Auto2, "WBI_Auto2", "Camera Auto 2", 1},
+ {LIBRAW_WBI_Auto3, "WBI_Auto3", "Camera Auto 3", 1},
+ {LIBRAW_WBI_Auto4, "WBI_Auto4", "Camera Auto 4", 1},
+ {LIBRAW_WBI_Custom, "WBI_Custom", "Custom", 1},
+ {LIBRAW_WBI_Custom1, "WBI_Custom1", "Custom 1", 1},
+ {LIBRAW_WBI_Custom2, "WBI_Custom2", "Custom 2", 1},
+ {LIBRAW_WBI_Custom3, "WBI_Custom3", "Custom 3", 1},
+ {LIBRAW_WBI_Custom4, "WBI_Custom4", "Custom 4", 1},
+ {LIBRAW_WBI_Custom5, "WBI_Custom5", "Custom 5", 1},
+ {LIBRAW_WBI_Custom6, "WBI_Custom6", "Custom 6", 1},
+ {LIBRAW_WBI_PC_Set1, "WBI_PC_Set1", "PC Set 1", 1},
+ {LIBRAW_WBI_PC_Set2, "WBI_PC_Set2", "PC Set 2", 1},
+ {LIBRAW_WBI_PC_Set3, "WBI_PC_Set3", "PC Set 3", 1},
+ {LIBRAW_WBI_PC_Set4, "WBI_PC_Set4", "PC Set 4", 1},
+ {LIBRAW_WBI_PC_Set5, "WBI_PC_Set5", "PC Set 5", 1},
+ {LIBRAW_WBI_Kelvin, "WBI_Kelvin", "Kelvin", 1},
+};
+
+const char *WB_idx2str(unsigned WBi)
+{
+ for (int i = 0; i < int(sizeof WBToStr / sizeof *WBToStr); i++)
+ if (WBToStr[i].NumId == (int)WBi)
+ return WBToStr[i].StrId;
+ return 0;
+}
+
+const char *WB_idx2hrstr(unsigned WBi)
+{
+ for (int i = 0; i < int(sizeof WBToStr / sizeof *WBToStr); i++)
+ if (WBToStr[i].NumId == (int)WBi)
+ return WBToStr[i].hrStrId;
+ return 0;
+}
+
+double _log2(double a)
+{
+ if(a > 0.00000000001) return log(a)/log(2.0);
+ return -1000;
+}
+
+void trimSpaces(char *s)
+{
+ char *p = s;
+ if (!strncasecmp(p, "NO=", 3))
+ p = p + 3; /* fix for Nikon D70, D70s */
+ int l = strlen(p);
+ if (!l)
+ return;
+ while (isspace(p[l - 1]))
+ p[--l] = 0; /* trim trailing spaces */
+ while (*p && isspace(*p))
+ ++p, --l; /* trim leading spaces */
+ memmove(s, p, l + 1);
+}
+
+void print_usage(const char *pname)
+{
+ printf("Usage: %s [options] inputfiles\n", pname);
+ printf("Options:\n"
+ "\t-v\tverbose output\n"
+ "\t-w\tprint white balance\n"
+ "\t-u\tprint unpack function\n"
+ "\t-f\tprint frame size (only w/ -u)\n"
+ "\t-s\tprint output image size\n"
+ "\t-h\tforce half-size mode (only for -s)\n"
+ "\t-M\tdisable use of raw-embedded color data\n"
+ "\t+M\tforce use of raw-embedded color data\n"
+ "\t-L filename\tread input files list from filename\n"
+ "\t-o filename\toutput to filename\n");
+}
+
+int main(int ac, char *av[])
+{
+ int ret;
+ int verbose = 0, print_sz = 0, print_unpack = 0, print_frame = 0, print_wb = 0;
+ LibRaw MyCoolRawProcessor;
+ char *filelistfile = NULL;
+ char *outputfilename = NULL;
+ FILE *outfile = stdout;
+ std::vector<std::string> filelist;
+
+ filelist.reserve(ac - 1);
+
+ for (int i = 1; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ if (!strcmp(av[i], "-v"))
+ verbose++;
+ if (!strcmp(av[i], "-w"))
+ print_wb++;
+ if (!strcmp(av[i], "-u"))
+ print_unpack++;
+ if (!strcmp(av[i], "-s"))
+ print_sz++;
+ if (!strcmp(av[i], "-h"))
+ O.half_size = 1;
+ if (!strcmp(av[i], "-f"))
+ print_frame++;
+ if (!strcmp(av[i], "-M"))
+ MyCoolRawProcessor.imgdata.params.use_camera_matrix = 0;
+ if (!strcmp(av[i], "-L") && i < ac - 1)
+ {
+ filelistfile = av[i + 1];
+ i++;
+ }
+ if (!strcmp(av[i], "-o") && i < ac - 1)
+ {
+ outputfilename = av[i + 1];
+ i++;
+ }
+ continue;
+ }
+ else if (!strcmp(av[i], "+M"))
+ {
+ MyCoolRawProcessor.imgdata.params.use_camera_matrix = 3;
+ continue;
+ }
+ filelist.push_back(av[i]);
+ }
+ if (filelistfile)
+ {
+ char *p;
+ char path[MAX_PATH + 1];
+ FILE *f = fopen(filelistfile, "r");
+ if (f)
+ {
+ while (fgets(path, MAX_PATH, f))
+ {
+ if ((p = strchr(path, '\n')))
+ *p = 0;
+ if ((p = strchr(path, '\r')))
+ *p = 0;
+ filelist.push_back(path);
+ }
+ fclose(f);
+ }
+ }
+ if (filelist.size() < 1)
+ {
+ print_usage(av[0]);
+ return 1;
+ }
+ if (outputfilename)
+ outfile = fopen(outputfilename, "wt");
+
+ for (int i = 0; i < (int)filelist.size(); i++)
+ {
+ if ((ret = MyCoolRawProcessor.open_file(filelist[i].c_str())) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot decode %s: %s\n", filelist[i].c_str(), libraw_strerror(ret));
+ continue; // no recycle, open_file will recycle
+ }
+
+ if (print_sz)
+ print_szfun(outfile, MyCoolRawProcessor, filelist[i]);
+ else if (verbose)
+ print_verbose(outfile, MyCoolRawProcessor, filelist[i]);
+ else if (print_unpack)
+ print_unpackfun(outfile, MyCoolRawProcessor, print_frame, filelist[i]);
+ else if (print_wb)
+ print_wbfun(outfile, MyCoolRawProcessor, filelist[i]);
+ else
+ fprintf(outfile, "%s is a %s %s image.\n", filelist[i].c_str(), P1.make, P1.model);
+
+ MyCoolRawProcessor.recycle();
+ } // endfor
+ return 0;
+}
+
+#define PRINTMATRIX3x4(of, mat, clrs) \
+ do \
+ { \
+ for (int r = 0; r < 3; r++) \
+ if (clrs == 4) \
+ fprintf(of, "%6.4f\t%6.4f\t%6.4f\t%6.4f\n", mat[r][0], mat[r][1], mat[r][2], mat[r][3]); \
+ else \
+ fprintf(of, "%6.4f\t%6.4f\t%6.4f\n", mat[r][0], mat[r][1], mat[r][2]); \
+ } while (0)
+
+#define PRINTMATRIX4x3(of, mat, clrs) \
+ do \
+ { \
+ for (int r = 0; r < clrs && r < 4; r++) \
+ fprintf(of, "%6.4f\t%6.4f\t%6.4f\n", mat[r][0], mat[r][1], mat[r][2]); \
+ } while (0)
+
+void print_verbose(FILE *outfile, LibRaw &MyCoolRawProcessor, std::string &fn)
+{
+ int WBi;
+ float denom;
+ int ret;
+
+ if ((ret = MyCoolRawProcessor.adjust_sizes_info_only()))
+ {
+ fprintf(outfile, "Cannot decode %s: %s\n", fn.c_str(), libraw_strerror(ret));
+ return; // no recycle, open_file will recycle
+ }
+
+ fprintf(outfile, "\nFilename: %s\n", fn.c_str());
+ if (C.OriginalRawFileName[0])
+ fprintf(outfile, "OriginalRawFileName: =%s=\n", C.OriginalRawFileName);
+ fprintf(outfile, "Timestamp: %s", ctime(&(P2.timestamp)));
+ fprintf(outfile, "Camera: %s %s ID: 0x%llx\n", P1.make, P1.model, mnLens.CamID);
+ fprintf(outfile, "Normalized Make/Model: =%s/%s= ", P1.normalized_make, P1.normalized_model);
+ fprintf(outfile, "CamMaker ID: %d\n", P1.maker_index);
+
+ {
+ int i = 0;
+ char sep[] = ", ";
+ if (C.UniqueCameraModel[0])
+ {
+ i++;
+ fprintf(outfile, "UniqueCameraModel: =%s=", C.UniqueCameraModel);
+ }
+ if (C.LocalizedCameraModel[0])
+ {
+ if (i)
+ {
+ fprintf(outfile, "%s", sep);
+ i++;
+ }
+ fprintf(outfile, "LocalizedCameraModel: =%s=", C.LocalizedCameraModel);
+ }
+ if (i)
+ {
+ fprintf(outfile, "\n");
+ i = 0;
+ }
+ if (C.ImageUniqueID[0])
+ {
+ if (i)
+ fprintf(outfile, "%s", sep);
+ i++;
+ fprintf(outfile, "ImageUniqueID: =%s=", C.ImageUniqueID);
+ }
+ if (C.RawDataUniqueID[0])
+ {
+ if (i)
+ fprintf(outfile, "%s", sep);
+ i++;
+ fprintf(outfile, "RawDataUniqueID: =%s=", C.RawDataUniqueID);
+ }
+ if (i)
+ fprintf(outfile, "\n");
+ }
+
+ if (ShootingInfo.BodySerial[0] && strcmp(ShootingInfo.BodySerial, "0"))
+ {
+ trimSpaces(ShootingInfo.BodySerial);
+ fprintf(outfile, "Body#: %s", ShootingInfo.BodySerial);
+ }
+ else if (C.model2[0] && (!strncasecmp(P1.normalized_make, "Kodak", 5)))
+ {
+ trimSpaces(C.model2);
+ fprintf(outfile, "Body#: %s", C.model2);
+ }
+ if (ShootingInfo.InternalBodySerial[0])
+ {
+ trimSpaces(ShootingInfo.InternalBodySerial);
+ fprintf(outfile, " BodyAssy#: %s", ShootingInfo.InternalBodySerial);
+ }
+ if (exifLens.LensSerial[0])
+ {
+ trimSpaces(exifLens.LensSerial);
+ fprintf(outfile, " Lens#: %s", exifLens.LensSerial);
+ }
+ if (exifLens.InternalLensSerial[0])
+ {
+ trimSpaces(exifLens.InternalLensSerial);
+ fprintf(outfile, " LensAssy#: %s", exifLens.InternalLensSerial);
+ }
+ if (P2.artist[0])
+ fprintf(outfile, " Owner: %s\n", P2.artist);
+ if (P1.dng_version)
+ {
+ fprintf(outfile, " DNG Version: ");
+ for (int i = 24; i >= 0; i -= 8)
+ fprintf(outfile, "%d%c", P1.dng_version >> i & 255, i ? '.' : '\n');
+ }
+ fprintf(outfile, "\nEXIF:\n");
+ fprintf(outfile, "\tMinFocal: %0.1f mm\n", exifLens.MinFocal);
+ fprintf(outfile, "\tMaxFocal: %0.1f mm\n", exifLens.MaxFocal);
+ fprintf(outfile, "\tMaxAp @MinFocal: f/%0.1f\n", exifLens.MaxAp4MinFocal);
+ fprintf(outfile, "\tMaxAp @MaxFocal: f/%0.1f\n", exifLens.MaxAp4MaxFocal);
+ fprintf(outfile, "\tCurFocal: %0.1f mm\n", P2.focal_len);
+ fprintf(outfile, "\tMaxAperture @CurFocal: f/%0.1f\n", exifLens.EXIF_MaxAp);
+ fprintf(outfile, "\tFocalLengthIn35mmFormat: %d mm\n", exifLens.FocalLengthIn35mmFormat);
+ fprintf(outfile, "\tLensMake: %s\n", exifLens.LensMake);
+ fprintf(outfile, "\tLens: %s\n", exifLens.Lens);
+ fprintf(outfile, "\n");
+
+ fprintf(outfile, "\nMakernotes:\n");
+ fprintf(outfile, "\tDriveMode: %d\n", ShootingInfo.DriveMode);
+ fprintf(outfile, "\tFocusMode: %d\n", ShootingInfo.FocusMode);
+ fprintf(outfile, "\tMeteringMode: %d\n", ShootingInfo.MeteringMode);
+ fprintf(outfile, "\tAFPoint: %d\n", ShootingInfo.AFPoint);
+ fprintf(outfile, "\tExposureMode: %d\n", ShootingInfo.ExposureMode);
+ fprintf(outfile, "\tExposureProgram: %d\n", ShootingInfo.ExposureProgram);
+ fprintf(outfile, "\tImageStabilization: %d\n", ShootingInfo.ImageStabilization);
+
+ fprintf(outfile, "\tLens: %s\n", mnLens.Lens);
+ fprintf(outfile, "\tLensFormat: %d, ", mnLens.LensFormat);
+
+ fprintf(outfile, "\tLensMount: %d, ", mnLens.LensMount);
+ fprintf(outfile, "\tFocalType: %d, ", mnLens.FocalType);
+ switch (mnLens.FocalType)
+ {
+ case LIBRAW_FT_UNDEFINED:
+ fprintf(outfile, "Undefined\n");
+ break;
+ case LIBRAW_FT_PRIME_LENS:
+ fprintf(outfile, "Prime lens\n");
+ break;
+ case LIBRAW_FT_ZOOM_LENS:
+ fprintf(outfile, "Zoom lens\n");
+ break;
+ default:
+ fprintf(outfile, "Unknown\n");
+ break;
+ }
+ fprintf(outfile, "\tLensFeatures_pre: %s\n", mnLens.LensFeatures_pre);
+ fprintf(outfile, "\tLensFeatures_suf: %s\n", mnLens.LensFeatures_suf);
+ fprintf(outfile, "\tMinFocal: %0.1f mm\n", mnLens.MinFocal);
+ fprintf(outfile, "\tMaxFocal: %0.1f mm\n", mnLens.MaxFocal);
+ fprintf(outfile, "\tMaxAp @MinFocal: f/%0.1f\n", mnLens.MaxAp4MinFocal);
+ fprintf(outfile, "\tMaxAp @MaxFocal: f/%0.1f\n", mnLens.MaxAp4MaxFocal);
+ fprintf(outfile, "\tMinAp @MinFocal: f/%0.1f\n", mnLens.MinAp4MinFocal);
+ fprintf(outfile, "\tMinAp @MaxFocal: f/%0.1f\n", mnLens.MinAp4MaxFocal);
+ fprintf(outfile, "\tMaxAp: f/%0.1f\n", mnLens.MaxAp);
+ fprintf(outfile, "\tMinAp: f/%0.1f\n", mnLens.MinAp);
+ fprintf(outfile, "\tCurFocal: %0.1f mm\n", mnLens.CurFocal);
+ fprintf(outfile, "\tCurAp: f/%0.1f\n", mnLens.CurAp);
+ fprintf(outfile, "\tMaxAp @CurFocal: f/%0.1f\n", mnLens.MaxAp4CurFocal);
+ fprintf(outfile, "\tMinAp @CurFocal: f/%0.1f\n", mnLens.MinAp4CurFocal);
+
+ if (exifLens.makernotes.FocalLengthIn35mmFormat > 1.0f)
+ fprintf(outfile, "\tFocalLengthIn35mmFormat: %0.1f mm\n", exifLens.makernotes.FocalLengthIn35mmFormat);
+
+ if (exifLens.nikon.EffectiveMaxAp > 0.1f)
+ fprintf(outfile, "\tEffectiveMaxAp: f/%0.1f\n", exifLens.nikon.EffectiveMaxAp);
+
+ if (exifLens.makernotes.LensFStops > 0.1f)
+ fprintf(outfile, "\tLensFStops @CurFocal: %0.2f\n", exifLens.makernotes.LensFStops);
+
+ fprintf(outfile, "\tTeleconverterID: %lld\n", mnLens.TeleconverterID);
+ fprintf(outfile, "\tTeleconverter: %s\n", mnLens.Teleconverter);
+ fprintf(outfile, "\tAdapterID: %lld\n", mnLens.AdapterID);
+ fprintf(outfile, "\tAdapter: %s\n", mnLens.Adapter);
+ fprintf(outfile, "\tAttachmentID: %lld\n", mnLens.AttachmentID);
+ fprintf(outfile, "\tAttachment: %s\n", mnLens.Attachment);
+ fprintf(outfile, "\n");
+
+ fprintf(outfile, "ISO speed: %d\n", (int)P2.iso_speed);
+ if (P3.real_ISO > 0.1f)
+ fprintf(outfile, "real ISO speed: %d\n", (int)P3.real_ISO);
+ fprintf(outfile, "Shutter: ");
+ if (P2.shutter > 0 && P2.shutter < 1)
+ P2.shutter = fprintf(outfile, "1/%0.1f\n", 1.0f / P2.shutter);
+ else if (P2.shutter >= 1)
+ fprintf(outfile, "%0.1f sec\n", P2.shutter);
+ else /* negative*/
+ fprintf(outfile, " negative value\n");
+ fprintf(outfile, "Aperture: f/%0.1f\n", P2.aperture);
+ fprintf(outfile, "Focal length: %0.1f mm\n", P2.focal_len);
+ if (P3.exifAmbientTemperature > -273.15f)
+ fprintf(outfile, "Ambient temperature (exif data): %6.2f° C\n", P3.exifAmbientTemperature);
+ if (P3.CameraTemperature > -273.15f)
+ fprintf(outfile, "Camera temperature: %6.2f° C\n", P3.CameraTemperature);
+ if (P3.SensorTemperature > -273.15f)
+ fprintf(outfile, "Sensor temperature: %6.2f° C\n", P3.SensorTemperature);
+ if (P3.SensorTemperature2 > -273.15f)
+ fprintf(outfile, "Sensor temperature2: %6.2f° C\n", P3.SensorTemperature2);
+ if (P3.LensTemperature > -273.15f)
+ fprintf(outfile, "Lens temperature: %6.2f° C\n", P3.LensTemperature);
+ if (P3.AmbientTemperature > -273.15f)
+ fprintf(outfile, "Ambient temperature: %6.2f° C\n", P3.AmbientTemperature);
+ if (P3.BatteryTemperature > -273.15f)
+ fprintf(outfile, "Battery temperature: %6.2f° C\n", P3.BatteryTemperature);
+ if (P3.FlashGN > 1.0f)
+ fprintf(outfile, "Flash Guide Number: %6.2f\n", P3.FlashGN);
+ fprintf(outfile, "Flash exposure compensation: %0.2f EV\n", P3.FlashEC);
+ if (C.profile)
+ fprintf(outfile, "Embedded ICC profile: yes, %d bytes\n", C.profile_length);
+ else
+ fprintf(outfile, "Embedded ICC profile: no\n");
+
+ if (C.dng_levels.baseline_exposure > -999.f)
+ fprintf(outfile, "Baseline exposure: %04.3f\n", C.dng_levels.baseline_exposure);
+
+ fprintf(outfile, "Number of raw images: %d\n", P1.raw_count);
+
+ if (S.pixel_aspect != 1)
+ fprintf(outfile, "Pixel Aspect Ratio: %0.6f\n", S.pixel_aspect);
+ if (T.tlength)
+ fprintf(outfile, "Thumb size: %4d x %d\n", T.twidth, T.theight);
+ fprintf(outfile, "Full size: %4d x %d\n", S.raw_width, S.raw_height);
+
+ if (S.raw_inset_crops[0].cwidth)
+ {
+ fprintf(outfile, "Raw inset, width x height: %4d x %d ", S.raw_inset_crops[0].cwidth, S.raw_inset_crops[0].cheight);
+ if (S.raw_inset_crops[0].cleft != 0xffff)
+ fprintf(outfile, "left: %d ", S.raw_inset_crops[0].cleft);
+ if (S.raw_inset_crops[0].ctop != 0xffff)
+ fprintf(outfile, "top: %d", S.raw_inset_crops[0].ctop);
+ fprintf(outfile, "\n");
+ }
+
+ fprintf(outfile, "Image size: %4d x %d\n", S.width, S.height);
+ fprintf(outfile, "Output size: %4d x %d\n", S.iwidth, S.iheight);
+ fprintf(outfile, "Image flip: %d\n", S.flip);
+
+ fprintf(outfile, "Raw colors: %d", P1.colors);
+ if (P1.filters)
+ {
+ fprintf(outfile, "\nFilter pattern: ");
+ if (!P1.cdesc[3])
+ P1.cdesc[3] = 'G';
+ for (int i = 0; i < 16; i++)
+ putchar(P1.cdesc[MyCoolRawProcessor.fcol(i >> 1, i & 1)]);
+ }
+
+ if (C.black)
+ {
+ fprintf(outfile, "\nblack: %d", C.black);
+ }
+ if (C.cblack[0] != 0)
+ {
+ fprintf(outfile, "\ncblack[0 .. 3]:");
+ for (int c = 0; c < 4; c++)
+ fprintf(outfile, " %d", C.cblack[c]);
+ }
+ if ((C.cblack[4] * C.cblack[5]) > 0)
+ {
+ fprintf(outfile, "\nBlackLevelRepeatDim: %d x %d\n", C.cblack[4], C.cblack[5]);
+ int n = C.cblack[4] * C.cblack[5];
+ fprintf(outfile, "cblack[6 .. %d]:", 6 + n - 1);
+ for (int c = 6; c < 6 + n; c++)
+ fprintf(outfile, " %d", C.cblack[c]);
+ }
+
+ if (C.linear_max[0] != 0)
+ {
+ fprintf(outfile, "\nHighlight linearity limits:");
+ for (int c = 0; c < 4; c++)
+ fprintf(outfile, " %ld", C.linear_max[c]);
+ }
+
+ if (P1.colors > 1)
+ {
+ fprintf(outfile, "\nMakernotes WB data: coeffs EVs");
+ if ((C.cam_mul[0] > 0) && (C.cam_mul[1] > 0))
+ {
+ fprintf(outfile, "\n %-23s %g %g %g %g %5.2f %5.2f %5.2f %5.2f", "As shot", C.cam_mul[0], C.cam_mul[1],
+ C.cam_mul[2], C.cam_mul[3], roundf(_log2(C.cam_mul[0] / C.cam_mul[1]) * 100.0f) / 100.0f, 0.0f,
+ roundf(_log2(C.cam_mul[2] / C.cam_mul[1]) * 100.0f) / 100.0f,
+ C.cam_mul[3] ? roundf(_log2(C.cam_mul[3] / C.cam_mul[1]) * 100.0f) / 100.0f : 0.0f);
+ }
+
+ for (int cnt = 0; cnt < int(sizeof WBToStr / sizeof *WBToStr); cnt++)
+ {
+ WBi = WBToStr[cnt].NumId;
+ if ((C.WB_Coeffs[WBi][0] > 0) && (C.WB_Coeffs[WBi][1] > 0))
+ {
+ denom = (float)C.WB_Coeffs[WBi][1];
+ fprintf(outfile, "\n %-23s %4d %4d %4d %4d %5.2f %5.2f %5.2f %5.2f", WBToStr[cnt].hrStrId,
+ C.WB_Coeffs[WBi][0], C.WB_Coeffs[WBi][1], C.WB_Coeffs[WBi][2], C.WB_Coeffs[WBi][3],
+ roundf(_log2((float)C.WB_Coeffs[WBi][0] / denom) * 100.0f) / 100.0f, 0.0f,
+ roundf(_log2((float)C.WB_Coeffs[WBi][2] / denom) * 100.0f) / 100.0f,
+ C.WB_Coeffs[3] ? roundf(_log2((float)C.WB_Coeffs[WBi][3] / denom) * 100.0f) / 100.0f : 0.0f);
+ }
+ }
+
+ if (C.rgb_cam[0][0] > 0.0001)
+ {
+ fprintf(outfile, "\n\nCamera2RGB matrix (mode: %d):\n", MyCoolRawProcessor.imgdata.params.use_camera_matrix);
+ PRINTMATRIX3x4(outfile, C.rgb_cam, P1.colors);
+ }
+
+ fprintf(outfile, "\nXYZ->CamRGB matrix:\n");
+ PRINTMATRIX4x3(outfile, C.cam_xyz, P1.colors);
+
+ for (int cnt = 0; cnt < 2; cnt++)
+ {
+ if (fabsf(C.P1_color[cnt].romm_cam[0]) > 0)
+ {
+ fprintf(outfile, "\nPhaseOne Matrix %d:\n", cnt + 1);
+ for (int i = 0; i < 3; i++)
+ fprintf(outfile, "%6.4f\t%6.4f\t%6.4f\n", C.P1_color[cnt].romm_cam[i * 3],
+ C.P1_color[cnt].romm_cam[i * 3 + 1], C.P1_color[cnt].romm_cam[i * 3 + 2]);
+ }
+ }
+
+ if (fabsf(C.cmatrix[0][0]) > 0)
+ {
+ fprintf(outfile, "\ncamRGB -> sRGB Matrix:\n");
+ PRINTMATRIX3x4(outfile, C.cmatrix, P1.colors);
+ }
+
+ if (fabsf(C.ccm[0][0]) > 0)
+ {
+ fprintf(outfile, "\nColor Correction Matrix:\n");
+ PRINTMATRIX3x4(outfile, C.ccm, P1.colors);
+ }
+
+ for (int cnt = 0; cnt < 2; cnt++)
+ {
+ if (C.dng_color[cnt].illuminant != LIBRAW_WBI_None)
+ {
+ if (C.dng_color[cnt].illuminant <= LIBRAW_WBI_StudioTungsten)
+ {
+ fprintf(outfile, "\nDNG Illuminant %d: %s", cnt + 1, WB_idx2hrstr(C.dng_color[cnt].illuminant));
+ }
+ else if (C.dng_color[cnt].illuminant == LIBRAW_WBI_Other)
+ {
+ fprintf(outfile, "\nDNG Illuminant %d: Other", cnt + 1);
+ }
+ else
+ {
+ fprintf(outfile,
+ "\nDNG Illuminant %d is out of EXIF LightSources range "
+ "[0:24, 255]: %d",
+ cnt + 1, C.dng_color[cnt].illuminant);
+ }
+ }
+ }
+
+ for (int n = 0; n < 2; n++)
+ {
+ if (fabsf(C.dng_color[n].colormatrix[0][0]) > 0)
+ {
+ fprintf(outfile, "\nDNG color matrix %d:\n", n + 1);
+ PRINTMATRIX4x3(outfile, C.dng_color[n].colormatrix, P1.colors);
+ }
+ }
+
+ for (int n = 0; n < 2; n++)
+ {
+ if (fabsf(C.dng_color[n].calibration[0][0]) > 0)
+ {
+ fprintf(outfile, "\nDNG calibration matrix %d:\n", n + 1);
+ for (int i = 0; i < P1.colors && i < 4; i++)
+ {
+ for (int j = 0; j < P1.colors && j < 4; j++)
+ fprintf(outfile, "%6.4f\t", C.dng_color[n].calibration[j][i]);
+ fprintf(outfile, "\n");
+ }
+ }
+ }
+
+ for (int n = 0; n < 2; n++)
+ {
+ if (fabsf(C.dng_color[n].forwardmatrix[0][0]) > 0)
+ {
+ fprintf(outfile, "\nDNG forward matrix %d:\n", n + 1);
+ PRINTMATRIX3x4(outfile, C.dng_color[n].forwardmatrix, P1.colors);
+ }
+ }
+
+ fprintf(outfile, "\nDerived D65 multipliers:");
+ for (int c = 0; c < P1.colors; c++)
+ fprintf(outfile, " %f", C.pre_mul[c]);
+ fprintf(outfile, "\n");
+ }
+}
+
+void print_wbfun(FILE *outfile, LibRaw &MyCoolRawProcessor, std::string &fn)
+{
+ int WBi;
+ float denom;
+ fprintf(outfile, "// %s %s\n", P1.make, P1.model);
+ for (int cnt = 0; cnt < int(sizeof WBToStr / sizeof *WBToStr); cnt++)
+ {
+ WBi = WBToStr[cnt].NumId;
+ if (C.WB_Coeffs[WBi][0] && C.WB_Coeffs[WBi][1] && !WBToStr[cnt].aux_setting)
+ {
+ denom = (float)C.WB_Coeffs[WBi][1];
+ fprintf(outfile, "{\"%s\", \"%s\", %s, {%6.5ff, 1.0f, %6.5ff, ", P1.normalized_make, P1.normalized_model,
+ WBToStr[cnt].StrId, C.WB_Coeffs[WBi][0] / denom, C.WB_Coeffs[WBi][2] / denom);
+ if (C.WB_Coeffs[WBi][1] == C.WB_Coeffs[WBi][3])
+ fprintf(outfile, "1.0f}},\n");
+ else
+ fprintf(outfile, "%6.5ff}},\n", C.WB_Coeffs[WBi][3] / denom);
+ }
+ }
+
+ for (int cnt = 0; cnt < 64; cnt++)
+ if (C.WBCT_Coeffs[cnt][0])
+ {
+ fprintf(outfile, "{\"%s\", \"%s\", %d, {%6.5ff, 1.0f, %6.5ff, ", P1.normalized_make, P1.normalized_model,
+ (int)C.WBCT_Coeffs[cnt][0], C.WBCT_Coeffs[cnt][1] / C.WBCT_Coeffs[cnt][2],
+ C.WBCT_Coeffs[cnt][3] / C.WBCT_Coeffs[cnt][2]);
+ if (C.WBCT_Coeffs[cnt][2] == C.WBCT_Coeffs[cnt][4])
+ fprintf(outfile, "1.0f}},\n");
+ else
+ fprintf(outfile, "%6.5ff}},\n", C.WBCT_Coeffs[cnt][4] / C.WBCT_Coeffs[cnt][2]);
+ }
+ else
+ break;
+ fprintf(outfile, "\n");
+}
+
+void print_szfun(FILE *outfile, LibRaw &MyCoolRawProcessor, std::string &fn)
+{
+ fprintf(outfile, "%s\t%s\t%s\t%d\t%d\n", fn.c_str(), P1.make, P1.model, S.width, S.height);
+}
+
+void print_unpackfun(FILE *outfile, LibRaw &MyCoolRawProcessor, int print_frame, std::string &fn)
+{
+ char frame[48] = "";
+ if (print_frame)
+ {
+ ushort right_margin = S.raw_width - S.width - S.left_margin;
+ ushort bottom_margin = S.raw_height - S.height - S.top_margin;
+ snprintf(frame, 48, "F=%dx%dx%dx%d RS=%dx%d", S.left_margin, S.top_margin, right_margin, bottom_margin, S.raw_width,
+ S.raw_height);
+ }
+ fprintf(outfile, "%s\t%s\t%s\t%s/%s\n", fn.c_str(), MyCoolRawProcessor.unpack_function_name(), frame, P1.make,
+ P1.model);
+}
diff --git a/libkdcraw/libraw/samples/rawtextdump.cpp b/libkdcraw/libraw/samples/rawtextdump.cpp
new file mode 100644
index 0000000..62c4c6f
--- /dev/null
+++ b/libkdcraw/libraw/samples/rawtextdump.cpp
@@ -0,0 +1,144 @@
+/* -*- C++ -*-
+ * File: raw2text.cpp
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Sun Sept 01, 2020
+ *
+ * LibRaw sample
+ * Dumps (small) selection of RAW data to text file
+ *
+
+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 <stdio.h>
+#include <string.h>
+#include <math.h>
+#ifndef WIN32
+#include <netinet/in.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include "libraw/libraw.h"
+
+void usage(const char *av)
+{
+ printf(
+ "Dump (small) selection of RAW file as tab-separated text file\n"
+ "Usage: %s inputfile COL ROW [CHANNEL] [width] [height]\n"
+ " COL - start column\n"
+ " ROW - start row\n"
+ " CHANNEL - raw channel to dump, default is 0 (red for rggb)\n"
+ " width - area width to dump, default is 16\n"
+ " height - area height to dump, default is 4\n"
+ , av);
+}
+
+unsigned subtract_bl(unsigned int val, int bl)
+{
+ return val > (unsigned)bl ? val - (unsigned)bl : 0;
+}
+
+class LibRaw_bl : public LibRaw
+{
+ public:
+ void adjust_blacklevel() { LibRaw::adjust_bl(); }
+};
+
+int main(int ac, char *av[])
+{
+ if (ac < 4)
+ {
+ usage(av[0]);
+ exit(1);
+ }
+ int colstart = atoi(av[2]);
+ int rowstart = atoi(av[3]);
+ int channel = 0;
+ if (ac > 4) channel = atoi(av[4]);
+ int width = 16;
+ if (ac > 5) width = atoi(av[5]);
+ int height = 4;
+ if (ac > 6) height = atoi(av[6]);
+ if (width <1 || height<1)
+ {
+ usage(av[0]);
+ exit(1);
+ }
+
+ LibRaw_bl lr;
+
+ if (lr.open_file(av[1]) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Unable to open file %s\n", av[1]);
+ exit(1);
+ }
+ if ((lr.imgdata.idata.colors == 1 && channel>0) || (channel >3))
+ {
+ fprintf(stderr, "Incorrect CHANNEL specified: %d\n", channel);
+ exit(1);
+ }
+ if (lr.unpack() != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Unable to unpack raw data from %s\n", av[1]);
+ exit(1);
+ }
+ lr.adjust_blacklevel();
+ printf("%s\t%d-%d-%dx%d\tchannel: %d\n", av[1], colstart, rowstart, width, height, channel);
+
+ printf("%6s", "R\\C");
+ for (int col = colstart; col < colstart + width && col < lr.imgdata.sizes.raw_width; col++)
+ printf("%6u", col);
+ printf("\n");
+
+ if (lr.imgdata.rawdata.raw_image)
+ {
+ for (int row = rowstart; row < rowstart + height && row < lr.imgdata.sizes.raw_height; row++)
+ {
+ unsigned rcolors[48];
+ if (lr.imgdata.idata.colors > 1)
+ for (int c = 0; c < 48; c++)
+ rcolors[c] = lr.COLOR(row, c);
+ else
+ memset(rcolors, 0, sizeof(rcolors));
+ unsigned short *rowdata = &lr.imgdata.rawdata.raw_image[row * lr.imgdata.sizes.raw_pitch / 2];
+ printf("%6u", row);
+ for (int col = colstart; col < colstart + width && col < lr.imgdata.sizes.raw_width; col++)
+ if (rcolors[col % 48] == (unsigned)channel) printf("%6u", subtract_bl(rowdata[col],lr.imgdata.color.cblack[channel]));
+ else printf(" -");
+ printf("\n");
+ }
+ }
+ else if (lr.imgdata.rawdata.color4_image && channel < 4)
+ {
+ for (int row = rowstart; row < rowstart + height && row < lr.imgdata.sizes.raw_height; row++)
+ {
+ unsigned short(*rowdata)[4] = &lr.imgdata.rawdata.color4_image[row * lr.imgdata.sizes.raw_pitch / 8];
+ printf("%6u", row);
+ for (int col = colstart; col < colstart + width && col < lr.imgdata.sizes.raw_width; col++)
+ printf("%6u", subtract_bl(rowdata[col][channel],lr.imgdata.color.cblack[channel]));
+ printf("\n");
+ }
+ }
+ else if (lr.imgdata.rawdata.color3_image && channel < 3)
+ {
+ for (int row = rowstart; row < rowstart + height && row < lr.imgdata.sizes.raw_height; row++)
+ {
+ unsigned short(*rowdata)[3] = &lr.imgdata.rawdata.color3_image[row * lr.imgdata.sizes.raw_pitch / 6];
+ printf("%6u", row);
+ for (int col = colstart; col < colstart + width && col < lr.imgdata.sizes.raw_width; col++)
+ printf("%6u", subtract_bl(rowdata[col][channel],lr.imgdata.color.cblack[channel]));
+ printf("\n");
+ }
+ }
+ else
+ printf("Unsupported file data (e.g. floating point format), or incorrect channel specified\n");
+}
diff --git a/libkdcraw/libraw/samples/simple_dcraw.cpp b/libkdcraw/libraw/samples/simple_dcraw.cpp
index e69bdf9..f96b23c 100644
--- a/libkdcraw/libraw/samples/simple_dcraw.cpp
+++ b/libkdcraw/libraw/samples/simple_dcraw.cpp
@@ -1,213 +1,217 @@
-/*
+/* -*- C++ -*-
* File: simple_dcraw.cpp
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
- * Created: Sat Mar 8 , 2008
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ * Created: Sat Mar 8, 2008
*
- * LibRaw simple C++ API (emulates call to "dcraw [-D] [-T] [-v] [-e] [-4]")
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+ * LibRaw simple C++ API: emulates call to "dcraw [-D] [-T] [-v] [-e] [-4]"
+
+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 <stdio.h>
#include <string.h>
#include <math.h>
-#ifndef WIN32
+#include "libraw/libraw.h"
+
+#ifndef LIBRAW_WIN32_CALLS
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#endif
-#include "libraw/libraw.h"
-
-#ifdef WIN32
+#ifdef LIBRAW_WIN32_CALLS
#define snprintf _snprintf
#endif
-int my_progress_callback(void *unused_data,enum LibRaw_progress state,int iter, int expected)
+int my_progress_callback(void *unused_data, enum LibRaw_progress state,
+ int iter, int expected)
{
- if(iter==0)
- printf("CB: state=%x, expected %d iterations\n",state,expected);
- return 0;
+ if (iter == 0)
+ printf("CB: state=%x, expected %d iterations\n", state, expected);
+ return 0;
}
+char *customCameras[] = {
+ (char *)"43704960,4080,5356, 0, 0, 0, 0,0,148,0,0, Dalsa, FTF4052C Full,0",
+ (char *)"42837504,4008,5344, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 3:4",
+ (char *)"32128128,4008,4008, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 1:1",
+ (char *)"24096096,4008,3006, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 4:3",
+ (char *)"18068064,4008,2254, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 16:9",
+ (char *)"67686894,5049,6703, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C Full",
+ (char *)"66573312,4992,6668, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 3:4",
+ (char *)"49840128,4992,4992, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 1:1",
+ (char *)"37400064,4992,3746, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 4:3",
+ (char *)"28035072,4992,2808, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 16:9",
+ NULL};
int main(int ac, char *av[])
{
- int i, ret, verbose=0, output_thumbs=0,use_mmap=0,msize;
- void *file_buffer;
-
- // don't use fixed size buffers in real apps!
- char outfn[1024],thumbfn[1024];
-
- LibRaw RawProcessor;
- if(ac<2)
+ int i, ret, verbose = 0, output_thumbs = 0, output_all_thumbs = 0;
+
+ // don't use fixed size buffers in real apps!
+ char outfn[1024], thumbfn[1024];
+
+ LibRaw* RawProcessor = new LibRaw;
+ RawProcessor->imgdata.rawparams.custom_camera_strings = customCameras;
+ if (ac < 2)
+ {
+ printf("simple_dcraw - LibRaw %s sample. Emulates dcraw [-D] [-T] [-v] "
+ "[-e] [-E]\n"
+ " %d cameras supported\n"
+ "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n"
+ "\t-4 - 16-bit mode\n"
+ "\t-L - list supported cameras and exit\n"
+ "\t-v - verbose output\n"
+ "\t-T - output TIFF files instead of .pgm/ppm\n"
+ "\t-e - extract thumbnails (same as dcraw -e in separate run)\n"
+ "\t-E - extract all thumbnails\n",
+ LibRaw::version(), LibRaw::cameraCount(), av[0]);
+ delete RawProcessor;
+ return 0;
+ }
+
+ putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
+
+#define P1 RawProcessor->imgdata.idata
+#define S RawProcessor->imgdata.sizes
+#define C RawProcessor->imgdata.color
+#define T RawProcessor->imgdata.thumbnail
+#define P2 RawProcessor->imgdata.other
+#define OUT RawProcessor->imgdata.params
+
+ for (i = 1; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ if (av[i][1] == 'T' && av[i][2] == 0)
+ OUT.output_tiff = 1;
+ if (av[i][1] == 'v' && av[i][2] == 0)
+ verbose++;
+ if (av[i][1] == 'e' && av[i][2] == 0)
+ output_thumbs++;
+ if (av[i][1] == 'E' && av[i][2] == 0)
+ {
+ output_thumbs++;
+ output_all_thumbs++;
+ }
+ if (av[i][1] == '4' && av[i][2] == 0)
+ OUT.output_bps = 16;
+ if (av[i][1] == 'C' && av[i][2] == 0)
+ RawProcessor->set_progress_handler(my_progress_callback, NULL);
+ if (av[i][1] == 'L' && av[i][2] == 0)
+ {
+ const char **clist = LibRaw::cameraList();
+ const char **cc = clist;
+ while (*cc)
{
- printf(
- "simple_dcraw - LibRaw %s sample. Emulates dcraw [-D] [-T] [-v] [-e] [-B]\n"
- " %d cameras supported\n"
- "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n"
- "\t-D - document mode emulation\n"
- "\t-4 - 16-bit mode\n"
- "\t-v - verbose output\n"
- "\t-T - output TIFF files instead of .pgm/ppm\n"
-#ifndef WIN32
- "\t-B - use mmap()-ed I/O (Unix only)\n"
-#endif
- "\t-e - extract thumbnails (same as dcraw -e in separate run)\n",LibRaw::version(),
- LibRaw::cameraCount(),
- av[0]);
- return 0;
+ printf("%s\n", *cc);
+ cc++;
}
-
- putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
-
-#define P1 RawProcessor.imgdata.idata
-#define S RawProcessor.imgdata.sizes
-#define C RawProcessor.imgdata.color
-#define T RawProcessor.imgdata.thumbnail
-#define P2 RawProcessor.imgdata.other
-#define OUT RawProcessor.imgdata.params
-
-
- for (i=1;i<ac;i++)
+ delete RawProcessor;
+ exit(0);
+ }
+ continue;
+ }
+
+ if (verbose)
+ printf("Processing file %s\n", av[i]);
+
+ if ((ret = RawProcessor->open_file(av[i])) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot open_file %s: %s\n", av[i], libraw_strerror(ret));
+ continue; // no recycle b/c open file will recycle itself
+ }
+
+ if (!output_thumbs) // No unpack for thumb extraction
+ if ((ret = RawProcessor->unpack()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
+ continue;
+ }
+
+ // thumbnail unpacking and output in the middle of main
+ // image processing - for test purposes!
+ if(output_all_thumbs)
+ {
+ if (verbose)
+ printf("Extracting %d thumbnails\n", RawProcessor->imgdata.thumbs_list.thumbcount);
+ for (int t = 0; t < RawProcessor->imgdata.thumbs_list.thumbcount; t++)
+ {
+ if ((ret = RawProcessor->unpack_thumb_ex(t)) != LIBRAW_SUCCESS)
+ fprintf(stderr, "Cannot unpack_thumb #%d from %s: %s\n", t, av[i], libraw_strerror(ret));
+ if (LIBRAW_FATAL_ERROR(ret))
+ break; // skip to next file
+ snprintf(thumbfn, sizeof(thumbfn), "%s.thumb.%d.%s", av[i], t,
+ T.tformat == LIBRAW_THUMBNAIL_JPEG ? "jpg" : "ppm");
+ if (verbose)
+ printf("Writing thumbnail file %s\n", thumbfn);
+ if (LIBRAW_SUCCESS != (ret = RawProcessor->dcraw_thumb_writer(thumbfn)))
{
- if(av[i][0]=='-')
- {
- if(av[i][1]=='T' && av[i][2]==0)
- OUT.output_tiff=1;
- if(av[i][1]=='v' && av[i][2]==0)
- verbose++;
- if(av[i][1]=='e' && av[i][2]==0)
- output_thumbs++;
- if(av[i][1]=='D' && av[i][2]==0)
- OUT.document_mode=2;
- if(av[i][1]=='B' && av[i][2]==0)
- use_mmap=1;
- if(av[i][1]=='4' && av[i][2]==0)
- OUT.output_bps=16;
- if(av[i][1]=='C' && av[i][2]==0)
- RawProcessor.set_progress_handler(my_progress_callback,NULL);
- continue;
- }
-
- if(verbose) printf("Processing file %s\n",av[i]);
-
-#ifndef WIN32
- if(use_mmap)
- {
- int file = open(av[i],O_RDONLY);
- struct stat st;
- if(file<0)
- {
- fprintf(stderr,"Cannot open %s: %s\n",av[i],strerror(errno));
- continue;
- }
- if(fstat(file,&st))
- {
- fprintf(stderr,"Cannot stat %s: %s\n",av[i],strerror(errno));
- close(file);
- continue;
- }
- int pgsz = getpagesize();
- msize = ((st.st_size+pgsz-1)/pgsz)*pgsz;
- file_buffer = mmap(NULL,msize,PROT_READ,MAP_PRIVATE,file,0);
- if(!file_buffer)
- {
- fprintf(stderr,"Cannot mmap %s: %s\n",av[i],strerror(errno));
- close(file);
- continue;
- }
- close(file);
- if( (ret = RawProcessor.open_buffer(file_buffer,st.st_size) != LIBRAW_SUCCESS))
- {
- fprintf(stderr,"Cannot open_buffer %s: %s\n",av[i],libraw_strerror(ret));
- continue; // no recycle b/c open file will recycle itself
- }
- }
- else
-#endif
- {
- if( (ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot open_file %s: %s\n",av[i],libraw_strerror(ret));
- continue; // no recycle b/c open file will recycle itself
- }
- }
-
- if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot unpack %s: %s\n",av[i],libraw_strerror(ret));
- continue;
- }
-
- // thumbnail unpacking and output in the middle of main
- // image processing - for test purposes!
- if(output_thumbs)
- {
- if( (ret = RawProcessor.unpack_thumb() ) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot unpack_thumb %s: %s\n",av[i],libraw_strerror(ret));
- if(LIBRAW_FATAL_ERROR(ret))
- continue; // skip to next file
- }
- else
- {
- snprintf(thumbfn,sizeof(thumbfn),"%s.%s",
- av[i],T.tformat == LIBRAW_THUMBNAIL_JPEG ? "thumb.jpg" : "thumb.ppm");
-
- if(verbose) printf("Writing thumbnail file %s\n",thumbfn);
- if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_thumb_writer(thumbfn)))
- {
- fprintf(stderr,"Cannot write %s: %s\n",thumbfn,libraw_strerror(ret));
- if(LIBRAW_FATAL_ERROR(ret))
- continue;
- }
- }
- }
-
- if(OUT.document_mode)
- ret = RawProcessor.dcraw_document_mode_processing();
- else
- ret = RawProcessor.dcraw_process();
-
- if(LIBRAW_SUCCESS !=ret)
- {
- fprintf(stderr,"Cannot do postpocessing on %s: %s\n",
- av[i],libraw_strerror(ret));
- if(LIBRAW_FATAL_ERROR(ret))
- continue;
- }
- snprintf(outfn,sizeof(outfn),
- "%s.%s",
- av[i], OUT.output_tiff ? "tiff" : (P1.colors>1?"ppm":"pgm"));
-
- if(verbose) printf("Writing file %s\n",outfn);
-
- if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
- fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret));
-
-#ifndef WIN32
- if(use_mmap && file_buffer)
- {
- munmap(file_buffer,msize);
- file_buffer=0;
- }
-#endif
- RawProcessor.recycle(); // just for show this call
+ fprintf(stderr, "Cannot write %s: %s\n", thumbfn, libraw_strerror(ret));
+ if (LIBRAW_FATAL_ERROR(ret))
+ break;
}
- return 0;
+ }
+ continue;
+ }
+ else if (output_thumbs)
+ {
+ if ((ret = RawProcessor->unpack_thumb()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack_thumb %s: %s\n", av[i],
+ libraw_strerror(ret));
+ if (LIBRAW_FATAL_ERROR(ret))
+ continue; // skip to next file
+ }
+ else
+ {
+ snprintf(thumbfn, sizeof(thumbfn), "%s.%s", av[i],
+ T.tformat == LIBRAW_THUMBNAIL_JPEG ? "thumb.jpg"
+ : (T.tcolors == 1? "thumb.pgm" : "thumb.ppm"));
+ if (verbose)
+ printf("Writing thumbnail file %s\n", thumbfn);
+ if (LIBRAW_SUCCESS != (ret = RawProcessor->dcraw_thumb_writer(thumbfn)))
+ {
+ fprintf(stderr, "Cannot write %s: %s\n", thumbfn,
+ libraw_strerror(ret));
+ if (LIBRAW_FATAL_ERROR(ret))
+ continue;
+ }
+ }
+ continue;
+ }
+
+ ret = RawProcessor->dcraw_process();
+
+ if (LIBRAW_SUCCESS != ret)
+ {
+ fprintf(stderr, "Cannot do postprocessing on %s: %s\n", av[i],
+ libraw_strerror(ret));
+ if (LIBRAW_FATAL_ERROR(ret))
+ continue;
+ }
+ snprintf(outfn, sizeof(outfn), "%s.%s", av[i],
+ OUT.output_tiff ? "tiff" : (P1.colors > 1 ? "ppm" : "pgm"));
+
+ if (verbose)
+ printf("Writing file %s\n", outfn);
+
+ if (LIBRAW_SUCCESS != (ret = RawProcessor->dcraw_ppm_tiff_writer(outfn)))
+ fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret));
+
+ RawProcessor->recycle(); // just for show this call
+ }
+
+ delete RawProcessor;
+ return 0;
}
diff --git a/libkdcraw/libraw/samples/unprocessed_raw.cpp b/libkdcraw/libraw/samples/unprocessed_raw.cpp
index 9e8dd65..2f30ce4 100644
--- a/libkdcraw/libraw/samples/unprocessed_raw.cpp
+++ b/libkdcraw/libraw/samples/unprocessed_raw.cpp
@@ -1,156 +1,319 @@
-/*
+/* -*- C++ -*-
* File: unprocessed_raw.cpp
- * Copyright 2009 Alex Tutubalin <[email protected]>
+ * Copyright 2009-2021 LibRaw LLC ([email protected])
* Created: Fri Jan 02, 2009
*
* LibRaw sample
- * Generates unprocessed raw image: with masked pixels and without black subtraction
+ * Generates unprocessed raw image: with masked pixels and without black
+subtraction
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+
+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 <stdio.h>
#include <string.h>
#include <math.h>
-#ifndef WIN32
+#include <time.h>
+
+#include "libraw/libraw.h"
+
+#ifndef LIBRAW_WIN32_CALLS
#include <netinet/in.h>
#else
+#include <sys/utime.h>
#include <winsock2.h>
#endif
-#include "libraw/libraw.h"
-
-#ifdef WIN32
+#ifdef LIBRAW_WIN32_CALLS
#define snprintf _snprintf
#endif
+#if !(LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0, 14))
+#error This code is for LibRaw 0.14+ only
+#endif
+
+void gamma_curve(unsigned short curve[]);
+void write_ppm(unsigned width, unsigned height, unsigned short *bitmap,
+ const char *basename);
+void write_tiff(int width, int height, unsigned short *bitmap,
+ const char *basename);
+
int main(int ac, char *av[])
{
- int i, ret;
- int verbose=1,autoscale=0;
- char outfn[1024],thumbfn[1024];
-
- LibRaw RawProcessor;
- if(ac<2)
- {
- usage:
- printf(
- "unprocessed_raw - LibRaw %s sample. %d cameras supported\n"
- "Usage: %s [-q] [-A] [-g] [-s N] [-N] raw-files....\n"
- "\t-q - be quiet\n"
- "\t-s N - select Nth image in file (default=0)\n"
- "\t-g - use gamma correction with gamma 2.2 (not precise,use for visual inspection only)\n"
- "\t-A - autoscaling (by integer factor)\n"
- "\t-N - no raw curve\n"
- ,LibRaw::version(),
- LibRaw::cameraCount(),
- av[0]);
- return 0;
- }
-
-#define P1 RawProcessor.imgdata.idata
+ int i, ret;
+ int verbose = 1, autoscale = 0, use_gamma = 0, out_tiff = 0;
+ char outfn[1024];
+
+ LibRaw RawProcessor;
+ if (ac < 2)
+ {
+ usage:
+ printf("unprocessed_raw - LibRaw %s sample. %d cameras supported\n"
+ "Usage: %s [-q] [-A] [-g] [-s N] raw-files....\n"
+ "\t-q - be quiet\n"
+ "\t-s N - select Nth image in file (default=0)\n"
+ "\t-g - use gamma correction with gamma 2.2 (not precise,use for "
+ "visual inspection only)\n"
+ "\t-A - autoscaling (by integer factor)\n"
+ "\t-T - write tiff instead of pgm\n",
+ LibRaw::version(), LibRaw::cameraCount(), av[0]);
+ return 0;
+ }
+
#define S RawProcessor.imgdata.sizes
-#define C RawProcessor.imgdata.color
-#define T RawProcessor.imgdata.thumbnail
-#define P2 RawProcessor.imgdata.other
#define OUT RawProcessor.imgdata.params
+#define OUTR RawProcessor.imgdata.rawparams
- OUT.document_mode=2;
- OUT.output_bps=16;
- OUT.output_tiff=1;
- OUT.user_flip=0;
- OUT.no_auto_bright = 1;
- OUT.filtering_mode=(LibRaw_filtering)( LIBRAW_FILTERING_NOBLACKS|LIBRAW_FILTERING_NOZEROES);
- for (i=1;i<ac;i++)
- {
- if(av[i][0]=='-')
- {
- if(av[i][1]=='q' && av[i][2]==0)
- verbose=0;
- else if(av[i][1]=='A' && av[i][2]==0)
- autoscale=1;
- else if(av[i][1]=='g' && av[i][2]==0)
- OUT.gamma_16bit=1;
- else if(av[i][1]=='N' && av[i][2]==0)
- OUT.filtering_mode=LIBRAW_FILTERING_NONE;
- else if(av[i][1]=='s' && av[i][2]==0)
- {
- i++;
- OUT.shot_select=atoi(av[i]);
- }
- else
- goto usage;
- continue;
- }
- int r,c;
- if(verbose) printf("Processing file %s\n",av[i]);
- if( (ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot open %s: %s\n",av[i],libraw_strerror(ret));
- continue; // no recycle b/c open file will recycle itself
- }
- if(verbose)
- {
- printf("Image size: %dx%d\nRaw size: %dx%d\n",S.width,S.height,S.raw_width,S.raw_height);
- printf("Margins: top=%d, left=%d, right=%d, bottom=%d\n",
- S.top_margin,S.left_margin,S.right_margin,S.bottom_margin);
- }
-
- if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot unpack %s: %s\n",av[i],libraw_strerror(ret));
- continue;
- }
- if(verbose)
- printf("Unpacked....\n");
-
- if( (ret = RawProcessor.add_masked_borders_to_bitmap() ) != LIBRAW_SUCCESS)
- {
- fprintf(stderr,"Cannot add mask data to bitmap %s\n",av[i]);
- }
- for(int r=0;r<S.iheight;r++)
- for(c=0;c<S.iwidth;c++)
- RawProcessor.imgdata.image[r*S.iwidth+c][0]
- = RawProcessor.imgdata.image[r*S.iwidth+c][RawProcessor.FC(r,c)];
-
- P1.colors=1;
- if(autoscale)
- {
- unsigned max=0,scale;
- for(int j=0; j<S.iheight*S.iwidth; j++)
- if(max < RawProcessor.imgdata.image[j][0])
- max = RawProcessor.imgdata.image[j][0];
- if (max >0 && max< 1<<15)
- {
- scale = (1<<16)/max;
- if(verbose)
- printf("Scaling with multiplier=%d (max=%d)\n",scale,max);
-
- for(int j=0; j<S.iheight*S.iwidth; j++)
- RawProcessor.imgdata.image[j][0] *= scale;
- }
- }
-
- if(OUT.shot_select)
- snprintf(outfn,sizeof(outfn),"%s-%d.tiff",av[i],OUT.shot_select);
- else
- snprintf(outfn,sizeof(outfn),"%s.tiff",av[i]);
-
- if(verbose) printf("Writing file %s\n",outfn);
- if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
- fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret));
- }
- return 0;
+ for (i = 1; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ if (av[i][1] == 'q' && av[i][2] == 0)
+ verbose = 0;
+ else if (av[i][1] == 'A' && av[i][2] == 0)
+ autoscale = 1;
+ else if (av[i][1] == 'g' && av[i][2] == 0)
+ use_gamma = 1;
+ else if (av[i][1] == 'T' && av[i][2] == 0)
+ out_tiff = 1;
+ else if (av[i][1] == 's' && av[i][2] == 0)
+ {
+ i++;
+ OUTR.shot_select = av[i] ? atoi(av[i]) : 0;
+ }
+ else
+ goto usage;
+ continue;
+ }
+
+ if (verbose)
+ printf("Processing file %s\n", av[i]);
+ if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret));
+ continue; // no recycle b/c open file will recycle itself
+ }
+ if (verbose)
+ {
+ printf("Image size: %dx%d\nRaw size: %dx%d\n", S.width, S.height,
+ S.raw_width, S.raw_height);
+ printf("Margins: top=%d, left=%d\n", S.top_margin, S.left_margin);
+ }
+
+ if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
+ {
+ fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
+ continue;
+ }
+
+ if (verbose)
+ printf("Unpacked....\n");
+
+ if (!(RawProcessor.imgdata.idata.filters ||
+ RawProcessor.imgdata.idata.colors == 1))
+ {
+ printf("Only Bayer-pattern RAW files supported, sorry....\n");
+ continue;
+ }
+
+ if (autoscale)
+ {
+ unsigned max = 0, scale;
+ for (int j = 0; j < S.raw_height * S.raw_width; j++)
+ if (max < RawProcessor.imgdata.rawdata.raw_image[j])
+ max = RawProcessor.imgdata.rawdata.raw_image[j];
+ if (max > 0 && max < 1 << 15)
+ {
+ scale = (1 << 16) / max;
+ if (verbose)
+ printf("Scaling with multiplier=%d (max=%d)\n", scale, max);
+
+ for (int j = 0; j < S.raw_height * S.raw_width; j++)
+ RawProcessor.imgdata.rawdata.raw_image[j] *= scale;
+ }
+ }
+ if (use_gamma)
+ {
+ unsigned short curve[0x10000];
+ gamma_curve(curve);
+ for (int j = 0; j < S.raw_height * S.raw_width; j++)
+ RawProcessor.imgdata.rawdata.raw_image[j] =
+ curve[RawProcessor.imgdata.rawdata.raw_image[j]];
+ if (verbose)
+ printf("Gamma-corrected....\n");
+ }
+
+ if (OUTR.shot_select)
+ snprintf(outfn, sizeof(outfn), "%s-%d.%s", av[i], OUTR.shot_select,
+ out_tiff ? "tiff" : "pgm");
+ else
+ snprintf(outfn, sizeof(outfn), "%s.%s", av[i], out_tiff ? "tiff" : "pgm");
+
+ if (out_tiff)
+ write_tiff(S.raw_width, S.raw_height,
+ RawProcessor.imgdata.rawdata.raw_image, outfn);
+ else
+ write_ppm(S.raw_width, S.raw_height,
+ RawProcessor.imgdata.rawdata.raw_image, outfn);
+
+ if (verbose)
+ printf("Stored to file %s\n", outfn);
+ }
+ return 0;
+}
+
+void write_ppm(unsigned width, unsigned height, unsigned short *bitmap,
+ const char *fname)
+{
+ if (!bitmap)
+ return;
+
+ FILE *f = fopen(fname, "wb");
+ if (!f)
+ return;
+ int bits = 16;
+ fprintf(f, "P5\n%d %d\n%d\n", width, height, (1 << bits) - 1);
+ unsigned char *data = (unsigned char *)bitmap;
+ unsigned data_size = width * height * 2;
+#define SWAP(a, b) \
+ { \
+ a ^= b; \
+ a ^= (b ^= a); \
+ }
+ for (unsigned i = 0; i < data_size; i += 2)
+ SWAP(data[i], data[i + 1]);
+#undef SWAP
+ fwrite(data, data_size, 1, f);
+ fclose(f);
+}
+
+/* == gamma curve and tiff writer - simplified cut'n'paste from dcraw.c */
+
+#define SQR(x) ((x) * (x))
+
+void gamma_curve(unsigned short *curve)
+{
+
+ double pwr = 1.0 / 2.2;
+ double ts = 0.0;
+ int imax = 0xffff;
+ int mode = 2;
+ int i;
+ double g[6], bnd[2] = {0, 0}, r;
+
+ g[0] = pwr;
+ g[1] = ts;
+ g[2] = g[3] = g[4] = 0;
+ bnd[g[1] >= 1] = 1;
+ if (g[1] && (g[1] - 1) * (g[0] - 1) <= 0)
+ {
+ for (i = 0; i < 48; i++)
+ {
+ g[2] = (bnd[0] + bnd[1]) / 2;
+ if (g[0])
+ bnd[(pow(g[2] / g[1], -g[0]) - 1) / g[0] - 1 / g[2] > -1] = g[2];
+ else
+ bnd[g[2] / exp(1 - 1 / g[2]) < g[1]] = g[2];
+ }
+ g[3] = g[2] / g[1];
+ if (g[0])
+ g[4] = g[2] * (1 / g[0] - 1);
+ }
+ if (g[0])
+ g[5] = 1 / (g[1] * SQR(g[3]) / 2 - g[4] * (1 - g[3]) +
+ (1 - pow(g[3], 1 + g[0])) * (1 + g[4]) / (1 + g[0])) -
+ 1;
+ else
+ g[5] = 1 / (g[1] * SQR(g[3]) / 2 + 1 - g[2] - g[3] -
+ g[2] * g[3] * (log(g[3]) - 1)) -
+ 1;
+ for (i = 0; i < 0x10000; i++)
+ {
+ curve[i] = 0xffff;
+ if ((r = (double)i / imax) < 1)
+ curve[i] =
+ 0x10000 *
+ (mode ? (r < g[3] ? r * g[1]
+ : (g[0] ? pow(r, g[0]) * (1 + g[4]) - g[4]
+ : log(r) * g[2] + 1))
+ : (r < g[2] ? r / g[1]
+ : (g[0] ? pow((r + g[4]) / (1 + g[4]), 1 / g[0])
+ : exp((r - 1) / g[2]))));
+ }
+}
+
+void tiff_set(ushort *ntag, ushort tag, ushort type, int count, int val)
+{
+ struct libraw_tiff_tag *tt;
+ int c;
+
+ tt = (struct libraw_tiff_tag *)(ntag + 1) + (*ntag)++;
+ tt->tag = tag;
+ tt->type = type;
+ tt->count = count;
+ if ((type < LIBRAW_EXIFTAG_TYPE_SHORT) && (count <= 4))
+ for (c = 0; c < 4; c++)
+ tt->val.c[c] = val >> (c << 3);
+ else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) && (count <= 2))
+ for (c = 0; c < 2; c++)
+ tt->val.s[c] = val >> (c << 4);
+ else
+ tt->val.i = val;
+}
+#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
+
+void tiff_head(int width, int height, struct tiff_hdr *th)
+{
+ int c;
+ time_t timestamp = time(NULL);
+ struct tm *t;
+
+ memset(th, 0, sizeof *th);
+ th->t_order = htonl(0x4d4d4949) >> 16;
+ th->magic = 42;
+ th->ifd = 10;
+ tiff_set(&th->ntag, 254, 4, 1, 0);
+ tiff_set(&th->ntag, 256, 4, 1, width);
+ tiff_set(&th->ntag, 257, 4, 1, height);
+ tiff_set(&th->ntag, 258, 3, 1, 16);
+ for (c = 0; c < 4; c++)
+ th->bps[c] = 16;
+ tiff_set(&th->ntag, 259, 3, 1, 1);
+ tiff_set(&th->ntag, 262, 3, 1, 1);
+ tiff_set(&th->ntag, 273, 4, 1, sizeof *th);
+ tiff_set(&th->ntag, 277, 3, 1, 1);
+ tiff_set(&th->ntag, 278, 4, 1, height);
+ tiff_set(&th->ntag, 279, 4, 1, height * width * 2);
+ tiff_set(&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
+ tiff_set(&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
+ tiff_set(&th->ntag, 284, 3, 1, 1);
+ tiff_set(&th->ntag, 296, 3, 1, 2);
+ tiff_set(&th->ntag, 306, 2, 20, TOFF(th->date));
+ th->rat[0] = th->rat[2] = 300;
+ th->rat[1] = th->rat[3] = 1;
+ t = localtime(&timestamp);
+ if (t)
+ sprintf(th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year + 1900,
+ t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
+}
+
+void write_tiff(int width, int height, unsigned short *bitmap, const char *fn)
+{
+ struct tiff_hdr th;
+
+ FILE *ofp = fopen(fn, "wb");
+ if (!ofp)
+ return;
+ tiff_head(width, height, &th);
+ fwrite(&th, sizeof th, 1, ofp);
+ fwrite(bitmap, 2, width * height, ofp);
+ fclose(ofp);
}
diff --git a/libkdcraw/libraw/src/Makefile b/libkdcraw/libraw/src/Makefile
new file mode 100644
index 0000000..a54d1a4
--- /dev/null
+++ b/libkdcraw/libraw/src/Makefile
@@ -0,0 +1,2 @@
+all:
+ (cd ..; make library)
diff --git a/libkdcraw/libraw/src/decoders/canon_600.cpp b/libkdcraw/libraw/src/decoders/canon_600.cpp
new file mode 100644
index 0000000..59576f1
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/canon_600.cpp
@@ -0,0 +1,225 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::canon_600_fixed_wb(int temp)
+{
+ static const short mul[4][5] = {{667, 358, 397, 565, 452},
+ {731, 390, 367, 499, 517},
+ {1119, 396, 348, 448, 537},
+ {1399, 485, 431, 508, 688}};
+ int lo, hi, i;
+ float frac = 0;
+
+ for (lo = 4; --lo;)
+ if (*mul[lo] <= temp)
+ break;
+ for (hi = 0; hi < 3; hi++)
+ if (*mul[hi] >= temp)
+ break;
+ if (lo != hi)
+ frac = (float)(temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
+ for (i = 1; i < 5; i++)
+ pre_mul[i - 1] = 1 / (frac * mul[hi][i] + (1 - frac) * mul[lo][i]);
+}
+
+/* Return values: 0 = white 1 = near white 2 = not white */
+int LibRaw::canon_600_color(int ratio[2], int mar)
+{
+ int clipped = 0, target, miss;
+
+ if (flash_used)
+ {
+ if (ratio[1] < -104)
+ {
+ ratio[1] = -104;
+ clipped = 1;
+ }
+ if (ratio[1] > 12)
+ {
+ ratio[1] = 12;
+ clipped = 1;
+ }
+ }
+ else
+ {
+ if (ratio[1] < -264 || ratio[1] > 461)
+ return 2;
+ if (ratio[1] < -50)
+ {
+ ratio[1] = -50;
+ clipped = 1;
+ }
+ if (ratio[1] > 307)
+ {
+ ratio[1] = 307;
+ clipped = 1;
+ }
+ }
+ target = flash_used || ratio[1] < 197 ? -38 - (398 * ratio[1] >> 10)
+ : -123 + (48 * ratio[1] >> 10);
+ if (target - mar <= ratio[0] && target + 20 >= ratio[0] && !clipped)
+ return 0;
+ miss = target - ratio[0];
+ if (abs(miss) >= mar * 4)
+ return 2;
+ if (miss < -20)
+ miss = -20;
+ if (miss > mar)
+ miss = mar;
+ ratio[0] = target - miss;
+ return 1;
+}
+
+void LibRaw::canon_600_auto_wb()
+{
+ int mar, row, col, i, j, st, count[] = {0, 0};
+ int test[8], total[2][8], ratio[2][2], stat[2];
+
+ memset(&total, 0, sizeof total);
+ i = int(canon_ev + 0.5);
+ if (i < 10)
+ mar = 150;
+ else if (i > 12)
+ mar = 20;
+ else
+ mar = 280 - 20 * i;
+ if (flash_used)
+ mar = 80;
+ for (row = 14; row < height - 14; row += 4)
+ for (col = 10; col < width; col += 2)
+ {
+ for (i = 0; i < 8; i++)
+ test[(i & 4) + FC(row + (i >> 1), col + (i & 1))] =
+ BAYER(row + (i >> 1), col + (i & 1));
+ for (i = 0; i < 8; i++)
+ if (test[i] < 150 || test[i] > 1500)
+ goto next;
+ for (i = 0; i < 4; i++)
+ if (abs(test[i] - test[i + 4]) > 50)
+ goto next;
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 4; j += 2)
+ ratio[i][j >> 1] =
+ ((test[i * 4 + j + 1] - test[i * 4 + j]) << 10) / test[i * 4 + j];
+ stat[i] = canon_600_color(ratio[i], mar);
+ }
+ if ((st = stat[0] | stat[1]) > 1)
+ goto next;
+ for (i = 0; i < 2; i++)
+ if (stat[i])
+ for (j = 0; j < 2; j++)
+ test[i * 4 + j * 2 + 1] =
+ test[i * 4 + j * 2] * (0x400 + ratio[i][j]) >> 10;
+ for (i = 0; i < 8; i++)
+ total[st][i] += test[i];
+ count[st]++;
+ next:;
+ }
+ if (count[0] | count[1])
+ {
+ st = count[0] * 200 < count[1];
+ for (i = 0; i < 4; i++)
+ if (total[st][i] + total[st][i + 4])
+ pre_mul[i] = 1.0f / (total[st][i] + total[st][i + 4]);
+ }
+}
+
+void LibRaw::canon_600_coeff()
+{
+ static const short table[6][12] = {
+ {-190, 702, -1878, 2390, 1861, -1349, 905, -393, -432, 944, 2617, -2105},
+ {-1203, 1715, -1136, 1648, 1388, -876, 267, 245, -1641, 2153, 3921,
+ -3409},
+ {-615, 1127, -1563, 2075, 1437, -925, 509, 3, -756, 1268, 2519, -2007},
+ {-190, 702, -1886, 2398, 2153, -1641, 763, -251, -452, 964, 3040, -2528},
+ {-190, 702, -1878, 2390, 1861, -1349, 905, -393, -432, 944, 2617, -2105},
+ {-807, 1319, -1785, 2297, 1388, -876, 769, -257, -230, 742, 2067, -1555}};
+ int t = 0, i, c;
+ float mc, yc;
+
+ mc = pre_mul[1] / pre_mul[2];
+ yc = pre_mul[3] / pre_mul[2];
+ if (mc > 1 && mc <= 1.28 && yc < 0.8789)
+ t = 1;
+ if (mc > 1.28 && mc <= 2)
+ {
+ if (yc < 0.8789)
+ t = 3;
+ else if (yc <= 2)
+ t = 4;
+ }
+ if (flash_used)
+ t = 5;
+ for (raw_color = i = 0; i < 3; i++)
+ FORCC rgb_cam[i][c] = float(table[t][i * 4 + c]) / 1024.f;
+}
+
+void LibRaw::canon_600_load_raw()
+{
+ uchar data[1120], *dp;
+ ushort *pix;
+ int irow, row;
+
+ for (irow = row = 0; irow < height; irow++)
+ {
+ checkCancel();
+ if (fread(data, 1, 1120, ifp) < 1120)
+ derror();
+ pix = raw_image + row * raw_width;
+ for (dp = data; dp < data + 1120; dp += 10, pix += 8)
+ {
+ pix[0] = (dp[0] << 2) + (dp[1] >> 6);
+ pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
+ pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
+ pix[3] = (dp[4] << 2) + (dp[1] & 3);
+ pix[4] = (dp[5] << 2) + (dp[9] & 3);
+ pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
+ pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
+ pix[7] = (dp[8] << 2) + (dp[9] >> 6);
+ }
+ if ((row += 2) > height)
+ row = 1;
+ }
+}
+
+void LibRaw::canon_600_correct()
+{
+ int row, col, val;
+ static const short mul[4][2] = {
+ {1141, 1145}, {1128, 1109}, {1178, 1149}, {1128, 1109}};
+
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < width; col++)
+ {
+ if ((val = BAYER(row, col) - black) < 0)
+ val = 0;
+ val = val * mul[row & 3][col & 1] >> 9;
+ BAYER(row, col) = val;
+ }
+ }
+ canon_600_fixed_wb(1311);
+ canon_600_auto_wb();
+ canon_600_coeff();
+ maximum = (0x3ff - black) * 1109 >> 9;
+ black = 0;
+}
diff --git a/libkdcraw/libraw/src/decoders/crx.cpp b/libkdcraw/libraw/src/decoders/crx.cpp
new file mode 100644
index 0000000..30a7020
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/crx.cpp
@@ -0,0 +1,2781 @@
+/* -*- C++ -*-
+ * File: libraw_crxdec.cpp
+ * Copyright (C) 2018-2019 Alexey Danilchenko
+ * Copyright (C) 2019 Alex Tutubalin, LibRaw LLC
+ *
+ Canon CR3 file decoder
+
+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"
+
+#ifdef _abs
+#undef _abs
+#undef _min
+#undef _constrain
+#endif
+#define _abs(x) (((x) ^ ((int32_t)(x) >> 31)) - ((int32_t)(x) >> 31))
+#define _min(a, b) ((a) < (b) ? (a) : (b))
+#define _constrain(x, l, u) ((x) < (l) ? (l) : ((x) > (u) ? (u) : (x)))
+
+#if defined(__clang__) || defined(__GNUG__)
+#define libraw_inline inline __attribute__((always_inline))
+#elif defined(_MSC_VER) && _MSC_VER > 1400
+#define libraw_inline __forceinline
+#else
+#define libraw_inline inline
+#endif
+
+// this should be divisible by 4
+#define CRX_BUF_SIZE 0x10000
+#if !defined(_WIN32) || (defined(__GNUC__) && !defined(__INTRINSIC_SPECIAL__BitScanReverse))
+/* __INTRINSIC_SPECIAL__BitScanReverse found in MinGW32-W64 v7.30 headers, may be there is a better solution? */
+typedef uint32_t DWORD;
+libraw_inline void _BitScanReverse(DWORD *Index, unsigned long Mask)
+{
+ *Index = sizeof(unsigned long) * 8 - 1 - __builtin_clzl(Mask);
+}
+#if LibRawBigEndian
+#define _byteswap_ulong(x) (x)
+#else
+#define _byteswap_ulong(x) __builtin_bswap32(x)
+#endif
+#endif
+
+struct CrxBitstream
+{
+ uint8_t mdatBuf[CRX_BUF_SIZE];
+ uint64_t mdatSize;
+ uint64_t curBufOffset;
+ uint32_t curPos;
+ uint32_t curBufSize;
+ uint32_t bitData;
+ int32_t bitsLeft;
+ LibRaw_abstract_datastream *input;
+};
+
+struct CrxBandParam
+{
+ CrxBitstream bitStream;
+ int16_t subbandWidth;
+ int16_t subbandHeight;
+ int32_t roundedBitsMask;
+ int32_t roundedBits;
+ int16_t curLine;
+ int32_t *lineBuf0;
+ int32_t *lineBuf1;
+ int32_t *lineBuf2;
+ int32_t sParam;
+ int32_t kParam;
+ int32_t *paramData;
+ int32_t *nonProgrData;
+ bool supportsPartial;
+};
+
+struct CrxWaveletTransform
+{
+ int32_t *subband0Buf;
+ int32_t *subband1Buf;
+ int32_t *subband2Buf;
+ int32_t *subband3Buf;
+ int32_t *lineBuf[8];
+ int16_t curLine;
+ int16_t curH;
+ int8_t fltTapH;
+ int16_t height;
+ int16_t width;
+};
+
+struct CrxSubband
+{
+ CrxBandParam *bandParam;
+ uint64_t mdatOffset;
+ uint8_t *bandBuf;
+ uint16_t width;
+ uint16_t height;
+ int32_t qParam;
+ int32_t kParam;
+ int32_t qStepBase;
+ uint32_t qStepMult;
+ bool supportsPartial;
+ int32_t bandSize;
+ uint64_t dataSize;
+ int64_t dataOffset;
+ short rowStartAddOn;
+ short rowEndAddOn;
+ short colStartAddOn;
+ short colEndAddOn;
+ short levelShift;
+};
+
+struct CrxPlaneComp
+{
+ uint8_t *compBuf;
+ CrxSubband *subBands;
+ CrxWaveletTransform *wvltTransform;
+ int8_t compNumber;
+ int64_t dataOffset;
+ int32_t compSize;
+ bool supportsPartial;
+ int32_t roundedBitsMask;
+ int8_t tileFlag;
+};
+
+struct CrxQStep
+{
+ uint32_t *qStepTbl;
+ int width;
+ int height;
+};
+
+struct CrxTile
+{
+ CrxPlaneComp *comps;
+ int8_t tileFlag;
+ int8_t tileNumber;
+ int64_t dataOffset;
+ int32_t tileSize;
+ uint16_t width;
+ uint16_t height;
+ bool hasQPData;
+ CrxQStep *qStep;
+ uint32_t mdatQPDataSize;
+ uint16_t mdatExtraSize;
+};
+
+struct CrxImage
+{
+ uint8_t nPlanes;
+ uint16_t planeWidth;
+ uint16_t planeHeight;
+ uint8_t samplePrecision;
+ uint8_t medianBits;
+ uint8_t subbandCount;
+ uint8_t levels;
+ uint8_t nBits;
+ uint8_t encType;
+ uint8_t tileCols;
+ uint8_t tileRows;
+ CrxTile *tiles;
+ uint64_t mdatOffset;
+ uint64_t mdatSize;
+ int16_t *outBufs[4]; // one per plane
+ int16_t *planeBuf;
+ LibRaw_abstract_datastream *input;
+#ifdef LIBRAW_CR3_MEMPOOL
+ libraw_memmgr memmgr;
+ CrxImage() : memmgr(0) {}
+#endif
+};
+
+enum TileFlags
+{
+ E_HAS_TILES_ON_THE_RIGHT = 1,
+ E_HAS_TILES_ON_THE_LEFT = 2,
+ E_HAS_TILES_ON_THE_BOTTOM = 4,
+ E_HAS_TILES_ON_THE_TOP = 8
+};
+
+int32_t exCoefNumTbl[144] = {1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0,
+ 0, 0, 1, 2, 2, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 2, 2,
+ 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 1, 1, 1,
+ 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 0, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+
+int32_t q_step_tbl[8] = {0x28, 0x2D, 0x33, 0x39, 0x40, 0x48};
+
+uint32_t JS[32] = {1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4,
+ 4, 8, 8, 8, 8, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40,
+ 0x80, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000};
+
+uint32_t J[32] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
+
+static inline void crxFillBuffer(CrxBitstream *bitStrm)
+{
+ if (bitStrm->curPos >= bitStrm->curBufSize && bitStrm->mdatSize)
+ {
+ bitStrm->curPos = 0;
+ bitStrm->curBufOffset += bitStrm->curBufSize;
+#ifdef LIBRAW_USE_OPENMP
+#pragma omp critical
+#endif
+ {
+#ifndef LIBRAW_USE_OPENMP
+ bitStrm->input->lock();
+#endif
+ bitStrm->input->seek(bitStrm->curBufOffset, SEEK_SET);
+ bitStrm->curBufSize = bitStrm->input->read(bitStrm->mdatBuf, 1, _min(bitStrm->mdatSize, CRX_BUF_SIZE));
+#ifndef LIBRAW_USE_OPENMP
+ bitStrm->input->unlock();
+#endif
+ }
+ if (bitStrm->curBufSize < 1) // nothing read
+ throw LIBRAW_EXCEPTION_IO_EOF;
+ bitStrm->mdatSize -= bitStrm->curBufSize;
+ }
+}
+
+libraw_inline int crxBitstreamGetZeros(CrxBitstream *bitStrm)
+{
+ uint32_t nonZeroBit = 0;
+ uint64_t nextData = 0;
+ int32_t result = 0;
+
+ if (bitStrm->bitData)
+ {
+ _BitScanReverse((DWORD *)&nonZeroBit, (DWORD)bitStrm->bitData);
+ result = 31 - nonZeroBit;
+ bitStrm->bitData <<= 32 - nonZeroBit;
+ bitStrm->bitsLeft -= 32 - nonZeroBit;
+ }
+ else
+ {
+ uint32_t bitsLeft = bitStrm->bitsLeft;
+ while (1)
+ {
+ while (bitStrm->curPos + 4 <= bitStrm->curBufSize)
+ {
+ nextData = _byteswap_ulong(*(uint32_t *)(bitStrm->mdatBuf + bitStrm->curPos));
+ bitStrm->curPos += 4;
+ crxFillBuffer(bitStrm);
+ if (nextData)
+ {
+ _BitScanReverse((DWORD *)&nonZeroBit, (DWORD)nextData);
+ result = bitsLeft + 31 - nonZeroBit;
+ bitStrm->bitData = nextData << (32 - nonZeroBit);
+ bitStrm->bitsLeft = nonZeroBit;
+ return result;
+ }
+ bitsLeft += 32;
+ }
+ if (bitStrm->curBufSize < bitStrm->curPos + 1)
+ break; // error
+ nextData = bitStrm->mdatBuf[bitStrm->curPos++];
+ crxFillBuffer(bitStrm);
+ if (nextData)
+ break;
+ bitsLeft += 8;
+ }
+ _BitScanReverse((DWORD *)&nonZeroBit, (DWORD)nextData);
+ result = (uint32_t)(bitsLeft + 7 - nonZeroBit);
+ bitStrm->bitData = nextData << (32 - nonZeroBit);
+ bitStrm->bitsLeft = nonZeroBit;
+ }
+ return result;
+}
+
+libraw_inline uint32_t crxBitstreamGetBits(CrxBitstream *bitStrm, int bits)
+{
+ int bitsLeft = bitStrm->bitsLeft;
+ uint32_t bitData = bitStrm->bitData;
+ uint32_t nextWord;
+ uint8_t nextByte;
+ uint32_t result;
+
+ if (bitsLeft < bits)
+ {
+ // get them from stream
+ if (bitStrm->curPos + 4 <= bitStrm->curBufSize)
+ {
+ nextWord = _byteswap_ulong(*(uint32_t *)(bitStrm->mdatBuf + bitStrm->curPos));
+ bitStrm->curPos += 4;
+ crxFillBuffer(bitStrm);
+ bitStrm->bitsLeft = 32 - (bits - bitsLeft);
+ result = ((nextWord >> bitsLeft) | bitData) >> (32 - bits);
+ bitStrm->bitData = nextWord << (bits - bitsLeft);
+ return result;
+ }
+ // less than a word left - read byte at a time
+ do
+ {
+ if (bitStrm->curPos >= bitStrm->curBufSize)
+ break; // error
+ bitsLeft += 8;
+ nextByte = bitStrm->mdatBuf[bitStrm->curPos++];
+ crxFillBuffer(bitStrm);
+ bitData |= nextByte << (32 - bitsLeft);
+ } while (bitsLeft < bits);
+ }
+ result = bitData >> (32 - bits); // 32-bits
+ bitStrm->bitData = bitData << bits;
+ bitStrm->bitsLeft = bitsLeft - bits;
+ return result;
+}
+
+libraw_inline int32_t crxPrediction(int32_t left, int32_t top, int32_t deltaH, int32_t deltaV)
+{
+ int32_t symb[4] = {left + deltaH, left + deltaH, left, top};
+
+ return symb[(((deltaV < 0) ^ (deltaH < 0)) << 1) + ((left < top) ^ (deltaH < 0))];
+}
+
+libraw_inline int32_t crxPredictKParameter(int32_t prevK, int32_t bitCode, int32_t maxVal = 0)
+{
+ int32_t newKParam = prevK - (bitCode < (1 << prevK >> 1)) + ((bitCode >> prevK) > 2) + ((bitCode >> prevK) > 5);
+
+ return !maxVal || newKParam < maxVal ? newKParam : maxVal;
+}
+
+libraw_inline void crxDecodeSymbolL1(CrxBandParam *param, int32_t doMedianPrediction, int32_t notEOL = 0)
+{
+ if (doMedianPrediction)
+ {
+ int32_t symb[4];
+
+ int32_t delta = param->lineBuf0[1] - param->lineBuf0[0];
+ symb[2] = param->lineBuf1[0];
+ symb[0] = symb[1] = delta + symb[2];
+ symb[3] = param->lineBuf0[1];
+
+ param->lineBuf1[1] = symb[(((param->lineBuf0[0] < param->lineBuf1[0]) ^ (delta < 0)) << 1) +
+ ((param->lineBuf1[0] < param->lineBuf0[1]) ^ (delta < 0))];
+ }
+ else
+ param->lineBuf1[1] = param->lineBuf0[1];
+
+ // get next error symbol
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+
+ // add converted (+/-) error code to predicted value
+ param->lineBuf1[1] += -(int32_t)(bitCode & 1) ^ (int32_t)(bitCode >> 1);
+
+ // for not end of the line - use one symbol ahead to estimate next K
+ if (notEOL)
+ {
+ int32_t nextDelta = (param->lineBuf0[2] - param->lineBuf0[1]) << 1;
+ bitCode = (bitCode + _abs(nextDelta)) >> 1;
+ ++param->lineBuf0;
+ }
+
+ // update K parameter
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+
+ ++param->lineBuf1;
+}
+
+int crxDecodeLine(CrxBandParam *param)
+{
+ int length = param->subbandWidth;
+
+ param->lineBuf1[0] = param->lineBuf0[1];
+ for (; length > 1; --length)
+ {
+ if (param->lineBuf1[0] != param->lineBuf0[1] || param->lineBuf1[0] != param->lineBuf0[2])
+ {
+ crxDecodeSymbolL1(param, 1, 1);
+ }
+ else
+ {
+ int nSyms = 0;
+ if (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms = 1;
+ while (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms += JS[param->sParam];
+ if (nSyms > length)
+ {
+ nSyms = length;
+ break;
+ }
+ if (param->sParam < 31)
+ ++param->sParam;
+ if (nSyms == length)
+ break;
+ }
+
+ if (nSyms < length)
+ {
+ if (J[param->sParam])
+ nSyms += crxBitstreamGetBits(&param->bitStream, J[param->sParam]);
+ if (param->sParam > 0)
+ --param->sParam;
+ if (nSyms > length)
+ return -1;
+ }
+
+ length -= nSyms;
+
+ // copy symbol nSyms times
+ param->lineBuf0 += nSyms;
+
+ // copy symbol nSyms times
+ while (nSyms-- > 0)
+ {
+ param->lineBuf1[1] = param->lineBuf1[0];
+ ++param->lineBuf1;
+ }
+ }
+
+ if (length > 0)
+ crxDecodeSymbolL1(param, 0, (length > 1));
+ }
+ }
+
+ if (length == 1)
+ crxDecodeSymbolL1(param, 1, 0);
+
+ param->lineBuf1[1] = param->lineBuf1[0] + 1;
+
+ return 0;
+}
+
+libraw_inline void crxDecodeSymbolL1Rounded(CrxBandParam *param, int32_t doSym = 1, int32_t doCode = 1)
+{
+ int32_t sym = param->lineBuf0[1];
+
+ if (doSym)
+ {
+ // calculate the next symbol gradient
+ int32_t symb[4];
+ int32_t deltaH = param->lineBuf0[1] - param->lineBuf0[0];
+ symb[2] = param->lineBuf1[0];
+ symb[0] = symb[1] = deltaH + symb[2];
+ symb[3] = param->lineBuf0[1];
+ sym = symb[(((param->lineBuf0[0] < param->lineBuf1[0]) ^ (deltaH < 0)) << 1) +
+ ((param->lineBuf1[0] < param->lineBuf0[1]) ^ (deltaH < 0))];
+ }
+
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ int32_t code = -(int32_t)(bitCode & 1) ^ (int32_t)(bitCode >> 1);
+ param->lineBuf1[1] = param->roundedBitsMask * 2 * code + (code >> 31) + sym;
+
+ if (doCode)
+ {
+ if (param->lineBuf0[2] > param->lineBuf0[1])
+ code = (param->lineBuf0[2] - param->lineBuf0[1] + param->roundedBitsMask - 1) >> param->roundedBits;
+ else
+ code = -((param->lineBuf0[1] - param->lineBuf0[2] + param->roundedBitsMask) >> param->roundedBits);
+
+ param->kParam = crxPredictKParameter(param->kParam, (bitCode + 2 * _abs(code)) >> 1, 15);
+ }
+ else
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+
+ ++param->lineBuf1;
+}
+
+int crxDecodeLineRounded(CrxBandParam *param)
+{
+ int32_t valueReached = 0;
+
+ param->lineBuf0[0] = param->lineBuf0[1];
+ param->lineBuf1[0] = param->lineBuf0[1];
+ int32_t length = param->subbandWidth;
+
+ for (; length > 1; --length)
+ {
+ if (_abs(param->lineBuf0[2] - param->lineBuf0[1]) > param->roundedBitsMask)
+ {
+ crxDecodeSymbolL1Rounded(param);
+ ++param->lineBuf0;
+ valueReached = 1;
+ }
+ else if (valueReached || _abs(param->lineBuf0[0] - param->lineBuf1[0]) > param->roundedBitsMask)
+ {
+ crxDecodeSymbolL1Rounded(param);
+ ++param->lineBuf0;
+ valueReached = 0;
+ }
+ else
+ {
+ int nSyms = 0;
+ if (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms = 1;
+ while (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms += JS[param->sParam];
+ if (nSyms > length)
+ {
+ nSyms = length;
+ break;
+ }
+ if (param->sParam < 31)
+ ++param->sParam;
+ if (nSyms == length)
+ break;
+ }
+ if (nSyms < length)
+ {
+ if (J[param->sParam])
+ nSyms += crxBitstreamGetBits(&param->bitStream, J[param->sParam]);
+ if (param->sParam > 0)
+ --param->sParam;
+ }
+ if (nSyms > length)
+ return -1;
+ }
+ length -= nSyms;
+
+ // copy symbol nSyms times
+ param->lineBuf0 += nSyms;
+
+ // copy symbol nSyms times
+ while (nSyms-- > 0)
+ {
+ param->lineBuf1[1] = param->lineBuf1[0];
+ ++param->lineBuf1;
+ }
+
+ if (length > 1)
+ {
+ crxDecodeSymbolL1Rounded(param, 0);
+ ++param->lineBuf0;
+ valueReached = _abs(param->lineBuf0[1] - param->lineBuf0[0]) > param->roundedBitsMask;
+ }
+ else if (length == 1)
+ crxDecodeSymbolL1Rounded(param, 0, 0);
+ }
+ }
+ if (length == 1)
+ crxDecodeSymbolL1Rounded(param, 1, 0);
+
+ param->lineBuf1[1] = param->lineBuf1[0] + 1;
+
+ return 0;
+}
+
+int crxDecodeLineNoRefPrevLine(CrxBandParam *param)
+{
+ int32_t i = 0;
+
+ for (; i < param->subbandWidth - 1; i++)
+ {
+ if (param->lineBuf0[i + 2] | param->lineBuf0[i + 1] | param->lineBuf1[i])
+ {
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ param->lineBuf1[i + 1] = -(int32_t)(bitCode & 1) ^ (int32_t)(bitCode >> 1);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode);
+ if (param->lineBuf2[i + 1] - param->kParam <= 1)
+ {
+ if (param->kParam >= 15)
+ param->kParam = 15;
+ }
+ else
+ ++param->kParam;
+ }
+ else
+ {
+ int nSyms = 0;
+ if (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms = 1;
+ if (i != param->subbandWidth - 1)
+ {
+ while (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms += JS[param->sParam];
+ if (i + nSyms > param->subbandWidth)
+ {
+ nSyms = param->subbandWidth - i;
+ break;
+ }
+ if (param->sParam < 31)
+ ++param->sParam;
+ if (i + nSyms == param->subbandWidth)
+ break;
+ }
+ if (i + nSyms < param->subbandWidth)
+ {
+ if (J[param->sParam])
+ nSyms += crxBitstreamGetBits(&param->bitStream, J[param->sParam]);
+ if (param->sParam > 0)
+ --param->sParam;
+ }
+ if (i + nSyms > param->subbandWidth)
+ return -1;
+ }
+ }
+ else if (i > param->subbandWidth)
+ return -1;
+
+ if (nSyms > 0)
+ {
+ memset(param->lineBuf1 + i + 1, 0, nSyms * sizeof(int32_t));
+ memset(param->lineBuf2 + i, 0, nSyms * sizeof(int32_t));
+ i += nSyms;
+ }
+
+ if (i >= param->subbandWidth - 1)
+ {
+ if (i == param->subbandWidth - 1)
+ {
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ param->lineBuf1[i + 1] = -(int32_t)((bitCode + 1) & 1) ^ (int32_t)((bitCode + 1) >> 1);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+ param->lineBuf2[i] = param->kParam;
+ }
+ continue;
+ }
+ else
+ {
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ param->lineBuf1[i + 1] = -(int32_t)((bitCode + 1) & 1) ^ (int32_t)((bitCode + 1) >> 1);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode);
+ if (param->lineBuf2[i + 1] - param->kParam <= 1)
+ {
+ if (param->kParam >= 15)
+ param->kParam = 15;
+ }
+ else
+ ++param->kParam;
+ }
+ }
+ param->lineBuf2[i] = param->kParam;
+ }
+ if (i == param->subbandWidth - 1)
+ {
+ int32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ param->lineBuf1[i + 1] = -(bitCode & 1) ^ (bitCode >> 1);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+ param->lineBuf2[i] = param->kParam;
+ }
+
+ return 0;
+}
+
+int crxDecodeTopLine(CrxBandParam *param)
+{
+ param->lineBuf1[0] = 0;
+
+ int32_t length = param->subbandWidth;
+
+ // read the line from bitstream
+ for (; length > 1; --length)
+ {
+ if (param->lineBuf1[0])
+ param->lineBuf1[1] = param->lineBuf1[0];
+ else
+ {
+ int nSyms = 0;
+ if (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms = 1;
+ while (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms += JS[param->sParam];
+ if (nSyms > length)
+ {
+ nSyms = length;
+ break;
+ }
+ if (param->sParam < 31)
+ ++param->sParam;
+ if (nSyms == length)
+ break;
+ }
+ if (nSyms < length)
+ {
+ if (J[param->sParam])
+ nSyms += crxBitstreamGetBits(&param->bitStream, J[param->sParam]);
+ if (param->sParam > 0)
+ --param->sParam;
+ if (nSyms > length)
+ return -1;
+ }
+
+ length -= nSyms;
+
+ // copy symbol nSyms times
+ while (nSyms-- > 0)
+ {
+ param->lineBuf1[1] = param->lineBuf1[0];
+ ++param->lineBuf1;
+ }
+
+ if (length <= 0)
+ break;
+ }
+
+ param->lineBuf1[1] = 0;
+ }
+
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ param->lineBuf1[1] += -(int32_t)(bitCode & 1) ^ (int32_t)(bitCode >> 1);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+ ++param->lineBuf1;
+ }
+
+ if (length == 1)
+ {
+ param->lineBuf1[1] = param->lineBuf1[0];
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ param->lineBuf1[1] += -(int32_t)(bitCode & 1) ^ (int32_t)(bitCode >> 1);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+ ++param->lineBuf1;
+ }
+
+ param->lineBuf1[1] = param->lineBuf1[0] + 1;
+
+ return 0;
+}
+
+int crxDecodeTopLineRounded(CrxBandParam *param)
+{
+ param->lineBuf1[0] = 0;
+
+ int32_t length = param->subbandWidth;
+
+ // read the line from bitstream
+ for (; length > 1; --length)
+ {
+ if (_abs(param->lineBuf1[0]) > param->roundedBitsMask)
+ param->lineBuf1[1] = param->lineBuf1[0];
+ else
+ {
+ int nSyms = 0;
+ if (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms = 1;
+ while (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms += JS[param->sParam];
+ if (nSyms > length)
+ {
+ nSyms = length;
+ break;
+ }
+ if (param->sParam < 31)
+ ++param->sParam;
+ if (nSyms == length)
+ break;
+ }
+ if (nSyms < length)
+ {
+ if (J[param->sParam])
+ nSyms += crxBitstreamGetBits(&param->bitStream, J[param->sParam]);
+ if (param->sParam > 0)
+ --param->sParam;
+ if (nSyms > length)
+ return -1;
+ }
+ }
+
+ length -= nSyms;
+
+ // copy symbol nSyms times
+ while (nSyms-- > 0)
+ {
+ param->lineBuf1[1] = param->lineBuf1[0];
+ ++param->lineBuf1;
+ }
+
+ if (length <= 0)
+ break;
+
+ param->lineBuf1[1] = 0;
+ }
+
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+
+ int32_t sVal = -(int32_t)(bitCode & 1) ^ (int32_t)(bitCode >> 1);
+ param->lineBuf1[1] += param->roundedBitsMask * 2 * sVal + (sVal >> 31);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+ ++param->lineBuf1;
+ }
+
+ if (length == 1)
+ {
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ int32_t sVal = -(int32_t)(bitCode & 1) ^ (int32_t)(bitCode >> 1);
+ param->lineBuf1[1] += param->roundedBitsMask * 2 * sVal + (sVal >> 31);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+ ++param->lineBuf1;
+ }
+
+ param->lineBuf1[1] = param->lineBuf1[0] + 1;
+
+ return 0;
+}
+
+int crxDecodeTopLineNoRefPrevLine(CrxBandParam *param)
+{
+ param->lineBuf0[0] = 0;
+ param->lineBuf1[0] = 0;
+ int32_t length = param->subbandWidth;
+ for (; length > 1; --length)
+ {
+ if (param->lineBuf1[0])
+ {
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ param->lineBuf1[1] = -(int32_t)(bitCode & 1) ^ (int32_t)(bitCode >> 1);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+ }
+ else
+ {
+ int nSyms = 0;
+ if (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms = 1;
+ while (crxBitstreamGetBits(&param->bitStream, 1))
+ {
+ nSyms += JS[param->sParam];
+ if (nSyms > length)
+ {
+ nSyms = length;
+ break;
+ }
+ if (param->sParam < 31)
+ ++param->sParam;
+ if (nSyms == length)
+ break;
+ }
+ if (nSyms < length)
+ {
+ if (J[param->sParam])
+ nSyms += crxBitstreamGetBits(&param->bitStream, J[param->sParam]);
+ if (param->sParam > 0)
+ --param->sParam;
+ if (nSyms > length)
+ return -1;
+ }
+ }
+
+ length -= nSyms;
+
+ // copy symbol nSyms times
+ while (nSyms-- > 0)
+ {
+ param->lineBuf2[0] = 0;
+ param->lineBuf1[1] = 0;
+ ++param->lineBuf1;
+ ++param->lineBuf2;
+ }
+
+ if (length <= 0)
+ break;
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ param->lineBuf1[1] = -(int32_t)((bitCode + 1) & 1) ^ (int32_t)((bitCode + 1) >> 1);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+ }
+ param->lineBuf2[0] = param->kParam;
+ ++param->lineBuf2;
+ ++param->lineBuf1;
+ }
+
+ if (length == 1)
+ {
+ uint32_t bitCode = crxBitstreamGetZeros(&param->bitStream);
+ if (bitCode >= 41)
+ bitCode = crxBitstreamGetBits(&param->bitStream, 21);
+ else if (param->kParam)
+ bitCode = crxBitstreamGetBits(&param->bitStream, param->kParam) | (bitCode << param->kParam);
+ param->lineBuf1[1] = -(int32_t)(bitCode & 1) ^ (int32_t)(bitCode >> 1);
+ param->kParam = crxPredictKParameter(param->kParam, bitCode, 15);
+ param->lineBuf2[0] = param->kParam;
+ ++param->lineBuf1;
+ }
+
+ param->lineBuf1[1] = 0;
+
+ return 0;
+}
+
+int crxDecodeLine(CrxBandParam *param, uint8_t *bandBuf)
+{
+ if (!param || !bandBuf)
+ return -1;
+ if (param->curLine >= param->subbandHeight)
+ return -1;
+
+ if (param->curLine == 0)
+ {
+ int32_t lineLength = param->subbandWidth + 2;
+
+ param->sParam = 0;
+ param->kParam = 0;
+ if (param->supportsPartial)
+ {
+ if (param->roundedBitsMask <= 0)
+ {
+ param->lineBuf0 = (int32_t *)param->paramData;
+ param->lineBuf1 = param->lineBuf0 + lineLength;
+ int32_t *lineBuf = param->lineBuf1 + 1;
+ if (crxDecodeTopLine(param))
+ return -1;
+ memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(int32_t));
+ ++param->curLine;
+ }
+ else
+ {
+ param->roundedBits = 1;
+ if (param->roundedBitsMask & ~1)
+ {
+ while (param->roundedBitsMask >> param->roundedBits)
+ ++param->roundedBits;
+ }
+ param->lineBuf0 = (int32_t *)param->paramData;
+ param->lineBuf1 = param->lineBuf0 + lineLength;
+ int32_t *lineBuf = param->lineBuf1 + 1;
+ if (crxDecodeTopLineRounded(param))
+ return -1;
+ memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(int32_t));
+ ++param->curLine;
+ }
+ }
+ else
+ {
+ param->lineBuf2 = (int32_t *)param->nonProgrData;
+ param->lineBuf0 = (int32_t *)param->paramData;
+ param->lineBuf1 = param->lineBuf0 + lineLength;
+ int32_t *lineBuf = param->lineBuf1 + 1;
+ if (crxDecodeTopLineNoRefPrevLine(param))
+ return -1;
+ memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(int32_t));
+ ++param->curLine;
+ }
+ }
+ else if (!param->supportsPartial)
+ {
+ int32_t lineLength = param->subbandWidth + 2;
+ param->lineBuf2 = (int32_t *)param->nonProgrData;
+ if (param->curLine & 1)
+ {
+ param->lineBuf1 = (int32_t *)param->paramData;
+ param->lineBuf0 = param->lineBuf1 + lineLength;
+ }
+ else
+ {
+ param->lineBuf0 = (int32_t *)param->paramData;
+ param->lineBuf1 = param->lineBuf0 + lineLength;
+ }
+ int32_t *lineBuf = param->lineBuf1 + 1;
+ if (crxDecodeLineNoRefPrevLine(param))
+ return -1;
+ memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(int32_t));
+ ++param->curLine;
+ }
+ else if (param->roundedBitsMask <= 0)
+ {
+ int32_t lineLength = param->subbandWidth + 2;
+ if (param->curLine & 1)
+ {
+ param->lineBuf1 = (int32_t *)param->paramData;
+ param->lineBuf0 = param->lineBuf1 + lineLength;
+ }
+ else
+ {
+ param->lineBuf0 = (int32_t *)param->paramData;
+ param->lineBuf1 = param->lineBuf0 + lineLength;
+ }
+ int32_t *lineBuf = param->lineBuf1 + 1;
+ if (crxDecodeLine(param))
+ return -1;
+ memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(int32_t));
+ ++param->curLine;
+ }
+ else
+ {
+ int32_t lineLength = param->subbandWidth + 2;
+ if (param->curLine & 1)
+ {
+ param->lineBuf1 = (int32_t *)param->paramData;
+ param->lineBuf0 = param->lineBuf1 + lineLength;
+ }
+ else
+ {
+ param->lineBuf0 = (int32_t *)param->paramData;
+ param->lineBuf1 = param->lineBuf0 + lineLength;
+ }
+ int32_t *lineBuf = param->lineBuf1 + 1;
+ if (crxDecodeLineRounded(param))
+ return -1;
+ memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(int32_t));
+ ++param->curLine;
+ }
+ return 0;
+}
+
+int crxUpdateQparam(CrxSubband *subband)
+{
+ uint32_t bitCode = crxBitstreamGetZeros(&subband->bandParam->bitStream);
+ if (bitCode >= 23)
+ bitCode = crxBitstreamGetBits(&subband->bandParam->bitStream, 8);
+ else if (subband->kParam)
+ bitCode = crxBitstreamGetBits(&subband->bandParam->bitStream, subband->kParam) | (bitCode << subband->kParam);
+
+ subband->qParam += -(int32_t)(bitCode & 1) ^ (int32_t)(bitCode >> 1); // converting encoded to signed integer
+ subband->kParam = crxPredictKParameter(subband->kParam, bitCode);
+ if (subband->kParam > 7)
+ return -1;
+ return 0;
+}
+
+libraw_inline int getSubbandRow(CrxSubband *band, int row)
+{
+ return row < band->rowStartAddOn
+ ? 0
+ : (row < band->height - band->rowEndAddOn ? row - band->rowEndAddOn
+ : band->height - band->rowEndAddOn - band->rowStartAddOn - 1);
+}
+int crxDecodeLineWithIQuantization(CrxSubband *band, CrxQStep *qStep)
+{
+ if (!band->dataSize)
+ {
+ memset(band->bandBuf, 0, band->bandSize);
+ return 0;
+ }
+
+ if (band->supportsPartial && !qStep && crxUpdateQparam(band))
+ return -1;
+ if (crxDecodeLine(band->bandParam, band->bandBuf))
+ return -1;
+
+ if (band->width <= 0)
+ return 0;
+
+ // update band buffers
+ int32_t *bandBuf = (int32_t *)band->bandBuf;
+ if (qStep)
+ {
+ // new version
+ uint32_t *qStepTblPtr = &qStep->qStepTbl[qStep->width * getSubbandRow(band, band->bandParam->curLine - 1)];
+
+ for (int i = 0; i < band->colStartAddOn; ++i)
+ {
+ int32_t quantVal = band->qStepBase + ((qStepTblPtr[0] * band->qStepMult) >> 3);
+ bandBuf[i] *= _constrain(quantVal, 1, 0x168000);
+ }
+
+ for (int i = band->colStartAddOn; i < band->width - band->colEndAddOn; ++i)
+ {
+ int32_t quantVal =
+ band->qStepBase + ((qStepTblPtr[(i - band->colStartAddOn) >> band->levelShift] * band->qStepMult) >> 3);
+ bandBuf[i] *= _constrain(quantVal, 1, 0x168000);
+ }
+ int lastIdx = (band->width - band->colEndAddOn - band->colStartAddOn - 1) >> band->levelShift;
+ for (int i = band->width - band->colEndAddOn; i < band->width; ++i)
+ {
+ int32_t quantVal = band->qStepBase + ((qStepTblPtr[lastIdx] * band->qStepMult) >> 3);
+ bandBuf[i] *= _constrain(quantVal, 1, 0x168000);
+ }
+ }
+ else
+ {
+ // prev. version
+ int32_t qScale = q_step_tbl[band->qParam % 6] >> (6 - band->qParam / 6);
+ if (band->qParam / 6 >= 6)
+ qScale = q_step_tbl[band->qParam % 6] * (1 << (band->qParam / 6 + 26));
+
+ if (qScale != 1)
+ for (int32_t i = 0; i < band->width; ++i)
+ bandBuf[i] *= qScale;
+ }
+
+ return 0;
+}
+
+void crxHorizontal53(int32_t *lineBufLA, int32_t *lineBufLB, CrxWaveletTransform *wavelet, uint32_t tileFlag)
+{
+ int32_t *band0Buf = wavelet->subband0Buf;
+ int32_t *band1Buf = wavelet->subband1Buf;
+ int32_t *band2Buf = wavelet->subband2Buf;
+ int32_t *band3Buf = wavelet->subband3Buf;
+
+ if (wavelet->width <= 1)
+ {
+ lineBufLA[0] = band0Buf[0];
+ lineBufLB[0] = band2Buf[0];
+ }
+ else
+ {
+ if (tileFlag & E_HAS_TILES_ON_THE_LEFT)
+ {
+ lineBufLA[0] = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ lineBufLB[0] = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2);
+ ++band1Buf;
+ ++band3Buf;
+ }
+ else
+ {
+ lineBufLA[0] = band0Buf[0] - ((band1Buf[0] + 1) >> 1);
+ lineBufLB[0] = band2Buf[0] - ((band3Buf[0] + 1) >> 1);
+ }
+ ++band0Buf;
+ ++band2Buf;
+
+ for (int i = 0; i < wavelet->width - 3; i += 2)
+ {
+ int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ lineBufLA[1] = band1Buf[0] + ((delta + lineBufLA[0]) >> 1);
+ lineBufLA[2] = delta;
+
+ delta = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2);
+ lineBufLB[1] = band3Buf[0] + ((delta + lineBufLB[0]) >> 1);
+ lineBufLB[2] = delta;
+
+ ++band0Buf;
+ ++band1Buf;
+ ++band2Buf;
+ ++band3Buf;
+ lineBufLA += 2;
+ lineBufLB += 2;
+ }
+ if (tileFlag & E_HAS_TILES_ON_THE_RIGHT)
+ {
+ int32_t deltaA = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ lineBufLA[1] = band1Buf[0] + ((deltaA + lineBufLA[0]) >> 1);
+
+ int32_t deltaB = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2);
+ lineBufLB[1] = band3Buf[0] + ((deltaB + lineBufLB[0]) >> 1);
+
+ if (wavelet->width & 1)
+ {
+ lineBufLA[2] = deltaA;
+ lineBufLB[2] = deltaB;
+ }
+ }
+ else if (wavelet->width & 1)
+ {
+ lineBufLA[1] = band1Buf[0] + ((lineBufLA[0] + band0Buf[0] - ((band1Buf[0] + 1) >> 1)) >> 1);
+ lineBufLA[2] = band0Buf[0] - ((band1Buf[0] + 1) >> 1);
+
+ lineBufLB[1] = band3Buf[0] + ((lineBufLB[0] + band2Buf[0] - ((band3Buf[0] + 1) >> 1)) >> 1);
+ lineBufLB[2] = band2Buf[0] - ((band3Buf[0] + 1) >> 1);
+ }
+ else
+ {
+ lineBufLA[1] = lineBufLA[0] + band1Buf[0];
+ lineBufLB[1] = lineBufLB[0] + band3Buf[0];
+ }
+ }
+}
+
+int32_t *crxIdwt53FilterGetLine(CrxPlaneComp *comp, int32_t level)
+{
+ int32_t *result = comp->wvltTransform[level]
+ .lineBuf[(comp->wvltTransform[level].fltTapH - comp->wvltTransform[level].curH + 5) % 5 + 3];
+ comp->wvltTransform[level].curH--;
+ return result;
+}
+
+int crxIdwt53FilterDecode(CrxPlaneComp *comp, int32_t level, CrxQStep *qStep)
+{
+ if (comp->wvltTransform[level].curH)
+ return 0;
+
+ CrxSubband *sband = comp->subBands + 3 * level;
+ CrxQStep *qStepLevel = qStep ? qStep + level : 0;
+
+ if (comp->wvltTransform[level].height - 3 <= comp->wvltTransform[level].curLine &&
+ !(comp->tileFlag & E_HAS_TILES_ON_THE_BOTTOM))
+ {
+ if (comp->wvltTransform[level].height & 1)
+ {
+ if (level)
+ {
+ if (crxIdwt53FilterDecode(comp, level - 1, qStep))
+ return -1;
+ }
+ else if (crxDecodeLineWithIQuantization(sband, qStepLevel))
+ return -1;
+
+ if (crxDecodeLineWithIQuantization(sband + 1, qStepLevel))
+ return -1;
+ }
+ }
+ else
+ {
+ if (level)
+ {
+ if (crxIdwt53FilterDecode(comp, level - 1, qStep))
+ return -1;
+ }
+ else if (crxDecodeLineWithIQuantization(sband, qStepLevel)) // LL band
+ return -1;
+
+ if (crxDecodeLineWithIQuantization(sband + 1, qStepLevel) || // HL band
+ crxDecodeLineWithIQuantization(sband + 2, qStepLevel) || // LH band
+ crxDecodeLineWithIQuantization(sband + 3, qStepLevel)) // HH band
+ return -1;
+ }
+
+ return 0;
+}
+
+int crxIdwt53FilterTransform(CrxPlaneComp *comp, uint32_t level)
+{
+ CrxWaveletTransform *wavelet = comp->wvltTransform + level;
+
+ if (wavelet->curH)
+ return 0;
+
+ if (wavelet->curLine >= wavelet->height - 3)
+ {
+ if (!(comp->tileFlag & E_HAS_TILES_ON_THE_BOTTOM))
+ {
+ if (wavelet->height & 1)
+ {
+ if (level)
+ {
+ if (!wavelet[-1].curH)
+ if (crxIdwt53FilterTransform(comp, level - 1))
+ return -1;
+ wavelet->subband0Buf = crxIdwt53FilterGetLine(comp, level - 1);
+ }
+ int32_t *band0Buf = wavelet->subband0Buf;
+ int32_t *band1Buf = wavelet->subband1Buf;
+ int32_t *lineBufH0 = wavelet->lineBuf[wavelet->fltTapH + 3];
+ int32_t *lineBufH1 = wavelet->lineBuf[(wavelet->fltTapH + 1) % 5 + 3];
+ int32_t *lineBufH2 = wavelet->lineBuf[(wavelet->fltTapH + 2) % 5 + 3];
+
+ int32_t *lineBufL0 = wavelet->lineBuf[0];
+ int32_t *lineBufL1 = wavelet->lineBuf[1];
+ wavelet->lineBuf[1] = wavelet->lineBuf[2];
+ wavelet->lineBuf[2] = lineBufL1;
+
+ // process L bands
+ if (wavelet->width <= 1)
+ {
+ lineBufL0[0] = band0Buf[0];
+ }
+ else
+ {
+ if (comp->tileFlag & E_HAS_TILES_ON_THE_LEFT)
+ {
+ lineBufL0[0] = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ ++band1Buf;
+ }
+ else
+ {
+ lineBufL0[0] = band0Buf[0] - ((band1Buf[0] + 1) >> 1);
+ }
+ ++band0Buf;
+ for (int i = 0; i < wavelet->width - 3; i += 2)
+ {
+ int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ lineBufL0[1] = band1Buf[0] + ((lineBufL0[0] + delta) >> 1);
+ lineBufL0[2] = delta;
+ ++band0Buf;
+ ++band1Buf;
+ lineBufL0 += 2;
+ }
+ if (comp->tileFlag & E_HAS_TILES_ON_THE_RIGHT)
+ {
+ int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ lineBufL0[1] = band1Buf[0] + ((lineBufL0[0] + delta) >> 1);
+ if (wavelet->width & 1)
+ lineBufL0[2] = delta;
+ }
+ else if (wavelet->width & 1)
+ {
+ int32_t delta = band0Buf[0] - ((band1Buf[0] + 1) >> 1);
+ lineBufL0[1] = band1Buf[0] + ((lineBufL0[0] + delta) >> 1);
+ lineBufL0[2] = delta;
+ }
+ else
+ lineBufL0[1] = band1Buf[0] + lineBufL0[0];
+ }
+
+ // process H bands
+ lineBufL0 = wavelet->lineBuf[0];
+ lineBufL1 = wavelet->lineBuf[1];
+ for (int32_t i = 0; i < wavelet->width; i++)
+ {
+ int32_t delta = lineBufL0[i] - ((lineBufL1[i] + 1) >> 1);
+ lineBufH1[i] = lineBufL1[i] + ((delta + lineBufH0[i]) >> 1);
+ lineBufH2[i] = delta;
+ }
+ wavelet->curH += 3;
+ wavelet->curLine += 3;
+ wavelet->fltTapH = (wavelet->fltTapH + 3) % 5;
+ }
+ else
+ {
+ int32_t *lineBufL2 = wavelet->lineBuf[2];
+ int32_t *lineBufH0 = wavelet->lineBuf[wavelet->fltTapH + 3];
+ int32_t *lineBufH1 = wavelet->lineBuf[(wavelet->fltTapH + 1) % 5 + 3];
+ wavelet->lineBuf[1] = lineBufL2;
+ wavelet->lineBuf[2] = wavelet->lineBuf[1];
+
+ for (int32_t i = 0; i < wavelet->width; i++)
+ lineBufH1[i] = lineBufH0[i] + lineBufL2[i];
+
+ wavelet->curH += 2;
+ wavelet->curLine += 2;
+ wavelet->fltTapH = (wavelet->fltTapH + 2) % 5;
+ }
+ }
+ }
+ else
+ {
+ if (level)
+ {
+ if (!wavelet[-1].curH && crxIdwt53FilterTransform(comp, level - 1))
+ return -1;
+ wavelet->subband0Buf = crxIdwt53FilterGetLine(comp, level - 1);
+ }
+
+ int32_t *band0Buf = wavelet->subband0Buf;
+ int32_t *band1Buf = wavelet->subband1Buf;
+ int32_t *band2Buf = wavelet->subband2Buf;
+ int32_t *band3Buf = wavelet->subband3Buf;
+
+ int32_t *lineBufL0 = wavelet->lineBuf[0];
+ int32_t *lineBufL1 = wavelet->lineBuf[1];
+ int32_t *lineBufL2 = wavelet->lineBuf[2];
+ int32_t *lineBufH0 = wavelet->lineBuf[wavelet->fltTapH + 3];
+ int32_t *lineBufH1 = wavelet->lineBuf[(wavelet->fltTapH + 1) % 5 + 3];
+ int32_t *lineBufH2 = wavelet->lineBuf[(wavelet->fltTapH + 2) % 5 + 3];
+
+ wavelet->lineBuf[1] = wavelet->lineBuf[2];
+ wavelet->lineBuf[2] = lineBufL1;
+
+ // process L bands
+ if (wavelet->width <= 1)
+ {
+ lineBufL0[0] = band0Buf[0];
+ lineBufL1[0] = band2Buf[0];
+ }
+ else
+ {
+ if (comp->tileFlag & E_HAS_TILES_ON_THE_LEFT)
+ {
+ lineBufL0[0] = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ lineBufL1[0] = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2);
+ ++band1Buf;
+ ++band3Buf;
+ }
+ else
+ {
+ lineBufL0[0] = band0Buf[0] - ((band1Buf[0] + 1) >> 1);
+ lineBufL1[0] = band2Buf[0] - ((band3Buf[0] + 1) >> 1);
+ }
+ ++band0Buf;
+ ++band2Buf;
+ for (int i = 0; i < wavelet->width - 3; i += 2)
+ {
+ int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ lineBufL0[1] = band1Buf[0] + ((delta + lineBufL0[0]) >> 1);
+ lineBufL0[2] = delta;
+
+ delta = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2);
+ lineBufL1[1] = band3Buf[0] + ((delta + lineBufL1[0]) >> 1);
+ lineBufL1[2] = delta;
+
+ ++band0Buf;
+ ++band1Buf;
+ ++band2Buf;
+ ++band3Buf;
+ lineBufL0 += 2;
+ lineBufL1 += 2;
+ }
+ if (comp->tileFlag & E_HAS_TILES_ON_THE_RIGHT)
+ {
+ int32_t deltaA = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ lineBufL0[1] = band1Buf[0] + ((deltaA + lineBufL0[0]) >> 1);
+
+ int32_t deltaB = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2);
+ lineBufL1[1] = band3Buf[0] + ((deltaB + lineBufL1[0]) >> 1);
+
+ if (wavelet->width & 1)
+ {
+ lineBufL0[2] = deltaA;
+ lineBufL1[2] = deltaB;
+ }
+ }
+ else if (wavelet->width & 1)
+ {
+ int32_t delta = band0Buf[0] - ((band1Buf[0] + 1) >> 1);
+ lineBufL0[1] = band1Buf[0] + ((delta + lineBufL0[0]) >> 1);
+ lineBufL0[2] = delta;
+
+ delta = band2Buf[0] - ((band3Buf[0] + 1) >> 1);
+ lineBufL1[1] = band3Buf[0] + ((delta + lineBufL1[0]) >> 1);
+ lineBufL1[2] = delta;
+ }
+ else
+ {
+ lineBufL0[1] = lineBufL0[0] + band1Buf[0];
+ lineBufL1[1] = lineBufL1[0] + band3Buf[0];
+ }
+ }
+
+ // process H bands
+ lineBufL0 = wavelet->lineBuf[0];
+ lineBufL1 = wavelet->lineBuf[1];
+ lineBufL2 = wavelet->lineBuf[2];
+ for (int32_t i = 0; i < wavelet->width; i++)
+ {
+ int32_t delta = lineBufL0[i] - ((lineBufL2[i] + lineBufL1[i] + 2) >> 2);
+ lineBufH1[i] = lineBufL1[i] + ((delta + lineBufH0[i]) >> 1);
+ lineBufH2[i] = delta;
+ }
+ if (wavelet->curLine >= wavelet->height - 3 && wavelet->height & 1)
+ {
+ wavelet->curH += 3;
+ wavelet->curLine += 3;
+ wavelet->fltTapH = (wavelet->fltTapH + 3) % 5;
+ }
+ else
+ {
+ wavelet->curH += 2;
+ wavelet->curLine += 2;
+ wavelet->fltTapH = (wavelet->fltTapH + 2) % 5;
+ }
+ }
+
+ return 0;
+}
+
+int crxIdwt53FilterInitialize(CrxPlaneComp *comp, int32_t level, CrxQStep *qStep)
+{
+ if (level == 0)
+ return 0;
+
+ for (int curLevel = 0, curBand = 0; curLevel < level; curLevel++, curBand += 3)
+ {
+ CrxQStep *qStepLevel = qStep ? qStep + curLevel : 0;
+ CrxWaveletTransform *wavelet = comp->wvltTransform + curLevel;
+ if (curLevel)
+ wavelet[0].subband0Buf = crxIdwt53FilterGetLine(comp, curLevel - 1);
+ else if (crxDecodeLineWithIQuantization(comp->subBands + curBand, qStepLevel))
+ return -1;
+
+ int32_t *lineBufH0 = wavelet->lineBuf[wavelet->fltTapH + 3];
+ if (wavelet->height > 1)
+ {
+ if (crxDecodeLineWithIQuantization(comp->subBands + curBand + 1, qStepLevel) ||
+ crxDecodeLineWithIQuantization(comp->subBands + curBand + 2, qStepLevel) ||
+ crxDecodeLineWithIQuantization(comp->subBands + curBand + 3, qStepLevel))
+ return -1;
+
+ int32_t *lineBufL0 = wavelet->lineBuf[0];
+ int32_t *lineBufL1 = wavelet->lineBuf[1];
+ int32_t *lineBufL2 = wavelet->lineBuf[2];
+
+ if (comp->tileFlag & E_HAS_TILES_ON_THE_TOP)
+ {
+ crxHorizontal53(lineBufL0, wavelet->lineBuf[1], wavelet, comp->tileFlag);
+ if (crxDecodeLineWithIQuantization(comp->subBands + curBand + 3, qStepLevel) ||
+ crxDecodeLineWithIQuantization(comp->subBands + curBand + 2, qStepLevel))
+ return -1;
+
+ int32_t *band2Buf = wavelet->subband2Buf;
+ int32_t *band3Buf = wavelet->subband3Buf;
+
+ // process L band
+ if (wavelet->width <= 1)
+ lineBufL2[0] = band2Buf[0];
+ else
+ {
+ if (comp->tileFlag & E_HAS_TILES_ON_THE_LEFT)
+ {
+ lineBufL2[0] = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2);
+ ++band3Buf;
+ }
+ else
+ lineBufL2[0] = band2Buf[0] - ((band3Buf[0] + 1) >> 1);
+
+ ++band2Buf;
+
+ for (int i = 0; i < wavelet->width - 3; i += 2)
+ {
+ int32_t delta = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2);
+ lineBufL2[1] = band3Buf[0] + ((lineBufL2[0] + delta) >> 1);
+ lineBufL2[2] = delta;
+
+ ++band2Buf;
+ ++band3Buf;
+ lineBufL2 += 2;
+ }
+ if (comp->tileFlag & E_HAS_TILES_ON_THE_RIGHT)
+ {
+ int32_t delta = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2);
+ lineBufL2[1] = band3Buf[0] + ((lineBufL2[0] + delta) >> 1);
+ if (wavelet->width & 1)
+ lineBufL2[2] = delta;
+ }
+ else if (wavelet->width & 1)
+ {
+ int32_t delta = band2Buf[0] - ((band3Buf[0] + 1) >> 1);
+
+ lineBufL2[1] = band3Buf[0] + ((lineBufL2[0] + delta) >> 1);
+ lineBufL2[2] = delta;
+ }
+ else
+ {
+ lineBufL2[1] = band3Buf[0] + lineBufL2[0];
+ }
+ }
+
+ // process H band
+ for (int32_t i = 0; i < wavelet->width; i++)
+ lineBufH0[i] = lineBufL0[i] - ((lineBufL1[i] + lineBufL2[i] + 2) >> 2);
+ }
+ else
+ {
+ crxHorizontal53(lineBufL0, wavelet->lineBuf[2], wavelet, comp->tileFlag);
+ for (int i = 0; i < wavelet->width; i++)
+ lineBufH0[i] = lineBufL0[i] - ((lineBufL2[i] + 1) >> 1);
+ }
+
+ if (crxIdwt53FilterDecode(comp, curLevel, qStep) || crxIdwt53FilterTransform(comp, curLevel))
+ return -1;
+ }
+ else
+ {
+ if (crxDecodeLineWithIQuantization(comp->subBands + curBand + 1, qStepLevel))
+ return -1;
+
+ int32_t *band0Buf = wavelet->subband0Buf;
+ int32_t *band1Buf = wavelet->subband1Buf;
+
+ // process H band
+ if (wavelet->width <= 1)
+ lineBufH0[0] = band0Buf[0];
+ else
+ {
+ if (comp->tileFlag & E_HAS_TILES_ON_THE_LEFT)
+ {
+ lineBufH0[0] = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ ++band1Buf;
+ }
+ else
+ lineBufH0[0] = band0Buf[0] - ((band1Buf[0] + 1) >> 1);
+
+ ++band0Buf;
+
+ for (int i = 0; i < wavelet->width - 3; i += 2)
+ {
+ int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ lineBufH0[1] = band1Buf[0] + ((lineBufH0[0] + delta) >> 1);
+ lineBufH0[2] = delta;
+
+ ++band0Buf;
+ ++band1Buf;
+ lineBufH0 += 2;
+ }
+
+ if (comp->tileFlag & E_HAS_TILES_ON_THE_RIGHT)
+ {
+ int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2);
+ lineBufH0[1] = band1Buf[0] + ((lineBufH0[0] + delta) >> 1);
+ lineBufH0[2] = delta;
+ }
+ else if (wavelet->width & 1)
+ {
+ int32_t delta = band0Buf[0] - ((band1Buf[0] + 1) >> 1);
+ lineBufH0[1] = band1Buf[0] + ((lineBufH0[0] + delta) >> 1);
+ lineBufH0[2] = delta;
+ }
+ else
+ {
+ lineBufH0[1] = band1Buf[0] + lineBufH0[0];
+ }
+ }
+ ++wavelet->curLine;
+ ++wavelet->curH;
+ wavelet->fltTapH = (wavelet->fltTapH + 1) % 5;
+ }
+ }
+
+ return 0;
+}
+
+void crxFreeSubbandData(CrxImage *image, CrxPlaneComp *comp)
+{
+ if (comp->compBuf)
+ {
+ free(comp->compBuf);
+ comp->compBuf = 0;
+ }
+
+ if (!comp->subBands)
+ return;
+
+ for (int32_t i = 0; i < image->subbandCount; i++)
+ {
+ if (comp->subBands[i].bandParam)
+ {
+ free(comp->subBands[i].bandParam);
+ comp->subBands[i].bandParam = 0LL;
+ }
+
+ comp->subBands[i].bandBuf = 0;
+ comp->subBands[i].bandSize = 0;
+ }
+}
+
+void crxConvertPlaneLine(CrxImage *img, int imageRow, int imageCol = 0, int plane = 0, int32_t *lineData = 0,
+ int lineLength = 0)
+{
+ if (lineData)
+ {
+ uint64_t rawOffset = 4 * img->planeWidth * imageRow + 2 * imageCol;
+ if (img->encType == 1)
+ {
+ int32_t maxVal = 1 << (img->nBits - 1);
+ int32_t minVal = -maxVal;
+ --maxVal;
+ for (int i = 0; i < lineLength; i++)
+ img->outBufs[plane][rawOffset + 2 * i] = _constrain(lineData[i], minVal, maxVal);
+ }
+ else if (img->encType == 3)
+ {
+ // copy to intermediate planeBuf
+ rawOffset = plane * img->planeWidth * img->planeHeight + img->planeWidth * imageRow + imageCol;
+ for (int i = 0; i < lineLength; i++)
+ img->planeBuf[rawOffset + i] = lineData[i];
+ }
+ else if (img->nPlanes == 4)
+ {
+ int32_t median = 1 << (img->nBits - 1);
+ int32_t maxVal = (1 << img->nBits) - 1;
+ for (int i = 0; i < lineLength; i++)
+ img->outBufs[plane][rawOffset + 2 * i] = _constrain(median + lineData[i], 0, maxVal);
+ }
+ else if (img->nPlanes == 1)
+ {
+ int32_t maxVal = (1 << img->nBits) - 1;
+ int32_t median = 1 << (img->nBits - 1);
+ rawOffset = img->planeWidth * imageRow + imageCol;
+ for (int i = 0; i < lineLength; i++)
+ img->outBufs[0][rawOffset + i] = _constrain(median + lineData[i], 0, maxVal);
+ }
+ }
+ else if (img->encType == 3 && img->planeBuf)
+ {
+ int32_t planeSize = img->planeWidth * img->planeHeight;
+ int16_t *plane0 = img->planeBuf + imageRow * img->planeWidth;
+ int16_t *plane1 = plane0 + planeSize;
+ int16_t *plane2 = plane1 + planeSize;
+ int16_t *plane3 = plane2 + planeSize;
+
+ int32_t median = (1 << (img->medianBits - 1)) << 10;
+ int32_t maxVal = (1 << img->medianBits) - 1;
+ uint32_t rawLineOffset = 4 * img->planeWidth * imageRow;
+
+ // for this stage - all except imageRow is ignored
+ for (int i = 0; i < img->planeWidth; i++)
+ {
+ int32_t gr = median + (plane0[i] << 10) - 168 * plane1[i] - 585 * plane3[i];
+ int32_t val = 0;
+ if (gr < 0)
+ gr = -(((_abs(gr) + 512) >> 9) & ~1);
+ else
+ gr = ((_abs(gr) + 512) >> 9) & ~1;
+
+ // Essentially R = round(median + P0 + 1.474*P3)
+ val = (median + (plane0[i] << 10) + 1510 * plane3[i] + 512) >> 10;
+ img->outBufs[0][rawLineOffset + 2 * i] = _constrain(val, 0, maxVal);
+ // Essentially G1 = round(median + P0 + P2 - 0.164*P1 - 0.571*P3)
+ val = (plane2[i] + gr + 1) >> 1;
+ img->outBufs[1][rawLineOffset + 2 * i] = _constrain(val, 0, maxVal);
+ // Essentially G2 = round(median + P0 - P2 - 0.164*P1 - 0.571*P3)
+ val = (gr - plane2[i] + 1) >> 1;
+ img->outBufs[2][rawLineOffset + 2 * i] = _constrain(val, 0, maxVal);
+ // Essentially B = round(median + P0 + 1.881*P1)
+ val = (median + (plane0[i] << 10) + 1927 * plane1[i] + 512) >> 10;
+ img->outBufs[3][rawLineOffset + 2 * i] = _constrain(val, 0, maxVal);
+ }
+ }
+}
+
+int crxParamInit(CrxImage *img, CrxBandParam **param, uint64_t subbandMdatOffset, uint64_t subbandDataSize,
+ uint32_t subbandWidth, uint32_t subbandHeight, bool supportsPartial, uint32_t roundedBitsMask)
+{
+ int32_t progrDataSize = supportsPartial ? 0 : sizeof(int32_t) * subbandWidth;
+ int32_t paramLength = 2 * subbandWidth + 4;
+ uint8_t *paramBuf = 0;
+ paramBuf = (uint8_t *)
+#ifdef LIBRAW_CR3_MEMPOOL
+ img->memmgr.
+#endif
+ calloc(1, sizeof(CrxBandParam) + sizeof(int32_t) * paramLength + progrDataSize);
+
+ if (!paramBuf)
+ return -1;
+
+ *param = (CrxBandParam *)paramBuf;
+
+ paramBuf += sizeof(CrxBandParam);
+
+ (*param)->paramData = (int32_t *)paramBuf;
+ (*param)->nonProgrData = progrDataSize ? (*param)->paramData + paramLength : 0;
+ (*param)->subbandWidth = subbandWidth;
+ (*param)->subbandHeight = subbandHeight;
+ (*param)->roundedBits = 0;
+ (*param)->curLine = 0;
+ (*param)->roundedBitsMask = roundedBitsMask;
+ (*param)->supportsPartial = supportsPartial;
+ (*param)->bitStream.bitData = 0;
+ (*param)->bitStream.bitsLeft = 0;
+ (*param)->bitStream.mdatSize = subbandDataSize;
+ (*param)->bitStream.curPos = 0;
+ (*param)->bitStream.curBufSize = 0;
+ (*param)->bitStream.curBufOffset = subbandMdatOffset;
+ (*param)->bitStream.input = img->input;
+
+ crxFillBuffer(&(*param)->bitStream);
+
+ return 0;
+}
+
+int crxSetupSubbandData(CrxImage *img, CrxPlaneComp *planeComp, const CrxTile *tile, uint32_t mdatOffset)
+{
+ long compDataSize = 0;
+ long waveletDataOffset = 0;
+ long compCoeffDataOffset = 0;
+ int32_t toSubbands = 3 * img->levels + 1;
+ int32_t transformWidth = 0;
+
+ CrxSubband *subbands = planeComp->subBands;
+
+ // calculate sizes
+ for (int32_t subbandNum = 0; subbandNum < toSubbands; subbandNum++)
+ {
+ subbands[subbandNum].bandSize = subbands[subbandNum].width * sizeof(int32_t); // 4bytes
+ compDataSize += subbands[subbandNum].bandSize;
+ }
+
+ if (img->levels)
+ {
+ int32_t encLevels = img->levels ? img->levels : 1;
+ waveletDataOffset = (compDataSize + 7) & ~7;
+ compDataSize = (sizeof(CrxWaveletTransform) * encLevels + waveletDataOffset + 7) & ~7;
+ compCoeffDataOffset = compDataSize;
+
+ // calc wavelet line buffer sizes (always at one level up from current)
+ for (int level = 0; level < img->levels; ++level)
+ if (level < img->levels - 1)
+ compDataSize += 8 * sizeof(int32_t) * planeComp->subBands[3 * (level + 1) + 2].width;
+ else
+ compDataSize += 8 * sizeof(int32_t) * tile->width;
+ }
+ // buffer allocation
+ planeComp->compBuf = (uint8_t *)
+#ifdef LIBRAW_CR3_MEMPOOL
+ img->memmgr.
+#endif
+ malloc(compDataSize);
+ if (!planeComp->compBuf)
+ return -1;
+
+ // subbands buffer and sizes initialisation
+ uint64_t subbandMdatOffset = img->mdatOffset + mdatOffset;
+ uint8_t *subbandBuf = planeComp->compBuf;
+
+ for (int32_t subbandNum = 0; subbandNum < toSubbands; subbandNum++)
+ {
+ subbands[subbandNum].bandBuf = subbandBuf;
+ subbandBuf += subbands[subbandNum].bandSize;
+ subbands[subbandNum].mdatOffset = subbandMdatOffset + subbands[subbandNum].dataOffset;
+ }
+
+ // wavelet data initialisation
+ if (img->levels)
+ {
+ CrxWaveletTransform *waveletTransforms = (CrxWaveletTransform *)(planeComp->compBuf + waveletDataOffset);
+ int32_t *paramData = (int32_t *)(planeComp->compBuf + compCoeffDataOffset);
+
+ planeComp->wvltTransform = waveletTransforms;
+ waveletTransforms[0].subband0Buf = (int32_t *)subbands->bandBuf;
+
+ for (int level = 0; level < img->levels; ++level)
+ {
+ int32_t band = 3 * level + 1;
+
+ if (level >= img->levels - 1)
+ {
+ waveletTransforms[level].height = tile->height;
+ transformWidth = tile->width;
+ }
+ else
+ {
+ waveletTransforms[level].height = subbands[band + 3].height;
+ transformWidth = subbands[band + 4].width;
+ }
+ waveletTransforms[level].width = transformWidth;
+ waveletTransforms[level].lineBuf[0] = paramData;
+ waveletTransforms[level].lineBuf[1] = waveletTransforms[level].lineBuf[0] + transformWidth;
+ waveletTransforms[level].lineBuf[2] = waveletTransforms[level].lineBuf[1] + transformWidth;
+ waveletTransforms[level].lineBuf[3] = waveletTransforms[level].lineBuf[2] + transformWidth;
+ waveletTransforms[level].lineBuf[4] = waveletTransforms[level].lineBuf[3] + transformWidth;
+ waveletTransforms[level].lineBuf[5] = waveletTransforms[level].lineBuf[4] + transformWidth;
+ waveletTransforms[level].lineBuf[6] = waveletTransforms[level].lineBuf[5] + transformWidth;
+ waveletTransforms[level].lineBuf[7] = waveletTransforms[level].lineBuf[6] + transformWidth;
+ waveletTransforms[level].curLine = 0;
+ waveletTransforms[level].curH = 0;
+ waveletTransforms[level].fltTapH = 0;
+ waveletTransforms[level].subband1Buf = (int32_t *)subbands[band].bandBuf;
+ waveletTransforms[level].subband2Buf = (int32_t *)subbands[band + 1].bandBuf;
+ waveletTransforms[level].subband3Buf = (int32_t *)subbands[band + 2].bandBuf;
+
+ paramData = waveletTransforms[level].lineBuf[7] + transformWidth;
+ }
+ }
+
+ // decoding params and bitstream initialisation
+ for (int32_t subbandNum = 0; subbandNum < toSubbands; subbandNum++)
+ {
+ if (subbands[subbandNum].dataSize)
+ {
+ bool supportsPartial = false;
+ uint32_t roundedBitsMask = 0;
+
+ if (planeComp->supportsPartial && subbandNum == 0)
+ {
+ roundedBitsMask = planeComp->roundedBitsMask;
+ supportsPartial = true;
+ }
+ if (crxParamInit(img, &subbands[subbandNum].bandParam, subbands[subbandNum].mdatOffset,
+ subbands[subbandNum].dataSize, subbands[subbandNum].width, subbands[subbandNum].height,
+ supportsPartial, roundedBitsMask))
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int LibRaw::crxDecodePlane(void *p, uint32_t planeNumber)
+{
+ CrxImage *img = (CrxImage *)p;
+ int imageRow = 0;
+ for (int tRow = 0; tRow < img->tileRows; tRow++)
+ {
+ int imageCol = 0;
+ for (int tCol = 0; tCol < img->tileCols; tCol++)
+ {
+ CrxTile *tile = img->tiles + tRow * img->tileCols + tCol;
+ CrxPlaneComp *planeComp = tile->comps + planeNumber;
+ uint64_t tileMdatOffset = tile->dataOffset + tile->mdatQPDataSize + tile->mdatExtraSize + planeComp->dataOffset;
+
+ // decode single tile
+ if (crxSetupSubbandData(img, planeComp, tile, tileMdatOffset))
+ return -1;
+
+ if (img->levels)
+ {
+ if (crxIdwt53FilterInitialize(planeComp, img->levels, tile->qStep))
+ return -1;
+ for (int i = 0; i < tile->height; ++i)
+ {
+ if (crxIdwt53FilterDecode(planeComp, img->levels - 1, tile->qStep) ||
+ crxIdwt53FilterTransform(planeComp, img->levels - 1))
+ return -1;
+ int32_t *lineData = crxIdwt53FilterGetLine(planeComp, img->levels - 1);
+ crxConvertPlaneLine(img, imageRow + i, imageCol, planeNumber, lineData, tile->width);
+ }
+ }
+ else
+ {
+ // we have the only subband in this case
+ if (!planeComp->subBands->dataSize)
+ {
+ memset(planeComp->subBands->bandBuf, 0, planeComp->subBands->bandSize);
+ return 0;
+ }
+
+ for (int i = 0; i < tile->height; ++i)
+ {
+ if (crxDecodeLine(planeComp->subBands->bandParam, planeComp->subBands->bandBuf))
+ return -1;
+ int32_t *lineData = (int32_t *)planeComp->subBands->bandBuf;
+ crxConvertPlaneLine(img, imageRow + i, imageCol, planeNumber, lineData, tile->width);
+ }
+ }
+ imageCol += tile->width;
+ }
+ imageRow += img->tiles[tRow * img->tileCols].height;
+ }
+
+ return 0;
+}
+
+uint32_t crxReadQP(CrxBitstream *bitStrm, int32_t kParam)
+{
+ uint32_t qp = crxBitstreamGetZeros(bitStrm);
+ if (qp >= 23)
+ qp = crxBitstreamGetBits(bitStrm, 8);
+ else if (kParam)
+ qp = crxBitstreamGetBits(bitStrm, kParam) | (qp << kParam);
+
+ return qp;
+}
+
+void crxDecodeGolombTop(CrxBitstream *bitStrm, int32_t width, int32_t *lineBuf, int32_t *kParam)
+{
+ lineBuf[0] = 0;
+ while (width-- > 0)
+ {
+ lineBuf[1] = lineBuf[0];
+ uint32_t qp = crxReadQP(bitStrm, *kParam);
+ lineBuf[1] += -(int32_t)(qp & 1) ^ (int32_t)(qp >> 1);
+ *kParam = crxPredictKParameter(*kParam, qp, 7);
+ ++lineBuf;
+ }
+ lineBuf[1] = lineBuf[0] + 1;
+}
+
+void crxDecodeGolombNormal(CrxBitstream *bitStrm, int32_t width, int32_t *lineBuf0, int32_t *lineBuf1, int32_t *kParam)
+{
+ lineBuf1[0] = lineBuf0[1];
+ int32_t deltaH = lineBuf0[1] - lineBuf0[0];
+ while (width-- > 0)
+ {
+ lineBuf1[1] = crxPrediction(lineBuf1[0], lineBuf0[1], deltaH, lineBuf0[0] - lineBuf1[0]);
+ uint32_t qp = crxReadQP(bitStrm, *kParam);
+ lineBuf1[1] += -(int32_t)(qp & 1) ^ (int32_t)(qp >> 1);
+ if (width)
+ {
+ deltaH = lineBuf0[2] - lineBuf0[1];
+ *kParam = crxPredictKParameter(*kParam, (qp + 2 * _abs(deltaH)) >> 1, 7);
+ ++lineBuf0;
+ }
+ else
+ *kParam = crxPredictKParameter(*kParam, qp, 7);
+ ++lineBuf1;
+ }
+ lineBuf1[1] = lineBuf1[0] + 1;
+}
+
+int crxMakeQStep(CrxImage *img, CrxTile *tile, int32_t *qpTable, uint32_t /*totalQP*/)
+{
+ if (img->levels > 3 || img->levels < 1)
+ return -1;
+ int qpWidth = (tile->width >> 3) + ((tile->width & 7) != 0);
+ int qpHeight = (tile->height >> 1) + (tile->height & 1);
+ int qpHeight4 = (tile->height >> 2) + ((tile->height & 3) != 0);
+ int qpHeight8 = (tile->height >> 3) + ((tile->height & 7) != 0);
+ uint32_t totalHeight = qpHeight;
+ if (img->levels > 1)
+ totalHeight += qpHeight4;
+ if (img->levels > 2)
+ totalHeight += qpHeight8;
+ tile->qStep = (CrxQStep *)
+#ifdef LIBRAW_CR3_MEMPOOL
+ img->memmgr.
+#endif
+ malloc(totalHeight * qpWidth * sizeof(uint32_t) + img->levels * sizeof(CrxQStep));
+
+ if (!tile->qStep)
+ return -1;
+ uint32_t *qStepTbl = (uint32_t *)(tile->qStep + img->levels);
+ CrxQStep *qStep = tile->qStep;
+ switch (img->levels)
+ {
+ case 3:
+ qStep->qStepTbl = qStepTbl;
+ qStep->width = qpWidth;
+ qStep->height = qpHeight8;
+ for (int qpRow = 0; qpRow < qpHeight8; ++qpRow)
+ {
+ int row0Idx = qpWidth * _min(4 * qpRow, qpHeight - 1);
+ int row1Idx = qpWidth * _min(4 * qpRow + 1, qpHeight - 1);
+ int row2Idx = qpWidth * _min(4 * qpRow + 2, qpHeight - 1);
+ int row3Idx = qpWidth * _min(4 * qpRow + 3, qpHeight - 1);
+
+ for (int qpCol = 0; qpCol < qpWidth; ++qpCol, ++qStepTbl)
+ {
+ int32_t quantVal = qpTable[row0Idx++] + qpTable[row1Idx++] + qpTable[row2Idx++] + qpTable[row3Idx++];
+ // not sure about this nonsense - why is it not just avg like with 2 levels?
+ quantVal = ((quantVal < 0) * 3 + quantVal) >> 2;
+ if (quantVal / 6 >= 6)
+ *qStepTbl = q_step_tbl[quantVal % 6] * (1 << (quantVal / 6 + 26));
+ else
+ *qStepTbl = q_step_tbl[quantVal % 6] >> (6 - quantVal / 6);
+ }
+ }
+ // continue to the next level - we always decode all levels
+ ++qStep;
+ case 2:
+ qStep->qStepTbl = qStepTbl;
+ qStep->width = qpWidth;
+ qStep->height = qpHeight4;
+ for (int qpRow = 0; qpRow < qpHeight4; ++qpRow)
+ {
+ int row0Idx = qpWidth * _min(2 * qpRow, qpHeight - 1);
+ int row1Idx = qpWidth * _min(2 * qpRow + 1, qpHeight - 1);
+
+ for (int qpCol = 0; qpCol < qpWidth; ++qpCol, ++qStepTbl)
+ {
+ int32_t quantVal = (qpTable[row0Idx++] + qpTable[row1Idx++]) / 2;
+ if (quantVal / 6 >= 6)
+ *qStepTbl = q_step_tbl[quantVal % 6] * (1 << (quantVal / 6 + 26));
+ else
+ *qStepTbl = q_step_tbl[quantVal % 6] >> (6 - quantVal / 6);
+ }
+ }
+ // continue to the next level - we always decode all levels
+ ++qStep;
+ case 1:
+ qStep->qStepTbl = qStepTbl;
+ qStep->width = qpWidth;
+ qStep->height = qpHeight;
+ for (int qpRow = 0; qpRow < qpHeight; ++qpRow)
+ for (int qpCol = 0; qpCol < qpWidth; ++qpCol, ++qStepTbl, ++qpTable)
+ if (*qpTable / 6 >= 6)
+ *qStepTbl = q_step_tbl[*qpTable % 6] * (1 << (*qpTable / 6 + 26));
+ else
+ *qStepTbl = q_step_tbl[*qpTable % 6] >> (6 - *qpTable / 6);
+
+ break;
+ }
+ return 0;
+}
+
+libraw_inline void crxSetupSubbandIdx(crx_data_header_t *hdr, CrxImage * /*img*/, CrxSubband *band, int level,
+ short colStartIdx, short bandWidthExCoef, short rowStartIdx,
+ short bandHeightExCoef)
+{
+ if (hdr->version == 0x200)
+ {
+ band->rowStartAddOn = rowStartIdx;
+ band->rowEndAddOn = bandHeightExCoef;
+ band->colStartAddOn = colStartIdx;
+ band->colEndAddOn = bandWidthExCoef;
+ band->levelShift = 3 - level;
+ }
+ else
+ {
+ band->rowStartAddOn = 0;
+ band->rowEndAddOn = 0;
+ band->colStartAddOn = 0;
+ band->colEndAddOn = 0;
+ band->levelShift = 0;
+ }
+}
+
+int crxProcessSubbands(crx_data_header_t *hdr, CrxImage *img, CrxTile *tile, CrxPlaneComp *comp)
+{
+ CrxSubband *band = comp->subBands + img->subbandCount - 1; // set to last band
+ uint32_t bandHeight = tile->height;
+ uint32_t bandWidth = tile->width;
+ int32_t bandWidthExCoef = 0;
+ int32_t bandHeightExCoef = 0;
+ if (img->levels)
+ {
+ // Build up subband sequences to crxDecode to a level in a header
+
+ // Coefficient structure is a bit unclear and convoluted:
+ // 3 levels max - 8 groups (for tile width rounded to 8 bytes)
+ // of 3 band per level 4 sets of coefficients for each
+ int32_t *rowExCoef = exCoefNumTbl + 0x30 * (img->levels - 1) + 6 * (tile->width & 7);
+ int32_t *colExCoef = exCoefNumTbl + 0x30 * (img->levels - 1) + 6 * (tile->height & 7);
+ for (int level = 0; level < img->levels; ++level)
+ {
+ int32_t widthOddPixel = bandWidth & 1;
+ int32_t heightOddPixel = bandHeight & 1;
+ bandWidth = (widthOddPixel + bandWidth) >> 1;
+ bandHeight = (heightOddPixel + bandHeight) >> 1;
+
+ int32_t bandWidthExCoef0 = 0;
+ int32_t bandWidthExCoef1 = 0;
+ int32_t bandHeightExCoef0 = 0;
+ int32_t bandHeightExCoef1 = 0;
+ int32_t colStartIdx = 0;
+ int32_t rowStartIdx = 0;
+ if (tile->tileFlag & E_HAS_TILES_ON_THE_RIGHT)
+ {
+ bandWidthExCoef0 = rowExCoef[2 * level];
+ bandWidthExCoef1 = rowExCoef[2 * level + 1];
+ }
+ if (tile->tileFlag & E_HAS_TILES_ON_THE_LEFT)
+ {
+ ++bandWidthExCoef0;
+ colStartIdx = 1;
+ }
+
+ if (tile->tileFlag & E_HAS_TILES_ON_THE_BOTTOM)
+ {
+ bandHeightExCoef0 = colExCoef[2 * level];
+ bandHeightExCoef1 = colExCoef[2 * level + 1];
+ }
+ if (tile->tileFlag & E_HAS_TILES_ON_THE_TOP)
+ {
+ ++bandHeightExCoef0;
+ rowStartIdx = 1;
+ }
+
+ band[0].width = bandWidth + bandWidthExCoef0 - widthOddPixel;
+ band[0].height = bandHeight + bandHeightExCoef0 - heightOddPixel;
+ crxSetupSubbandIdx(hdr, img, band, level + 1, colStartIdx, bandWidthExCoef0 - colStartIdx, rowStartIdx,
+ bandHeightExCoef0 - rowStartIdx);
+
+ band[-1].width = bandWidth + bandWidthExCoef1;
+ band[-1].height = bandHeight + bandHeightExCoef0 - heightOddPixel;
+
+ crxSetupSubbandIdx(hdr, img, band - 1, level + 1, 0, bandWidthExCoef1, rowStartIdx,
+ bandHeightExCoef0 - rowStartIdx);
+
+ band[-2].width = bandWidth + bandWidthExCoef0 - widthOddPixel;
+ band[-2].height = bandHeight + bandHeightExCoef1;
+ crxSetupSubbandIdx(hdr, img, band - 2, level + 1, colStartIdx, bandWidthExCoef0 - colStartIdx, 0,
+ bandHeightExCoef1);
+
+ band -= 3;
+ }
+ bandWidthExCoef = bandHeightExCoef = 0;
+ if (tile->tileFlag & E_HAS_TILES_ON_THE_RIGHT)
+ bandWidthExCoef = rowExCoef[2 * img->levels - 1];
+ if (tile->tileFlag & E_HAS_TILES_ON_THE_BOTTOM)
+ bandHeightExCoef = colExCoef[2 * img->levels - 1];
+ }
+ band->width = bandWidthExCoef + bandWidth;
+ band->height = bandHeightExCoef + bandHeight;
+ if (img->levels)
+ crxSetupSubbandIdx(hdr, img, band, img->levels, 0, bandWidthExCoef, 0, bandHeightExCoef);
+
+ return 0;
+}
+
+int crxReadSubbandHeaders(crx_data_header_t * /*hdr*/, CrxImage *img, CrxTile * /*tile*/, CrxPlaneComp *comp,
+ uint8_t **subbandMdatPtr, int32_t *mdatSize)
+{
+ if (!img->subbandCount)
+ return 0;
+ int32_t subbandOffset = 0;
+ CrxSubband *band = comp->subBands;
+ for (int curSubband = 0; curSubband < img->subbandCount; curSubband++, band++)
+ {
+ if (*mdatSize < 4)
+ return -1;
+
+ int hdrSign = LibRaw::sgetn(2, *subbandMdatPtr);
+ int hdrSize = LibRaw::sgetn(2, *subbandMdatPtr + 2);
+ if (*mdatSize < hdrSize + 4)
+ return -1;
+ if ((hdrSign != 0xFF03 || hdrSize != 8) && (hdrSign != 0xFF13 || hdrSize != 16))
+ return -1;
+
+ int32_t subbandSize = LibRaw::sgetn(4, *subbandMdatPtr + 4);
+
+ if (curSubband != ((*subbandMdatPtr)[8] & 0xF0) >> 4)
+ {
+ band->dataSize = subbandSize;
+ return -1;
+ }
+
+ band->dataOffset = subbandOffset;
+ band->kParam = 0;
+ band->bandParam = 0;
+ band->bandBuf = 0;
+ band->bandSize = 0;
+
+ if (hdrSign == 0xFF03)
+ {
+ // old header
+ uint32_t bitData = LibRaw::sgetn(4, *subbandMdatPtr + 8);
+ band->dataSize = subbandSize - (bitData & 0x7FFFF);
+ band->supportsPartial = bitData & 0x8000000;
+ band->qParam = (bitData >> 19) & 0xFF;
+ band->qStepBase = 0;
+ band->qStepMult = 0;
+ }
+ else
+ {
+ // new header
+ if (LibRaw::sgetn(2, *subbandMdatPtr + 8) & 0xFFF)
+ // partial and qParam are not supported
+ return -1;
+ if (LibRaw::sgetn(2, *subbandMdatPtr + 18))
+ // new header terninated by 2 zero bytes
+ return -1;
+ band->supportsPartial = false;
+ band->qParam = 0;
+ band->dataSize = subbandSize - LibRaw::sgetn(2, *subbandMdatPtr + 16);
+ band->qStepBase = LibRaw::sgetn(4, *subbandMdatPtr + 12);
+ ;
+ band->qStepMult = LibRaw::sgetn(2, *subbandMdatPtr + 10);
+ ;
+ }
+
+ subbandOffset += subbandSize;
+
+ *subbandMdatPtr += hdrSize + 4;
+ *mdatSize -= hdrSize + 4;
+ }
+
+ return 0;
+}
+
+int crxReadImageHeaders(crx_data_header_t *hdr, CrxImage *img, uint8_t *mdatPtr, int32_t mdatHdrSize)
+{
+ int nTiles = img->tileRows * img->tileCols;
+
+ if (!nTiles)
+ return -1;
+
+ if (!img->tiles)
+ {
+ img->tiles = (CrxTile *)
+#ifdef LIBRAW_CR3_MEMPOOL
+ img->memmgr.
+#endif
+ calloc(sizeof(CrxTile) * nTiles + sizeof(CrxPlaneComp) * nTiles * img->nPlanes +
+ sizeof(CrxSubband) * nTiles * img->nPlanes * img->subbandCount,
+ 1);
+ if (!img->tiles)
+ return -1;
+
+ // memory areas in allocated chunk
+ CrxTile *tile = img->tiles;
+ CrxPlaneComp *comps = (CrxPlaneComp *)(tile + nTiles);
+ CrxSubband *bands = (CrxSubband *)(comps + img->nPlanes * nTiles);
+
+ for (int curTile = 0; curTile < nTiles; curTile++, tile++)
+ {
+ tile->tileFlag = 0; // tile neighbouring flags
+ tile->tileNumber = curTile;
+ tile->tileSize = 0;
+ tile->comps = comps + curTile * img->nPlanes;
+
+ if ((curTile + 1) % img->tileCols)
+ {
+ // not the last tile in a tile row
+ tile->width = hdr->tileWidth;
+ if (img->tileCols > 1)
+ {
+ tile->tileFlag = E_HAS_TILES_ON_THE_RIGHT;
+ if (curTile % img->tileCols)
+ // not the first tile in tile row
+ tile->tileFlag |= E_HAS_TILES_ON_THE_LEFT;
+ }
+ }
+ else
+ {
+ // last tile in a tile row
+ tile->width = img->planeWidth - hdr->tileWidth * (img->tileCols - 1);
+ if (img->tileCols > 1)
+ tile->tileFlag = E_HAS_TILES_ON_THE_LEFT;
+ }
+ if (curTile < nTiles - img->tileCols)
+ {
+ // in first tile row
+ tile->height = hdr->tileHeight;
+ if (img->tileRows > 1)
+ {
+ tile->tileFlag |= E_HAS_TILES_ON_THE_BOTTOM;
+ if (curTile >= img->tileCols)
+ tile->tileFlag |= E_HAS_TILES_ON_THE_TOP;
+ }
+ }
+ else
+ {
+ // non first tile row
+ tile->height = img->planeHeight - hdr->tileHeight * (img->tileRows - 1);
+ if (img->tileRows > 1)
+ tile->tileFlag |= E_HAS_TILES_ON_THE_TOP;
+ }
+ if (img->nPlanes)
+ {
+ CrxPlaneComp *comp = tile->comps;
+ CrxSubband *band = bands + curTile * img->nPlanes * img->subbandCount;
+
+ for (int curComp = 0; curComp < img->nPlanes; curComp++, comp++)
+ {
+ comp->compNumber = curComp;
+ comp->supportsPartial = true;
+ comp->tileFlag = tile->tileFlag;
+ comp->subBands = band;
+ comp->compBuf = 0;
+ comp->wvltTransform = 0;
+ if (img->subbandCount)
+ {
+ for (int curBand = 0; curBand < img->subbandCount; curBand++, band++)
+ {
+ band->supportsPartial = false;
+ band->qParam = 4;
+ band->bandParam = 0;
+ band->dataSize = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ uint32_t tileOffset = 0;
+ int32_t dataSize = mdatHdrSize;
+ uint8_t *dataPtr = mdatPtr;
+ CrxTile *tile = img->tiles;
+
+ for (int curTile = 0; curTile < nTiles; ++curTile, ++tile)
+ {
+ if (dataSize < 4)
+ return -1;
+
+ int hdrSign = LibRaw::sgetn(2, dataPtr);
+ int hdrSize = LibRaw::sgetn(2, dataPtr + 2);
+ if ((hdrSign != 0xFF01 || hdrSize != 8) && (hdrSign != 0xFF11 || (hdrSize != 8 && hdrSize != 16)))
+ return -1;
+ if (dataSize < hdrSize + 4)
+ return -1;
+ int tailSign = LibRaw::sgetn(2, dataPtr + 10);
+ if ((hdrSize == 8 && tailSign) || (hdrSize == 16 && tailSign != 0x4000))
+ return -1;
+ if (LibRaw::sgetn(2, dataPtr + 8) != (unsigned)curTile)
+ return -1;
+
+ dataSize -= hdrSize + 4;
+
+ tile->tileSize = LibRaw::sgetn(4, dataPtr + 4);
+ tile->dataOffset = tileOffset;
+ tile->qStep = 0;
+ if (hdrSize == 16)
+ {
+ // extended header data - terminated by 0 bytes
+ if (LibRaw::sgetn(2, dataPtr + 18) != 0)
+ return -1;
+ tile->hasQPData = true;
+ tile->mdatQPDataSize = LibRaw::sgetn(4, dataPtr + 12);
+ tile->mdatExtraSize = LibRaw::sgetn(2, dataPtr + 16);
+ }
+ else
+ {
+ tile->hasQPData = false;
+ tile->mdatQPDataSize = 0;
+ tile->mdatExtraSize = 0;
+ }
+
+ dataPtr += hdrSize + 4;
+ tileOffset += tile->tileSize;
+
+ uint32_t compOffset = 0;
+ CrxPlaneComp *comp = tile->comps;
+
+ for (int compNum = 0; compNum < img->nPlanes; ++compNum, ++comp)
+ {
+ if (dataSize < 0xC)
+ return -1;
+ hdrSign = LibRaw::sgetn(2, dataPtr);
+ hdrSize = LibRaw::sgetn(2, dataPtr + 2);
+ if ((hdrSign != 0xFF02 && hdrSign != 0xFF12) || hdrSize != 8)
+ return -1;
+ if (compNum != dataPtr[8] >> 4)
+ return -1;
+ if (LibRaw::sgetn(3, dataPtr + 9) != 0)
+ return -1;
+
+ comp->compSize = LibRaw::sgetn(4, dataPtr + 4);
+
+ int32_t compHdrRoundedBits = (dataPtr[8] >> 1) & 3;
+ comp->supportsPartial = (dataPtr[8] & 8) != 0;
+
+ comp->dataOffset = compOffset;
+ comp->tileFlag = tile->tileFlag;
+
+ compOffset += comp->compSize;
+ dataSize -= 0xC;
+ dataPtr += 0xC;
+
+ comp->roundedBitsMask = 0;
+
+ if (compHdrRoundedBits)
+ {
+ if (img->levels || !comp->supportsPartial)
+ return -1;
+
+ comp->roundedBitsMask = 1 << (compHdrRoundedBits - 1);
+ }
+
+ if (crxReadSubbandHeaders(hdr, img, tile, comp, &dataPtr, &dataSize) || crxProcessSubbands(hdr, img, tile, comp))
+ return -1;
+ }
+ }
+
+ if (hdr->version != 0x200)
+ return 0;
+
+ tile = img->tiles;
+ for (int curTile = 0; curTile < nTiles; ++curTile, ++tile)
+ {
+ if (tile->hasQPData)
+ {
+ CrxBitstream bitStrm;
+ bitStrm.bitData = 0;
+ bitStrm.bitsLeft = 0;
+ bitStrm.curPos = 0;
+ bitStrm.curBufSize = 0;
+ bitStrm.mdatSize = tile->mdatQPDataSize;
+ bitStrm.curBufOffset = img->mdatOffset + tile->dataOffset;
+ bitStrm.input = img->input;
+
+ crxFillBuffer(&bitStrm);
+
+ unsigned int qpWidth = (tile->width >> 3) + ((tile->width & 7) != 0);
+ unsigned int qpHeight = (tile->height >> 1) + (tile->height & 1);
+ unsigned long totalQP = qpHeight * qpWidth;
+
+ try
+ {
+ std::vector<int32_t> qpTable(totalQP + 2 * (qpWidth + 2));
+ int32_t *qpCurElem = qpTable.data();
+ // 2 lines padded with extra pixels at the start and at the end
+ int32_t *qpLineBuf = qpTable.data() + totalQP;
+ int32_t kParam = 0;
+ for (unsigned qpRow = 0; qpRow < qpHeight; ++qpRow)
+ {
+ int32_t *qpLine0 = qpRow & 1 ? qpLineBuf + qpWidth + 2 : qpLineBuf;
+ int32_t *qpLine1 = qpRow & 1 ? qpLineBuf : qpLineBuf + qpWidth + 2;
+
+ if (qpRow)
+ crxDecodeGolombNormal(&bitStrm, qpWidth, qpLine0, qpLine1, &kParam);
+ else
+ crxDecodeGolombTop(&bitStrm, qpWidth, qpLine1, &kParam);
+
+ for (unsigned qpCol = 0; qpCol < qpWidth; ++qpCol)
+ *qpCurElem++ = qpLine1[qpCol + 1] + 4;
+ }
+
+ // now we read QP data - build tile QStep
+ if (crxMakeQStep(img, tile, qpTable.data(), totalQP))
+ return -1;
+ }
+ catch (...)
+ {
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int crxSetupImageData(crx_data_header_t *hdr, CrxImage *img, int16_t *outBuf, uint64_t mdatOffset, uint32_t mdatSize,
+ uint8_t *mdatHdrPtr, int32_t mdatHdrSize)
+{
+ int IncrBitTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0};
+
+ img->planeWidth = hdr->f_width;
+ img->planeHeight = hdr->f_height;
+
+ if (hdr->tileWidth < 0x16 || hdr->tileHeight < 0x16 || img->planeWidth > 0x7FFF || img->planeHeight > 0x7FFF)
+ return -1;
+
+ img->tileCols = (img->planeWidth + hdr->tileWidth - 1) / hdr->tileWidth;
+ img->tileRows = (img->planeHeight + hdr->tileHeight - 1) / hdr->tileHeight;
+
+ if (img->tileCols > 0xFF || img->tileRows > 0xFF || img->planeWidth - hdr->tileWidth * (img->tileCols - 1) < 0x16 ||
+ img->planeHeight - hdr->tileHeight * (img->tileRows - 1) < 0x16)
+ return -1;
+
+ img->tiles = 0;
+ img->levels = hdr->imageLevels;
+ img->subbandCount = 3 * img->levels + 1; // 3 bands per level + one last LL
+ img->nPlanes = hdr->nPlanes;
+ img->nBits = hdr->nBits;
+ img->encType = hdr->encType;
+ img->samplePrecision = hdr->nBits + IncrBitTable[4 * hdr->encType + 2] + 1;
+ img->mdatOffset = mdatOffset + hdr->mdatHdrSize;
+ img->mdatSize = mdatSize;
+ img->planeBuf = 0;
+ img->outBufs[0] = img->outBufs[1] = img->outBufs[2] = img->outBufs[3] = 0;
+ img->medianBits = hdr->medianBits;
+
+ // The encoding type 3 needs all 4 planes to be decoded to generate row of
+ // RGGB values. It seems to be using some other colour space for raw encoding
+ // It is a massive buffer so ideallly it will need a different approach:
+ // decode planes line by line and convert single line then without
+ // intermediate plane buffer. At the moment though it's too many changes so
+ // left as is.
+ if (img->encType == 3 && img->nPlanes == 4 && img->nBits > 8)
+ {
+ img->planeBuf = (int16_t *)
+#ifdef LIBRAW_CR3_MEMPOOL
+ img->memmgr.
+#endif
+ malloc(img->planeHeight * img->planeWidth * img->nPlanes * ((img->samplePrecision + 7) >> 3));
+ if (!img->planeBuf)
+ return -1;
+ }
+
+ int32_t rowSize = 2 * img->planeWidth;
+
+ if (img->nPlanes == 1)
+ img->outBufs[0] = outBuf;
+ else
+ switch (hdr->cfaLayout)
+ {
+ case 0:
+ // R G
+ // G B
+ img->outBufs[0] = outBuf;
+ img->outBufs[1] = outBuf + 1;
+ img->outBufs[2] = outBuf + rowSize;
+ img->outBufs[3] = img->outBufs[2] + 1;
+ break;
+ case 1:
+ // G R
+ // B G
+ img->outBufs[1] = outBuf;
+ img->outBufs[0] = outBuf + 1;
+ img->outBufs[3] = outBuf + rowSize;
+ img->outBufs[2] = img->outBufs[3] + 1;
+ break;
+ case 2:
+ // G B
+ // R G
+ img->outBufs[2] = outBuf;
+ img->outBufs[3] = outBuf + 1;
+ img->outBufs[0] = outBuf + rowSize;
+ img->outBufs[1] = img->outBufs[0] + 1;
+ break;
+ case 3:
+ // B G
+ // G R
+ img->outBufs[3] = outBuf;
+ img->outBufs[2] = outBuf + 1;
+ img->outBufs[1] = outBuf + rowSize;
+ img->outBufs[0] = img->outBufs[1] + 1;
+ break;
+ }
+
+ // read header
+ return crxReadImageHeaders(hdr, img, mdatHdrPtr, mdatHdrSize);
+}
+
+int crxFreeImageData(CrxImage *img)
+{
+#ifdef LIBRAW_CR3_MEMPOOL
+ img->memmgr.cleanup();
+#else
+ CrxTile *tile = img->tiles;
+ int nTiles = img->tileRows * img->tileCols;
+
+ if (img->tiles)
+ {
+ for (int32_t curTile = 0; curTile < nTiles; curTile++)
+ {
+ if (tile[curTile].comps)
+ for (int32_t curPlane = 0; curPlane < img->nPlanes; curPlane++)
+ crxFreeSubbandData(img, tile[curTile].comps + curPlane);
+ if (tile[curTile].qStep)
+ free(tile[curTile].qStep);
+ }
+ free(img->tiles);
+ img->tiles = 0;
+ }
+
+ if (img->planeBuf)
+ {
+ free(img->planeBuf);
+ img->planeBuf = 0;
+ }
+#endif
+ return 0;
+}
+void LibRaw::crxLoadDecodeLoop(void *img, int nPlanes)
+{
+#ifdef LIBRAW_USE_OPENMP
+ int results[4] ={0,0,0,0}; // nPlanes is always <= 4
+#pragma omp parallel for
+ for (int32_t plane = 0; plane < nPlanes; ++plane)
+ try {
+ results[plane] = crxDecodePlane(img, plane);
+ } catch (...) {
+ results[plane] = 1;
+ }
+
+ for (int32_t plane = 0; plane < nPlanes; ++plane)
+ if (results[plane])
+ derror();
+#else
+ for (int32_t plane = 0; plane < nPlanes; ++plane)
+ if (crxDecodePlane(img, plane))
+ derror();
+#endif
+}
+
+void LibRaw::crxConvertPlaneLineDf(void *p, int imageRow) { crxConvertPlaneLine((CrxImage *)p, imageRow); }
+
+void LibRaw::crxLoadFinalizeLoopE3(void *p, int planeHeight)
+{
+#ifdef LIBRAW_USE_OPENMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < planeHeight; ++i)
+ crxConvertPlaneLineDf(p, i);
+}
+
+void LibRaw::crxLoadRaw()
+{
+ CrxImage img;
+ if (libraw_internal_data.unpacker_data.crx_track_selected < 0 ||
+ libraw_internal_data.unpacker_data.crx_track_selected >= LIBRAW_CRXTRACKS_MAXCOUNT)
+ derror();
+
+ crx_data_header_t hdr =
+ libraw_internal_data.unpacker_data.crx_header[libraw_internal_data.unpacker_data.crx_track_selected];
+
+ if (libraw_internal_data.unpacker_data.data_size < (unsigned)hdr.mdatHdrSize)
+ derror();
+
+ img.input = libraw_internal_data.internal_data.input;
+
+ // update sizes for the planes
+ if (hdr.nPlanes == 4)
+ {
+ hdr.f_width >>= 1;
+ hdr.f_height >>= 1;
+ hdr.tileWidth >>= 1;
+ hdr.tileHeight >>= 1;
+ }
+
+ imgdata.color.maximum = (1 << hdr.nBits) - 1;
+
+ std::vector<uint8_t> hdrBuf(hdr.mdatHdrSize);
+
+ unsigned bytes = 0;
+ // read image header
+#ifdef LIBRAW_USE_OPENMP
+#pragma omp critical
+#endif
+ {
+#ifndef LIBRAW_USE_OPENMP
+ libraw_internal_data.internal_data.input->lock();
+#endif
+ libraw_internal_data.internal_data.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
+ bytes = libraw_internal_data.internal_data.input->read(hdrBuf.data(), 1, hdr.mdatHdrSize);
+#ifndef LIBRAW_USE_OPENMP
+ libraw_internal_data.internal_data.input->unlock();
+#endif
+ }
+
+ if (bytes != hdr.mdatHdrSize)
+ throw LIBRAW_EXCEPTION_IO_EOF;
+
+ // parse and setup the image data
+ if (crxSetupImageData(&hdr, &img, (int16_t *)imgdata.rawdata.raw_image,
+ libraw_internal_data.unpacker_data.data_offset, libraw_internal_data.unpacker_data.data_size,
+ hdrBuf.data(), hdr.mdatHdrSize))
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ crxLoadDecodeLoop(&img, hdr.nPlanes);
+
+ if (img.encType == 3)
+ crxLoadFinalizeLoopE3(&img, img.planeHeight);
+
+ crxFreeImageData(&img);
+}
+
+int LibRaw::crxParseImageHeader(uchar *cmp1TagData, int nTrack, int size)
+{
+ if (nTrack < 0 || nTrack >= LIBRAW_CRXTRACKS_MAXCOUNT)
+ return -1;
+ if (!cmp1TagData)
+ return -1;
+
+ crx_data_header_t *hdr = &libraw_internal_data.unpacker_data.crx_header[nTrack];
+
+ hdr->version = sgetn(2, cmp1TagData + 4);
+ hdr->f_width = sgetn(4, cmp1TagData + 8);
+ hdr->f_height = sgetn(4, cmp1TagData + 12);
+ hdr->tileWidth = sgetn(4, cmp1TagData + 16);
+ hdr->tileHeight = sgetn(4, cmp1TagData + 20);
+ hdr->nBits = cmp1TagData[24];
+ hdr->nPlanes = cmp1TagData[25] >> 4;
+ hdr->cfaLayout = cmp1TagData[25] & 0xF;
+ hdr->encType = cmp1TagData[26] >> 4;
+ hdr->imageLevels = cmp1TagData[26] & 0xF;
+ hdr->hasTileCols = cmp1TagData[27] >> 7;
+ hdr->hasTileRows = (cmp1TagData[27] >> 6) & 1;
+ hdr->mdatHdrSize = sgetn(4, cmp1TagData + 28);
+ int extHeader = cmp1TagData[32] >> 7;
+ int useMedianBits = 0;
+ hdr->medianBits = hdr->nBits;
+
+ if (extHeader && size >= 56 && hdr->nPlanes == 4)
+ useMedianBits = cmp1TagData[56] >> 6 & 1;
+
+ if (useMedianBits && size >= 84)
+ hdr->medianBits = cmp1TagData[84];
+
+ // validation
+ if ((hdr->version != 0x100 && hdr->version != 0x200) || !hdr->mdatHdrSize)
+ return -1;
+ if (hdr->encType == 1)
+ {
+ if (hdr->nBits > 15)
+ return -1;
+ }
+ else
+ {
+ if (hdr->encType && hdr->encType != 3)
+ return -1;
+ if (hdr->nBits > 14)
+ return -1;
+ }
+
+ if (hdr->nPlanes == 1)
+ {
+ if (hdr->cfaLayout || hdr->encType || hdr->nBits != 8)
+ return -1;
+ }
+ else if (hdr->nPlanes != 4 || hdr->f_width & 1 || hdr->f_height & 1 || hdr->tileWidth & 1 || hdr->tileHeight & 1 ||
+ hdr->cfaLayout > 3 || hdr->nBits == 8)
+ return -1;
+
+ if (hdr->tileWidth > hdr->f_width || hdr->tileHeight > hdr->f_height)
+ return -1;
+
+ if (hdr->imageLevels > 3 || hdr->hasTileCols > 1 || hdr->hasTileRows > 1)
+ return -1;
+ return 0;
+}
+
+#undef _abs
+#undef _min
+#undef _constrain
+#undef libraw_inline
diff --git a/libkdcraw/libraw/src/decoders/decoders_dcraw.cpp b/libkdcraw/libraw/src/decoders/decoders_dcraw.cpp
new file mode 100644
index 0000000..721d385
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/decoders_dcraw.cpp
@@ -0,0 +1,1799 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+#include "../../internal/libraw_cameraids.h"
+
+unsigned LibRaw::getbithuff(int nbits, ushort *huff)
+{
+#ifdef LIBRAW_NOTHREADS
+ static unsigned bitbuf = 0;
+ static int vbits = 0, reset = 0;
+#else
+#define bitbuf tls->getbits.bitbuf
+#define vbits tls->getbits.vbits
+#define reset tls->getbits.reset
+#endif
+ unsigned c;
+
+ if (nbits > 25)
+ return 0;
+ if (nbits < 0)
+ return bitbuf = vbits = reset = 0;
+ if (nbits == 0 || vbits < 0)
+ return 0;
+ while (!reset && vbits < nbits && (c = fgetc(ifp)) != (unsigned)EOF &&
+ !(reset = zero_after_ff && c == 0xff && fgetc(ifp)))
+ {
+ bitbuf = (bitbuf << 8) + (uchar)c;
+ vbits += 8;
+ }
+ c = vbits == 0 ? 0 : bitbuf << (32 - vbits) >> (32 - nbits);
+ if (huff)
+ {
+ vbits -= huff[c] >> 8;
+ c = (uchar)huff[c];
+ }
+ else
+ vbits -= nbits;
+ if (vbits < 0)
+ derror();
+ return c;
+#ifndef LIBRAW_NOTHREADS
+#undef bitbuf
+#undef vbits
+#undef reset
+#endif
+}
+
+/*
+ Construct a decode tree according the specification in *source.
+ The first 16 bytes specify how many codes should be 1-bit, 2-bit
+ 3-bit, etc. Bytes after that are the leaf values.
+
+ For example, if the source is
+
+ { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
+ 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
+
+ then the code is
+
+ 00 0x04
+ 010 0x03
+ 011 0x05
+ 100 0x06
+ 101 0x02
+ 1100 0x07
+ 1101 0x01
+ 11100 0x08
+ 11101 0x09
+ 11110 0x00
+ 111110 0x0a
+ 1111110 0x0b
+ 1111111 0xff
+ */
+ushort *LibRaw::make_decoder_ref(const uchar **source)
+{
+ int max, len, h, i, j;
+ const uchar *count;
+ ushort *huff;
+
+ count = (*source += 16) - 17;
+ for (max = 16; max && !count[max]; max--)
+ ;
+ huff = (ushort *)calloc(1 + (1 << max), sizeof *huff);
+ huff[0] = max;
+ for (h = len = 1; len <= max; len++)
+ for (i = 0; i < count[len]; i++, ++*source)
+ for (j = 0; j < 1 << (max - len); j++)
+ if (h <= 1 << max)
+ huff[h++] = len << 8 | **source;
+ return huff;
+}
+
+ushort *LibRaw::make_decoder(const uchar *source)
+{
+ return make_decoder_ref(&source);
+}
+
+void LibRaw::crw_init_tables(unsigned table, ushort *huff[2])
+{
+ static const uchar first_tree[3][29] = {
+ {0, 1, 4, 2, 3, 1, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0x04, 0x03, 0x05, 0x06,
+ 0x02, 0x07, 0x01, 0x08, 0x09, 0x00, 0x0a, 0x0b, 0xff},
+ {0, 2, 2, 3, 1, 1, 1, 1, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0x03, 0x02, 0x04, 0x01,
+ 0x05, 0x00, 0x06, 0x07, 0x09, 0x08, 0x0a, 0x0b, 0xff},
+ {0, 0, 6, 3, 1, 1, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0x06, 0x05, 0x07, 0x04,
+ 0x08, 0x03, 0x09, 0x02, 0x00, 0x0a, 0x01, 0x0b, 0xff},
+ };
+ static const uchar second_tree[3][180] = {
+ {0, 2, 2, 2, 1, 4, 2, 1, 2, 5, 1, 1,
+ 0, 0, 0, 139, 0x03, 0x04, 0x02, 0x05, 0x01, 0x06, 0x07, 0x08,
+ 0x12, 0x13, 0x11, 0x14, 0x09, 0x15, 0x22, 0x00, 0x21, 0x16, 0x0a, 0xf0,
+ 0x23, 0x17, 0x24, 0x31, 0x32, 0x18, 0x19, 0x33, 0x25, 0x41, 0x34, 0x42,
+ 0x35, 0x51, 0x36, 0x37, 0x38, 0x29, 0x79, 0x26, 0x1a, 0x39, 0x56, 0x57,
+ 0x28, 0x27, 0x52, 0x55, 0x58, 0x43, 0x76, 0x59, 0x77, 0x54, 0x61, 0xf9,
+ 0x71, 0x78, 0x75, 0x96, 0x97, 0x49, 0xb7, 0x53, 0xd7, 0x74, 0xb6, 0x98,
+ 0x47, 0x48, 0x95, 0x69, 0x99, 0x91, 0xfa, 0xb8, 0x68, 0xb5, 0xb9, 0xd6,
+ 0xf7, 0xd8, 0x67, 0x46, 0x45, 0x94, 0x89, 0xf8, 0x81, 0xd5, 0xf6, 0xb4,
+ 0x88, 0xb1, 0x2a, 0x44, 0x72, 0xd9, 0x87, 0x66, 0xd4, 0xf5, 0x3a, 0xa7,
+ 0x73, 0xa9, 0xa8, 0x86, 0x62, 0xc7, 0x65, 0xc8, 0xc9, 0xa1, 0xf4, 0xd1,
+ 0xe9, 0x5a, 0x92, 0x85, 0xa6, 0xe7, 0x93, 0xe8, 0xc1, 0xc6, 0x7a, 0x64,
+ 0xe1, 0x4a, 0x6a, 0xe6, 0xb3, 0xf1, 0xd3, 0xa5, 0x8a, 0xb2, 0x9a, 0xba,
+ 0x84, 0xa4, 0x63, 0xe5, 0xc5, 0xf3, 0xd2, 0xc4, 0x82, 0xaa, 0xda, 0xe4,
+ 0xf2, 0xca, 0x83, 0xa3, 0xa2, 0xc3, 0xea, 0xc2, 0xe2, 0xe3, 0xff, 0xff},
+ {0, 2, 2, 1, 4, 1, 4, 1, 3, 3, 1, 0,
+ 0, 0, 0, 140, 0x02, 0x03, 0x01, 0x04, 0x05, 0x12, 0x11, 0x06,
+ 0x13, 0x07, 0x08, 0x14, 0x22, 0x09, 0x21, 0x00, 0x23, 0x15, 0x31, 0x32,
+ 0x0a, 0x16, 0xf0, 0x24, 0x33, 0x41, 0x42, 0x19, 0x17, 0x25, 0x18, 0x51,
+ 0x34, 0x43, 0x52, 0x29, 0x35, 0x61, 0x39, 0x71, 0x62, 0x36, 0x53, 0x26,
+ 0x38, 0x1a, 0x37, 0x81, 0x27, 0x91, 0x79, 0x55, 0x45, 0x28, 0x72, 0x59,
+ 0xa1, 0xb1, 0x44, 0x69, 0x54, 0x58, 0xd1, 0xfa, 0x57, 0xe1, 0xf1, 0xb9,
+ 0x49, 0x47, 0x63, 0x6a, 0xf9, 0x56, 0x46, 0xa8, 0x2a, 0x4a, 0x78, 0x99,
+ 0x3a, 0x75, 0x74, 0x86, 0x65, 0xc1, 0x76, 0xb6, 0x96, 0xd6, 0x89, 0x85,
+ 0xc9, 0xf5, 0x95, 0xb4, 0xc7, 0xf7, 0x8a, 0x97, 0xb8, 0x73, 0xb7, 0xd8,
+ 0xd9, 0x87, 0xa7, 0x7a, 0x48, 0x82, 0x84, 0xea, 0xf4, 0xa6, 0xc5, 0x5a,
+ 0x94, 0xa4, 0xc6, 0x92, 0xc3, 0x68, 0xb5, 0xc8, 0xe4, 0xe5, 0xe6, 0xe9,
+ 0xa2, 0xa3, 0xe3, 0xc2, 0x66, 0x67, 0x93, 0xaa, 0xd4, 0xd5, 0xe7, 0xf8,
+ 0x88, 0x9a, 0xd7, 0x77, 0xc4, 0x64, 0xe2, 0x98, 0xa5, 0xca, 0xda, 0xe8,
+ 0xf3, 0xf6, 0xa9, 0xb2, 0xb3, 0xf2, 0xd2, 0x83, 0xba, 0xd3, 0xff, 0xff},
+ {0, 0, 6, 2, 1, 3, 3, 2, 5, 1, 2, 2,
+ 8, 10, 0, 117, 0x04, 0x05, 0x03, 0x06, 0x02, 0x07, 0x01, 0x08,
+ 0x09, 0x12, 0x13, 0x14, 0x11, 0x15, 0x0a, 0x16, 0x17, 0xf0, 0x00, 0x22,
+ 0x21, 0x18, 0x23, 0x19, 0x24, 0x32, 0x31, 0x25, 0x33, 0x38, 0x37, 0x34,
+ 0x35, 0x36, 0x39, 0x79, 0x57, 0x58, 0x59, 0x28, 0x56, 0x78, 0x27, 0x41,
+ 0x29, 0x77, 0x26, 0x42, 0x76, 0x99, 0x1a, 0x55, 0x98, 0x97, 0xf9, 0x48,
+ 0x54, 0x96, 0x89, 0x47, 0xb7, 0x49, 0xfa, 0x75, 0x68, 0xb6, 0x67, 0x69,
+ 0xb9, 0xb8, 0xd8, 0x52, 0xd7, 0x88, 0xb5, 0x74, 0x51, 0x46, 0xd9, 0xf8,
+ 0x3a, 0xd6, 0x87, 0x45, 0x7a, 0x95, 0xd5, 0xf6, 0x86, 0xb4, 0xa9, 0x94,
+ 0x53, 0x2a, 0xa8, 0x43, 0xf5, 0xf7, 0xd4, 0x66, 0xa7, 0x5a, 0x44, 0x8a,
+ 0xc9, 0xe8, 0xc8, 0xe7, 0x9a, 0x6a, 0x73, 0x4a, 0x61, 0xc7, 0xf4, 0xc6,
+ 0x65, 0xe9, 0x72, 0xe6, 0x71, 0x91, 0x93, 0xa6, 0xda, 0x92, 0x85, 0x62,
+ 0xf3, 0xc5, 0xb2, 0xa4, 0x84, 0xba, 0x64, 0xa5, 0xb3, 0xd2, 0x81, 0xe5,
+ 0xd3, 0xaa, 0xc4, 0xca, 0xf2, 0xb1, 0xe4, 0xd1, 0x83, 0x63, 0xea, 0xc3,
+ 0xe2, 0x82, 0xf1, 0xa3, 0xc2, 0xa1, 0xc1, 0xe3, 0xa2, 0xe1, 0xff, 0xff}};
+ if (table > 2)
+ table = 2;
+ huff[0] = make_decoder(first_tree[table]);
+ huff[1] = make_decoder(second_tree[table]);
+}
+
+/*
+ Return 0 if the image starts with compressed data,
+ 1 if it starts with uncompressed low-order bits.
+
+ In Canon compressed data, 0xff is always followed by 0x00.
+ */
+int LibRaw::canon_has_lowbits()
+{
+ uchar test[0x4000];
+ int ret = 1, i;
+
+ fseek(ifp, 0, SEEK_SET);
+ fread(test, 1, sizeof test, ifp);
+ for (i = 540; i < int(sizeof test - 1); i++)
+ if (test[i] == 0xff)
+ {
+ if (test[i + 1])
+ return 1;
+ ret = 0;
+ }
+ return ret;
+}
+
+void LibRaw::canon_load_raw()
+{
+ ushort *pixel, *prow, *huff[2];
+ int nblocks, lowbits, i, c, row, r, val;
+ INT64 save;
+ int block, diffbuf[64], leaf, len, diff, carry = 0, pnum = 0, base[2];
+
+ crw_init_tables(tiff_compress, huff);
+ lowbits = canon_has_lowbits();
+ if (!lowbits)
+ maximum = 0x3ff;
+ fseek(ifp, 540 + lowbits * raw_height * raw_width / 4, SEEK_SET);
+ zero_after_ff = 1;
+ getbits(-1);
+ try
+ {
+ for (row = 0; row < raw_height; row += 8)
+ {
+ checkCancel();
+ pixel = raw_image + row * raw_width;
+ nblocks = MIN(8, raw_height - row) * raw_width >> 6;
+ for (block = 0; block < nblocks; block++)
+ {
+ memset(diffbuf, 0, sizeof diffbuf);
+ for (i = 0; i < 64; i++)
+ {
+ leaf = gethuff(huff[i > 0]);
+ if (leaf == 0 && i)
+ break;
+ if (leaf == 0xff)
+ continue;
+ i += leaf >> 4;
+ len = leaf & 15;
+ if (len == 0)
+ continue;
+ diff = getbits(len);
+ if ((diff & (1 << (len - 1))) == 0)
+ diff -= (1 << len) - 1;
+ if (i < 64)
+ diffbuf[i] = diff;
+ }
+ diffbuf[0] += carry;
+ carry = diffbuf[0];
+ for (i = 0; i < 64; i++)
+ {
+ if (pnum++ % raw_width == 0)
+ base[0] = base[1] = 512;
+ if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
+ derror();
+ }
+ }
+ if (lowbits)
+ {
+ save = ftell(ifp);
+ fseek(ifp, 26 + row * raw_width / 4, SEEK_SET);
+ for (prow = pixel, i = 0; i < raw_width * 2; i++)
+ {
+ c = fgetc(ifp);
+ for (r = 0; r < 8; r += 2, prow++)
+ {
+ val = (*prow << 2) + ((c >> r) & 3);
+ if (raw_width == 2672 && val < 512)
+ val += 2;
+ *prow = val;
+ }
+ }
+ fseek(ifp, save, SEEK_SET);
+ }
+ }
+ }
+ catch (...)
+ {
+ FORC(2) free(huff[c]);
+ throw;
+ }
+ FORC(2) free(huff[c]);
+}
+
+int LibRaw::ljpeg_start(struct jhead *jh, int info_only)
+{
+ ushort c, tag, len;
+ int cnt = 0;
+ std::vector<uchar> data_buffer(0x10000);
+ uchar* data = &data_buffer[0];
+ const uchar *dp;
+
+ memset(jh, 0, sizeof *jh);
+ jh->restart = INT_MAX;
+ if (fread(data, 2, 1, ifp) != 1 || data[1] != 0xd8)
+ return 0;
+ do
+ {
+ if (feof(ifp))
+ return 0;
+ if (cnt++ > 1024)
+ return 0; // 1024 tags limit
+ if (fread(data, 2, 2, ifp) != 2)
+ return 0;
+ tag = data[0] << 8 | data[1];
+ len = (data[2] << 8 | data[3]) - 2;
+ if (tag <= 0xff00)
+ return 0;
+ if (fread(data, 1, len, ifp) != len)
+ return 0;
+ switch (tag)
+ {
+ case 0xffc3: // start of frame; lossless, Huffman
+ jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
+ case 0xffc1:
+ case 0xffc0:
+ jh->algo = tag & 0xff;
+ jh->bits = data[0];
+ jh->high = data[1] << 8 | data[2];
+ jh->wide = data[3] << 8 | data[4];
+ jh->clrs = data[5] + jh->sraw;
+ if (len == 9 && !dng_version)
+ getc(ifp);
+ break;
+ case 0xffc4: // define Huffman tables
+ if (info_only)
+ break;
+ for (dp = data; dp < data + len && !((c = *dp++) & -20);)
+ jh->free[c] = jh->huff[c] = make_decoder_ref(&dp);
+ break;
+ case 0xffda: // start of scan
+ jh->psv = data[1 + data[0] * 2];
+ jh->bits -= data[3 + data[0] * 2] & 15;
+ break;
+ case 0xffdb:
+ FORC(64) jh->quant[c] = data[c * 2 + 1] << 8 | data[c * 2 + 2];
+ break;
+ case 0xffdd:
+ jh->restart = data[0] << 8 | data[1];
+ }
+ } while (tag != 0xffda);
+ if (jh->bits > 16 || jh->clrs > 6 || !jh->bits || !jh->high || !jh->wide ||
+ !jh->clrs)
+ return 0;
+ if (info_only)
+ return 1;
+ if (!jh->huff[0])
+ return 0;
+ FORC(19) if (!jh->huff[c + 1]) jh->huff[c + 1] = jh->huff[c];
+ if (jh->sraw)
+ {
+ FORC(4) jh->huff[2 + c] = jh->huff[1];
+ FORC(jh->sraw) jh->huff[1 + c] = jh->huff[0];
+ }
+ jh->row = (ushort *)calloc(jh->wide * jh->clrs, 16);
+ return zero_after_ff = 1;
+}
+
+void LibRaw::ljpeg_end(struct jhead *jh)
+{
+ int c;
+ FORC4 if (jh->free[c]) free(jh->free[c]);
+ free(jh->row);
+}
+
+int LibRaw::ljpeg_diff(ushort *huff)
+{
+ int len, diff;
+ if (!huff)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ len = gethuff(huff);
+ if (len == 16 && (!dng_version || dng_version >= 0x1010000))
+ return -32768;
+ diff = getbits(len);
+
+
+ if ((diff & (1 << (len - 1))) == 0)
+ diff -= (1 << len) - 1;
+ return diff;
+}
+
+ushort *LibRaw::ljpeg_row(int jrow, struct jhead *jh)
+{
+ int col, c, diff, pred, spred = 0;
+ ushort mark = 0, *row[3];
+
+ // Use the optimized, unrolled version if possible.
+ if (!jh->sraw)
+ return ljpeg_row_unrolled(jrow, jh);
+
+ if (jh->restart != 0 && jrow * jh->wide % jh->restart == 0)
+ {
+ FORC(6) jh->vpred[c] = 1 << (jh->bits - 1);
+ if (jrow)
+ {
+ fseek(ifp, -2, SEEK_CUR);
+ do
+ mark = (mark << 8) + (c = fgetc(ifp));
+ while (c != EOF && mark >> 4 != 0xffd);
+ }
+ getbits(-1);
+ }
+ FORC3 row[c] = jh->row + jh->wide * jh->clrs * ((jrow + c) & 1);
+ for (col = 0; col < jh->wide; col++)
+ FORC(jh->clrs)
+ {
+ diff = ljpeg_diff(jh->huff[c]);
+ if (jh->sraw && c <= jh->sraw && (col | c))
+ pred = spred;
+ else if (col)
+ pred = row[0][-jh->clrs];
+ else
+ pred = (jh->vpred[c] += diff) - diff;
+ if (jrow && col)
+ switch (jh->psv)
+ {
+ case 1:
+ break;
+ case 2:
+ pred = row[1][0];
+ break;
+ case 3:
+ pred = row[1][-jh->clrs];
+ break;
+ case 4:
+ pred = pred + row[1][0] - row[1][-jh->clrs];
+ break;
+ case 5:
+ pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1);
+ break;
+ case 6:
+ pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1);
+ break;
+ case 7:
+ pred = (pred + row[1][0]) >> 1;
+ break;
+ default:
+ pred = 0;
+ }
+ if ((**row = pred + diff) >> jh->bits)
+ if(!(load_flags & 512))
+ derror();
+ if (c <= jh->sraw)
+ spred = **row;
+ row[0]++;
+ row[1]++;
+ }
+ return row[2];
+}
+
+ushort *LibRaw::ljpeg_row_unrolled(int jrow, struct jhead *jh)
+{
+ int col, c, diff, pred;
+ ushort mark = 0, *row[3];
+
+ if (jh->restart != 0 && jrow * jh->wide % jh->restart == 0)
+ {
+ FORC(6) jh->vpred[c] = 1 << (jh->bits - 1);
+ if (jrow)
+ {
+ fseek(ifp, -2, SEEK_CUR);
+ do
+ mark = (mark << 8) + (c = fgetc(ifp));
+ while (c != EOF && mark >> 4 != 0xffd);
+ }
+ getbits(-1);
+ }
+ FORC3 row[c] = jh->row + jh->wide * jh->clrs * ((jrow + c) & 1);
+
+ // The first column uses one particular predictor.
+ FORC(jh->clrs)
+ {
+ diff = ljpeg_diff(jh->huff[c]);
+ pred = (jh->vpred[c] += diff) - diff;
+ if ((**row = pred + diff) >> jh->bits)
+ derror();
+ row[0]++;
+ row[1]++;
+ }
+
+ if (!jrow)
+ {
+ for (col = 1; col < jh->wide; col++)
+ FORC(jh->clrs)
+ {
+ diff = ljpeg_diff(jh->huff[c]);
+ pred = row[0][-jh->clrs];
+ if ((**row = pred + diff) >> jh->bits)
+ derror();
+ row[0]++;
+ row[1]++;
+ }
+ }
+ else if (jh->psv == 1)
+ {
+ for (col = 1; col < jh->wide; col++)
+ FORC(jh->clrs)
+ {
+ diff = ljpeg_diff(jh->huff[c]);
+ pred = row[0][-jh->clrs];
+ if ((**row = pred + diff) >> jh->bits)
+ derror();
+ row[0]++;
+ }
+ }
+ else
+ {
+ for (col = 1; col < jh->wide; col++)
+ FORC(jh->clrs)
+ {
+ diff = ljpeg_diff(jh->huff[c]);
+ pred = row[0][-jh->clrs];
+ switch (jh->psv)
+ {
+ case 1:
+ break;
+ case 2:
+ pred = row[1][0];
+ break;
+ case 3:
+ pred = row[1][-jh->clrs];
+ break;
+ case 4:
+ pred = pred + row[1][0] - row[1][-jh->clrs];
+ break;
+ case 5:
+ pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1);
+ break;
+ case 6:
+ pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1);
+ break;
+ case 7:
+ pred = (pred + row[1][0]) >> 1;
+ break;
+ default:
+ pred = 0;
+ }
+ if ((**row = pred + diff) >> jh->bits)
+ derror();
+ row[0]++;
+ row[1]++;
+ }
+ }
+ return row[2];
+}
+
+void LibRaw::lossless_jpeg_load_raw()
+{
+ int jwide, jhigh, jrow, jcol, val, jidx, i, j, row = 0, col = 0;
+ struct jhead jh;
+ ushort *rp;
+
+ if (!ljpeg_start(&jh, 0))
+ return;
+
+ if (jh.wide < 1 || jh.high < 1 || jh.clrs < 1 || jh.bits < 1)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ if(cr2_slice[0] && !cr2_slice[1])
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ jwide = jh.wide * jh.clrs;
+ jhigh = jh.high;
+ if (jh.clrs == 4 && jwide >= raw_width * 2)
+ jhigh *= 2;
+
+ try
+ {
+ for (jrow = 0; jrow < jh.high; jrow++)
+ {
+ checkCancel();
+ rp = ljpeg_row(jrow, &jh);
+ if (load_flags & 1)
+ row = jrow & 1 ? height - 1 - jrow / 2 : jrow / 2;
+ for (jcol = 0; jcol < jwide; jcol++)
+ {
+ val = curve[*rp++];
+ if (cr2_slice[0])
+ {
+ jidx = jrow * jwide + jcol;
+ i = jidx / (cr2_slice[1] * raw_height);
+ if ((j = i >= cr2_slice[0]))
+ i = cr2_slice[0];
+ jidx -= i * (cr2_slice[1] * raw_height);
+ row = jidx / cr2_slice[1 + j];
+ col = jidx % cr2_slice[1 + j] + i * cr2_slice[1];
+ }
+ if (raw_width == 3984 && (col -= 2) < 0)
+ col += (row--, raw_width);
+ if (row > raw_height)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ if ((unsigned)row < raw_height)
+ RAW(row, col) = val;
+ if (++col >= raw_width)
+ col = (row++, 0);
+ }
+ }
+ }
+ catch (...)
+ {
+ ljpeg_end(&jh);
+ throw;
+ }
+ ljpeg_end(&jh);
+}
+
+void LibRaw::canon_sraw_load_raw()
+{
+ struct jhead jh;
+ short *rp = 0, (*ip)[4];
+ int jwide, slice, scol, ecol, row, col, jrow = 0, jcol = 0, pix[3], c;
+ int v[3] = {0, 0, 0}, ver, hue;
+ int saved_w = width, saved_h = height;
+ char *cp;
+
+ if (!ljpeg_start(&jh, 0) || jh.clrs < 4)
+ return;
+ jwide = (jh.wide >>= 1) * jh.clrs;
+
+ if (load_flags & 256)
+ {
+ width = raw_width;
+ height = raw_height;
+ }
+
+ try
+ {
+ for (ecol = slice = 0; slice <= cr2_slice[0]; slice++)
+ {
+ scol = ecol;
+ ecol += cr2_slice[1] * 2 / jh.clrs;
+ if (!cr2_slice[0] || ecol > raw_width - 1)
+ ecol = raw_width & -2;
+ for (row = 0; row < height; row += (jh.clrs >> 1) - 1)
+ {
+ checkCancel();
+ ip = (short(*)[4])image + row * width;
+ for (col = scol; col < ecol; col += 2, jcol += jh.clrs)
+ {
+ if ((jcol %= jwide) == 0)
+ rp = (short *)ljpeg_row(jrow++, &jh);
+ if (col >= width)
+ continue;
+ if (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE)
+ {
+ FORC(jh.clrs - 2)
+ {
+ ip[col + (c >> 1) * width + (c & 1)][0] = rp[jcol + c];
+ ip[col + (c >> 1) * width + (c & 1)][1] =
+ ip[col + (c >> 1) * width + (c & 1)][2] = 8192;
+ }
+ ip[col][1] = rp[jcol + jh.clrs - 2] - 8192;
+ ip[col][2] = rp[jcol + jh.clrs - 1] - 8192;
+ }
+ else if (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SRAW_NO_RGB)
+ {
+ FORC(jh.clrs - 2)
+ ip[col + (c >> 1) * width + (c & 1)][0] = rp[jcol + c];
+ ip[col][1] = rp[jcol + jh.clrs - 2] - 8192;
+ ip[col][2] = rp[jcol + jh.clrs - 1] - 8192;
+ }
+ else
+ {
+ FORC(jh.clrs - 2)
+ ip[col + (c >> 1) * width + (c & 1)][0] = rp[jcol + c];
+ ip[col][1] = rp[jcol + jh.clrs - 2] - 16384;
+ ip[col][2] = rp[jcol + jh.clrs - 1] - 16384;
+ }
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ ljpeg_end(&jh);
+ throw;
+ }
+
+ if (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE)
+ {
+ ljpeg_end(&jh);
+ maximum = 0x3fff;
+ height = saved_h;
+ width = saved_w;
+ return;
+ }
+
+ try
+ {
+ for (cp = model2; *cp && !isdigit(*cp); cp++)
+ ;
+ sscanf(cp, "%d.%d.%d", v, v + 1, v + 2);
+ ver = (v[0] * 1000 + v[1]) * 1000 + v[2];
+ hue = (jh.sraw + 1) << 2;
+ if (unique_id >= 0x80000281ULL ||
+ (unique_id == 0x80000218ULL && ver > 1000006))
+ hue = jh.sraw << 1;
+ ip = (short(*)[4])image;
+ rp = ip[0];
+ for (row = 0; row < height; row++, ip += width)
+ {
+ checkCancel();
+ if (row & (jh.sraw >> 1))
+ {
+ for (col = 0; col < width; col += 2)
+ for (c = 1; c < 3; c++)
+ if (row == height - 1)
+ {
+ ip[col][c] = ip[col - width][c];
+ }
+ else
+ {
+ ip[col][c] = (ip[col - width][c] + ip[col + width][c] + 1) >> 1;
+ }
+ }
+ for (col = 1; col < width; col += 2)
+ for (c = 1; c < 3; c++)
+ if (col == width - 1)
+ ip[col][c] = ip[col - 1][c];
+ else
+ ip[col][c] = (ip[col - 1][c] + ip[col + 1][c] + 1) >> 1;
+ }
+ if (!(imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SRAW_NO_RGB))
+ for (; rp < ip[0]; rp += 4)
+ {
+ checkCancel();
+ if ((unique_id == CanonID_EOS_5D_Mark_II) ||
+ (unique_id == CanonID_EOS_7D) ||
+ (unique_id == CanonID_EOS_50D) ||
+ (unique_id == CanonID_EOS_1D_Mark_IV) ||
+ (unique_id == CanonID_EOS_60D))
+ {
+ rp[1] = (rp[1] << 2) + hue;
+ rp[2] = (rp[2] << 2) + hue;
+ pix[0] = rp[0] + ((50 * rp[1] + 22929 * rp[2]) >> 14);
+ pix[1] = rp[0] + ((-5640 * rp[1] - 11751 * rp[2]) >> 14);
+ pix[2] = rp[0] + ((29040 * rp[1] - 101 * rp[2]) >> 14);
+ }
+ else
+ {
+ if (unique_id < CanonID_EOS_5D_Mark_II)
+ rp[0] -= 512;
+ pix[0] = rp[0] + rp[2];
+ pix[2] = rp[0] + rp[1];
+ pix[1] = rp[0] + ((-778 * rp[1] - (rp[2] << 11)) >> 12);
+ }
+ FORC3 rp[c] = CLIP15(pix[c] * sraw_mul[c] >> 10);
+ }
+ }
+ catch (...)
+ {
+ ljpeg_end(&jh);
+ throw;
+ }
+ height = saved_h;
+ width = saved_w;
+ ljpeg_end(&jh);
+ maximum = 0x3fff;
+}
+
+void LibRaw::ljpeg_idct(struct jhead *jh)
+{
+ int c, i, j, len, skip, coef;
+ float work[3][8][8];
+ static float cs[106] = {0};
+ static const uchar zigzag[80] = {
+ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63};
+
+ if (!cs[0])
+ FORC(106) cs[c] = cos((c & 31) * M_PI / 16) / 2;
+ memset(work, 0, sizeof work);
+ work[0][0][0] = jh->vpred[0] += ljpeg_diff(jh->huff[0]) * jh->quant[0];
+ for (i = 1; i < 64; i++)
+ {
+ len = gethuff(jh->huff[16]);
+ i += skip = len >> 4;
+ if (!(len &= 15) && skip < 15)
+ break;
+ coef = getbits(len);
+ if ((coef & (1 << (len - 1))) == 0)
+ coef -= (1 << len) - 1;
+ ((float *)work)[zigzag[i]] = coef * jh->quant[i];
+ }
+ FORC(8) work[0][0][c] *= float(M_SQRT1_2);
+ FORC(8) work[0][c][0] *= float(M_SQRT1_2);
+ for (i = 0; i < 8; i++)
+ for (j = 0; j < 8; j++)
+ FORC(8) work[1][i][j] += work[0][i][c] * cs[(j * 2 + 1) * c];
+ for (i = 0; i < 8; i++)
+ for (j = 0; j < 8; j++)
+ FORC(8) work[2][i][j] += work[1][c][j] * cs[(i * 2 + 1) * c];
+
+ FORC(64) jh->idct[c] = CLIP(((float *)work[2])[c] + 0.5);
+}
+
+void LibRaw::pentax_load_raw()
+{
+ ushort bit[2][15], huff[4097];
+ int dep, row, col, diff, c, i;
+ ushort vpred[2][2] = {{0, 0}, {0, 0}}, hpred[2];
+
+ fseek(ifp, meta_offset, SEEK_SET);
+ dep = (get2() + 12) & 15;
+ fseek(ifp, 12, SEEK_CUR);
+ FORC(dep) bit[0][c] = get2();
+ FORC(dep) bit[1][c] = fgetc(ifp);
+ FORC(dep)
+ for (i = bit[0][c]; i <= ((bit[0][c] + (4096 >> bit[1][c]) - 1) & 4095);)
+ huff[++i] = bit[1][c] << 8 | c;
+ huff[0] = 12;
+ fseek(ifp, data_offset, SEEK_SET);
+ getbits(-1);
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < raw_width; col++)
+ {
+ diff = ljpeg_diff(huff);
+ if (col < 2)
+ hpred[col] = vpred[row & 1][col] += diff;
+ else
+ hpred[col & 1] += diff;
+ RAW(row, col) = hpred[col & 1];
+ if (hpred[col & 1] >> tiff_bps)
+ derror();
+ }
+ }
+}
+void LibRaw::nikon_read_curve()
+{
+ ushort ver0, ver1, vpred[2][2], csize;
+ int i, step, max;
+
+ fseek(ifp, meta_offset, SEEK_SET);
+ ver0 = fgetc(ifp);
+ ver1 = fgetc(ifp);
+ if (ver0 == 0x49 || ver1 == 0x58)
+ fseek(ifp, 2110, SEEK_CUR);
+ read_shorts(vpred[0], 4);
+ step = max = 1 << tiff_bps & 0x7fff;
+ if ((csize = get2()) > 1)
+ step = max / (csize - 1);
+ if (ver0 == 0x44 && (ver1 == 0x20 || (ver1 == 0x40 && step > 3)) && step > 0)
+ {
+ if (ver1 == 0x40)
+ {
+ step /= 4;
+ max /= 4;
+ }
+ for (i = 0; i < csize; i++)
+ curve[i * step] = get2();
+ for (i = 0; i < max; i++)
+ curve[i] = (curve[i - i % step] * (step - i % step) +
+ curve[i - i % step + step] * (i % step)) /
+ step;
+ }
+ else if (ver0 != 0x46 && csize <= 0x4001)
+ read_shorts(curve, max = csize);
+}
+
+void LibRaw::nikon_load_raw()
+{
+ static const uchar nikon_tree[][32] = {
+ {0, 1, 5, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, /* 12-bit lossy */
+ 5, 4, 3, 6, 2, 7, 1, 0, 8, 9, 11, 10, 12},
+ {0, 1, 5, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0,
+ 0, 0, /* 12-bit lossy after split */
+ 0x39, 0x5a, 0x38, 0x27, 0x16, 5, 4, 3, 2, 1, 0, 11, 12, 12},
+
+ {0, 1, 4, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 12-bit lossless */
+ 5, 4, 6, 3, 7, 2, 8, 1, 9, 0, 10, 11, 12},
+ {0, 1, 4, 3, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, /* 14-bit lossy */
+ 5, 6, 4, 7, 8, 3, 9, 2, 1, 0, 10, 11, 12, 13, 14},
+ {0, 1, 5, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0,
+ 0, /* 14-bit lossy after split */
+ 8, 0x5c, 0x4b, 0x3a, 0x29, 7, 6, 5, 4, 3, 2, 1, 0, 13, 14},
+ {0, 1, 4, 2, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, /* 14-bit lossless */
+ 7, 6, 8, 5, 9, 4, 10, 3, 11, 12, 2, 0, 1, 13, 14}};
+ ushort *huff, ver0, ver1, vpred[2][2], hpred[2];
+ int i, min, max, tree = 0, split = 0, row, col, len, shl, diff;
+
+ fseek(ifp, meta_offset, SEEK_SET);
+ ver0 = fgetc(ifp);
+ ver1 = fgetc(ifp);
+ if (ver0 == 0x49 || ver1 == 0x58)
+ fseek(ifp, 2110, SEEK_CUR);
+ if (ver0 == 0x46)
+ tree = 2;
+ if (tiff_bps == 14)
+ tree += 3;
+ read_shorts(vpred[0], 4);
+ max = 1 << tiff_bps & 0x7fff;
+ if (ver0 == 0x44 && (ver1 == 0x20 || ver1 == 0x40))
+ {
+ if (ver1 == 0x40)
+ max /= 4;
+ fseek(ifp, meta_offset + 562, SEEK_SET);
+ split = get2();
+ }
+
+ while (max > 2 && (curve[max - 2] == curve[max - 1]))
+ max--;
+ huff = make_decoder(nikon_tree[tree]);
+ fseek(ifp, data_offset, SEEK_SET);
+ getbits(-1);
+ try
+ {
+ for (min = row = 0; row < height; row++)
+ {
+ checkCancel();
+ if (split && row == split)
+ {
+ free(huff);
+ huff = make_decoder(nikon_tree[tree + 1]);
+ max += (min = 16) << 1;
+ }
+ for (col = 0; col < raw_width; col++)
+ {
+ i = gethuff(huff);
+ len = i & 15;
+ shl = i >> 4;
+ diff = ((getbits(len - shl) << 1) + 1) << shl >> 1;
+ if (len > 0 && (diff & (1 << (len - 1))) == 0)
+ diff -= (1 << len) - !shl;
+ if (col < 2)
+ hpred[col] = vpred[row & 1][col] += diff;
+ else
+ hpred[col & 1] += diff;
+ if ((ushort)(hpred[col & 1] + min) >= max)
+ derror();
+ RAW(row, col) = curve[LIM((short)hpred[col & 1], 0, 0x3fff)];
+ }
+ }
+ }
+ catch (...)
+ {
+ free(huff);
+ throw;
+ }
+ free(huff);
+}
+
+void LibRaw::nikon_yuv_load_raw()
+{
+ if (!image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ int row, col, yuv[4]={0,0,0,0}, rgb[3], b, c;
+ UINT64 bitbuf = 0;
+ float cmul[4];
+ FORC4 { cmul[c] = cam_mul[c] > 0.001f ? cam_mul[c] : 1.f; }
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+
+ for (col = 0; col < raw_width; col++)
+ {
+ if (!(b = col & 1))
+ {
+ bitbuf = 0;
+ FORC(6) bitbuf |= (UINT64)fgetc(ifp) << c * 8;
+ FORC(4) yuv[c] = (bitbuf >> c * 12 & 0xfff) - (c >> 1 << 11);
+ }
+ rgb[0] = yuv[b] + 1.370705 * yuv[3];
+ rgb[1] = yuv[b] - 0.337633 * yuv[2] - 0.698001 * yuv[3];
+ rgb[2] = yuv[b] + 1.732446 * yuv[2];
+ FORC3 image[row * width + col][c] =
+ curve[LIM(rgb[c], 0, 0xfff)] / cmul[c];
+ }
+ }
+}
+
+void LibRaw::rollei_load_raw()
+{
+ uchar pixel[10];
+ unsigned iten = 0, isix, i, buffer = 0, todo[16];
+ if (raw_width > 32767 || raw_height > 32767)
+ throw LIBRAW_EXCEPTION_IO_BADFILE;
+ unsigned maxpixel = raw_width * (raw_height + 7);
+
+ isix = raw_width * raw_height * 5 / 8;
+ while (fread(pixel, 1, 10, ifp) == 10)
+ {
+ checkCancel();
+ for (i = 0; i < 10; i += 2)
+ {
+ todo[i] = iten++;
+ todo[i + 1] = pixel[i] << 8 | pixel[i + 1];
+ buffer = pixel[i] >> 2 | buffer << 6;
+ }
+ for (; i < 16; i += 2)
+ {
+ todo[i] = isix++;
+ todo[i + 1] = buffer >> (14 - i) * 5;
+ }
+ for (i = 0; i < 16; i += 2)
+ if (todo[i] < maxpixel)
+ raw_image[todo[i]] = (todo[i + 1] & 0x3ff);
+ else
+ derror();
+ }
+ maximum = 0x3ff;
+}
+
+void LibRaw::nokia_load_raw()
+{
+ uchar *dp;
+ int rev, dwide, row, col, c;
+ double sum[] = {0, 0};
+
+ rev = 3 * (order == 0x4949);
+ dwide = (raw_width * 5 + 1) / 4;
+#ifdef USE_6BY9RPI
+ if (raw_stride)
+ dwide = raw_stride;
+#endif
+ std::vector<uchar> data(dwide * 2 + 4);
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ if (fread(data.data() + dwide, 1, dwide, ifp) < dwide)
+ derror();
+ FORC(dwide) data[c] = data[dwide + (c ^ rev)];
+ for (dp = data.data(), col = 0; col < raw_width; dp += 5, col += 4)
+ FORC4 RAW(row, col + c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
+ }
+ maximum = 0x3ff;
+#ifdef USE_6BY9RPI
+ if (!strcmp(make, "OmniVision") ||
+ !strcmp(make, "Sony") ||
+ !strcmp(make, "RaspberryPi")) return;
+#else
+ if (strncmp(make, "OmniVision", 10))
+ return;
+#endif
+ row = raw_height / 2;
+ FORC(width - 1)
+ {
+ sum[c & 1] += SQR(RAW(row, c) - RAW(row + 1, c + 1));
+ sum[~c & 1] += SQR(RAW(row + 1, c) - RAW(row, c + 1));
+ }
+ if (sum[1] > sum[0])
+ filters = 0x4b4b4b4b;
+}
+
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+
+void LibRaw::canon_rmf_load_raw()
+{
+ int row, col, bits, orow, ocol, c;
+
+ int *words = (int *)malloc(sizeof(int) * (raw_width / 3 + 1));
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ fread(words, sizeof(int), raw_width / 3, ifp);
+ for (col = 0; col < raw_width - 2; col += 3)
+ {
+ bits = words[col / 3];
+ FORC3
+ {
+ orow = row;
+ if ((ocol = col + c - 4) < 0)
+ {
+ ocol += raw_width;
+ if ((orow -= 2) < 0)
+ orow += raw_height;
+ }
+ RAW(orow, ocol) = curve[bits >> (10 * c + 2) & 0x3ff];
+ }
+ }
+ }
+ free(words);
+ maximum = curve[0x3ff];
+}
+#endif
+
+unsigned LibRaw::pana_data(int nb, unsigned *bytes)
+{
+#ifndef LIBRAW_NOTHREADS
+#define vpos tls->pana_data.vpos
+#define buf tls->pana_data.buf
+#else
+ static uchar buf[0x4002];
+ static int vpos;
+#endif
+ int byte;
+
+ if (!nb && !bytes)
+ return vpos = 0;
+
+ if (!vpos)
+ {
+ fread(buf + load_flags, 1, 0x4000 - load_flags, ifp);
+ fread(buf, 1, load_flags, ifp);
+ }
+
+ if (pana_encoding == 5)
+ {
+ for (byte = 0; byte < 16; byte++)
+ {
+ bytes[byte] = buf[vpos++];
+ vpos &= 0x3FFF;
+ }
+ }
+ else
+ {
+ vpos = (vpos - nb) & 0x1ffff;
+ byte = vpos >> 3 ^ 0x3ff0;
+ return (buf[byte] | buf[byte + 1] << 8) >> (vpos & 7) & ~((~0u) << nb);
+ }
+ return 0;
+#ifndef LIBRAW_NOTHREADS
+#undef vpos
+#undef buf
+#endif
+}
+
+void LibRaw::panasonic_load_raw()
+{
+ int row, col, i, j, sh = 0, pred[2], nonz[2];
+ unsigned bytes[16];
+ memset(bytes,0,sizeof(bytes)); // make gcc11 happy
+ ushort *raw_block_data;
+
+ pana_data(0, 0);
+
+ int enc_blck_size = pana_bpp == 12 ? 10 : 9;
+ if (pana_encoding == 5)
+ {
+ for (row = 0; row < raw_height; row++)
+ {
+ raw_block_data = raw_image + row * raw_width;
+ checkCancel();
+ for (col = 0; col < raw_width; col += enc_blck_size)
+ {
+ pana_data(0, bytes);
+
+ if (pana_bpp == 12)
+ {
+ raw_block_data[col] = ((bytes[1] & 0xF) << 8) + bytes[0];
+ raw_block_data[col + 1] = 16 * bytes[2] + (bytes[1] >> 4);
+ raw_block_data[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3];
+ raw_block_data[col + 3] = 16 * bytes[5] + (bytes[4] >> 4);
+ raw_block_data[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6];
+ raw_block_data[col + 5] = 16 * bytes[8] + (bytes[7] >> 4);
+ raw_block_data[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9];
+ raw_block_data[col + 7] = 16 * bytes[11] + (bytes[10] >> 4);
+ raw_block_data[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12];
+ raw_block_data[col + 9] = 16 * bytes[14] + (bytes[13] >> 4);
+ }
+ else if (pana_bpp == 14)
+ {
+ raw_block_data[col] = bytes[0] + ((bytes[1] & 0x3F) << 8);
+ raw_block_data[col + 1] =
+ (bytes[1] >> 6) + 4 * (bytes[2]) + ((bytes[3] & 0xF) << 10);
+ raw_block_data[col + 2] =
+ (bytes[3] >> 4) + 16 * (bytes[4]) + ((bytes[5] & 3) << 12);
+ raw_block_data[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6);
+ raw_block_data[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8);
+ raw_block_data[col + 5] =
+ (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10);
+ raw_block_data[col + 6] =
+ (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12);
+ raw_block_data[col + 7] =
+ ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6);
+ raw_block_data[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < raw_width; col++)
+ {
+ if ((i = col % 14) == 0)
+ pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
+ if (i % 3 == 2)
+ sh = 4 >> (3 - pana_data(2, 0));
+ if (nonz[i & 1])
+ {
+ if ((j = pana_data(8, 0)))
+ {
+ if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
+ pred[i & 1] &= ~((~0u) << sh);
+ pred[i & 1] += j << sh;
+ }
+ }
+ else if ((nonz[i & 1] = pana_data(8, 0)) || i > 11)
+ pred[i & 1] = nonz[i & 1] << 4 | pana_data(4, 0);
+ if ((RAW(row, col) = pred[col & 1]) > 4098 && col < width &&
+ row < height)
+ derror();
+ }
+ }
+ }
+}
+
+void LibRaw::olympus_load_raw()
+{
+ ushort huff[4096];
+ int row, col, nbits, sign, low, high, i, c, w, n, nw;
+ int acarry[2][3], *carry, pred, diff;
+
+ huff[n = 0] = 0xc0c;
+ for (i = 12; i--;)
+ FORC(2048 >> i) huff[++n] = (i + 1) << 8 | i;
+ fseek(ifp, 7, SEEK_CUR);
+ getbits(-1);
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ memset(acarry, 0, sizeof acarry);
+ for (col = 0; col < raw_width; col++)
+ {
+ carry = acarry[col & 1];
+ i = 2 * (carry[2] < 3);
+ for (nbits = 2 + i; (ushort)carry[0] >> (nbits + i); nbits++)
+ ;
+ low = (sign = getbits(3)) & 3;
+ sign = sign << 29 >> 31;
+ if ((high = getbithuff(12, huff)) == 12)
+ high = getbits(16 - nbits) >> 1;
+ carry[0] = (high << nbits) | getbits(nbits);
+ diff = (carry[0] ^ sign) + carry[1];
+ carry[1] = (diff * 3 + carry[1]) >> 5;
+ carry[2] = carry[0] > 16 ? 0 : carry[2] + 1;
+ if (col >= width)
+ continue;
+ if (row < 2 && col < 2)
+ pred = 0;
+ else if (row < 2)
+ pred = RAW(row, col - 2);
+ else if (col < 2)
+ pred = RAW(row - 2, col);
+ else
+ {
+ w = RAW(row, col - 2);
+ n = RAW(row - 2, col);
+ nw = RAW(row - 2, col - 2);
+ if ((w < nw && nw < n) || (n < nw && nw < w))
+ {
+ if (ABS(w - nw) > 32 || ABS(n - nw) > 32)
+ pred = w + n - nw;
+ else
+ pred = (w + n) >> 1;
+ }
+ else
+ pred = ABS(w - nw) > ABS(n - nw) ? w : n;
+ }
+ if ((RAW(row, col) = pred + ((diff << 2) | low)) >> 12)
+ derror();
+ }
+ }
+}
+
+void LibRaw::minolta_rd175_load_raw()
+{
+ uchar pixel[768];
+ unsigned irow, box, row, col;
+
+ for (irow = 0; irow < 1481; irow++)
+ {
+ checkCancel();
+ if (fread(pixel, 1, 768, ifp) < 768)
+ derror();
+ box = irow / 82;
+ row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box - 12) * 2);
+ switch (irow)
+ {
+ case 1477:
+ case 1479:
+ continue;
+ case 1476:
+ row = 984;
+ break;
+ case 1480:
+ row = 985;
+ break;
+ case 1478:
+ row = 985;
+ box = 1;
+ }
+ if ((box < 12) && (box & 1))
+ {
+ for (col = 0; col < 1533; col++, row ^= 1)
+ if (col != 1)
+ RAW(row, col) = (col + 1) & 2
+ ? pixel[col / 2 - 1] + pixel[col / 2 + 1]
+ : pixel[col / 2] << 1;
+ RAW(row, 1) = pixel[1] << 1;
+ RAW(row, 1533) = pixel[765] << 1;
+ }
+ else
+ for (col = row & 1; col < 1534; col += 2)
+ RAW(row, col) = pixel[col / 2] << 1;
+ }
+ maximum = 0xff << 1;
+}
+
+void LibRaw::quicktake_100_load_raw()
+{
+ std::vector<uchar> pixel_buffer(484 * 644, 0x80);
+ uchar* pixel = &pixel_buffer[0];
+ static const short gstep[16] = {-89, -60, -44, -32, -22, -15, -8, -2,
+ 2, 8, 15, 22, 32, 44, 60, 89};
+ static const short rstep[6][4] = {{-3, -1, 1, 3}, {-5, -1, 1, 5},
+ {-8, -2, 2, 8}, {-13, -3, 3, 13},
+ {-19, -4, 4, 19}, {-28, -6, 6, 28}};
+ static const short t_curve[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 88, 90,
+ 92, 94, 97, 99, 101, 103, 105, 107, 110, 112, 114, 116, 118, 120,
+ 123, 125, 127, 129, 131, 134, 136, 138, 140, 142, 144, 147, 149, 151,
+ 153, 155, 158, 160, 162, 164, 166, 168, 171, 173, 175, 177, 179, 181,
+ 184, 186, 188, 190, 192, 195, 197, 199, 201, 203, 205, 208, 210, 212,
+ 214, 216, 218, 221, 223, 226, 230, 235, 239, 244, 248, 252, 257, 261,
+ 265, 270, 274, 278, 283, 287, 291, 296, 300, 305, 309, 313, 318, 322,
+ 326, 331, 335, 339, 344, 348, 352, 357, 361, 365, 370, 374, 379, 383,
+ 387, 392, 396, 400, 405, 409, 413, 418, 422, 426, 431, 435, 440, 444,
+ 448, 453, 457, 461, 466, 470, 474, 479, 483, 487, 492, 496, 500, 508,
+ 519, 531, 542, 553, 564, 575, 587, 598, 609, 620, 631, 643, 654, 665,
+ 676, 687, 698, 710, 721, 732, 743, 754, 766, 777, 788, 799, 810, 822,
+ 833, 844, 855, 866, 878, 889, 900, 911, 922, 933, 945, 956, 967, 978,
+ 989, 1001, 1012, 1023};
+ int rb, row, col, sharp, val = 0;
+
+ if (width > 640 || height > 480)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ getbits(-1);
+ for (row = 2; row < height + 2; row++)
+ {
+ checkCancel();
+ for (col = 2 + (row & 1); col < width + 2; col += 2)
+ {
+ val = ((pixel[(row - 1) * 644 + col - 1] + 2 * pixel[(row - 1) * 644 + col + 1] + pixel[row * 644 + col - 2]) >> 2) + gstep[getbits(4)];
+ pixel[row * 644 + col] = val = LIM(val, 0, 255);
+ if (col < 4)
+ pixel[row * 644 + col - 2] = pixel[(row + 1) * 644 + (~row & 1)] = val;
+ if (row == 2)
+ pixel[(row - 1) * 644 + col + 1] = pixel[(row - 1) * 644 + col + 3] = val;
+ }
+ pixel[row * 644 + col] = val;
+ }
+ for (rb = 0; rb < 2; rb++)
+ for (row = 2 + rb; row < height + 2; row += 2)
+ {
+ checkCancel();
+ for (col = 3 - (row & 1); col < width + 2; col += 2)
+ {
+ if (row < 4 || col < 4)
+ sharp = 2;
+ else
+ {
+ val = ABS(pixel[(row - 2) * 644 + col] - pixel[row * 644 + col - 2]) + ABS(pixel[(row - 2) * 644 + col] - pixel[(row - 2) * 644 + col - 2]) +
+ ABS(pixel[row * 644 + col - 2] - pixel[(row - 2) * 644 + col - 2]);
+ sharp = val < 4
+ ? 0
+ : val < 8
+ ? 1
+ : val < 16 ? 2 : val < 32 ? 3 : val < 48 ? 4 : 5;
+ }
+ val = ((pixel[(row - 2) * 644 + col] + pixel[row * 644 + col - 2]) >> 1) + rstep[sharp][getbits(2)];
+ pixel[row * 644 + col] = val = LIM(val, 0, 255);
+ if (row < 4)
+ pixel[(row - 2) * 644 + col + 2] = val;
+ if (col < 4)
+ pixel[(row + 2) * 644 + col - 2] = val;
+ }
+ }
+ for (row = 2; row < height + 2; row++)
+ {
+ checkCancel();
+ for (col = 3 - (row & 1); col < width + 2; col += 2)
+ {
+ val = ((pixel[row * 644 + col - 1] + (pixel[row * 644 + col] << 2) + pixel[row * 644 + col + 1]) >> 1) - 0x100;
+ pixel[row * 644 + col] = LIM(val, 0, 255);
+ }
+ }
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < width; col++)
+ RAW(row, col) = t_curve[pixel[(row + 2) * 644 + col + 2]];
+ }
+ maximum = 0x3ff;
+}
+
+void LibRaw::sony_load_raw()
+{
+ uchar head[40];
+ ushort *pixel;
+ unsigned i, key, row, col;
+
+ fseek(ifp, 200896, SEEK_SET);
+ fseek(ifp, (unsigned)fgetc(ifp) * 4 - 1, SEEK_CUR);
+ order = 0x4d4d;
+ key = get4();
+
+ fseek(ifp, 164600, SEEK_SET);
+ fread(head, 1, 40, ifp);
+ sony_decrypt((unsigned *)head, 10, 1, key);
+ for (i = 26; i-- > 22;)
+ key = key << 8 | head[i];
+
+ fseek(ifp, data_offset, SEEK_SET);
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ pixel = raw_image + row * raw_width;
+ if (fread(pixel, 2, raw_width, ifp) < raw_width)
+ derror();
+ sony_decrypt((unsigned *)pixel, raw_width / 2, !row, key);
+ for (col = 0; col < raw_width; col++)
+ if ((pixel[col] = ntohs(pixel[col])) >> 14)
+ derror();
+ }
+ maximum = 0x3ff0;
+}
+
+void LibRaw::sony_arw_load_raw()
+{
+ std::vector<ushort> huff_buffer(32770);
+ ushort* huff = &huff_buffer[0];
+ static const ushort tab[18] = {0xf11, 0xf10, 0xe0f, 0xd0e, 0xc0d, 0xb0c,
+ 0xa0b, 0x90a, 0x809, 0x708, 0x607, 0x506,
+ 0x405, 0x304, 0x303, 0x300, 0x202, 0x201};
+ int i, c, n, col, row, sum = 0;
+
+ huff[0] = 15;
+ for (n = i = 0; i < 18; i++)
+ FORC(32768 >> (tab[i] >> 8)) huff[++n] = tab[i];
+ getbits(-1);
+ for (col = raw_width; col--;)
+ {
+ checkCancel();
+ for (row = 0; row < raw_height + 1; row += 2)
+ {
+ if (row == raw_height)
+ row = 1;
+ if ((sum += ljpeg_diff(huff)) >> 12)
+ derror();
+ if (row < height)
+ RAW(row, col) = sum;
+ }
+ }
+}
+
+void LibRaw::sony_arw2_load_raw()
+{
+ uchar *data, *dp;
+ ushort pix[16];
+ int row, col, val, max, min, imax, imin, sh, bit, i;
+
+ data = (uchar *)malloc(raw_width + 1);
+ try
+ {
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ fread(data, 1, raw_width, ifp);
+ for (dp = data, col = 0; col < raw_width - 30; dp += 16)
+ {
+ max = 0x7ff & (val = sget4(dp));
+ min = 0x7ff & val >> 11;
+ imax = 0x0f & val >> 22;
+ imin = 0x0f & val >> 26;
+ for (sh = 0; sh < 4 && 0x80 << sh <= max - min; sh++)
+ ;
+ /* flag checks if outside of loop */
+ if (!(imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SONYARW2_ALLFLAGS) // no flag set
+ || (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SONYARW2_DELTATOVALUE))
+ {
+ for (bit = 30, i = 0; i < 16; i++)
+ if (i == imax)
+ pix[i] = max;
+ else if (i == imin)
+ pix[i] = min;
+ else
+ {
+ pix[i] =
+ ((sget2(dp + (bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
+ if (pix[i] > 0x7ff)
+ pix[i] = 0x7ff;
+ bit += 7;
+ }
+ }
+ else if (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SONYARW2_BASEONLY)
+ {
+ for (bit = 30, i = 0; i < 16; i++)
+ if (i == imax)
+ pix[i] = max;
+ else if (i == imin)
+ pix[i] = min;
+ else
+ pix[i] = 0;
+ }
+ else if (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SONYARW2_DELTAONLY)
+ {
+ for (bit = 30, i = 0; i < 16; i++)
+ if (i == imax)
+ pix[i] = 0;
+ else if (i == imin)
+ pix[i] = 0;
+ else
+ {
+ pix[i] =
+ ((sget2(dp + (bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
+ if (pix[i] > 0x7ff)
+ pix[i] = 0x7ff;
+ bit += 7;
+ }
+ }
+ else if (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SONYARW2_DELTAZEROBASE)
+ {
+ for (bit = 30, i = 0; i < 16; i++)
+ if (i == imax)
+ pix[i] = 0;
+ else if (i == imin)
+ pix[i] = 0;
+ else
+ {
+ pix[i] = ((sget2(dp + (bit >> 3)) >> (bit & 7) & 0x7f) << sh);
+ if (pix[i] > 0x7ff)
+ pix[i] = 0x7ff;
+ bit += 7;
+ }
+ }
+
+ if (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SONYARW2_DELTATOVALUE)
+ {
+ for (i = 0; i < 16; i++, col += 2)
+ {
+ unsigned slope =
+ pix[i] < 1001 ? 2
+ : curve[pix[i] << 1] - curve[(pix[i] << 1) - 2];
+ unsigned step = 1 << sh;
+ RAW(row, col) =
+ curve[pix[i] << 1] >
+ black + imgdata.rawparams.sony_arw2_posterization_thr
+ ? LIM(((slope * step * 1000) /
+ (curve[pix[i] << 1] - black)),
+ 0, 10000)
+ : 0;
+ }
+ }
+ else
+ for (i = 0; i < 16; i++, col += 2)
+ RAW(row, col) = curve[pix[i] << 1];
+ col -= col & 1 ? 1 : 31;
+ }
+ }
+ }
+ catch (...)
+ {
+ free(data);
+ throw;
+ }
+ if (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SONYARW2_DELTATOVALUE)
+ maximum = 10000;
+ free(data);
+}
+
+void LibRaw::samsung_load_raw()
+{
+ int row, col, c, i, dir, op[4], len[4];
+ if (raw_width > 32768 ||
+ raw_height > 32768) // definitely too much for old samsung
+ throw LIBRAW_EXCEPTION_IO_BADFILE;
+ unsigned maxpixels = raw_width * (raw_height + 7);
+
+ order = 0x4949;
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ fseek(ifp, strip_offset + row * 4, SEEK_SET);
+ fseek(ifp, data_offset + get4(), SEEK_SET);
+ ph1_bits(-1);
+ FORC4 len[c] = row < 2 ? 7 : 4;
+ for (col = 0; col < raw_width; col += 16)
+ {
+ dir = ph1_bits(1);
+ FORC4 op[c] = ph1_bits(2);
+ FORC4 switch (op[c])
+ {
+ case 3:
+ len[c] = ph1_bits(4);
+ break;
+ case 2:
+ len[c]--;
+ break;
+ case 1:
+ len[c]++;
+ }
+ for (c = 0; c < 16; c += 2)
+ {
+ i = len[((c & 1) << 1) | (c >> 3)];
+ unsigned idest = RAWINDEX(row, col + c);
+ unsigned isrc = (dir ? RAWINDEX(row + (~c | -2), col + c)
+ : col ? RAWINDEX(row, col + (c | -2)) : 0);
+ if (idest < maxpixels &&
+ isrc <
+ maxpixels) // less than zero is handled by unsigned conversion
+ RAW(row, col + c) = (i > 0 ? ((signed)ph1_bits(i) << (32 - i) >> (32 - i)) : 0) +
+ (dir ? RAW(row + (~c | -2), col + c) : col ? RAW(row, col + (c | -2)) : 128);
+ else
+ derror();
+ if (c == 14)
+ c = -1;
+ }
+ }
+ }
+ for (row = 0; row < raw_height - 1; row += 2)
+ for (col = 0; col < raw_width - 1; col += 2)
+ SWAP(RAW(row, col + 1), RAW(row + 1, col));
+}
+
+void LibRaw::samsung2_load_raw()
+{
+ static const ushort tab[14] = {0x304, 0x307, 0x206, 0x205, 0x403,
+ 0x600, 0x709, 0x80a, 0x90b, 0xa0c,
+ 0xa0d, 0x501, 0x408, 0x402};
+ ushort huff[1026], vpred[2][2] = {{0, 0}, {0, 0}}, hpred[2];
+ int i, c, n, row, col, diff;
+
+ huff[0] = 10;
+ for (n = i = 0; i < 14; i++)
+ FORC(1024 >> (tab[i] >> 8)) huff[++n] = tab[i];
+ getbits(-1);
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < raw_width; col++)
+ {
+ diff = ljpeg_diff(huff);
+ if (col < 2)
+ hpred[col] = vpred[row & 1][col] += diff;
+ else
+ hpred[col & 1] += diff;
+ RAW(row, col) = hpred[col & 1];
+ if (hpred[col & 1] >> tiff_bps)
+ derror();
+ }
+ }
+}
+
+void LibRaw::samsung3_load_raw()
+{
+ int opt, init, mag, pmode, row, tab, col, pred, diff, i, c;
+ ushort lent[3][2], len[4], *prow[2];
+ order = 0x4949;
+ fseek(ifp, 9, SEEK_CUR);
+ opt = fgetc(ifp);
+ init = (get2(), get2());
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ fseek(ifp, (data_offset - ftell(ifp)) & 15, SEEK_CUR);
+ ph1_bits(-1);
+ mag = 0;
+ pmode = 7;
+ FORC(6)((ushort *)lent)[c] = row < 2 ? 7 : 4;
+ prow[row & 1] = &RAW(row - 1, 1 - ((row & 1) << 1)); // green
+ prow[~row & 1] = &RAW(row - 2, 0); // red and blue
+ for (tab = 0; tab + 15 < raw_width; tab += 16)
+ {
+ if (~opt & 4 && !(tab & 63))
+ {
+ i = ph1_bits(2);
+ mag = i < 3 ? mag - '2' + "204"[i] : ph1_bits(12);
+ }
+ if (opt & 2)
+ pmode = 7 - 4 * ph1_bits(1);
+ else if (!ph1_bits(1))
+ pmode = ph1_bits(3);
+ if (opt & 1 || !ph1_bits(1))
+ {
+ FORC4 len[c] = ph1_bits(2);
+ FORC4
+ {
+ i = ((row & 1) << 1 | (c & 1)) % 3;
+ if (i < 0)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ len[c] = len[c] < 3 ? lent[i][0] - '1' + "120"[len[c]] : ph1_bits(4);
+ lent[i][0] = lent[i][1];
+ lent[i][1] = len[c];
+ }
+ }
+ FORC(16)
+ {
+ col = tab + (((c & 7) << 1) ^ (c >> 3) ^ (row & 1));
+ if (col < 0)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ if (pmode < 0)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ if (pmode != 7 && row >= 2 && (col - '4' + "0224468"[pmode]) < 0)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ pred = (pmode == 7 || row < 2)
+ ? (tab ? RAW(row, tab - 2 + (col & 1)) : init)
+ : (prow[col & 1][col - '4' + "0224468"[pmode]] +
+ prow[col & 1][col - '4' + "0244668"[pmode]] + 1) >>
+ 1;
+ diff = ph1_bits(i = len[c >> 2]);
+ if (i > 0 && diff >> (i - 1))
+ diff -= 1 << i;
+ diff = diff * (mag * 2 + 1) + mag;
+ RAW(row, col) = pred + diff;
+ }
+ }
+ }
+}
+
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+void LibRaw::redcine_load_raw()
+{
+#ifndef NO_JASPER
+ int c, row, col;
+ jas_stream_t *in;
+ jas_image_t *jimg;
+ jas_matrix_t *jmat;
+ jas_seqent_t *data;
+ ushort *img, *pix;
+
+ jas_init();
+ in = (jas_stream_t *)ifp->make_jas_stream();
+ if (!in)
+ throw LIBRAW_EXCEPTION_DECODE_JPEG2000;
+ jas_stream_seek(in, data_offset + 20, SEEK_SET);
+ jimg = jas_image_decode(in, -1, 0);
+ if (!jimg)
+ {
+ jas_stream_close(in);
+ throw LIBRAW_EXCEPTION_DECODE_JPEG2000;
+ }
+ jmat = jas_matrix_create(height / 2, width / 2);
+ img = (ushort *)calloc((height + 2), (width + 2) * 2);
+ bool fastexitflag = false;
+ try
+ {
+ FORC4
+ {
+ checkCancel();
+ jas_image_readcmpt(jimg, c, 0, 0, width / 2, height / 2, jmat);
+ data = jas_matrix_getref(jmat, 0, 0);
+ for (row = c >> 1; row < height; row += 2)
+ for (col = c & 1; col < width; col += 2)
+ img[(row + 1) * (width + 2) + col + 1] =
+ data[(row / 2) * (width / 2) + col / 2];
+ }
+ for (col = 1; col <= width; col++)
+ {
+ img[col] = img[2 * (width + 2) + col];
+ img[(height + 1) * (width + 2) + col] =
+ img[(height - 1) * (width + 2) + col];
+ }
+ for (row = 0; row < height + 2; row++)
+ {
+ img[row * (width + 2)] = img[row * (width + 2) + 2];
+ img[(row + 1) * (width + 2) - 1] = img[(row + 1) * (width + 2) - 3];
+ }
+ for (row = 1; row <= height; row++)
+ {
+ checkCancel();
+ pix = img + row * (width + 2) + (col = 1 + (FC(row, 1) & 1));
+ for (; col <= width; col += 2, pix += 2)
+ {
+ c = (((pix[0] - 0x800) << 3) + pix[-(width + 2)] + pix[width + 2] +
+ pix[-1] + pix[1]) >>
+ 2;
+ pix[0] = LIM(c, 0, 4095);
+ }
+ }
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < width; col++)
+ RAW(row, col) = curve[img[(row + 1) * (width + 2) + col + 1]];
+ }
+ }
+ catch (...)
+ {
+ fastexitflag = true;
+ }
+ free(img);
+ jas_matrix_destroy(jmat);
+ jas_image_destroy(jimg);
+ jas_stream_close(in);
+ if (fastexitflag)
+ throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK;
+#endif
+}
+#endif
diff --git a/libkdcraw/libraw/src/decoders/decoders_libraw.cpp b/libkdcraw/libraw/src/decoders/decoders_libraw.cpp
new file mode 100644
index 0000000..332e2af
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/decoders_libraw.cpp
@@ -0,0 +1,861 @@
+/* -*- C++ -*-
+ * Copyright 2019-2022 LibRaw LLC ([email protected])
+ *
+ * PhaseOne IIQ-Sv2 decoder is inspired by code provided by Daniel Vogelbacher <[email protected]>
+ *
+
+ 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"
+#include <vector>
+#include <algorithm> // for std::sort
+
+void LibRaw::sony_arq_load_raw()
+{
+ int row, col;
+ read_shorts(imgdata.rawdata.raw_image,
+ imgdata.sizes.raw_width * imgdata.sizes.raw_height * 4);
+ libraw_internal_data.internal_data.input->seek(
+ -2, SEEK_CUR); // avoid wrong eof error
+
+ if(imgdata.rawparams.options & LIBRAW_RAWOPTIONS_ARQ_SKIP_CHANNEL_SWAP)
+ return;
+
+ for (row = 0; row < imgdata.sizes.raw_height; row++)
+ {
+ unsigned short(*rowp)[4] =
+ (unsigned short(*)[4]) &
+ imgdata.rawdata.raw_image[row * imgdata.sizes.raw_width * 4];
+ for (col = 0; col < imgdata.sizes.raw_width; col++)
+ {
+ unsigned short g2 = rowp[col][2];
+ rowp[col][2] = rowp[col][3];
+ rowp[col][3] = g2;
+ if (((unsigned)(row - imgdata.sizes.top_margin) < imgdata.sizes.height) &&
+ ((unsigned)(col - imgdata.sizes.left_margin) < imgdata.sizes.width) &&
+ (MAX(MAX(rowp[col][0], rowp[col][1]),
+ MAX(rowp[col][2], rowp[col][3])) > imgdata.color.maximum))
+ derror();
+ }
+ }
+}
+
+void LibRaw::pentax_4shot_load_raw()
+{
+ ushort *plane = (ushort *)malloc(imgdata.sizes.raw_width *
+ imgdata.sizes.raw_height * sizeof(ushort));
+ int alloc_sz = imgdata.sizes.raw_width * (imgdata.sizes.raw_height + 16) * 4 *
+ sizeof(ushort);
+ ushort(*result)[4] = (ushort(*)[4])malloc(alloc_sz);
+ struct movement_t
+ {
+ int row, col;
+ } _move[4] = {
+ {1, 1},
+ {0, 1},
+ {0, 0},
+ {1, 0},
+ };
+
+ int tidx = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ int move_row, move_col;
+ if (imgdata.rawparams.p4shot_order[i] >= '0' &&
+ imgdata.rawparams.p4shot_order[i] <= '3')
+ {
+ move_row = ((imgdata.rawparams.p4shot_order[i] - '0') & 2) ? 1 : 0;
+ move_col = ((imgdata.rawparams.p4shot_order[i] - '0') & 1) ? 1 : 0;
+ }
+ else
+ {
+ move_row = _move[i].row;
+ move_col = _move[i].col;
+ }
+ for (; tidx < 16; tidx++)
+ if (tiff_ifd[tidx].t_width == imgdata.sizes.raw_width &&
+ tiff_ifd[tidx].t_height == imgdata.sizes.raw_height &&
+ tiff_ifd[tidx].bps > 8 && tiff_ifd[tidx].samples == 1)
+ break;
+ if (tidx >= 16)
+ break;
+ imgdata.rawdata.raw_image = plane;
+ ID.input->seek(tiff_ifd[tidx].offset, SEEK_SET);
+ imgdata.idata.filters = 0xb4b4b4b4;
+ libraw_internal_data.unpacker_data.data_offset = tiff_ifd[tidx].offset;
+ (this->*pentax_component_load_raw)();
+ for (int row = 0; row < imgdata.sizes.raw_height - move_row; row++)
+ {
+ int colors[2];
+ for (int c = 0; c < 2; c++)
+ colors[c] = COLOR(row, c);
+ ushort *srcrow = &plane[imgdata.sizes.raw_width * row];
+ ushort(*dstrow)[4] =
+ &result[(imgdata.sizes.raw_width) * (row + move_row) + move_col];
+ for (int col = 0; col < imgdata.sizes.raw_width - move_col; col++)
+ dstrow[col][colors[col % 2]] = srcrow[col];
+ }
+ tidx++;
+ }
+
+ if (imgdata.color.cblack[4] == 2 && imgdata.color.cblack[5] == 2)
+ for (int c = 0; c < 4; c++)
+ imgdata.color.cblack[FC(c / 2, c % 2)] +=
+ imgdata.color.cblack[6 +
+ c / 2 % imgdata.color.cblack[4] *
+ imgdata.color.cblack[5] +
+ c % 2 % imgdata.color.cblack[5]];
+ imgdata.color.cblack[4] = imgdata.color.cblack[5] = 0;
+
+ // assign things back:
+ imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 8;
+ imgdata.idata.filters = 0;
+ imgdata.rawdata.raw_alloc = imgdata.rawdata.color4_image = result;
+ free(plane);
+ imgdata.rawdata.raw_image = 0;
+}
+
+void LibRaw::hasselblad_full_load_raw()
+{
+ int row, col;
+
+ for (row = 0; row < S.height; row++)
+ for (col = 0; col < S.width; col++)
+ {
+ read_shorts(&imgdata.image[row * S.width + col][2], 1); // B
+ read_shorts(&imgdata.image[row * S.width + col][1], 1); // G
+ read_shorts(&imgdata.image[row * S.width + col][0], 1); // R
+ }
+}
+
+static inline void unpack7bytesto4x16(unsigned char *src, unsigned short *dest)
+{
+ dest[0] = (src[0] << 6) | (src[1] >> 2);
+ dest[1] = ((src[1] & 0x3) << 12) | (src[2] << 4) | (src[3] >> 4);
+ dest[2] = (src[3] & 0xf) << 10 | (src[4] << 2) | (src[5] >> 6);
+ dest[3] = ((src[5] & 0x3f) << 8) | src[6];
+}
+
+static inline void unpack28bytesto16x16ns(unsigned char *src,
+ unsigned short *dest)
+{
+ dest[0] = (src[3] << 6) | (src[2] >> 2);
+ dest[1] = ((src[2] & 0x3) << 12) | (src[1] << 4) | (src[0] >> 4);
+ dest[2] = (src[0] & 0xf) << 10 | (src[7] << 2) | (src[6] >> 6);
+ dest[3] = ((src[6] & 0x3f) << 8) | src[5];
+ dest[4] = (src[4] << 6) | (src[11] >> 2);
+ dest[5] = ((src[11] & 0x3) << 12) | (src[10] << 4) | (src[9] >> 4);
+ dest[6] = (src[9] & 0xf) << 10 | (src[8] << 2) | (src[15] >> 6);
+ dest[7] = ((src[15] & 0x3f) << 8) | src[14];
+ dest[8] = (src[13] << 6) | (src[12] >> 2);
+ dest[9] = ((src[12] & 0x3) << 12) | (src[19] << 4) | (src[18] >> 4);
+ dest[10] = (src[18] & 0xf) << 10 | (src[17] << 2) | (src[16] >> 6);
+ dest[11] = ((src[16] & 0x3f) << 8) | src[23];
+ dest[12] = (src[22] << 6) | (src[21] >> 2);
+ dest[13] = ((src[21] & 0x3) << 12) | (src[20] << 4) | (src[27] >> 4);
+ dest[14] = (src[27] & 0xf) << 10 | (src[26] << 2) | (src[25] >> 6);
+ dest[15] = ((src[25] & 0x3f) << 8) | src[24];
+}
+
+#define swab32(x) \
+ ((unsigned int)((((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
+ (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \
+ (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \
+ (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24)))
+
+static inline void swab32arr(unsigned *arr, unsigned len)
+{
+ for (unsigned i = 0; i < len; i++)
+ arr[i] = swab32(arr[i]);
+}
+#undef swab32
+
+static inline void unpack7bytesto4x16_nikon(unsigned char *src,
+ unsigned short *dest)
+{
+ dest[3] = (src[6] << 6) | (src[5] >> 2);
+ dest[2] = ((src[5] & 0x3) << 12) | (src[4] << 4) | (src[3] >> 4);
+ dest[1] = (src[3] & 0xf) << 10 | (src[2] << 2) | (src[1] >> 6);
+ dest[0] = ((src[1] & 0x3f) << 8) | src[0];
+}
+
+void LibRaw::nikon_14bit_load_raw()
+{
+ const unsigned linelen =
+ (unsigned)(ceilf((float)(S.raw_width * 7 / 4) / 16.0)) *
+ 16; // 14512; // S.raw_width * 7 / 4;
+ const unsigned pitch = S.raw_pitch ? S.raw_pitch / 2 : S.raw_width;
+ unsigned char *buf = (unsigned char *)malloc(linelen);
+ for (int row = 0; row < S.raw_height; row++)
+ {
+ unsigned bytesread =
+ libraw_internal_data.internal_data.input->read(buf, 1, linelen);
+ unsigned short *dest = &imgdata.rawdata.raw_image[pitch * row];
+ // swab32arr((unsigned *)buf, bytesread / 4);
+ for (unsigned int sp = 0, dp = 0;
+ dp < pitch - 3 && sp < linelen - 6 && sp < bytesread - 6;
+ sp += 7, dp += 4)
+ unpack7bytesto4x16_nikon(buf + sp, dest + dp);
+ }
+ free(buf);
+}
+
+void LibRaw::fuji_14bit_load_raw()
+{
+ const unsigned linelen = S.raw_width * 7 / 4;
+ const unsigned pitch = S.raw_pitch ? S.raw_pitch / 2 : S.raw_width;
+ unsigned char *buf = (unsigned char *)malloc(linelen);
+
+ for (int row = 0; row < S.raw_height; row++)
+ {
+ unsigned bytesread =
+ libraw_internal_data.internal_data.input->read(buf, 1, linelen);
+ unsigned short *dest = &imgdata.rawdata.raw_image[pitch * row];
+ if (bytesread % 28)
+ {
+ swab32arr((unsigned *)buf, bytesread / 4);
+ for (unsigned int sp = 0, dp = 0;
+ dp < pitch - 3 && sp < linelen - 6 && sp < bytesread - 6;
+ sp += 7, dp += 4)
+ unpack7bytesto4x16(buf + sp, dest + dp);
+ }
+ else
+ for (unsigned int sp = 0, dp = 0;
+ dp < pitch - 15 && sp < linelen - 27 && sp < bytesread - 27;
+ sp += 28, dp += 16)
+ unpack28bytesto16x16ns(buf + sp, dest + dp);
+ }
+ free(buf);
+}
+void LibRaw::nikon_load_padded_packed_raw() // 12 bit per pixel, padded to 16
+ // bytes
+{
+ // libraw_internal_data.unpacker_data.load_flags -> row byte count
+ if (libraw_internal_data.unpacker_data.load_flags < 2000 ||
+ libraw_internal_data.unpacker_data.load_flags > 64000)
+ return;
+ unsigned char *buf =
+ (unsigned char *)malloc(libraw_internal_data.unpacker_data.load_flags);
+ for (int row = 0; row < S.raw_height; row++)
+ {
+ checkCancel();
+ libraw_internal_data.internal_data.input->read(
+ buf, libraw_internal_data.unpacker_data.load_flags, 1);
+ for (int icol = 0; icol < S.raw_width / 2; icol++)
+ {
+ imgdata.rawdata.raw_image[(row)*S.raw_width + (icol * 2)] =
+ ((buf[icol * 3 + 1] & 0xf) << 8) | buf[icol * 3];
+ imgdata.rawdata.raw_image[(row)*S.raw_width + (icol * 2 + 1)] =
+ buf[icol * 3 + 2] << 4 | ((buf[icol * 3 + 1] & 0xf0) >> 4);
+ }
+ }
+ free(buf);
+}
+
+void LibRaw::nikon_load_striped_packed_raw()
+{
+ int vbits = 0, bwide, rbits, bite, row, col, i;
+
+ UINT64 bitbuf = 0;
+ unsigned load_flags = 24; // libraw_internal_data.unpacker_data.load_flags;
+ unsigned tiff_bps = libraw_internal_data.unpacker_data.tiff_bps;
+
+ struct tiff_ifd_t *ifd = &tiff_ifd[0];
+ while (ifd < &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds] &&
+ ifd->offset != libraw_internal_data.unpacker_data.data_offset)
+ ++ifd;
+ if (ifd == &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds])
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+
+ if (!ifd->rows_per_strip || !ifd->strip_offsets_count)
+ return; // not unpacked
+ int stripcnt = 0;
+
+ bwide = S.raw_width * tiff_bps / 8;
+ bwide += bwide & load_flags >> 7;
+ rbits = bwide * 8 - S.raw_width * tiff_bps;
+ if (load_flags & 1)
+ bwide = bwide * 16 / 15;
+ bite = 8 + (load_flags & 24);
+ for (row = 0; row < S.raw_height; row++)
+ {
+ checkCancel();
+ if (!(row % ifd->rows_per_strip))
+ {
+ if (stripcnt >= ifd->strip_offsets_count)
+ return; // run out of data
+ libraw_internal_data.internal_data.input->seek(
+ ifd->strip_offsets[stripcnt], SEEK_SET);
+ stripcnt++;
+ }
+ for (col = 0; col < S.raw_width; col++)
+ {
+ for (vbits -= tiff_bps; vbits < 0; vbits += bite)
+ {
+ bitbuf <<= bite;
+ for (i = 0; i < bite; i += 8)
+ bitbuf |=
+ (unsigned)(libraw_internal_data.internal_data.input->get_char()
+ << i);
+ }
+ imgdata.rawdata.raw_image[(row)*S.raw_width + (col)] =
+ bitbuf << (64 - tiff_bps - vbits) >> (64 - tiff_bps);
+ }
+ vbits -= rbits;
+ }
+}
+
+struct pana_cs6_page_decoder
+{
+ unsigned int pixelbuffer[18], lastoffset, maxoffset;
+ unsigned char current, *buffer;
+ pana_cs6_page_decoder(unsigned char *_buffer, unsigned int bsize)
+ : lastoffset(0), maxoffset(bsize), current(0), buffer(_buffer)
+ {
+ }
+ void read_page(); // will throw IO error if not enough space in buffer
+ void read_page12(); // 12-bit variant
+ unsigned int nextpixel() { return current < 14 ? pixelbuffer[current++] : 0; }
+ unsigned int nextpixel12() { return current < 18 ? pixelbuffer[current++] : 0; }
+};
+
+void pana_cs6_page_decoder::read_page()
+{
+ if (!buffer || (maxoffset - lastoffset < 16))
+ throw LIBRAW_EXCEPTION_IO_EOF;
+#define wbuffer(i) ((unsigned short)buffer[lastoffset + 15 - i])
+ pixelbuffer[0] = (wbuffer(0) << 6) | (wbuffer(1) >> 2); // 14 bit
+ pixelbuffer[1] = (((wbuffer(1) & 0x3) << 12) | (wbuffer(2) << 4) | (wbuffer(3) >> 4)) & 0x3fff; // 14 bit
+ pixelbuffer[2] = (wbuffer(3) >> 2) & 0x3; // 2
+ pixelbuffer[3] = ((wbuffer(3) & 0x3) << 8) | wbuffer(4); // 10
+ pixelbuffer[4] = (wbuffer(5) << 2) | (wbuffer(6) >> 6); // 10
+ pixelbuffer[5] = ((wbuffer(6) & 0x3f) << 4) | (wbuffer(7) >> 4); // 10
+ pixelbuffer[6] = (wbuffer(7) >> 2) & 0x3;
+ pixelbuffer[7] = ((wbuffer(7) & 0x3) << 8) | wbuffer(8);
+ pixelbuffer[8] = ((wbuffer(9) << 2) & 0x3fc) | (wbuffer(10) >> 6);
+ pixelbuffer[9] = ((wbuffer(10) << 4) | (wbuffer(11) >> 4)) & 0x3ff;
+ pixelbuffer[10] = (wbuffer(11) >> 2) & 0x3;
+ pixelbuffer[11] = ((wbuffer(11) & 0x3) << 8) | wbuffer(12);
+ pixelbuffer[12] = (((wbuffer(13) << 2) & 0x3fc) | wbuffer(14) >> 6) & 0x3ff;
+ pixelbuffer[13] = ((wbuffer(14) << 4) | (wbuffer(15) >> 4)) & 0x3ff;
+#undef wbuffer
+ current = 0;
+ lastoffset += 16;
+}
+
+void pana_cs6_page_decoder::read_page12()
+{
+ if (!buffer || (maxoffset - lastoffset < 16))
+ throw LIBRAW_EXCEPTION_IO_EOF;
+#define wb(i) ((unsigned short)buffer[lastoffset + 15 - i])
+ pixelbuffer[0] = (wb(0) << 4) | (wb(1) >> 4); // 12 bit: 8/0 + 4 upper bits of /1
+ pixelbuffer[1] = (((wb(1) & 0xf) << 8) | (wb(2))) & 0xfff; // 12 bit: 4l/1 + 8/2
+
+ pixelbuffer[2] = (wb(3) >> 6) & 0x3; // 2; 2u/3, 6 low bits remains in wb(3)
+ pixelbuffer[3] = ((wb(3) & 0x3f) << 2) | (wb(4) >> 6); // 8; 6l/3 + 2u/4; 6 low bits remains in wb(4)
+ pixelbuffer[4] = ((wb(4) & 0x3f) << 2) | (wb(5) >> 6); // 8: 6l/4 + 2u/5; 6 low bits remains in wb(5)
+ pixelbuffer[5] = ((wb(5) & 0x3f) << 2) | (wb(6) >> 6); // 8: 6l/5 + 2u/6, 6 low bits remains in wb(6)
+
+ pixelbuffer[6] = (wb(6) >> 4) & 0x3; // 2, 4 low bits remains in wb(6)
+ pixelbuffer[7] = ((wb(6) & 0xf) << 4) | (wb(7) >> 4); // 8: 4 low bits from wb(6), 4 upper bits from wb(7)
+ pixelbuffer[8] = ((wb(7) & 0xf) << 4) | (wb(8) >> 4); // 8: 4 low bits from wb7, 4 upper bits from wb8
+ pixelbuffer[9] = ((wb(8) & 0xf) << 4) | (wb(9) >> 4); // 8: 4 low bits from wb8, 4 upper bits from wb9
+
+ pixelbuffer[10] = (wb(9) >> 2) & 0x3; // 2: bits 2-3 from wb9, two low bits remain in wb9
+ pixelbuffer[11] = ((wb(9) & 0x3) << 6) | (wb(10) >> 2); // 8: 2 bits from wb9, 6 bits from wb10
+ pixelbuffer[12] = ((wb(10) & 0x3) << 6) | (wb(11) >> 2); // 8: 2 bits from wb10, 6 bits from wb11
+ pixelbuffer[13] = ((wb(11) & 0x3) << 6) | (wb(12) >> 2); // 8: 2 bits from wb11, 6 bits from wb12
+
+ pixelbuffer[14] = wb(12) & 0x3; // 2: low bits from wb12
+ pixelbuffer[15] = wb(13);
+ pixelbuffer[16] = wb(14);
+ pixelbuffer[17] = wb(15);
+#undef wb
+ current = 0;
+ lastoffset += 16;
+}
+
+void LibRaw::panasonicC6_load_raw()
+{
+ const int rowstep = 16;
+ const bool _12bit = libraw_internal_data.unpacker_data.pana_bpp == 12;
+ const int pixperblock = _12bit ? 14 : 11;
+ const int blocksperrow = imgdata.sizes.raw_width / pixperblock;
+ const int rowbytes = blocksperrow * 16;
+ const unsigned pixelbase0 = _12bit ? 0x80 : 0x200;
+ const unsigned pixelbase_compare = _12bit ? 0x800 : 0x2000;
+ const unsigned spix_compare = _12bit ? 0x3fff : 0xffff;
+ const unsigned pixel_mask = _12bit ? 0xfff : 0x3fff;
+ std::vector<unsigned char> iobuf;
+ try
+ {
+ iobuf.resize(rowbytes * rowstep);
+ }
+ catch (...)
+ {
+ throw LIBRAW_EXCEPTION_ALLOC;
+ }
+
+ for (int row = 0; row < imgdata.sizes.raw_height - rowstep + 1;
+ row += rowstep)
+ {
+ int rowstoread = MIN(rowstep, imgdata.sizes.raw_height - row);
+ if (libraw_internal_data.internal_data.input->read(
+ iobuf.data(), rowbytes, rowstoread) != rowstoread)
+ throw LIBRAW_EXCEPTION_IO_EOF;
+ pana_cs6_page_decoder page(iobuf.data(), rowbytes * rowstoread);
+ for (int crow = 0, col = 0; crow < rowstoread; crow++, col = 0)
+ {
+ unsigned short *rowptr =
+ &imgdata.rawdata
+ .raw_image[(row + crow) * imgdata.sizes.raw_pitch / 2];
+ for (int rblock = 0; rblock < blocksperrow; rblock++)
+ {
+ if (_12bit)
+ page.read_page12();
+ else
+ page.read_page();
+ unsigned oddeven[2] = {0, 0}, nonzero[2] = {0, 0};
+ unsigned pmul = 0, pixel_base = 0;
+ for (int pix = 0; pix < pixperblock; pix++)
+ {
+ if (pix % 3 == 2)
+ {
+ unsigned base = _12bit ? page.nextpixel12(): page.nextpixel();
+ if (base > 3)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT; // not possible b/c of 2-bit
+ // field, but....
+ if (base == 3)
+ base = 4;
+ pixel_base = pixelbase0 << base;
+ pmul = 1 << base;
+ }
+ unsigned epixel = _12bit ? page.nextpixel12() : page.nextpixel();
+ if (oddeven[pix % 2])
+ {
+ epixel *= pmul;
+ if (pixel_base < pixelbase_compare && nonzero[pix % 2] > pixel_base)
+ epixel += nonzero[pix % 2] - pixel_base;
+ nonzero[pix % 2] = epixel;
+ }
+ else
+ {
+ oddeven[pix % 2] = epixel;
+ if (epixel)
+ nonzero[pix % 2] = epixel;
+ else
+ epixel = nonzero[pix % 2];
+ }
+ unsigned spix = epixel - 0xf;
+ if (spix <= spix_compare)
+ rowptr[col++] = spix & spix_compare;
+ else
+ {
+ epixel = (((signed int)(epixel + 0x7ffffff1)) >> 0x1f);
+ rowptr[col++] = epixel & pixel_mask;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void LibRaw::panasonicC7_load_raw()
+{
+ const int rowstep = 16;
+ int pixperblock = libraw_internal_data.unpacker_data.pana_bpp == 14 ? 9 : 10;
+ int rowbytes = imgdata.sizes.raw_width / pixperblock * 16;
+ unsigned char *iobuf = (unsigned char *)malloc(rowbytes * rowstep);
+ for (int row = 0; row < imgdata.sizes.raw_height - rowstep + 1;
+ row += rowstep)
+ {
+ int rowstoread = MIN(rowstep, imgdata.sizes.raw_height - row);
+ if (libraw_internal_data.internal_data.input->read(
+ iobuf, rowbytes, rowstoread) != rowstoread)
+ throw LIBRAW_EXCEPTION_IO_EOF;
+ unsigned char *bytes = iobuf;
+ for (int crow = 0; crow < rowstoread; crow++)
+ {
+ unsigned short *rowptr =
+ &imgdata.rawdata
+ .raw_image[(row + crow) * imgdata.sizes.raw_pitch / 2];
+ for (int col = 0; col < imgdata.sizes.raw_width - pixperblock + 1;
+ col += pixperblock, bytes += 16)
+ {
+ if (libraw_internal_data.unpacker_data.pana_bpp == 14)
+ {
+ rowptr[col] = bytes[0] + ((bytes[1] & 0x3F) << 8);
+ rowptr[col + 1] =
+ (bytes[1] >> 6) + 4 * (bytes[2]) + ((bytes[3] & 0xF) << 10);
+ rowptr[col + 2] =
+ (bytes[3] >> 4) + 16 * (bytes[4]) + ((bytes[5] & 3) << 12);
+ rowptr[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6);
+ rowptr[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8);
+ rowptr[col + 5] =
+ (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10);
+ rowptr[col + 6] =
+ (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12);
+ rowptr[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6);
+ rowptr[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8);
+ }
+ else if (libraw_internal_data.unpacker_data.pana_bpp ==
+ 12) // have not seen in the wild yet
+ {
+ rowptr[col] = ((bytes[1] & 0xF) << 8) + bytes[0];
+ rowptr[col + 1] = 16 * bytes[2] + (bytes[1] >> 4);
+ rowptr[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3];
+ rowptr[col + 3] = 16 * bytes[5] + (bytes[4] >> 4);
+ rowptr[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6];
+ rowptr[col + 5] = 16 * bytes[8] + (bytes[7] >> 4);
+ rowptr[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9];
+ rowptr[col + 7] = 16 * bytes[11] + (bytes[10] >> 4);
+ rowptr[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12];
+ rowptr[col + 9] = 16 * bytes[14] + (bytes[13] >> 4);
+ }
+ }
+ }
+ }
+ free(iobuf);
+}
+
+void LibRaw::unpacked_load_raw_fuji_f700s20()
+{
+ int base_offset = 0;
+ int row_size = imgdata.sizes.raw_width * 2; // in bytes
+ if (imgdata.idata.raw_count == 2 && imgdata.rawparams.shot_select)
+ {
+ libraw_internal_data.internal_data.input->seek(-row_size, SEEK_CUR);
+ base_offset = row_size; // in bytes
+ }
+ unsigned char *buffer = (unsigned char *)malloc(row_size * 2);
+ for (int row = 0; row < imgdata.sizes.raw_height; row++)
+ {
+ read_shorts((ushort *)buffer, imgdata.sizes.raw_width * 2);
+ memmove(&imgdata.rawdata.raw_image[row * imgdata.sizes.raw_pitch / 2],
+ buffer + base_offset, row_size);
+ }
+ free(buffer);
+}
+
+void LibRaw::nikon_load_sraw()
+{
+ // We're already seeked to data!
+ unsigned char *rd =
+ (unsigned char *)malloc(3 * (imgdata.sizes.raw_width + 2));
+ if (!rd)
+ throw LIBRAW_EXCEPTION_ALLOC;
+ try
+ {
+ int row, col;
+ for (row = 0; row < imgdata.sizes.raw_height; row++)
+ {
+ checkCancel();
+ libraw_internal_data.internal_data.input->read(rd, 3,
+ imgdata.sizes.raw_width);
+ for (col = 0; col < imgdata.sizes.raw_width - 1; col += 2)
+ {
+ int bi = col * 3;
+ ushort bits1 = (rd[bi + 1] & 0xf) << 8 | rd[bi]; // 3,0,1
+ ushort bits2 = rd[bi + 2] << 4 | ((rd[bi + 1] >> 4) & 0xf); // 452
+ ushort bits3 = ((rd[bi + 4] & 0xf) << 8) | rd[bi + 3]; // 967
+ ushort bits4 = rd[bi + 5] << 4 | ((rd[bi + 4] >> 4) & 0xf); // ab8
+ imgdata.image[row * imgdata.sizes.raw_width + col][0] = bits1;
+ imgdata.image[row * imgdata.sizes.raw_width + col][1] = bits3;
+ imgdata.image[row * imgdata.sizes.raw_width + col][2] = bits4;
+ imgdata.image[row * imgdata.sizes.raw_width + col + 1][0] = bits2;
+ imgdata.image[row * imgdata.sizes.raw_width + col + 1][1] = 2048;
+ imgdata.image[row * imgdata.sizes.raw_width + col + 1][2] = 2048;
+ }
+ }
+ }
+ catch (...)
+ {
+ free(rd);
+ throw;
+ }
+ free(rd);
+ C.maximum = 0xfff; // 12 bit?
+ if (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE)
+ {
+ return; // no CbCr interpolation
+ }
+ // Interpolate CC channels
+ int row, col;
+ for (row = 0; row < imgdata.sizes.raw_height; row++)
+ {
+ checkCancel(); // will throw out
+ for (col = 0; col < imgdata.sizes.raw_width; col += 2)
+ {
+ int col2 = col < imgdata.sizes.raw_width - 2 ? col + 2 : col;
+ imgdata.image[row * imgdata.sizes.raw_width + col + 1][1] =
+ (unsigned short)(int(imgdata.image[row * imgdata.sizes.raw_width +
+ col][1] +
+ imgdata.image[row * imgdata.sizes.raw_width +
+ col2][1]) /
+ 2);
+ imgdata.image[row * imgdata.sizes.raw_width + col + 1][2] =
+ (unsigned short)(int(imgdata.image[row * imgdata.sizes.raw_width +
+ col][2] +
+ imgdata.image[row * imgdata.sizes.raw_width +
+ col2][2]) /
+ 2);
+ }
+ }
+ if (imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_SRAW_NO_RGB)
+ return;
+
+ for (row = 0; row < imgdata.sizes.raw_height; row++)
+ {
+ checkCancel(); // will throw out
+ for (col = 0; col < imgdata.sizes.raw_width; col++)
+ {
+ float Y =
+ float(imgdata.image[row * imgdata.sizes.raw_width + col][0]) / 2549.f;
+ float Ch2 =
+ float(imgdata.image[row * imgdata.sizes.raw_width + col][1] - 1280) /
+ 1536.f;
+ float Ch3 =
+ float(imgdata.image[row * imgdata.sizes.raw_width + col][2] - 1280) /
+ 1536.f;
+ if (Y > 1.f)
+ Y = 1.f;
+ if (Y > 0.803f)
+ Ch2 = Ch3 = 0.5f;
+ float r = Y + 1.40200f * (Ch3 - 0.5f);
+ if (r < 0.f)
+ r = 0.f;
+ if (r > 1.f)
+ r = 1.f;
+ float g = Y - 0.34414f * (Ch2 - 0.5f) - 0.71414 * (Ch3 - 0.5f);
+ if (g > 1.f)
+ g = 1.f;
+ if (g < 0.f)
+ g = 0.f;
+ float b = Y + 1.77200 * (Ch2 - 0.5f);
+ if (b > 1.f)
+ b = 1.f;
+ if (b < 0.f)
+ b = 0.f;
+ imgdata.image[row * imgdata.sizes.raw_width + col][0] =
+ imgdata.color.curve[int(r * 3072.f)];
+ imgdata.image[row * imgdata.sizes.raw_width + col][1] =
+ imgdata.color.curve[int(g * 3072.f)];
+ imgdata.image[row * imgdata.sizes.raw_width + col][2] =
+ imgdata.color.curve[int(b * 3072.f)];
+ }
+ }
+ C.maximum = 16383;
+}
+
+/*
+ Each row is decoded independently. Each row starts with a 16 bit prefix.
+ The hi byte is zero, the lo byte (first 3 bits) indicates a bit_base.
+ Other bits remain unused.
+
+ |0000 0000|0000 0XXX| => XXX is bit_base
+
+ After the prefix the pixel data starts. Pixels are grouped into clusters
+ forming 8 output pixel. Each cluster starts with a variable length of
+ bits, indicating decompression flags.
+
+
+*/
+
+#undef MIN
+#undef MAX
+#undef LIM
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define LIM(x, min, max) MAX(min, MIN(x, max))
+
+struct iiq_bitstream_t
+{
+ uint64_t curr;
+ uint32_t *input;
+ uint8_t used;
+ iiq_bitstream_t(uint32_t *img_input): curr(0),input(img_input),used(0){}
+
+ void fill()
+ {
+ if (used <= 32)
+ {
+ uint64_t bitpump_next = *input++;
+ curr = (curr << 32) | bitpump_next;
+ used += 32;
+ }
+ }
+ uint64_t peek(uint8_t len)
+ {
+ if (len >= used)
+ fill();
+
+ uint64_t res = curr >> (used - len);
+ return res & ((1 << (uint8_t)len) - 1);
+ }
+
+ void consume(uint8_t len)
+ {
+ peek(len); // fill buffer if needed
+ used -= len;
+ }
+
+ uint64_t get(char len)
+ {
+ uint64_t val = peek(len);
+ consume(len);
+ return val;
+ }
+
+};
+
+void decode_S_type(int32_t out_width, uint32_t *img_input, ushort *outbuf /*, int bit_depth*/)
+{
+#if 0
+ if (((bit_depth - 12) & 0xFFFFFFFD) != 0)
+ return 0;
+#endif
+ iiq_bitstream_t stream(img_input);
+
+ const int pix_corr_shift = 2; // 16 - bit_depth;
+ unsigned int bit_check[2] = { 0, 0 };
+
+ const uint8_t used_corr[8] = {
+ 3, 3, 3, 3, 1, 1, 1, 1,
+ };
+
+ const uint8_t extra_bits[8] = {
+ 1, 2, 3, 4, 0, 0, 0, 0,
+ };
+
+ const uint8_t bit_indicator[8 * 4] = {
+ 9, 8, 0, 7, 6, 6, 5, 5, 1, 1, 1, 1, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
+ };
+
+ const uint8_t skip_bits[8 * 4] = {5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
+
+ int block_count = ((out_width - 8) >> 3) + 1;
+ int block_total_bytes = 8 * block_count;
+
+ int32_t prev_pix_value[2] = { 0, 0 };
+
+ uint8_t init_bits = stream.get(16) & 7;
+
+ if (out_width - 7 > 0)
+ {
+ uint8_t pix_sub_init = 17 - init_bits;
+
+ for (int blk_id = 0; blk_id < block_count; ++blk_id)
+ {
+ int8_t idx_even = stream.peek(7);
+ stream.consume(2);
+
+ if ((unsigned int)idx_even >= 32)
+ bit_check[0] = ((unsigned int)idx_even >> 5) + bit_check[0] - 2;
+ else
+ {
+ bit_check[0] = bit_indicator[idx_even];
+ stream.consume(skip_bits[idx_even]);
+ }
+
+ int8_t idx_odd = stream.peek(7);
+ stream.consume(2);
+
+ if ((unsigned int)idx_odd >= 32)
+ bit_check[1] = ((unsigned int)idx_odd >> 5) + bit_check[1] - 2;
+ else
+ {
+ bit_check[1] = bit_indicator[idx_odd];
+ stream.consume(skip_bits[idx_odd]);
+ }
+
+ uint8_t bidx = stream.peek(3);
+ stream.consume(used_corr[bidx]);
+
+ uint8_t take_bits = init_bits + extra_bits[bidx]; // 11 or less
+
+ uint32_t bp_shift[2] = {bit_check[0] - extra_bits[bidx], bit_check[1] - extra_bits[bidx]};
+
+ int pix_sub[2] = {0xFFFF >> (pix_sub_init - bit_check[0]), 0xFFFF >> (pix_sub_init - bit_check[1])};
+
+ for (int i = 0; i < 8; i++) // MAIN LOOP for pixel decoding
+ {
+ int32_t value = 0;
+ if (bit_check[i & 1] == 9)
+ value = stream.get(14);
+ else
+ value = prev_pix_value[i & 1] + ((uint32_t)stream.get(take_bits) << bp_shift[i & 1]) - pix_sub[i & 1];
+
+ outbuf[i] = LIM(value << pix_corr_shift, 0, 0xffff);
+ prev_pix_value[i & 1] = value;
+ }
+ outbuf += 8; // always produce 8 pixels from this cluster
+ }
+ } // if width > 7 // End main if
+
+ // Final block
+ // maybe fill/unpack extra bytes if width % 8 <> 0?
+ if (block_total_bytes < out_width)
+ {
+ do
+ {
+ stream.fill();
+ uint32_t pix_value = stream.get(14);
+ ++block_total_bytes;
+ *outbuf++ = pix_value << pix_corr_shift;
+ } while (block_total_bytes < out_width);
+ }
+}
+
+struct p1_row_info_t
+{
+ unsigned row;
+ INT64 offset;
+ p1_row_info_t(): row(0),offset(0){}
+ p1_row_info_t(const p1_row_info_t& q): row(q.row),offset(q.offset){}
+ bool operator < (const p1_row_info_t & rhs) const { return offset < rhs.offset; }
+};
+
+void LibRaw::phase_one_load_raw_s()
+{
+ if(!libraw_internal_data.unpacker_data.strip_offset || !imgdata.rawdata.raw_image || !libraw_internal_data.unpacker_data.data_offset)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ std::vector<p1_row_info_t> stripes(imgdata.sizes.raw_height+1);
+ libraw_internal_data.internal_data.input->seek(libraw_internal_data.unpacker_data.strip_offset, SEEK_SET);
+ for (unsigned row = 0; row < imgdata.sizes.raw_height; row++)
+ {
+ stripes[row].row = row;
+ stripes[row].offset = INT64(get4()) + libraw_internal_data.unpacker_data.data_offset;
+ }
+ stripes[imgdata.sizes.raw_height].row = imgdata.sizes.raw_height;
+ stripes[imgdata.sizes.raw_height].offset = libraw_internal_data.unpacker_data.data_offset + INT64(libraw_internal_data.unpacker_data.data_size);
+ std::sort(stripes.begin(), stripes.end());
+ INT64 maxsz = imgdata.sizes.raw_width * 3 + 2; // theor max: 17 bytes per 8 pix + row header
+ std::vector<uint8_t> datavec(maxsz);
+
+ for (unsigned row = 0; row < imgdata.sizes.raw_height; row++)
+ {
+ if (stripes[row].row >= imgdata.sizes.raw_height) continue;
+ ushort *datap = imgdata.rawdata.raw_image + stripes[row].row * imgdata.sizes.raw_width;
+ libraw_internal_data.internal_data.input->seek(stripes[row].offset, SEEK_SET);
+ INT64 readsz = stripes[row + 1].offset - stripes[row].offset;
+ if (readsz > maxsz)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ if(libraw_internal_data.internal_data.input->read(datavec.data(), 1, readsz) != readsz)
+ derror(); // TODO: check read state
+
+ decode_S_type(imgdata.sizes.raw_width, (uint32_t *)datavec.data(), datap /*, 14 */);
+ }
+}
diff --git a/libkdcraw/libraw/src/decoders/decoders_libraw_dcrdefs.cpp b/libkdcraw/libraw/src/decoders/decoders_libraw_dcrdefs.cpp
new file mode 100644
index 0000000..89d8259
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/decoders_libraw_dcrdefs.cpp
@@ -0,0 +1,411 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::packed_tiled_dng_load_raw()
+{
+ ushort *rp;
+ unsigned row, col;
+
+ int ss = shot_select;
+ shot_select = libraw_internal_data.unpacker_data.dng_frames[LIM(ss, 0, (LIBRAW_IFD_MAXCOUNT * 2 - 1))] & 0xff;
+ std::vector<ushort> pixel;
+
+ try
+ {
+ int ntiles = 1 + (raw_width) / tile_width;
+ if ((unsigned)ntiles * tile_width > raw_width * 2u) throw LIBRAW_EXCEPTION_ALLOC;
+ pixel.resize(tile_width * ntiles * tiff_samples);
+ }
+ catch (...)
+ {
+ throw LIBRAW_EXCEPTION_ALLOC; // rethrow
+ }
+ try
+ {
+ unsigned trow = 0, tcol = 0;
+ INT64 save;
+ while (trow < raw_height)
+ {
+ checkCancel();
+ save = ftell(ifp);
+ if (tile_length < INT_MAX)
+ fseek(ifp, get4(), SEEK_SET);
+
+ for (row = 0; row < tile_length && (row + trow) < raw_height; row++)
+ {
+ if (tiff_bps == 16)
+ read_shorts(pixel.data(), tile_width * tiff_samples);
+ else
+ {
+ getbits(-1);
+ for (col = 0; col < tile_width * tiff_samples; col++)
+ pixel[col] = getbits(tiff_bps);
+ }
+ for (rp = pixel.data(), col = 0; col < tile_width; col++)
+ adobe_copy_pixel(trow+row, tcol+col, &rp);
+ }
+ fseek(ifp, save + 4, SEEK_SET);
+ if ((tcol += tile_width) >= raw_width)
+ trow += tile_length + (tcol = 0);
+ }
+ }
+ catch (...)
+ {
+ shot_select = ss;
+ throw;
+ }
+ shot_select = ss;
+}
+
+
+
+void LibRaw::sony_ljpeg_load_raw()
+{
+ unsigned trow = 0, tcol = 0, jrow, jcol, row, col;
+ INT64 save;
+ struct jhead jh;
+
+ while (trow < raw_height)
+ {
+ checkCancel();
+ save = ftell(ifp); // We're at
+ if (tile_length < INT_MAX)
+ fseek(ifp, get4(), SEEK_SET);
+ if (!ljpeg_start(&jh, 0))
+ break;
+ try
+ {
+ for (row = jrow = 0; jrow < (unsigned)jh.high; jrow++, row += 2)
+ {
+ checkCancel();
+ ushort(*rowp)[4] = (ushort(*)[4])ljpeg_row(jrow, &jh);
+ for (col = jcol = 0; jcol < (unsigned)jh.wide; jcol++, col += 2)
+ {
+ RAW(trow + row, tcol + col) = rowp[jcol][0];
+ RAW(trow + row, tcol + col + 1) = rowp[jcol][1];
+ RAW(trow + row + 1, tcol + col) = rowp[jcol][2];
+ RAW(trow + row + 1, tcol + col + 1) = rowp[jcol][3];
+ }
+ }
+ }
+ catch (...)
+ {
+ ljpeg_end(&jh);
+ throw;
+ }
+ fseek(ifp, save + 4, SEEK_SET);
+ if ((tcol += tile_width) >= raw_width)
+ trow += tile_length + (tcol = 0);
+ ljpeg_end(&jh);
+ }
+}
+
+void LibRaw::nikon_he_load_raw_placeholder()
+{
+ throw LIBRAW_EXCEPTION_UNSUPPORTED_FORMAT;
+}
+
+void LibRaw::nikon_coolscan_load_raw()
+{
+ int clrs = colors == 3 ? 3 : 1;
+
+ if (clrs == 3 && !image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ if(clrs == 1 && !raw_image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ int bypp = tiff_bps <= 8 ? 1 : 2;
+ int bufsize = width * clrs * bypp;
+ unsigned char *buf = (unsigned char *)malloc(bufsize);
+ unsigned short *ubuf = (unsigned short *)buf;
+
+ if (tiff_bps <= 8)
+ gamma_curve(1.0 / imgdata.rawparams.coolscan_nef_gamma, 0., 1, 255);
+ else
+ gamma_curve(1.0 / imgdata.rawparams.coolscan_nef_gamma, 0., 1, 65535);
+ fseek(ifp, data_offset, SEEK_SET);
+ for (int row = 0; row < raw_height; row++)
+ {
+ if(tiff_bps <=8)
+ fread(buf, 1, bufsize, ifp);
+ else
+ read_shorts(ubuf,width*clrs);
+
+ unsigned short(*ip)[4] = (unsigned short(*)[4])image + row * width;
+ unsigned short *rp = raw_image + row * raw_width;
+
+ if (is_NikonTransfer == 2)
+ { // it is also (tiff_bps == 8)
+ if (clrs == 3)
+ {
+ for (int col = 0; col < width; col++)
+ {
+ ip[col][0] = ((float)curve[buf[col * 3]]) / 255.0f;
+ ip[col][1] = ((float)curve[buf[col * 3 + 1]]) / 255.0f;
+ ip[col][2] = ((float)curve[buf[col * 3 + 2]]) / 255.0f;
+ ip[col][3] = 0;
+ }
+ }
+ else
+ {
+ for (int col = 0; col < width; col++)
+ rp[col] = ((float)curve[buf[col]]) / 255.0f;
+ }
+ }
+ else if (tiff_bps <= 8)
+ {
+ if (clrs == 3)
+ {
+ for (int col = 0; col < width; col++)
+ {
+ ip[col][0] = curve[buf[col * 3]];
+ ip[col][1] = curve[buf[col * 3 + 1]];
+ ip[col][2] = curve[buf[col * 3 + 2]];
+ ip[col][3] = 0;
+ }
+ }
+ else
+ {
+ for (int col = 0; col < width; col++)
+ rp[col] = curve[buf[col]];
+ }
+ }
+ else
+ {
+ if (clrs == 3)
+ {
+ for (int col = 0; col < width; col++)
+ {
+ ip[col][0] = curve[ubuf[col * 3]];
+ ip[col][1] = curve[ubuf[col * 3 + 1]];
+ ip[col][2] = curve[ubuf[col * 3 + 2]];
+ ip[col][3] = 0;
+ }
+ }
+ else
+ {
+ for (int col = 0; col < width; col++)
+ rp[col] = curve[ubuf[col]];
+ }
+ }
+ }
+ free(buf);
+}
+
+void LibRaw::broadcom_load_raw()
+{
+ uchar *dp;
+ int rev, row, col, c;
+ rev = 3 * (order == 0x4949);
+ std::vector<uchar> data(raw_stride * 2);
+
+ for (row = 0; row < raw_height; row++)
+ {
+ if (fread(data.data() + raw_stride, 1, raw_stride, ifp) < raw_stride)
+ derror();
+ FORC(raw_stride) data[c] = data[raw_stride + (c ^ rev)];
+ for (dp = data.data(), col = 0; col < raw_width; dp += 5, col += 4)
+ FORC4 RAW(row, col + c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
+ }
+}
+
+void LibRaw::android_tight_load_raw()
+{
+ uchar *data, *dp;
+ int bwide, row, col, c;
+
+ bwide = -(-5 * raw_width >> 5) << 3;
+ data = (uchar *)malloc(bwide);
+ for (row = 0; row < raw_height; row++)
+ {
+ if (fread(data, 1, bwide, ifp) < bwide)
+ derror();
+ for (dp = data, col = 0; col < raw_width; dp += 5, col += 4)
+ FORC4 RAW(row, col + c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
+ }
+ free(data);
+}
+
+void LibRaw::android_loose_load_raw()
+{
+ uchar *data, *dp;
+ int bwide, row, col, c;
+ UINT64 bitbuf = 0;
+
+ bwide = (raw_width + 5) / 6 << 3;
+ data = (uchar *)malloc(bwide);
+ for (row = 0; row < raw_height; row++)
+ {
+ if (fread(data, 1, bwide, ifp) < bwide)
+ derror();
+ for (dp = data, col = 0; col < raw_width; dp += 8, col += 6)
+ {
+ FORC(8) bitbuf = (bitbuf << 8) | dp[c ^ 7];
+ FORC(6) RAW(row, col + c) = (bitbuf >> c * 10) & 0x3ff;
+ }
+ }
+ free(data);
+}
+
+void LibRaw::unpacked_load_raw_reversed()
+{
+ int row, col, bits = 0;
+ while (1 << ++bits < (int)maximum)
+ ;
+ for (row = raw_height - 1; row >= 0; row--)
+ {
+ checkCancel();
+ read_shorts(&raw_image[row * raw_width], raw_width);
+ for (col = 0; col < raw_width; col++)
+ if ((RAW(row, col) >>= load_flags) >> bits &&
+ (unsigned)(row - top_margin) < height &&
+ (unsigned)(col - left_margin) < width)
+ derror();
+ }
+}
+
+#ifdef USE_6BY9RPI
+
+void LibRaw::rpi_load_raw8()
+{
+ uchar *data, *dp;
+ int rev, dwide, row, col, c;
+ double sum[] = { 0,0 };
+ rev = 3 * (order == 0x4949);
+ if (raw_stride == 0)
+ dwide = raw_width;
+ else
+ dwide = raw_stride;
+ data = (uchar *)malloc(dwide * 2);
+ for (row = 0; row < raw_height; row++) {
+ if (fread(data + dwide, 1, dwide, ifp) < dwide) derror();
+ FORC(dwide) data[c] = data[dwide + (c ^ rev)];
+ for (dp = data, col = 0; col < raw_width; dp++, col++)
+ RAW(row, col + c) = dp[c];
+ }
+ free(data);
+ maximum = 0xff;
+ if (!strcmp(make, "OmniVision") ||
+ !strcmp(make, "Sony") ||
+ !strcmp(make, "RaspberryPi")) return;
+
+ row = raw_height / 2;
+ FORC(width - 1) {
+ sum[c & 1] += SQR(RAW(row, c) - RAW(row + 1, c + 1));
+ sum[~c & 1] += SQR(RAW(row + 1, c) - RAW(row, c + 1));
+ }
+ if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
+}
+
+void LibRaw::rpi_load_raw12()
+{
+ uchar *data, *dp;
+ int rev, dwide, row, col, c;
+ double sum[] = { 0,0 };
+ rev = 3 * (order == 0x4949);
+ if (raw_stride == 0)
+ dwide = (raw_width * 3 + 1) / 2;
+ else
+ dwide = raw_stride;
+ data = (uchar *)malloc(dwide * 2);
+ for (row = 0; row < raw_height; row++) {
+ if (fread(data + dwide, 1, dwide, ifp) < dwide) derror();
+ FORC(dwide) data[c] = data[dwide + (c ^ rev)];
+ for (dp = data, col = 0; col < raw_width; dp += 3, col += 2)
+ FORC(2) RAW(row, col + c) = (dp[c] << 4) | (dp[2] >> (c << 2) & 0xF);
+ }
+ free(data);
+ maximum = 0xfff;
+ if (!strcmp(make, "OmniVision") ||
+ !strcmp(make, "Sony") ||
+ !strcmp(make, "RaspberryPi")) return;
+
+ row = raw_height / 2;
+ FORC(width - 1) {
+ sum[c & 1] += SQR(RAW(row, c) - RAW(row + 1, c + 1));
+ sum[~c & 1] += SQR(RAW(row + 1, c) - RAW(row, c + 1));
+ }
+ if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
+}
+
+void LibRaw::rpi_load_raw14()
+{
+ uchar *data, *dp;
+ int rev, dwide, row, col, c;
+ double sum[] = { 0,0 };
+ rev = 3 * (order == 0x4949);
+ if (raw_stride == 0)
+ dwide = ((raw_width * 7) + 3) >> 2;
+ else
+ dwide = raw_stride;
+ data = (uchar *)malloc(dwide * 2);
+ for (row = 0; row < raw_height; row++) {
+ if (fread(data + dwide, 1, dwide, ifp) < dwide) derror();
+ FORC(dwide) data[c] = data[dwide + (c ^ rev)];
+ for (dp = data, col = 0; col < raw_width; dp += 7, col += 4) {
+ RAW(row, col + 0) = (dp[0] << 6) | (dp[4] >> 2);
+ RAW(row, col + 1) = (dp[1] << 6) | ((dp[4] & 0x3) << 4) | ((dp[5] & 0xf0) >> 4);
+ RAW(row, col + 2) = (dp[2] << 6) | ((dp[5] & 0xf) << 2) | ((dp[6] & 0xc0) >> 6);
+ RAW(row, col + 3) = (dp[3] << 6) | ((dp[6] & 0x3f) << 2);
+ }
+ }
+ free(data);
+ maximum = 0x3fff;
+ if (!strcmp(make, "OmniVision") ||
+ !strcmp(make, "Sony") ||
+ !strcmp(make, "RaspberryPi")) return;
+
+ row = raw_height / 2;
+ FORC(width - 1) {
+ sum[c & 1] += SQR(RAW(row, c) - RAW(row + 1, c + 1));
+ sum[~c & 1] += SQR(RAW(row + 1, c) - RAW(row, c + 1));
+ }
+ if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
+}
+
+void LibRaw::rpi_load_raw16()
+{
+ uchar *data, *dp;
+ int rev, dwide, row, col, c;
+ double sum[] = { 0,0 };
+ rev = 3 * (order == 0x4949);
+ if (raw_stride == 0)
+ dwide = (raw_width * 2);
+ else
+ dwide = raw_stride;
+ data = (uchar *)malloc(dwide * 2);
+ for (row = 0; row < raw_height; row++) {
+ if (fread(data + dwide, 1, dwide, ifp) < dwide) derror();
+ FORC(dwide) data[c] = data[dwide + (c ^ rev)];
+ for (dp = data, col = 0; col < raw_width; dp += 2, col++)
+ RAW(row, col + c) = (dp[1] << 8) | dp[0];
+ }
+ free(data);
+ maximum = 0xffff;
+ if (!strcmp(make, "OmniVision") ||
+ !strcmp(make, "Sony") ||
+ !strcmp(make, "RaspberryPi")) return;
+
+ row = raw_height / 2;
+ FORC(width - 1) {
+ sum[c & 1] += SQR(RAW(row, c) - RAW(row + 1, c + 1));
+ sum[~c & 1] += SQR(RAW(row + 1, c) - RAW(row, c + 1));
+ }
+ if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
+}
+
+#endif
diff --git a/libkdcraw/libraw/src/decoders/dng.cpp b/libkdcraw/libraw/src/decoders/dng.cpp
new file mode 100644
index 0000000..89537a5
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/dng.cpp
@@ -0,0 +1,278 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::vc5_dng_load_raw_placeholder()
+{
+ // placeholder only, real decoding implemented in GPR SDK
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+}
+
+void LibRaw::adobe_copy_pixel(unsigned row, unsigned col, ushort **rp)
+{
+ int c;
+
+ if (tiff_samples == 2 && shot_select)
+ (*rp)++;
+ if (raw_image)
+ {
+ if (row < raw_height && col < raw_width)
+ RAW(row, col) = curve[**rp];
+ *rp += tiff_samples;
+ }
+ else
+ {
+ if (row < raw_height && col < raw_width)
+ FORC(int(tiff_samples))
+ image[row * raw_width + col][c] = curve[(*rp)[c]];
+ *rp += tiff_samples;
+ }
+ if (tiff_samples == 2 && shot_select)
+ (*rp)--;
+}
+void LibRaw::lossless_dng_load_raw()
+{
+ unsigned trow = 0, tcol = 0, jwide, jrow, jcol, row, col, i, j;
+ INT64 save;
+ struct jhead jh;
+ ushort *rp;
+
+ int ss = shot_select;
+ shot_select = libraw_internal_data.unpacker_data.dng_frames[LIM(ss,0,(LIBRAW_IFD_MAXCOUNT*2-1))] & 0xff;
+
+ while (trow < raw_height)
+ {
+ checkCancel();
+ save = ftell(ifp);
+ if (tile_length < INT_MAX)
+ fseek(ifp, get4(), SEEK_SET);
+ if (!ljpeg_start(&jh, 0))
+ break;
+ jwide = jh.wide;
+ if (filters)
+ jwide *= jh.clrs;
+
+ if(filters && (tiff_samples == 2)) // Fuji Super CCD
+ jwide /= 2;
+ try
+ {
+ switch (jh.algo)
+ {
+ case 0xc1:
+ jh.vpred[0] = 16384;
+ getbits(-1);
+ for (jrow = 0; jrow + 7 < (unsigned)jh.high; jrow += 8)
+ {
+ checkCancel();
+ for (jcol = 0; jcol + 7 < (unsigned)jh.wide; jcol += 8)
+ {
+ ljpeg_idct(&jh);
+ rp = jh.idct;
+ row = trow + jcol / tile_width + jrow * 2;
+ col = tcol + jcol % tile_width;
+ for (i = 0; i < 16; i += 2)
+ for (j = 0; j < 8; j++)
+ adobe_copy_pixel(row + i, col + j, &rp);
+ }
+ }
+ break;
+ case 0xc3:
+ for (row = col = jrow = 0; jrow < (unsigned)jh.high; jrow++)
+ {
+ checkCancel();
+ rp = ljpeg_row(jrow, &jh);
+ if (tiff_samples == 1 && jh.clrs > 1 && jh.clrs * jwide == raw_width)
+ for (jcol = 0; jcol < jwide * jh.clrs; jcol++)
+ {
+ adobe_copy_pixel(trow + row, tcol + col, &rp);
+ if (++col >= tile_width || col >= raw_width)
+ row += 1 + (col = 0);
+ }
+ else
+ for (jcol = 0; jcol < jwide; jcol++)
+ {
+ adobe_copy_pixel(trow + row, tcol + col, &rp);
+ if (++col >= tile_width || col >= raw_width)
+ row += 1 + (col = 0);
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ ljpeg_end(&jh);
+ shot_select = ss;
+ throw;
+ }
+ fseek(ifp, save + 4, SEEK_SET);
+ if ((tcol += tile_width) >= raw_width)
+ trow += tile_length + (tcol = 0);
+ ljpeg_end(&jh);
+ }
+ shot_select = ss;
+}
+
+void LibRaw::packed_dng_load_raw()
+{
+ ushort *pixel, *rp;
+ unsigned row, col;
+
+ if (tile_length < INT_MAX)
+ {
+ packed_tiled_dng_load_raw();
+ return;
+ }
+
+ int ss = shot_select;
+ shot_select = libraw_internal_data.unpacker_data.dng_frames[LIM(ss,0,(LIBRAW_IFD_MAXCOUNT*2-1))] & 0xff;
+
+ pixel = (ushort *)calloc(raw_width, tiff_samples * sizeof *pixel);
+ try
+ {
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ if (tiff_bps == 16)
+ read_shorts(pixel, raw_width * tiff_samples);
+ else
+ {
+ getbits(-1);
+ for (col = 0; col < raw_width * tiff_samples; col++)
+ pixel[col] = getbits(tiff_bps);
+ }
+ for (rp = pixel, col = 0; col < raw_width; col++)
+ adobe_copy_pixel(row, col, &rp);
+ }
+ }
+ catch (...)
+ {
+ free(pixel);
+ shot_select = ss;
+ throw;
+ }
+ free(pixel);
+ shot_select = ss;
+}
+#ifdef NO_JPEG
+void LibRaw::lossy_dng_load_raw() {}
+#else
+
+static void jpegErrorExit_d(j_common_ptr /*cinfo*/)
+{
+ throw LIBRAW_EXCEPTION_DECODE_JPEG;
+}
+
+void LibRaw::lossy_dng_load_raw()
+{
+ if (!image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ struct jpeg_decompress_struct cinfo;
+ JSAMPARRAY buf;
+ JSAMPLE(*pixel)[3];
+ unsigned sorder = order, ntags, opcode, deg, i, j, c;
+ unsigned trow = 0, tcol = 0, row, col;
+ INT64 save = data_offset - 4;
+ ushort cur[3][256];
+ double coeff[9], tot;
+
+ if (meta_offset)
+ {
+ fseek(ifp, meta_offset, SEEK_SET);
+ order = 0x4d4d;
+ ntags = get4();
+ while (ntags--)
+ {
+ opcode = get4();
+ get4();
+ get4();
+ if (opcode != 8)
+ {
+ fseek(ifp, get4(), SEEK_CUR);
+ continue;
+ }
+ fseek(ifp, 20, SEEK_CUR);
+ if ((c = get4()) > 2)
+ break;
+ fseek(ifp, 12, SEEK_CUR);
+ if ((deg = get4()) > 8)
+ break;
+ for (i = 0; i <= deg && i < 9; i++)
+ coeff[i] = getreal(LIBRAW_EXIFTAG_TYPE_DOUBLE);
+ for (i = 0; i < 256; i++)
+ {
+ for (tot = j = 0; j <= deg; j++)
+ tot += coeff[j] * pow(i / 255.0, (int)j);
+ cur[c][i] = (ushort)(tot * 0xffff);
+ }
+ }
+ order = sorder;
+ }
+ else
+ {
+ gamma_curve(1 / 2.4, 12.92, 1, 255);
+ FORC3 memcpy(cur[c], curve, sizeof cur[0]);
+ }
+
+ struct jpeg_error_mgr pub;
+ cinfo.err = jpeg_std_error(&pub);
+ pub.error_exit = jpegErrorExit_d;
+
+ jpeg_create_decompress(&cinfo);
+
+ while (trow < raw_height)
+ {
+ fseek(ifp, save += 4, SEEK_SET);
+ if (tile_length < INT_MAX)
+ fseek(ifp, get4(), SEEK_SET);
+ if (libraw_internal_data.internal_data.input->jpeg_src(&cinfo) == -1)
+ {
+ jpeg_destroy_decompress(&cinfo);
+ throw LIBRAW_EXCEPTION_DECODE_JPEG;
+ }
+ jpeg_read_header(&cinfo, TRUE);
+ jpeg_start_decompress(&cinfo);
+ buf = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE,
+ cinfo.output_width * 3, 1);
+ try
+ {
+ while (cinfo.output_scanline < cinfo.output_height &&
+ (row = trow + cinfo.output_scanline) < height)
+ {
+ checkCancel();
+ jpeg_read_scanlines(&cinfo, buf, 1);
+ pixel = (JSAMPLE(*)[3])buf[0];
+ for (col = 0; col < cinfo.output_width && tcol + col < width; col++)
+ {
+ FORC3 image[row * width + tcol + col][c] = cur[c][pixel[col][c]];
+ }
+ }
+ }
+ catch (...)
+ {
+ jpeg_destroy_decompress(&cinfo);
+ throw;
+ }
+ jpeg_abort_decompress(&cinfo);
+ if ((tcol += tile_width) >= raw_width)
+ trow += tile_length + (tcol = 0);
+ }
+ jpeg_destroy_decompress(&cinfo);
+ maximum = 0xffff;
+}
+#endif
diff --git a/libkdcraw/libraw/src/decoders/fp_dng.cpp b/libkdcraw/libraw/src/decoders/fp_dng.cpp
new file mode 100644
index 0000000..0566ad2
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/fp_dng.cpp
@@ -0,0 +1,689 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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"
+
+inline unsigned int __DNG_HalfToFloat(ushort halfValue)
+{
+ int sign = (halfValue >> 15) & 0x00000001;
+ int exponent = (halfValue >> 10) & 0x0000001f;
+ int mantissa = halfValue & 0x000003ff;
+ if (exponent == 0)
+ {
+ if (mantissa == 0)
+ {
+ return (unsigned int)(sign << 31);
+ }
+ else
+ {
+ while (!(mantissa & 0x00000400))
+ {
+ mantissa <<= 1;
+ exponent -= 1;
+ }
+ exponent += 1;
+ mantissa &= ~0x00000400;
+ }
+ }
+ else if (exponent == 31)
+ {
+ if (mantissa == 0)
+ {
+ return (unsigned int)((sign << 31) | ((0x1eL + 127 - 15) << 23) |
+ (0x3ffL << 13));
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ exponent += (127 - 15);
+ mantissa <<= 13;
+ return (unsigned int)((sign << 31) | (exponent << 23) | mantissa);
+}
+
+inline unsigned int __DNG_FP24ToFloat(const unsigned char *input)
+{
+ int sign = (input[0] >> 7) & 0x01;
+ int exponent = (input[0]) & 0x7F;
+ int mantissa = (((int)input[1]) << 8) | input[2];
+ if (exponent == 0)
+ {
+ if (mantissa == 0)
+ {
+ return (unsigned int)(sign << 31);
+ }
+ else
+ {
+ while (!(mantissa & 0x00010000))
+ {
+ mantissa <<= 1;
+ exponent -= 1;
+ }
+ exponent += 1;
+ mantissa &= ~0x00010000;
+ }
+ }
+ else if (exponent == 127)
+ {
+ if (mantissa == 0)
+ {
+ return (unsigned int)((sign << 31) | ((0x7eL + 128 - 64) << 23) |
+ (0xffffL << 7));
+ }
+ else
+ {
+ // Nan -- Just set to zero.
+ return 0;
+ }
+ }
+ exponent += (128 - 64);
+ mantissa <<= 7;
+ return (uint32_t)((sign << 31) | (exponent << 23) | mantissa);
+}
+
+inline void DecodeDeltaBytes(unsigned char *bytePtr, int cols, int channels)
+{
+ if (channels == 1)
+ {
+ unsigned char b0 = bytePtr[0];
+ bytePtr += 1;
+ for (int col = 1; col < cols; ++col)
+ {
+ b0 += bytePtr[0];
+ bytePtr[0] = b0;
+ bytePtr += 1;
+ }
+ }
+ else if (channels == 3)
+ {
+ unsigned char b0 = bytePtr[0];
+ unsigned char b1 = bytePtr[1];
+ unsigned char b2 = bytePtr[2];
+ bytePtr += 3;
+ for (int col = 1; col < cols; ++col)
+ {
+ b0 += bytePtr[0];
+ b1 += bytePtr[1];
+ b2 += bytePtr[2];
+ bytePtr[0] = b0;
+ bytePtr[1] = b1;
+ bytePtr[2] = b2;
+ bytePtr += 3;
+ }
+ }
+ else if (channels == 4)
+ {
+ unsigned char b0 = bytePtr[0];
+ unsigned char b1 = bytePtr[1];
+ unsigned char b2 = bytePtr[2];
+ unsigned char b3 = bytePtr[3];
+ bytePtr += 4;
+ for (int col = 1; col < cols; ++col)
+ {
+ b0 += bytePtr[0];
+ b1 += bytePtr[1];
+ b2 += bytePtr[2];
+ b3 += bytePtr[3];
+ bytePtr[0] = b0;
+ bytePtr[1] = b1;
+ bytePtr[2] = b2;
+ bytePtr[3] = b3;
+ bytePtr += 4;
+ }
+ }
+ else
+ {
+ for (int col = 1; col < cols; ++col)
+ {
+ for (int chan = 0; chan < channels; ++chan)
+ {
+ bytePtr[chan + channels] += bytePtr[chan];
+ }
+ bytePtr += channels;
+ }
+ }
+}
+
+#ifdef USE_ZLIB
+static void DecodeFPDelta(unsigned char *input, unsigned char *output, int cols,
+ int channels, int bytesPerSample)
+{
+ DecodeDeltaBytes(input, cols * bytesPerSample, channels);
+ int32_t rowIncrement = cols * channels;
+
+ if (bytesPerSample == 2)
+ {
+
+#if LibRawBigEndian
+ const unsigned char *input0 = input;
+ const unsigned char *input1 = input + rowIncrement;
+#else
+ const unsigned char *input1 = input;
+ const unsigned char *input0 = input + rowIncrement;
+#endif
+ for (int col = 0; col < rowIncrement; ++col)
+ {
+ output[0] = input0[col];
+ output[1] = input1[col];
+ output += 2;
+ }
+ }
+ else if (bytesPerSample == 3)
+ {
+ const unsigned char *input0 = input;
+ const unsigned char *input1 = input + rowIncrement;
+ const unsigned char *input2 = input + rowIncrement * 2;
+ for (int col = 0; col < rowIncrement; ++col)
+ {
+ output[0] = input0[col];
+ output[1] = input1[col];
+ output[2] = input2[col];
+ output += 3;
+ }
+ }
+ else
+ {
+#if LibRawBigEndian
+ const unsigned char *input0 = input;
+ const unsigned char *input1 = input + rowIncrement;
+ const unsigned char *input2 = input + rowIncrement * 2;
+ const unsigned char *input3 = input + rowIncrement * 3;
+#else
+ const unsigned char *input3 = input;
+ const unsigned char *input2 = input + rowIncrement;
+ const unsigned char *input1 = input + rowIncrement * 2;
+ const unsigned char *input0 = input + rowIncrement * 3;
+#endif
+ for (int col = 0; col < rowIncrement; ++col)
+ {
+ output[0] = input0[col];
+ output[1] = input1[col];
+ output[2] = input2[col];
+ output[3] = input3[col];
+ output += 4;
+ }
+ }
+}
+#endif
+
+static float expandFloats(unsigned char *dst, int tileWidth, int bytesps)
+{
+ float max = 0.f;
+ if (bytesps == 2)
+ {
+ uint16_t *dst16 = (ushort *)dst;
+ uint32_t *dst32 = (unsigned int *)dst;
+ float *f32 = (float *)dst;
+ for (int index = tileWidth - 1; index >= 0; --index)
+ {
+ dst32[index] = __DNG_HalfToFloat(dst16[index]);
+ max = MAX(max, f32[index]);
+ }
+ }
+ else if (bytesps == 3)
+ {
+ uint8_t *dst8 = ((unsigned char *)dst) + (tileWidth - 1) * 3;
+ uint32_t *dst32 = (unsigned int *)dst;
+ float *f32 = (float *)dst;
+ for (int index = tileWidth - 1; index >= 0; --index, dst8 -= 3)
+ {
+ dst32[index] = __DNG_FP24ToFloat(dst8);
+ max = MAX(max, f32[index]);
+ }
+ }
+ else if (bytesps == 4)
+ {
+ float *f32 = (float *)dst;
+ for (int index = 0; index < tileWidth; index++)
+ max = MAX(max, f32[index]);
+ }
+ return max;
+}
+
+struct tile_stripe_data_t
+{
+ bool tiled, striped;
+ int tileCnt;
+ unsigned tileWidth, tileHeight, tilesH, tilesV;
+ size_t maxBytesInTile;
+ std::vector<size_t> tOffsets, tBytes;
+ tile_stripe_data_t() : tiled(false), striped(false),tileCnt(0),
+ tileWidth(0),tileHeight(0),tilesH(0),tilesV(0),
+ maxBytesInTile(0){}
+ void init(tiff_ifd_t *ifd, const libraw_image_sizes_t&, const unpacker_data_t&,
+ short _order,
+ LibRaw_abstract_datastream *stream);
+};
+
+static unsigned static_get4(LibRaw_abstract_datastream *stream, short _order)
+{
+ uchar str[4] = { 0xff, 0xff, 0xff, 0xff };
+ stream->read(str, 1, 4);
+ return libraw_sget4_static(_order, str);
+}
+
+
+void tile_stripe_data_t::init(tiff_ifd_t *ifd, const libraw_image_sizes_t& sizes,
+ const unpacker_data_t& unpacker_data, short _order, LibRaw_abstract_datastream *stream)
+{
+ tiled = (unpacker_data.tile_width <= sizes.raw_width) && (unpacker_data.tile_length <= sizes.raw_height);
+ striped = (ifd->rows_per_strip > 0 && ifd->rows_per_strip < sizes.raw_height) && ifd->strip_byte_counts_count > 0;
+
+ tileWidth = tiled ? unpacker_data.tile_width : sizes.raw_width;
+ tileHeight = tiled ? unpacker_data.tile_length :(striped ? ifd->rows_per_strip : sizes.raw_height);
+ tilesH = tiled ? (sizes.raw_width + tileWidth - 1) / tileWidth : 1;
+ tilesV = tiled ? (sizes.raw_height + tileHeight - 1) / tileHeight :
+ (striped ? ((sizes.raw_height + ifd->rows_per_strip - 1) / ifd->rows_per_strip) : 1);
+ tileCnt = tilesH * tilesV;
+
+ if (tileCnt < 1 || tileCnt > 1000000)
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+
+ tOffsets = std::vector<size_t>(tileCnt);
+ tBytes = std::vector <size_t>(tileCnt);
+
+ if (tiled)
+ for (int t = 0; t < tileCnt; ++t)
+ tOffsets[t] = static_get4(stream, _order);
+ else if (striped)
+ for (int t = 0; t < tileCnt && t < ifd->strip_offsets_count; ++t)
+ tOffsets[t] = ifd->strip_offsets[t];
+ else
+ tOffsets[0] = ifd->offset;
+
+ maxBytesInTile = 0;
+
+ if (tileCnt == 1 || (!tiled && !striped))
+ tBytes[0] = maxBytesInTile = ifd->bytes;
+ else if (tiled)
+ {
+ // ifd->bytes points to tile size table if more than 1 tile exists
+ stream->seek(ifd->bytes, SEEK_SET);
+ for (int t = 0; t < tileCnt; ++t)
+ {
+ tBytes[t] = static_get4(stream, _order); ;
+ maxBytesInTile = MAX(maxBytesInTile, tBytes[t]);
+ }
+ }
+ else if (striped)
+ for (int t = 0; t < tileCnt && t < ifd->strip_byte_counts_count; ++t)
+ {
+ tBytes[t] = ifd->strip_byte_counts[t];
+ maxBytesInTile = MAX(maxBytesInTile, tBytes[t]);
+ }
+}
+
+#ifdef USE_ZLIB
+void LibRaw::deflate_dng_load_raw()
+{
+ int iifd = find_ifd_by_offset(libraw_internal_data.unpacker_data.data_offset);
+ if(iifd < 0 || iifd > (int)libraw_internal_data.identify_data.tiff_nifds)
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+ struct tiff_ifd_t *ifd = &tiff_ifd[iifd];
+
+ float *float_raw_image = 0;
+ float max = 0.f;
+
+ if (ifd->samples != 1 && ifd->samples != 3 && ifd->samples != 4)
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+
+ if (libraw_internal_data.unpacker_data.tiff_samples != (unsigned)ifd->samples)
+ throw LIBRAW_EXCEPTION_DECODE_RAW; // Wrong IFD
+
+ if (imgdata.idata.filters && ifd->samples > 1)
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+
+ tile_stripe_data_t tiles;
+ tiles.init(ifd, imgdata.sizes, libraw_internal_data.unpacker_data, libraw_internal_data.unpacker_data.order,
+ libraw_internal_data.internal_data.input);
+
+ if (ifd->sample_format == 3)
+ float_raw_image = (float *)calloc(tiles.tileCnt * tiles.tileWidth * tiles.tileHeight *ifd->samples, sizeof(float));
+ else
+ throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float deflated supported
+
+ int xFactor;
+ switch (ifd->predictor)
+ {
+ case 3:
+ default:
+ xFactor = 1;
+ break;
+ case 34894:
+ xFactor = 2;
+ break;
+ case 34895:
+ xFactor = 4;
+ break;
+ }
+
+ unsigned tilePixels = tiles.tileWidth * tiles.tileHeight;
+ unsigned pixelSize = sizeof(float) * ifd->samples;
+ unsigned tileBytes = tilePixels * pixelSize;
+ unsigned tileRowBytes = tiles.tileWidth * pixelSize;
+
+ if(INT64(tiles.maxBytesInTile) > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024) )
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ std::vector<uchar> cBuffer(tiles.maxBytesInTile);
+ std::vector<uchar> uBuffer(tileBytes + tileRowBytes); // extra row for decoding
+
+ for (size_t y = 0, t = 0; y < imgdata.sizes.raw_height; y += tiles.tileHeight)
+ {
+ for (size_t x = 0; x < imgdata.sizes.raw_width; x += tiles.tileWidth, ++t)
+ {
+ libraw_internal_data.internal_data.input->seek(tiles.tOffsets[t], SEEK_SET);
+ libraw_internal_data.internal_data.input->read(cBuffer.data(), 1, tiles.tBytes[t]);
+ unsigned long dstLen = tileBytes;
+ int err =
+ uncompress(uBuffer.data() + tileRowBytes, &dstLen, cBuffer.data(), (unsigned long)tiles.tBytes[t]);
+ if (err != Z_OK)
+ {
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+ return;
+ }
+ else
+ {
+ int bytesps = ifd->bps >> 3;
+ size_t rowsInTile = y + tiles.tileHeight > imgdata.sizes.raw_height ? imgdata.sizes.raw_height - y : tiles.tileHeight;
+ size_t colsInTile = x + tiles.tileWidth > imgdata.sizes.raw_width ? imgdata.sizes.raw_width - x : tiles.tileWidth;
+
+ for (size_t row = 0; row < rowsInTile; ++row) // do not process full tile if not needed
+ {
+ unsigned char *dst = uBuffer.data() + row * tiles.tileWidth * bytesps * ifd->samples;
+ unsigned char *src = dst + tileRowBytes;
+ DecodeFPDelta(src, dst, tiles.tileWidth / xFactor, ifd->samples * xFactor, bytesps);
+ float lmax = expandFloats(dst, tiles.tileWidth * ifd->samples, bytesps);
+ max = MAX(max, lmax);
+ unsigned char *dst2 = (unsigned char *)&float_raw_image
+ [((y + row) * imgdata.sizes.raw_width + x) * ifd->samples];
+ memmove(dst2, dst, colsInTile * ifd->samples * sizeof(float));
+ }
+ }
+ }
+ }
+
+ imgdata.color.fmaximum = max;
+
+ // Set fields according to data format
+
+ imgdata.rawdata.raw_alloc = float_raw_image;
+ if (ifd->samples == 1)
+ {
+ imgdata.rawdata.float_image = float_raw_image;
+ imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch =
+ imgdata.sizes.raw_width * 4;
+ }
+ else if (ifd->samples == 3)
+ {
+ imgdata.rawdata.float3_image = (float(*)[3])float_raw_image;
+ imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch =
+ imgdata.sizes.raw_width * 12;
+ }
+ else if (ifd->samples == 4)
+ {
+ imgdata.rawdata.float4_image = (float(*)[4])float_raw_image;
+ imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch =
+ imgdata.sizes.raw_width * 16;
+ }
+
+ if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT)
+ convertFloatToInt(); // with default settings
+}
+#else
+void LibRaw::deflate_dng_load_raw() { throw LIBRAW_EXCEPTION_DECODE_RAW; }
+#endif
+
+int LibRaw::is_floating_point()
+{
+ struct tiff_ifd_t *ifd = &tiff_ifd[0];
+ while (ifd < &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds] &&
+ ifd->offset != libraw_internal_data.unpacker_data.data_offset)
+ ++ifd;
+ if (ifd == &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds])
+ return 0;
+
+ return ifd->sample_format == 3;
+}
+
+int LibRaw::have_fpdata()
+{
+ return imgdata.rawdata.float_image || imgdata.rawdata.float3_image ||
+ imgdata.rawdata.float4_image;
+}
+
+void LibRaw::convertFloatToInt(float dmin /* =4096.f */,
+ float dmax /* =32767.f */,
+ float dtarget /*= 16383.f */)
+{
+ int samples = 0;
+ float *data = 0;
+ void *orawalloc = imgdata.rawdata.raw_alloc;
+ if (imgdata.rawdata.float_image)
+ {
+ samples = 1;
+ data = imgdata.rawdata.float_image;
+ }
+ else if (imgdata.rawdata.float3_image)
+ {
+ samples = 3;
+ data = (float *)imgdata.rawdata.float3_image;
+ }
+ else if (imgdata.rawdata.float4_image)
+ {
+ samples = 4;
+ data = (float *)imgdata.rawdata.float4_image;
+ }
+ else
+ return;
+
+ ushort *raw_alloc = (ushort *)malloc(
+ imgdata.sizes.raw_height * imgdata.sizes.raw_width *
+ libraw_internal_data.unpacker_data.tiff_samples * sizeof(ushort));
+ float tmax = MAX(imgdata.color.maximum, 1);
+ float datamax = imgdata.color.fmaximum;
+
+ tmax = MAX(tmax, datamax);
+ tmax = MAX(tmax, 1.f);
+
+ float multip = 1.f;
+ if (tmax < dmin || tmax > dmax)
+ {
+ imgdata.rawdata.color.fnorm = imgdata.color.fnorm = multip = dtarget / tmax;
+ imgdata.rawdata.color.maximum = imgdata.color.maximum = dtarget;
+ imgdata.rawdata.color.black = imgdata.color.black =
+ (float)imgdata.color.black * multip;
+ for (int i = 0;
+ i < int(sizeof(imgdata.color.cblack)/sizeof(imgdata.color.cblack[0]));
+ i++)
+ if (i != 4 && i != 5)
+ imgdata.rawdata.color.cblack[i] = imgdata.color.cblack[i] =
+ (float)imgdata.color.cblack[i] * multip;
+ }
+ else
+ imgdata.rawdata.color.fnorm = imgdata.color.fnorm = 0.f;
+
+ for (size_t i = 0; i < imgdata.sizes.raw_height * imgdata.sizes.raw_width *
+ libraw_internal_data.unpacker_data.tiff_samples;
+ ++i)
+ {
+ float val = MAX(data[i], 0.f);
+ raw_alloc[i] = (ushort)(val * multip);
+ }
+
+ if (samples == 1)
+ {
+ imgdata.rawdata.raw_alloc = imgdata.rawdata.raw_image = raw_alloc;
+ imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch =
+ imgdata.sizes.raw_width * 2;
+ }
+ else if (samples == 3)
+ {
+ imgdata.rawdata.raw_alloc = imgdata.rawdata.color3_image =
+ (ushort(*)[3])raw_alloc;
+ imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch =
+ imgdata.sizes.raw_width * 6;
+ }
+ else if (samples == 4)
+ {
+ imgdata.rawdata.raw_alloc = imgdata.rawdata.color4_image =
+ (ushort(*)[4])raw_alloc;
+ imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch =
+ imgdata.sizes.raw_width * 8;
+ }
+ if(orawalloc)
+ free(orawalloc); // remove old allocation
+ imgdata.rawdata.float_image = 0;
+ imgdata.rawdata.float3_image = 0;
+ imgdata.rawdata.float4_image = 0;
+}
+
+static
+#if (defined(_MSC_VER) && !defined(__clang__))
+_forceinline
+#else
+inline
+#endif
+void swap24(uchar *data, int len)
+{
+ for (int i = 0; i < len - 2; i += 3)
+ {
+ uchar t = data[i];
+ data[i] = data[i + 2];
+ data[i + 2] = t;
+ }
+}
+
+static
+#if (defined(_MSC_VER) && !defined(__clang__))
+_forceinline
+#else
+inline
+#endif
+void swap32(uchar *data, int len)
+{
+ unsigned *d = (unsigned*)data;
+ for (int i = 0; i < len / 4; i++)
+ {
+ unsigned x = d[i];
+ d[i] = (x << 24) + ((x << 8) & 0x00FF0000) +
+ ((x >> 8) & 0x0000FF00) + (x >> 24);
+ }
+}
+
+
+void LibRaw::uncompressed_fp_dng_load_raw()
+{
+ int iifd = find_ifd_by_offset(libraw_internal_data.unpacker_data.data_offset);
+ if (iifd < 0 || iifd > (int)libraw_internal_data.identify_data.tiff_nifds)
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+ struct tiff_ifd_t *ifd = &tiff_ifd[iifd];
+
+ float *float_raw_image = 0;
+
+ if (ifd->samples != 1 && ifd->samples != 3 && ifd->samples != 4)
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+
+ if(imgdata.idata.filters && ifd->samples > 1)
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+
+ if ((int)libraw_internal_data.unpacker_data.tiff_samples != ifd->samples)
+ throw LIBRAW_EXCEPTION_DECODE_RAW; // Wrong IFD
+
+ int bytesps = (ifd->bps + 7) >> 3; // round to upper value
+
+ if(bytesps < 1 || bytesps > 4)
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+
+ tile_stripe_data_t tiles;
+ tiles.init(ifd, imgdata.sizes, libraw_internal_data.unpacker_data, libraw_internal_data.unpacker_data.order,
+ libraw_internal_data.internal_data.input);
+
+ INT64 allocsz = INT64(tiles.tileCnt) * INT64(tiles.tileWidth) * INT64(tiles.tileHeight) * INT64(ifd->samples) * INT64(sizeof(float));
+ if (allocsz > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ if (ifd->sample_format == 3)
+ float_raw_image = (float *)calloc(tiles.tileCnt * tiles.tileWidth * tiles.tileHeight *ifd->samples, sizeof(float));
+ else
+ throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float supported
+
+ bool difford = (libraw_internal_data.unpacker_data.order == 0x4949) == (ntohs(0x1234) == 0x1234);
+ float max = 0.f;
+
+ std::vector<uchar> rowbuf(tiles.tileWidth *sizeof(float) * ifd->samples); // line buffer for last tile in tile row
+
+ for (size_t y = 0, t = 0; y < imgdata.sizes.raw_height; y += tiles.tileHeight)
+ {
+ for (unsigned x = 0; x < imgdata.sizes.raw_width && t < (unsigned)tiles.tileCnt; x += tiles.tileWidth, ++t)
+ {
+ libraw_internal_data.internal_data.input->seek(tiles.tOffsets[t], SEEK_SET);
+ size_t rowsInTile = y + tiles.tileHeight > imgdata.sizes.raw_height ? imgdata.sizes.raw_height - y : tiles.tileHeight;
+ size_t colsInTile = x + tiles.tileWidth > imgdata.sizes.raw_width ? imgdata.sizes.raw_width - x : tiles.tileWidth;
+
+ size_t inrowbytes = colsInTile * bytesps * ifd->samples;
+ int fullrowbytes = tiles.tileWidth *bytesps * ifd->samples;
+ size_t outrowbytes = colsInTile * sizeof(float) * ifd->samples;
+
+ for (size_t row = 0; row < rowsInTile; ++row) // do not process full tile if not needed
+ {
+ unsigned char *dst = fullrowbytes > inrowbytes ? rowbuf.data(): // last tile in row, use buffer
+ (unsigned char *)&float_raw_image
+ [((y + row) * imgdata.sizes.raw_width + x) * ifd->samples];
+ libraw_internal_data.internal_data.input->read(dst, 1, fullrowbytes);
+ if (bytesps == 2 && difford)
+ libraw_swab(dst, fullrowbytes);
+ else if (bytesps == 3 && (libraw_internal_data.unpacker_data.order == 0x4949)) // II-16bit
+ swap24(dst, fullrowbytes);
+ if (bytesps == 4 && difford)
+ swap32(dst, fullrowbytes);
+
+ float lmax = expandFloats(
+ dst,
+ tiles.tileWidth * ifd->samples,
+ bytesps);
+ if (fullrowbytes > inrowbytes) // last tile in row: copy buffer to destination
+ memmove(&float_raw_image[((y + row) * imgdata.sizes.raw_width + x) * ifd->samples], dst, outrowbytes);
+ max = MAX(max, lmax);
+ }
+ }
+ }
+
+ imgdata.color.fmaximum = max;
+
+ // setup outpuf fields
+ imgdata.rawdata.raw_alloc = float_raw_image;
+ if (ifd->samples == 1)
+ {
+ imgdata.rawdata.float_image = float_raw_image;
+ imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch =
+ imgdata.sizes.raw_width * 4;
+ }
+ else if (ifd->samples == 3)
+ {
+ imgdata.rawdata.float3_image = (float(*)[3])float_raw_image;
+ imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch =
+ imgdata.sizes.raw_width * 12;
+ }
+ else if (ifd->samples == 4)
+ {
+ imgdata.rawdata.float4_image = (float(*)[4])float_raw_image;
+ imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch =
+ imgdata.sizes.raw_width * 16;
+ }
+
+ if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT)
+ convertFloatToInt();
+}
diff --git a/libkdcraw/libraw/src/decoders/fuji_compressed.cpp b/libkdcraw/libraw/src/decoders/fuji_compressed.cpp
new file mode 100644
index 0000000..9ca82f6
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/fuji_compressed.cpp
@@ -0,0 +1,1210 @@
+/* -*- C++ -*-
+ * File: libraw_fuji_compressed.cpp
+ * Copyright (C) 2016-2019 Alexey Danilchenko
+ *
+ * Adopted to LibRaw by Alex Tutubalin, [email protected]
+ * LibRaw Fujifilm/compressed decoder
+
+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"
+
+#ifdef _abs
+#undef _abs
+#undef _min
+#undef _max
+#endif
+#define _abs(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
+#define _min(a, b) ((a) < (b) ? (a) : (b))
+#define _max(a, b) ((a) > (b) ? (a) : (b))
+
+struct int_pair
+{
+ int value1;
+ int value2;
+};
+
+enum _xt_lines
+{
+ _R0 = 0,
+ _R1,
+ _R2,
+ _R3,
+ _R4,
+ _G0,
+ _G1,
+ _G2,
+ _G3,
+ _G4,
+ _G5,
+ _G6,
+ _G7,
+ _B0,
+ _B1,
+ _B2,
+ _B3,
+ _B4,
+ _ltotal
+};
+
+// tables of gradients for single sample level
+struct fuji_grads
+{
+ int_pair grads[41];
+ int_pair lossy_grads[3][5];
+};
+
+struct fuji_compressed_block
+{
+ int cur_bit; // current bit being read (from left to right)
+ int cur_pos; // current position in a buffer
+ INT64 cur_buf_offset; // offset of this buffer in a file
+ unsigned max_read_size; // Amount of data to be read
+ int cur_buf_size; // buffer size
+ uchar *cur_buf; // currently read block
+ int fillbytes; // Counter to add extra byte for block size N*16
+ LibRaw_abstract_datastream *input;
+ fuji_grads even[3]; // tables of even gradients
+ fuji_grads odd[3]; // tables of odd gradients
+ ushort *linealloc;
+ ushort *linebuf[_ltotal];
+};
+
+static inline int log2ceil(int val)
+{
+ int result = 0;
+ if (val--)
+ do
+ ++result;
+ while (val >>= 1);
+
+ return result;
+}
+
+void setup_qlut(int8_t *qt, int *q_point)
+{
+ for (int curVal = -q_point[4]; curVal <= q_point[4]; ++qt, ++curVal)
+ {
+ if (curVal <= -q_point[3])
+ *qt = -4;
+ else if (curVal <= -q_point[2])
+ *qt = -3;
+ else if (curVal <= -q_point[1])
+ *qt = -2;
+ else if (curVal < -q_point[0])
+ *qt = -1;
+ else if (curVal <= q_point[0])
+ *qt = 0;
+ else if (curVal < q_point[1])
+ *qt = 1;
+ else if (curVal < q_point[2])
+ *qt = 2;
+ else if (curVal < q_point[3])
+ *qt = 3;
+ else
+ *qt = 4;
+ }
+}
+
+void init_main_qtable(fuji_compressed_params *params, uchar q_base)
+{
+ fuji_q_table *qt = params->qt;
+ int qp[5];
+ int maxVal = params->max_value + 1;
+ qp[0] = q_base;
+ qp[1] = 3 * q_base + 0x12;
+ qp[2] = 5 * q_base + 0x43;
+ qp[3] = 7 * q_base + 0x114;
+ qp[4] = params->max_value;
+ if (qp[1] >= maxVal || qp[1] < q_base + 1)
+ qp[1] = q_base + 1;
+ if (qp[2] < qp[1] || qp[2] >= maxVal)
+ qp[2] = qp[1];
+ if (qp[3] < qp[2] || qp[3] >= maxVal)
+ qp[3] = qp[2];
+ setup_qlut(qt->q_table, qp);
+ qt->q_base = q_base;
+ qt->max_grad = 0;
+ qt->total_values = (qp[4] + 2 * q_base) / (2 * q_base + 1) + 1;
+ qt->raw_bits = log2ceil(qt->total_values);
+ qt->q_grad_mult = 9;
+ params->max_bits = 4 * log2ceil(qp[4] + 1);
+}
+
+void LibRaw::init_fuji_compr(fuji_compressed_params *params)
+{
+ if ((libraw_internal_data.unpacker_data.fuji_block_width % 3 &&
+ libraw_internal_data.unpacker_data.fuji_raw_type == 16) ||
+ (libraw_internal_data.unpacker_data.fuji_block_width & 1 &&
+ libraw_internal_data.unpacker_data.fuji_raw_type == 0))
+ derror();
+
+ size_t q_table_size = 2 << libraw_internal_data.unpacker_data.fuji_bits;
+ if (libraw_internal_data.unpacker_data.fuji_lossless)
+ params->buf = malloc(q_table_size);
+ else
+ params->buf = malloc(3 * q_table_size);
+
+ if (libraw_internal_data.unpacker_data.fuji_raw_type == 16)
+ params->line_width = (libraw_internal_data.unpacker_data.fuji_block_width * 2) / 3;
+ else
+ params->line_width = libraw_internal_data.unpacker_data.fuji_block_width >> 1;
+
+ params->min_value = 0x40;
+ params->max_value = (1 << libraw_internal_data.unpacker_data.fuji_bits) - 1;
+
+ // setup qtables
+ if (libraw_internal_data.unpacker_data.fuji_lossless)
+ {
+ // setup main qtable only, zero the rest
+ memset(params->qt + 1, 0, 3 * sizeof(fuji_q_table));
+ params->qt[0].q_table = (int8_t *)params->buf;
+ params->qt[0].q_base = -1;
+ init_main_qtable(params, 0);
+ }
+ else
+ {
+ // setup 3 extra qtables - main one will be set for each block
+ memset(params->qt, 0, sizeof(fuji_q_table));
+ int qp[5];
+
+ qp[0] = 0;
+ qp[4] = params->max_value;
+
+ // table 0
+ params->qt[1].q_table = (int8_t *)params->buf;
+ params->qt[1].q_base = 0;
+ params->qt[1].max_grad = 5;
+ params->qt[1].q_grad_mult = 3;
+ params->qt[1].total_values = qp[4] + 1;
+ params->qt[1].raw_bits = log2ceil(params->qt[1].total_values);
+
+ qp[1] = qp[4] >= 0x12 ? 0x12 : qp[0] + 1;
+ qp[2] = qp[4] >= 0x43 ? 0x43 : qp[1];
+ qp[3] = qp[4] >= 0x114 ? 0x114 : qp[2];
+ setup_qlut(params->qt[1].q_table, qp);
+
+ // table 1
+ params->qt[2].q_table = params->qt[1].q_table + q_table_size;
+ params->qt[2].q_base = 1;
+ params->qt[2].max_grad = 6;
+ params->qt[2].q_grad_mult = 3;
+ params->qt[2].total_values = (qp[4] + 2) / 3 + 1;
+ params->qt[2].raw_bits = log2ceil(params->qt[2].total_values);
+
+ qp[0] = params->qt[2].q_base;
+ qp[1] = qp[4] >= 0x15 ? 0x15 : qp[0] + 1;
+ qp[2] = qp[4] >= 0x48 ? 0x48 : qp[1];
+ qp[3] = qp[4] >= 0x11B ? 0x11B : qp[2];
+ setup_qlut(params->qt[2].q_table, qp);
+
+ // table 2
+ params->qt[3].q_table = params->qt[2].q_table + q_table_size;
+ params->qt[3].q_base = 2;
+ params->qt[3].max_grad = 7;
+ params->qt[3].q_grad_mult = 3;
+ params->qt[3].total_values = (qp[4] + 4) / 5 + 1;
+ params->qt[3].raw_bits = log2ceil(params->qt[3].total_values);
+
+ qp[0] = params->qt[3].q_base;
+ qp[1] = qp[4] >= 0x18 ? 0x18 : qp[0] + 1;
+ qp[2] = qp[4] >= 0x4D ? 0x4D : qp[1];
+ qp[3] = qp[4] >= 0x122 ? 0x122 : qp[2];
+ setup_qlut(params->qt[3].q_table, qp);
+ }
+}
+
+#define XTRANS_BUF_SIZE 0x10000
+
+static inline void fuji_fill_buffer(fuji_compressed_block *info)
+{
+ if (info->cur_pos >= info->cur_buf_size)
+ {
+ info->cur_pos = 0;
+ info->cur_buf_offset += info->cur_buf_size;
+#ifdef LIBRAW_USE_OPENMP
+#pragma omp critical
+#endif
+ {
+#ifndef LIBRAW_USE_OPENMP
+ info->input->lock();
+#endif
+ info->input->seek(info->cur_buf_offset, SEEK_SET);
+ info->cur_buf_size = info->input->read(info->cur_buf, 1, _min(info->max_read_size, XTRANS_BUF_SIZE));
+#ifndef LIBRAW_USE_OPENMP
+ info->input->unlock();
+#endif
+ if (info->cur_buf_size < 1) // nothing read
+ {
+ if (info->fillbytes > 0)
+ {
+ int ls = _max(1, _min(info->fillbytes, XTRANS_BUF_SIZE));
+ memset(info->cur_buf, 0, ls);
+ info->fillbytes -= ls;
+ }
+ else
+ throw LIBRAW_EXCEPTION_IO_EOF;
+ }
+ info->max_read_size -= info->cur_buf_size;
+ }
+ }
+}
+
+void init_main_grads(const fuji_compressed_params *params, fuji_compressed_block *info)
+{
+ int max_diff = _max(2, (params->qt->total_values + 0x20) >> 6);
+ for (int j = 0; j < 3; j++)
+ for (int i = 0; i < 41; i++)
+ {
+ info->even[j].grads[i].value1 = max_diff;
+ info->even[j].grads[i].value2 = 1;
+ info->odd[j].grads[i].value1 = max_diff;
+ info->odd[j].grads[i].value2 = 1;
+ }
+}
+
+void LibRaw::init_fuji_block(fuji_compressed_block *info, const fuji_compressed_params *params, INT64 raw_offset,
+ unsigned dsize)
+{
+ info->linealloc = (ushort *)calloc(sizeof(ushort), _ltotal * (params->line_width + 2));
+
+ INT64 fsize = libraw_internal_data.internal_data.input->size();
+ info->max_read_size = _min(unsigned(fsize - raw_offset), dsize); // Data size may be incorrect?
+ info->fillbytes = 1;
+
+ info->input = libraw_internal_data.internal_data.input;
+ info->linebuf[_R0] = info->linealloc;
+ for (int i = _R1; i <= _B4; i++)
+ info->linebuf[i] = info->linebuf[i - 1] + params->line_width + 2;
+
+ // init buffer
+ info->cur_buf = (uchar *)malloc(XTRANS_BUF_SIZE);
+ info->cur_bit = 0;
+ info->cur_pos = 0;
+ info->cur_buf_offset = raw_offset;
+ info->cur_buf_size = 0;
+ fuji_fill_buffer(info);
+
+ // init grads for lossy and lossless
+ if (libraw_internal_data.unpacker_data.fuji_lossless)
+ init_main_grads(params, info);
+ else
+ {
+ // init static grads for lossy only - main ones are done per line
+ for (int k = 0; k < 3; ++k)
+ {
+ int max_diff = _max(2, ((params->qt[k + 1].total_values + 0x20) >> 6));
+ for (int j = 0; j < 3; ++j)
+ for (int i = 0; i < 5; ++i)
+ {
+ info->even[j].lossy_grads[k][i].value1 = max_diff;
+ info->even[j].lossy_grads[k][i].value2 = 1;
+ info->odd[j].lossy_grads[k][i].value1 = max_diff;
+ info->odd[j].lossy_grads[k][i].value2 = 1;
+ }
+ }
+ }
+}
+
+void LibRaw::copy_line_to_xtrans(fuji_compressed_block *info, int cur_line, int cur_block, int cur_block_width)
+{
+ ushort *lineBufB[3];
+ ushort *lineBufG[6];
+ ushort *lineBufR[3];
+ unsigned pixel_count;
+ ushort *line_buf;
+ int index;
+
+ int offset = libraw_internal_data.unpacker_data.fuji_block_width * cur_block + 6 * imgdata.sizes.raw_width * cur_line;
+ ushort *raw_block_data = imgdata.rawdata.raw_image + offset;
+ int row_count = 0;
+
+ for (int i = 0; i < 3; i++)
+ {
+ lineBufR[i] = info->linebuf[_R2 + i] + 1;
+ lineBufB[i] = info->linebuf[_B2 + i] + 1;
+ }
+ for (int i = 0; i < 6; i++)
+ lineBufG[i] = info->linebuf[_G2 + i] + 1;
+
+ while (row_count < 6)
+ {
+ pixel_count = 0;
+ while (pixel_count < (unsigned)cur_block_width)
+ {
+ switch (imgdata.idata.xtrans_abs[row_count][(pixel_count % 6)])
+ {
+ case 0: // red
+ line_buf = lineBufR[row_count >> 1];
+ break;
+ case 1: // green
+ default: // to make static analyzer happy
+ line_buf = lineBufG[row_count];
+ break;
+ case 2: // blue
+ line_buf = lineBufB[row_count >> 1];
+ break;
+ }
+
+ index = (((pixel_count * 2 / 3) & 0x7FFFFFFE) | ((pixel_count % 3) & 1)) + ((pixel_count % 3) >> 1);
+ raw_block_data[pixel_count] = line_buf[index];
+
+ ++pixel_count;
+ }
+ ++row_count;
+ raw_block_data += imgdata.sizes.raw_width;
+ }
+}
+
+void LibRaw::copy_line_to_bayer(fuji_compressed_block *info, int cur_line, int cur_block, int cur_block_width)
+{
+ ushort *lineBufB[3];
+ ushort *lineBufG[6];
+ ushort *lineBufR[3];
+ unsigned pixel_count;
+ ushort *line_buf;
+
+ int fuji_bayer[2][2];
+ for (int r = 0; r < 2; r++)
+ for (int c = 0; c < 2; c++)
+ fuji_bayer[r][c] = FC(r, c); // We'll downgrade G2 to G below
+
+ int offset = libraw_internal_data.unpacker_data.fuji_block_width * cur_block + 6 * imgdata.sizes.raw_width * cur_line;
+ ushort *raw_block_data = imgdata.rawdata.raw_image + offset;
+ int row_count = 0;
+
+ for (int i = 0; i < 3; i++)
+ {
+ lineBufR[i] = info->linebuf[_R2 + i] + 1;
+ lineBufB[i] = info->linebuf[_B2 + i] + 1;
+ }
+ for (int i = 0; i < 6; i++)
+ lineBufG[i] = info->linebuf[_G2 + i] + 1;
+
+ while (row_count < 6)
+ {
+ pixel_count = 0;
+ while (pixel_count < (unsigned)cur_block_width)
+ {
+ switch (fuji_bayer[row_count & 1][pixel_count & 1])
+ {
+ case 0: // red
+ line_buf = lineBufR[row_count >> 1];
+ break;
+ case 1: // green
+ case 3: // second green
+ default: // to make static analyzer happy
+ line_buf = lineBufG[row_count];
+ break;
+ case 2: // blue
+ line_buf = lineBufB[row_count >> 1];
+ break;
+ }
+
+ raw_block_data[pixel_count] = line_buf[pixel_count >> 1];
+ ++pixel_count;
+ }
+ ++row_count;
+ raw_block_data += imgdata.sizes.raw_width;
+ }
+}
+
+#define fuji_quant_gradient(max, q, v1, v2) (q->q_grad_mult * q->q_table[(max) + (v1)] + q->q_table[(max) + (v2)])
+
+static inline void fuji_zerobits(fuji_compressed_block *info, int *count)
+{
+ uchar zero = 0;
+ *count = 0;
+ while (zero == 0)
+ {
+ zero = (info->cur_buf[info->cur_pos] >> (7 - info->cur_bit)) & 1;
+ info->cur_bit++;
+ info->cur_bit &= 7;
+ if (!info->cur_bit)
+ {
+ ++info->cur_pos;
+ fuji_fill_buffer(info);
+ }
+ if (zero)
+ break;
+ ++*count;
+ }
+}
+
+static inline void fuji_read_code(fuji_compressed_block *info, int *data, int bits_to_read)
+{
+ uchar bits_left = bits_to_read;
+ uchar bits_left_in_byte = 8 - (info->cur_bit & 7);
+ *data = 0;
+ if (!bits_to_read)
+ return;
+ if (bits_to_read >= bits_left_in_byte)
+ {
+ do
+ {
+ *data <<= bits_left_in_byte;
+ bits_left -= bits_left_in_byte;
+ *data |= info->cur_buf[info->cur_pos] & ((1 << bits_left_in_byte) - 1);
+ ++info->cur_pos;
+ fuji_fill_buffer(info);
+ bits_left_in_byte = 8;
+ } while (bits_left >= 8);
+ }
+ if (!bits_left)
+ {
+ info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7;
+ return;
+ }
+ *data <<= bits_left;
+ bits_left_in_byte -= bits_left;
+ *data |= ((1 << bits_left) - 1) & ((unsigned)info->cur_buf[info->cur_pos] >> bits_left_in_byte);
+ info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7;
+}
+
+static inline int bitDiff(int value1, int value2)
+{
+ int decBits = 0;
+ if (value2 < value1)
+ while (decBits <= 14 && (value2 << ++decBits) < value1)
+ ;
+ return decBits;
+}
+
+static inline int fuji_decode_sample_even(fuji_compressed_block *info, const fuji_compressed_params *params,
+ ushort *line_buf, int pos, fuji_grads *grad_params)
+{
+ int interp_val = 0;
+ // ushort decBits;
+ int errcnt = 0;
+
+ int sample = 0, code = 0;
+ ushort *line_buf_cur = line_buf + pos;
+ int Rb = line_buf_cur[-2 - params->line_width];
+ int Rc = line_buf_cur[-3 - params->line_width];
+ int Rd = line_buf_cur[-1 - params->line_width];
+ int Rf = line_buf_cur[-4 - 2 * params->line_width];
+
+ int grad, gradient, diffRcRb, diffRfRb, diffRdRb;
+
+ diffRcRb = _abs(Rc - Rb);
+ diffRfRb = _abs(Rf - Rb);
+ diffRdRb = _abs(Rd - Rb);
+
+ const fuji_q_table *qt = params->qt;
+ int_pair *grads = grad_params->grads;
+ for (int i = 1; params->qt[0].q_base >= i && i < 4; ++i)
+ if (diffRfRb + diffRcRb <= params->qt[i].max_grad)
+ {
+ qt = params->qt + i;
+ grads = grad_params->lossy_grads[i - 1];
+ break;
+ }
+
+ grad = fuji_quant_gradient(params->max_value, qt, Rb - Rf, Rc - Rb);
+ gradient = _abs(grad);
+
+ if (diffRcRb > diffRfRb && diffRcRb > diffRdRb)
+ interp_val = Rf + Rd + 2 * Rb;
+ else if (diffRdRb > diffRcRb && diffRdRb > diffRfRb)
+ interp_val = Rf + Rc + 2 * Rb;
+ else
+ interp_val = Rd + Rc + 2 * Rb;
+
+ fuji_zerobits(info, &sample);
+
+ if (sample < params->max_bits - qt->raw_bits - 1)
+ {
+ int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2);
+ fuji_read_code(info, &code, decBits);
+ code += sample << decBits;
+ }
+ else
+ {
+ fuji_read_code(info, &code, qt->raw_bits);
+ ++code;
+ }
+
+ if (code < 0 || code >= qt->total_values)
+ ++errcnt;
+
+ if (code & 1)
+ code = -1 - code / 2;
+ else
+ code /= 2;
+
+ grads[gradient].value1 += _abs(code);
+ if (grads[gradient].value2 == params->min_value)
+ {
+ grads[gradient].value1 >>= 1;
+ grads[gradient].value2 >>= 1;
+ }
+ ++grads[gradient].value2;
+ if (grad < 0)
+ interp_val = (interp_val >> 2) - code * (2 * qt->q_base + 1);
+ else
+ interp_val = (interp_val >> 2) + code * (2 * qt->q_base + 1);
+ if (interp_val < -qt->q_base)
+ interp_val += qt->total_values * (2 * qt->q_base + 1);
+ else if (interp_val > qt->q_base + params->max_value)
+ interp_val -= qt->total_values * (2 * qt->q_base + 1);
+
+ if (interp_val >= 0)
+ line_buf_cur[0] = _min(interp_val, params->max_value);
+ else
+ line_buf_cur[0] = 0;
+ return errcnt;
+}
+
+static inline int fuji_decode_sample_odd(fuji_compressed_block *info, const fuji_compressed_params *params,
+ ushort *line_buf, int pos, fuji_grads *grad_params)
+{
+ int interp_val = 0;
+ int errcnt = 0;
+
+ int sample = 0, code = 0;
+ ushort *line_buf_cur = line_buf + pos;
+ int Ra = line_buf_cur[-1];
+ int Rb = line_buf_cur[-2 - params->line_width];
+ int Rc = line_buf_cur[-3 - params->line_width];
+ int Rd = line_buf_cur[-1 - params->line_width];
+ int Rg = line_buf_cur[1];
+
+ int grad, gradient;
+
+ int diffRcRa = _abs(Rc - Ra);
+ int diffRbRc = _abs(Rb - Rc);
+
+ const fuji_q_table *qt = params->qt;
+ int_pair *grads = grad_params->grads;
+ for (int i = 1; params->qt[0].q_base >= i && i < 4; ++i)
+ if (diffRbRc + diffRcRa <= params->qt[i].max_grad)
+ {
+ qt = params->qt + i;
+ grads = grad_params->lossy_grads[i - 1];
+ break;
+ }
+
+ grad = fuji_quant_gradient(params->max_value, qt, Rb - Rc, Rc - Ra);
+ gradient = _abs(grad);
+
+ if ((Rb > Rc && Rb > Rd) || (Rb < Rc && Rb < Rd))
+ interp_val = (Rg + Ra + 2 * Rb) >> 2;
+ else
+ interp_val = (Ra + Rg) >> 1;
+
+ fuji_zerobits(info, &sample);
+
+ if (sample < params->max_bits - qt->raw_bits - 1)
+ {
+ int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2);
+ fuji_read_code(info, &code, decBits);
+ code += sample << decBits;
+ }
+ else
+ {
+ fuji_read_code(info, &code, qt->raw_bits);
+ ++code;
+ }
+
+ if (code < 0 || code >= qt->total_values)
+ ++errcnt;
+
+ if (code & 1)
+ code = -1 - code / 2;
+ else
+ code /= 2;
+
+ grads[gradient].value1 += _abs(code);
+ if (grads[gradient].value2 == params->min_value)
+ {
+ grads[gradient].value1 >>= 1;
+ grads[gradient].value2 >>= 1;
+ }
+ ++grads[gradient].value2;
+ if (grad < 0)
+ interp_val -= code * (2 * qt->q_base + 1);
+ else
+ interp_val += code * (2 * qt->q_base + 1);
+ if (interp_val < -qt->q_base)
+ interp_val += qt->total_values * (2 * qt->q_base + 1);
+ else if (interp_val > qt->q_base + params->max_value)
+ interp_val -= qt->total_values * (2 * qt->q_base + 1);
+
+ if (interp_val >= 0)
+ line_buf_cur[0] = _min(interp_val, params->max_value);
+ else
+ line_buf_cur[0] = 0;
+ return errcnt;
+}
+
+static void fuji_decode_interpolation_even(int line_width, ushort *line_buf, int pos)
+{
+ ushort *line_buf_cur = line_buf + pos;
+ int Rb = line_buf_cur[-2 - line_width];
+ int Rc = line_buf_cur[-3 - line_width];
+ int Rd = line_buf_cur[-1 - line_width];
+ int Rf = line_buf_cur[-4 - 2 * line_width];
+ int diffRcRb = _abs(Rc - Rb);
+ int diffRfRb = _abs(Rf - Rb);
+ int diffRdRb = _abs(Rd - Rb);
+ if (diffRcRb > diffRfRb && diffRcRb > diffRdRb)
+ *line_buf_cur = (Rf + Rd + 2 * Rb) >> 2;
+ else if (diffRdRb > diffRcRb && diffRdRb > diffRfRb)
+ *line_buf_cur = (Rf + Rc + 2 * Rb) >> 2;
+ else
+ *line_buf_cur = (Rd + Rc + 2 * Rb) >> 2;
+}
+
+static void fuji_extend_generic(ushort *linebuf[_ltotal], int line_width, int start, int end)
+{
+ for (int i = start; i <= end; i++)
+ {
+ linebuf[i][0] = linebuf[i - 1][1];
+ linebuf[i][line_width + 1] = linebuf[i - 1][line_width];
+ }
+}
+
+static void fuji_extend_red(ushort *linebuf[_ltotal], int line_width)
+{
+ fuji_extend_generic(linebuf, line_width, _R2, _R4);
+}
+
+static void fuji_extend_green(ushort *linebuf[_ltotal], int line_width)
+{
+ fuji_extend_generic(linebuf, line_width, _G2, _G7);
+}
+
+static void fuji_extend_blue(ushort *linebuf[_ltotal], int line_width)
+{
+ fuji_extend_generic(linebuf, line_width, _B2, _B4);
+}
+
+void LibRaw::xtrans_decode_block(fuji_compressed_block *info, const fuji_compressed_params *params, int /*cur_line*/)
+{
+ int r_even_pos = 0, r_odd_pos = 1;
+ int g_even_pos = 0, g_odd_pos = 1;
+ int b_even_pos = 0, b_odd_pos = 1;
+
+ int errcnt = 0;
+
+ const int line_width = params->line_width;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ fuji_decode_interpolation_even(line_width, info->linebuf[_R2] + 1, r_even_pos);
+ r_even_pos += 2;
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G2] + 1, g_even_pos, &info->even[0]);
+ g_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R2] + 1, r_odd_pos, &info->odd[0]);
+ r_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G2] + 1, g_odd_pos, &info->odd[0]);
+ g_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_red(info->linebuf, line_width);
+ fuji_extend_green(info->linebuf, line_width);
+
+ g_even_pos = 0, g_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G3] + 1, g_even_pos, &info->even[1]);
+ g_even_pos += 2;
+ fuji_decode_interpolation_even(line_width, info->linebuf[_B2] + 1, b_even_pos);
+ b_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G3] + 1, g_odd_pos, &info->odd[1]);
+ g_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B2] + 1, b_odd_pos, &info->odd[1]);
+ b_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_green(info->linebuf, line_width);
+ fuji_extend_blue(info->linebuf, line_width);
+
+ r_even_pos = 0, r_odd_pos = 1;
+ g_even_pos = 0, g_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ if (r_even_pos & 3)
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R3] + 1, r_even_pos, &info->even[2]);
+ else
+ fuji_decode_interpolation_even(line_width, info->linebuf[_R3] + 1, r_even_pos);
+ r_even_pos += 2;
+ fuji_decode_interpolation_even(line_width, info->linebuf[_G4] + 1, g_even_pos);
+ g_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R3] + 1, r_odd_pos, &info->odd[2]);
+ r_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G4] + 1, g_odd_pos, &info->odd[2]);
+ g_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_red(info->linebuf, line_width);
+ fuji_extend_green(info->linebuf, line_width);
+
+ g_even_pos = 0, g_odd_pos = 1;
+ b_even_pos = 0, b_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G5] + 1, g_even_pos, &info->even[0]);
+ g_even_pos += 2;
+ if ((b_even_pos & 3) == 2)
+ fuji_decode_interpolation_even(line_width, info->linebuf[_B3] + 1, b_even_pos);
+ else
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B3] + 1, b_even_pos, &info->even[0]);
+ b_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G5] + 1, g_odd_pos, &info->odd[0]);
+ g_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B3] + 1, b_odd_pos, &info->odd[0]);
+ b_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_green(info->linebuf, line_width);
+ fuji_extend_blue(info->linebuf, line_width);
+
+ r_even_pos = 0, r_odd_pos = 1;
+ g_even_pos = 0, g_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ if ((r_even_pos & 3) == 2)
+ fuji_decode_interpolation_even(line_width, info->linebuf[_R4] + 1, r_even_pos);
+ else
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R4] + 1, r_even_pos, &info->even[1]);
+ r_even_pos += 2;
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G6] + 1, g_even_pos, &info->even[1]);
+ g_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R4] + 1, r_odd_pos, &info->odd[1]);
+ r_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G6] + 1, g_odd_pos, &info->odd[1]);
+ g_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_red(info->linebuf, line_width);
+ fuji_extend_green(info->linebuf, line_width);
+
+ g_even_pos = 0, g_odd_pos = 1;
+ b_even_pos = 0, b_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ fuji_decode_interpolation_even(line_width, info->linebuf[_G7] + 1, g_even_pos);
+ g_even_pos += 2;
+ if (b_even_pos & 3)
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B4] + 1, b_even_pos, &info->even[2]);
+ else
+ fuji_decode_interpolation_even(line_width, info->linebuf[_B4] + 1, b_even_pos);
+ b_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G7] + 1, g_odd_pos, &info->odd[2]);
+ g_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B4] + 1, b_odd_pos, &info->odd[2]);
+ b_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_green(info->linebuf, line_width);
+ fuji_extend_blue(info->linebuf, line_width);
+
+ if (errcnt)
+ derror();
+}
+
+void LibRaw::fuji_bayer_decode_block(fuji_compressed_block *info, const fuji_compressed_params *params, int /*cur_line*/)
+{
+ int r_even_pos = 0, r_odd_pos = 1;
+ int g_even_pos = 0, g_odd_pos = 1;
+ int b_even_pos = 0, b_odd_pos = 1;
+
+ int errcnt = 0;
+
+ const int line_width = params->line_width;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R2] + 1, r_even_pos, &info->even[0]);
+ r_even_pos += 2;
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G2] + 1, g_even_pos, &info->even[0]);
+ g_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R2] + 1, r_odd_pos, &info->odd[0]);
+ r_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G2] + 1, g_odd_pos, &info->odd[0]);
+ g_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_red(info->linebuf, line_width);
+ fuji_extend_green(info->linebuf, line_width);
+
+ g_even_pos = 0, g_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G3] + 1, g_even_pos, &info->even[1]);
+ g_even_pos += 2;
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B2] + 1, b_even_pos, &info->even[1]);
+ b_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G3] + 1, g_odd_pos, &info->odd[1]);
+ g_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B2] + 1, b_odd_pos, &info->odd[1]);
+ b_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_green(info->linebuf, line_width);
+ fuji_extend_blue(info->linebuf, line_width);
+
+ r_even_pos = 0, r_odd_pos = 1;
+ g_even_pos = 0, g_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R3] + 1, r_even_pos, &info->even[2]);
+ r_even_pos += 2;
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G4] + 1, g_even_pos, &info->even[2]);
+ g_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R3] + 1, r_odd_pos, &info->odd[2]);
+ r_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G4] + 1, g_odd_pos, &info->odd[2]);
+ g_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_red(info->linebuf, line_width);
+ fuji_extend_green(info->linebuf, line_width);
+
+ g_even_pos = 0, g_odd_pos = 1;
+ b_even_pos = 0, b_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G5] + 1, g_even_pos, &info->even[0]);
+ g_even_pos += 2;
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B3] + 1, b_even_pos, &info->even[0]);
+ b_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G5] + 1, g_odd_pos, &info->odd[0]);
+ g_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B3] + 1, b_odd_pos, &info->odd[0]);
+ b_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_green(info->linebuf, line_width);
+ fuji_extend_blue(info->linebuf, line_width);
+
+ r_even_pos = 0, r_odd_pos = 1;
+ g_even_pos = 0, g_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R4] + 1, r_even_pos, &info->even[1]);
+ r_even_pos += 2;
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G6] + 1, g_even_pos, &info->even[1]);
+ g_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R4] + 1, r_odd_pos, &info->odd[1]);
+ r_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G6] + 1, g_odd_pos, &info->odd[1]);
+ g_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_red(info->linebuf, line_width);
+ fuji_extend_green(info->linebuf, line_width);
+
+ g_even_pos = 0, g_odd_pos = 1;
+ b_even_pos = 0, b_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width)
+ {
+ if (g_even_pos < line_width)
+ {
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G7] + 1, g_even_pos, &info->even[2]);
+ g_even_pos += 2;
+ errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B4] + 1, b_even_pos, &info->even[2]);
+ b_even_pos += 2;
+ }
+ if (g_even_pos > 8)
+ {
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G7] + 1, g_odd_pos, &info->odd[2]);
+ g_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B4] + 1, b_odd_pos, &info->odd[2]);
+ b_odd_pos += 2;
+ }
+ }
+
+ fuji_extend_green(info->linebuf, line_width);
+ fuji_extend_blue(info->linebuf, line_width);
+
+ if (errcnt)
+ derror();
+}
+
+void LibRaw::fuji_decode_strip(fuji_compressed_params *params, int cur_block, INT64 raw_offset, unsigned dsize,
+ uchar *q_bases)
+{
+ int cur_block_width, cur_line;
+ unsigned line_size;
+ fuji_compressed_block info;
+ fuji_compressed_params *info_common = params;
+
+ if (!libraw_internal_data.unpacker_data.fuji_lossless)
+ {
+ int buf_size = sizeof(fuji_compressed_params) + (2 << libraw_internal_data.unpacker_data.fuji_bits);
+
+ info_common = (fuji_compressed_params *)malloc(buf_size);
+ memcpy(info_common, params, sizeof(fuji_compressed_params));
+ info_common->qt[0].q_table = (int8_t *)(info_common + 1);
+ info_common->qt[0].q_base = -1;
+ }
+ init_fuji_block(&info, info_common, raw_offset, dsize);
+ line_size = sizeof(ushort) * (info_common->line_width + 2);
+
+ cur_block_width = libraw_internal_data.unpacker_data.fuji_block_width;
+ if (cur_block + 1 == libraw_internal_data.unpacker_data.fuji_total_blocks)
+ {
+ cur_block_width = imgdata.sizes.raw_width - (libraw_internal_data.unpacker_data.fuji_block_width * cur_block);
+ /* Old code, may get incorrect results on GFX50, but luckily large optical
+ black cur_block_width = imgdata.sizes.raw_width %
+ libraw_internal_data.unpacker_data.fuji_block_width;
+ */
+ }
+
+ struct i_pair
+ {
+ int a, b;
+ };
+ const i_pair mtable[6] = {{_R0, _R3}, {_R1, _R4}, {_G0, _G6}, {_G1, _G7}, {_B0, _B3}, {_B1, _B4}},
+ ztable[3] = {{_R2, 3}, {_G2, 6}, {_B2, 3}};
+ for (cur_line = 0; cur_line < libraw_internal_data.unpacker_data.fuji_total_lines; cur_line++)
+ {
+ // init grads and main qtable
+ if (!libraw_internal_data.unpacker_data.fuji_lossless)
+ {
+ int q_base = q_bases ? q_bases[cur_line] : 0;
+ if (!cur_line || q_base != info_common->qt[0].q_base)
+ {
+ init_main_qtable(info_common, q_bases[cur_line]);
+ init_main_grads(info_common, &info);
+ }
+ }
+
+ if (libraw_internal_data.unpacker_data.fuji_raw_type == 16)
+ xtrans_decode_block(&info, info_common, cur_line);
+ else
+ fuji_bayer_decode_block(&info, info_common, cur_line);
+
+ // copy data from line buffers and advance
+ for (int i = 0; i < 6; i++)
+ memcpy(info.linebuf[mtable[i].a], info.linebuf[mtable[i].b], line_size);
+
+ if (libraw_internal_data.unpacker_data.fuji_raw_type == 16)
+ copy_line_to_xtrans(&info, cur_line, cur_block, cur_block_width);
+ else
+ copy_line_to_bayer(&info, cur_line, cur_block, cur_block_width);
+
+ for (int i = 0; i < 3; i++)
+ {
+ memset(info.linebuf[ztable[i].a], 0, ztable[i].b * line_size);
+ info.linebuf[ztable[i].a][0] = info.linebuf[ztable[i].a - 1][1];
+ info.linebuf[ztable[i].a][info_common->line_width + 1] = info.linebuf[ztable[i].a - 1][info_common->line_width];
+ }
+ }
+
+ // release data
+ if (!libraw_internal_data.unpacker_data.fuji_lossless)
+ free(info_common);
+ free(info.linealloc);
+ free(info.cur_buf);
+}
+
+void LibRaw::fuji_compressed_load_raw()
+{
+ fuji_compressed_params common_info;
+ int cur_block;
+ unsigned *block_sizes;
+ uchar *q_bases = 0;
+ INT64 raw_offset, *raw_block_offsets;
+
+ init_fuji_compr(&common_info);
+
+ // read block sizes
+ block_sizes = (unsigned *)malloc(sizeof(unsigned) * libraw_internal_data.unpacker_data.fuji_total_blocks);
+ raw_block_offsets = (INT64 *)malloc(sizeof(INT64) * libraw_internal_data.unpacker_data.fuji_total_blocks);
+
+ libraw_internal_data.internal_data.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
+ int sizesToRead = sizeof(unsigned) * libraw_internal_data.unpacker_data.fuji_total_blocks;
+ if (libraw_internal_data.internal_data.input->read(block_sizes, 1, sizesToRead) != sizesToRead)
+ {
+ free(block_sizes);
+ free(raw_block_offsets);
+ throw LIBRAW_EXCEPTION_IO_EOF;
+ }
+
+ raw_offset = ((sizeof(unsigned) * libraw_internal_data.unpacker_data.fuji_total_blocks) + 0xF) & ~0xF;
+
+ // read q bases for lossy
+ if (!libraw_internal_data.unpacker_data.fuji_lossless)
+ {
+ int total_q_bases = libraw_internal_data.unpacker_data.fuji_total_blocks *
+ ((libraw_internal_data.unpacker_data.fuji_total_lines + 0xF) & ~0xF);
+ q_bases = (uchar *)malloc(total_q_bases);
+ libraw_internal_data.internal_data.input->seek(raw_offset + libraw_internal_data.unpacker_data.data_offset,
+ SEEK_SET);
+ libraw_internal_data.internal_data.input->read(q_bases, 1, total_q_bases);
+ raw_offset += total_q_bases;
+ }
+
+ raw_offset += libraw_internal_data.unpacker_data.data_offset;
+
+ // calculating raw block offsets
+ raw_block_offsets[0] = raw_offset;
+ for (cur_block = 0; cur_block < libraw_internal_data.unpacker_data.fuji_total_blocks; cur_block++)
+ {
+ unsigned bsize = sgetn(4, (uchar *)(block_sizes + cur_block));
+ block_sizes[cur_block] = bsize;
+ }
+
+ for (cur_block = 1; cur_block < libraw_internal_data.unpacker_data.fuji_total_blocks; cur_block++)
+ raw_block_offsets[cur_block] = raw_block_offsets[cur_block - 1] + block_sizes[cur_block - 1];
+
+ fuji_decode_loop(&common_info, libraw_internal_data.unpacker_data.fuji_total_blocks, raw_block_offsets, block_sizes,
+ q_bases);
+
+ free(q_bases);
+ free(block_sizes);
+ free(raw_block_offsets);
+ free(common_info.buf);
+}
+
+void LibRaw::fuji_decode_loop(fuji_compressed_params *common_info, int count, INT64 *raw_block_offsets,
+ unsigned *block_sizes, uchar *q_bases)
+{
+ int cur_block;
+ const int lineStep = (libraw_internal_data.unpacker_data.fuji_total_lines + 0xF) & ~0xF;
+#ifdef LIBRAW_USE_OPENMP
+#pragma omp parallel for private(cur_block)
+#endif
+ for (cur_block = 0; cur_block < count; cur_block++)
+ {
+ fuji_decode_strip(common_info, cur_block, raw_block_offsets[cur_block], block_sizes[cur_block],
+ q_bases ? q_bases + cur_block * lineStep : 0);
+ }
+}
+
+void LibRaw::parse_fuji_compressed_header()
+{
+ unsigned signature, lossless, h_raw_type, h_raw_bits, h_raw_height, h_raw_rounded_width, h_raw_width, h_block_size,
+ h_blocks_in_row, h_total_lines;
+
+ uchar header[16];
+
+ libraw_internal_data.internal_data.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
+ if (libraw_internal_data.internal_data.input->read(header, 1, sizeof(header)) != sizeof(header))
+ return;
+
+ // read all header
+ signature = sgetn(2, header);
+ lossless = header[2];
+ h_raw_type = header[3];
+ h_raw_bits = header[4];
+ h_raw_height = sgetn(2, header + 5);
+ h_raw_rounded_width = sgetn(2, header + 7);
+ h_raw_width = sgetn(2, header + 9);
+ h_block_size = sgetn(2, header + 11);
+ h_blocks_in_row = header[13];
+ h_total_lines = sgetn(2, header + 14);
+
+ // general validation
+ if (signature != 0x4953 || lossless > 1 || h_raw_height > 0x4002 || h_raw_height < 6 || h_raw_height % 6 ||
+ h_block_size < 1 || h_raw_width > 0x4200 || h_raw_width < 0x300 || h_raw_width % 24 ||
+ h_raw_rounded_width > 0x4200 || h_raw_rounded_width < h_block_size || h_raw_rounded_width % h_block_size ||
+ h_raw_rounded_width - h_raw_width >= h_block_size || h_block_size != 0x300 || h_blocks_in_row > 0x10 ||
+ h_blocks_in_row == 0 || h_blocks_in_row != h_raw_rounded_width / h_block_size || h_total_lines > 0xAAB ||
+ h_total_lines == 0 || h_total_lines != h_raw_height / 6 ||
+ (h_raw_bits != 12 && h_raw_bits != 14 && h_raw_bits != 16) || (h_raw_type != 16 && h_raw_type != 0))
+ return;
+
+ // modify data
+ libraw_internal_data.unpacker_data.fuji_total_lines = h_total_lines;
+ libraw_internal_data.unpacker_data.fuji_total_blocks = h_blocks_in_row;
+ libraw_internal_data.unpacker_data.fuji_block_width = h_block_size;
+ libraw_internal_data.unpacker_data.fuji_bits = h_raw_bits;
+ libraw_internal_data.unpacker_data.fuji_raw_type = h_raw_type;
+ libraw_internal_data.unpacker_data.fuji_lossless = lossless;
+ imgdata.sizes.raw_width = h_raw_width;
+ imgdata.sizes.raw_height = h_raw_height;
+ libraw_internal_data.unpacker_data.data_offset += 16;
+ load_raw = &LibRaw::fuji_compressed_load_raw;
+}
+
+#undef _abs
+#undef _min
diff --git a/libkdcraw/libraw/src/decoders/generic.cpp b/libkdcraw/libraw/src/decoders/generic.cpp
new file mode 100644
index 0000000..6c521d8
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/generic.cpp
@@ -0,0 +1,101 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::unpacked_load_raw()
+{
+ int row, col, bits = 0;
+ while (1 << ++bits < (int)maximum)
+ ;
+ read_shorts(raw_image, raw_width * raw_height);
+ fseek(ifp, -2, SEEK_CUR); // avoid EOF error
+ if (maximum < 0xffff || load_flags)
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < raw_width; col++)
+ if ((RAW(row, col) >>= load_flags) >> bits &&
+ (unsigned)(row - top_margin) < height &&
+ (unsigned)(col - left_margin) < width)
+ derror();
+ }
+}
+
+void LibRaw::packed_load_raw()
+{
+ int vbits = 0, bwide, rbits, bite, half, irow, row, col, val, i;
+ UINT64 bitbuf = 0;
+
+ bwide = raw_width * tiff_bps / 8;
+ bwide += bwide & load_flags >> 7;
+ rbits = bwide * 8 - raw_width * tiff_bps;
+ if (load_flags & 1)
+ bwide = bwide * 16 / 15;
+ bite = 8 + (load_flags & 24);
+ half = (raw_height + 1) >> 1;
+ for (irow = 0; irow < raw_height; irow++)
+ {
+ checkCancel();
+ row = irow;
+ if (load_flags & 2 && (row = irow % half * 2 + irow / half) == 1 &&
+ load_flags & 4)
+ {
+ if (vbits = 0, tiff_compress)
+ fseek(ifp, data_offset - (-half * bwide & -2048), SEEK_SET);
+ else
+ {
+ fseek(ifp, 0, SEEK_END);
+ fseek(ifp, ftell(ifp) >> 3 << 2, SEEK_SET);
+ }
+ }
+ if (feof(ifp))
+ throw LIBRAW_EXCEPTION_IO_EOF;
+ for (col = 0; col < raw_width; col++)
+ {
+ for (vbits -= tiff_bps; vbits < 0; vbits += bite)
+ {
+ bitbuf <<= bite;
+ for (i = 0; i < bite; i += 8)
+ bitbuf |= (unsigned(fgetc(ifp)) << i);
+ }
+ val = bitbuf << (64 - tiff_bps - vbits) >> (64 - tiff_bps);
+ RAW(row, col ^ (load_flags >> 6 & 1)) = val;
+ if (load_flags & 1 && (col % 10) == 9 && fgetc(ifp) &&
+ row < height + top_margin && col < width + left_margin)
+ derror();
+ }
+ vbits -= rbits;
+ }
+}
+
+void LibRaw::eight_bit_load_raw()
+{
+ unsigned row, col;
+
+ std::vector<uchar> pixel(raw_width);
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ if (fread(pixel.data(), 1, raw_width, ifp) < raw_width)
+ derror();
+ for (col = 0; col < raw_width; col++)
+ RAW(row, col) = curve[pixel[col]];
+ }
+ maximum = curve[0xff];
+}
diff --git a/libkdcraw/libraw/src/decoders/kodak_decoders.cpp b/libkdcraw/libraw/src/decoders/kodak_decoders.cpp
new file mode 100644
index 0000000..e4b1b39
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/kodak_decoders.cpp
@@ -0,0 +1,524 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+#define radc_token(tree) ((signed char)getbithuff(8, huff + (tree) * 256))
+
+#define FORYX \
+ for (y = 1; y < 3; y++) \
+ for (x = col + 1; x >= col; x--)
+
+#define PREDICTOR \
+ (c ? (buf[c][y - 1][x] + buf[c][y][x + 1]) / 2 \
+ : (buf[c][y - 1][x + 1] + 2 * buf[c][y - 1][x] + buf[c][y][x + 1]) / 4)
+
+#ifdef __GNUC__
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+#pragma GCC optimize("no-aggressive-loop-optimizations")
+#endif
+#endif
+
+void LibRaw::kodak_radc_load_raw()
+{
+ // All kodak radc images are 768x512
+ if (width > 768 || raw_width > 768 || height > 512 || raw_height > 512)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ static const signed char src[] = {
+ 1, 1, 2, 3, 3, 4, 4, 2, 5, 7, 6, 5, 7, 6, 7, 8, 1, 0,
+ 2, 1, 3, 3, 4, 4, 5, 2, 6, 7, 7, 6, 8, 5, 8, 8, 2, 1,
+ 2, 3, 3, 0, 3, 2, 3, 4, 4, 6, 5, 5, 6, 7, 6, 8, 2, 0,
+ 2, 1, 2, 3, 3, 2, 4, 4, 5, 6, 6, 7, 7, 5, 7, 8, 2, 1,
+ 2, 4, 3, 0, 3, 2, 3, 3, 4, 7, 5, 5, 6, 6, 6, 8, 2, 3,
+ 3, 1, 3, 2, 3, 4, 3, 5, 3, 6, 4, 7, 5, 0, 5, 8, 2, 3,
+ 2, 6, 3, 0, 3, 1, 4, 4, 4, 5, 4, 7, 5, 2, 5, 8, 2, 4,
+ 2, 7, 3, 3, 3, 6, 4, 1, 4, 2, 4, 5, 5, 0, 5, 8, 2, 6,
+ 3, 1, 3, 3, 3, 5, 3, 7, 3, 8, 4, 0, 5, 2, 5, 4, 2, 0,
+ 2, 1, 3, 2, 3, 3, 4, 4, 4, 5, 5, 6, 5, 7, 4, 8, 1, 0,
+ 2, 2, 2, -2, 1, -3, 1, 3, 2, -17, 2, -5, 2, 5, 2, 17, 2, -7,
+ 2, 2, 2, 9, 2, 18, 2, -18, 2, -9, 2, -2, 2, 7, 2, -28, 2, 28,
+ 3, -49, 3, -9, 3, 9, 4, 49, 5, -79, 5, 79, 2, -1, 2, 13, 2, 26,
+ 3, 39, 4, -16, 5, 55, 6, -37, 6, 76, 2, -26, 2, -13, 2, 1, 3, -39,
+ 4, 16, 5, -55, 6, -76, 6, 37};
+ std::vector<ushort> huff_buffer(19 * 256);
+ ushort* huff = &huff_buffer[0];
+ int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
+ short last[3] = {16, 16, 16}, mul[3], buf[3][3][386];
+ static const ushort pt[] = {0, 0, 1280, 1344, 2320, 3616,
+ 3328, 8000, 4095, 16383, 65535, 16383};
+
+ for (i = 2; i < 12; i += 2)
+ for (c = pt[i - 2]; c <= pt[i]; c++)
+ curve[c] = (float)(c - pt[i - 2]) / (pt[i] - pt[i - 2]) *
+ (pt[i + 1] - pt[i - 1]) +
+ pt[i - 1] + 0.5;
+ for (s = i = 0; i < int(sizeof src); i += 2)
+ FORC(256 >> src[i])
+ ((ushort *)huff)[s++] = src[i] << 8 | (uchar)src[i + 1];
+ s = kodak_cbpp == 243 ? 2 : 3;
+ FORC(256) huff[18 * 256 + c] = (8 - s) << 8 | c >> s << s | 1 << (s - 1);
+ getbits(-1);
+ for (i = 0; i < int(sizeof(buf) / sizeof(short)); i++)
+ ((short *)buf)[i] = 2048;
+ for (row = 0; row < height; row += 4)
+ {
+ checkCancel();
+ FORC3 mul[c] = getbits(6);
+ if (!mul[0] || !mul[1] || !mul[2])
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ FORC3
+ {
+ val = ((0x1000000 / last[c] + 0x7ff) >> 12) * mul[c];
+ s = val > 65564 ? 10 : 12;
+ x = ~((~0u) << (s - 1));
+ val <<= 12 - s;
+ for (i = 0; i < int(sizeof(buf[0]) / sizeof(short)); i++)
+ ((short *)buf[c])[i] = MIN(0x7FFFFFFF, (((short *)buf[c])[i] * static_cast<long long>(val) + x)) >> s;
+ last[c] = mul[c];
+ for (r = 0; r <= int(!c); r++)
+ {
+ buf[c][1][width / 2] = buf[c][2][width / 2] = mul[c] << 7;
+ for (tree = 1, col = width / 2; col > 0;)
+ {
+ if ((tree = radc_token(tree)))
+ {
+ col -= 2;
+ if (col >= 0)
+ {
+ if (tree == 8)
+ FORYX buf[c][y][x] = (uchar)radc_token(18) * mul[c];
+ else
+ FORYX buf[c][y][x] = radc_token(tree + 10) * 16 + PREDICTOR;
+ }
+ }
+ else
+ do
+ {
+ nreps = (col > 2) ? radc_token(9) + 1 : 1;
+ for (rep = 0; rep < 8 && rep < nreps && col > 0; rep++)
+ {
+ col -= 2;
+ if (col >= 0)
+ FORYX buf[c][y][x] = PREDICTOR;
+ if (rep & 1)
+ {
+ step = radc_token(10) << 4;
+ FORYX buf[c][y][x] += step;
+ }
+ }
+ } while (nreps == 9);
+ }
+ for (y = 0; y < 2; y++)
+ for (x = 0; x < width / 2; x++)
+ {
+ val = (buf[c][y + 1][x] << 4) / mul[c];
+ if (val < 0)
+ val = 0;
+ if (c)
+ RAW(row + y * 2 + c - 1, x * 2 + 2 - c) = val;
+ else
+ RAW(row + r * 2 + y, x * 2 + y) = val;
+ }
+ memcpy(buf[c][0] + !c, buf[c][2], sizeof buf[c][0] - 2 * !c);
+ }
+ }
+ for (y = row; y < row + 4; y++)
+ for (x = 0; x < width; x++)
+ if ((x + y) & 1)
+ {
+ r = x ? x - 1 : x + 1;
+ s = x + 1 < width ? x + 1 : x - 1;
+ val = (RAW(y, x) - 2048) * 2 + (RAW(y, r) + RAW(y, s)) / 2;
+ if (val < 0)
+ val = 0;
+ RAW(y, x) = val;
+ }
+ }
+ for (i = 0; i < height * width; i++)
+ raw_image[i] = curve[raw_image[i]];
+ maximum = 0x3fff;
+}
+
+#undef FORYX
+#undef PREDICTOR
+
+#ifdef NO_JPEG
+void LibRaw::kodak_jpeg_load_raw() {}
+#else
+static void jpegErrorExit_k(j_common_ptr /*cinfo*/)
+{
+ throw LIBRAW_EXCEPTION_DECODE_JPEG;
+}
+
+// LibRaw's Kodak_jpeg_load_raw
+void LibRaw::kodak_jpeg_load_raw()
+{
+ if (data_size < 1)
+ throw LIBRAW_EXCEPTION_DECODE_JPEG;
+
+ int row, col;
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr pub;
+ cinfo.err = jpeg_std_error(&pub);
+ pub.error_exit = jpegErrorExit_k;
+
+ if (INT64(data_size) >
+ INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ unsigned char *jpg_buf = (unsigned char *)malloc(data_size);
+ std::vector<uchar> pixel_buf(width * 3);
+ jpeg_create_decompress(&cinfo);
+
+ fread(jpg_buf, data_size, 1, ifp);
+ libraw_swab(jpg_buf, data_size);
+ try
+ {
+ jpeg_mem_src(&cinfo, jpg_buf, data_size);
+ int rc = jpeg_read_header(&cinfo, TRUE);
+ if (rc != 1)
+ throw LIBRAW_EXCEPTION_DECODE_JPEG;
+
+ jpeg_start_decompress(&cinfo);
+ if ((cinfo.output_width != width) || (cinfo.output_height * 2 != height) ||
+ (cinfo.output_components != 3))
+ {
+ throw LIBRAW_EXCEPTION_DECODE_JPEG;
+ }
+
+ unsigned char *buf[1];
+ buf[0] = pixel_buf.data();
+
+ while (cinfo.output_scanline < cinfo.output_height)
+ {
+ checkCancel();
+ row = cinfo.output_scanline * 2;
+ jpeg_read_scanlines(&cinfo, buf, 1);
+ unsigned char(*pixel)[3] = (unsigned char(*)[3])buf[0];
+ for (col = 0; col < width; col += 2)
+ {
+ RAW(row + 0, col + 0) = pixel[col + 0][1] << 1;
+ RAW(row + 1, col + 1) = pixel[col + 1][1] << 1;
+ RAW(row + 0, col + 1) = pixel[col][0] + pixel[col + 1][0];
+ RAW(row + 1, col + 0) = pixel[col][2] + pixel[col + 1][2];
+ }
+ }
+ }
+ catch (...)
+ {
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+ free(jpg_buf);
+ throw;
+ }
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+ free(jpg_buf);
+ maximum = 0xff << 1;
+}
+#endif
+
+void LibRaw::kodak_dc120_load_raw()
+{
+ static const int mul[4] = {162, 192, 187, 92};
+ static const int add[4] = {0, 636, 424, 212};
+ uchar pixel[848];
+ int row, shift, col;
+
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ if (fread(pixel, 1, 848, ifp) < 848)
+ derror();
+ shift = row * mul[row & 3] + add[row & 3];
+ for (col = 0; col < width; col++)
+ RAW(row, col) = (ushort)pixel[(col + shift) % 848];
+ }
+ maximum = 0xff;
+}
+void LibRaw::kodak_c330_load_raw()
+{
+ if (!image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ int row, col, y, cb, cr, rgb[3], c;
+
+ std::vector<uchar> pixel(raw_width*2 + 4);
+
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ if (fread(pixel.data(), raw_width, 2, ifp) < 2)
+ derror();
+ if (load_flags && (row & 31) == 31)
+ fseek(ifp, raw_width * 32, SEEK_CUR);
+ for (col = 0; col < width; col++)
+ {
+ y = pixel[col * 2];
+ cb = pixel[(col * 2 & -4) | 1] - 128;
+ cr = pixel[(col * 2 & -4) | 3] - 128;
+ rgb[1] = y - ((cb + cr + 2) >> 2);
+ rgb[2] = rgb[1] + cb;
+ rgb[0] = rgb[1] + cr;
+ FORC3 image[row * width + col][c] = curve[LIM(rgb[c], 0, 255)];
+ }
+ }
+ maximum = curve[0xff];
+}
+
+void LibRaw::kodak_c603_load_raw()
+{
+ if (!image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ int row, col, y, cb, cr, rgb[3], c;
+
+ std::vector<uchar> pixel(raw_width * 3);
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ if (~row & 1)
+ if (fread(pixel.data(), raw_width, 3, ifp) < 3)
+ derror();
+ for (col = 0; col < width; col++)
+ {
+ y = pixel[width * 2 * (row & 1) + col];
+ cb = pixel[width + (col & -2)] - 128;
+ cr = pixel[width + (col & -2) + 1] - 128;
+ rgb[1] = y - ((cb + cr + 2) >> 2);
+ rgb[2] = rgb[1] + cb;
+ rgb[0] = rgb[1] + cr;
+ FORC3 image[row * width + col][c] = curve[LIM(rgb[c], 0, 255)];
+ }
+ }
+ maximum = curve[0xff];
+}
+
+void LibRaw::kodak_262_load_raw()
+{
+ static const uchar kodak_tree[2][26] = {
+ {0, 1, 5, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+ {0, 3, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
+ ushort *huff[2];
+ int *strip, ns, c, row, col, chess, pi = 0, pi1, pi2, pred, val;
+
+ FORC(2) huff[c] = make_decoder(kodak_tree[c]);
+ ns = (raw_height + 63) >> 5;
+ std::vector<uchar> pixel(raw_width * 32 + ns * 4);
+ strip = (int *)(pixel.data() + raw_width * 32);
+ order = 0x4d4d;
+ FORC(ns) strip[c] = get4();
+ try
+ {
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ if ((row & 31) == 0)
+ {
+ fseek(ifp, strip[row >> 5], SEEK_SET);
+ getbits(-1);
+ pi = 0;
+ }
+ for (col = 0; col < raw_width; col++)
+ {
+ chess = (row + col) & 1;
+ pi1 = chess ? pi - 2 : pi - raw_width - 1;
+ pi2 = chess ? pi - 2 * raw_width : pi - raw_width + 1;
+ if (col <= chess)
+ pi1 = -1;
+ if (pi1 < 0)
+ pi1 = pi2;
+ if (pi2 < 0)
+ pi2 = pi1;
+ if (pi1 < 0 && col > 1)
+ pi1 = pi2 = pi - 2;
+ pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
+ pixel[pi] = val = pred + ljpeg_diff(huff[chess]);
+ if (val >> 8)
+ derror();
+ val = curve[pixel[pi++]];
+ RAW(row, col) = val;
+ }
+ }
+ }
+ catch (...)
+ {
+ FORC(2) free(huff[c]);
+ throw;
+ }
+ FORC(2) free(huff[c]);
+}
+
+int LibRaw::kodak_65000_decode(short *out, int bsize)
+{
+ uchar c, blen[768];
+ ushort raw[6];
+ INT64 bitbuf = 0;
+ int save, bits = 0, i, j, len, diff;
+
+ save = ftell(ifp);
+ bsize = (bsize + 3) & -4;
+ for (i = 0; i < bsize; i += 2)
+ {
+ c = fgetc(ifp);
+ if ((blen[i] = c & 15) > 12 || (blen[i + 1] = c >> 4) > 12)
+ {
+ fseek(ifp, save, SEEK_SET);
+ for (i = 0; i < bsize; i += 8)
+ {
+ read_shorts(raw, 6);
+ out[i] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
+ out[i + 1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
+ for (j = 0; j < 6; j++)
+ out[i + 2 + j] = raw[j] & 0xfff;
+ }
+ return 1;
+ }
+ }
+ if ((bsize & 7) == 4)
+ {
+ bitbuf = fgetc(ifp) << 8;
+ bitbuf += fgetc(ifp);
+ bits = 16;
+ }
+ for (i = 0; i < bsize; i++)
+ {
+ len = blen[i];
+ if (bits < len)
+ {
+ for (j = 0; j < 32; j += 8)
+ bitbuf += (INT64)fgetc(ifp) << (bits + (j ^ 8));
+ bits += 32;
+ }
+ diff = bitbuf & (0xffff >> (16 - len));
+ bitbuf >>= len;
+ bits -= len;
+ if (len > 0 && (diff & (1 << (len - 1))) == 0)
+ diff -= (1 << len) - 1;
+ out[i] = diff;
+ }
+ return 0;
+}
+
+void LibRaw::kodak_65000_load_raw()
+{
+ short buf[272]; /* 264 looks enough */
+ int row, col, len, pred[2], ret, i;
+
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < width; col += 256)
+ {
+ pred[0] = pred[1] = 0;
+ len = MIN(256, width - col);
+ ret = kodak_65000_decode(buf, len);
+ for (i = 0; i < len; i++)
+ {
+ int idx = ret ? buf[i] : (pred[i & 1] += buf[i]);
+ if (idx >= 0 && idx < 0xffff)
+ {
+ if ((RAW(row, col + i) = curve[idx]) >> 12)
+ derror();
+ }
+ else
+ derror();
+ }
+ }
+ }
+}
+
+void LibRaw::kodak_ycbcr_load_raw()
+{
+ if (!image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ short buf[384], *bp;
+ int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
+ ushort *ip;
+
+ unsigned int bits =
+ (load_flags && load_flags > 9 && load_flags < 17) ? load_flags : 10;
+ const int pixels = int(width)*int(height);
+ for (row = 0; row < height; row += 2)
+ {
+ checkCancel();
+ for (col = 0; col < width; col += 128)
+ {
+ len = MIN(128, width - col);
+ kodak_65000_decode(buf, len * 3);
+ y[0][1] = y[1][1] = cb = cr = 0;
+ for (bp = buf, i = 0; i < len; i += 2, bp += 2)
+ {
+ cb += bp[4];
+ cr += bp[5];
+ rgb[1] = -((cb + cr + 2) >> 2);
+ rgb[2] = rgb[1] + cb;
+ rgb[0] = rgb[1] + cr;
+ for (j = 0; j < 2; j++)
+ for (k = 0; k < 2; k++)
+ {
+ if ((y[j][k] = y[j][k ^ 1] + *bp++) >> bits)
+ derror();
+ int indx = (row + j) * width + col + i + k;
+ if(indx>=0 && indx < pixels)
+ {
+ ip = image[indx];
+ FORC3 ip[c] = curve[LIM(y[j][k] + rgb[c], 0, 0xfff)];
+ }
+ }
+ }
+ }
+ }
+}
+
+void LibRaw::kodak_rgb_load_raw()
+{
+ if (!image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ short buf[768], *bp;
+ int row, col, len, c, i, rgb[3], ret;
+ ushort *ip = image[0];
+
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < width; col += 256)
+ {
+ len = MIN(256, width - col);
+ ret = kodak_65000_decode(buf, len * 3);
+ memset(rgb, 0, sizeof rgb);
+ for (bp = buf, i = 0; i < len; i++, ip += 4)
+ if (load_flags == 12)
+ FORC3 ip[c] = ret ? (*bp++) : (rgb[c] += *bp++);
+ else
+ FORC3 if ((ip[c] = ret ? (*bp++) : (rgb[c] += *bp++)) >> 12) derror();
+ }
+ }
+}
+
+void LibRaw::kodak_thumb_load_raw()
+{
+ if (!image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ int row, col;
+ colors = thumb_misc >> 5;
+ for (row = 0; row < height; row++)
+ for (col = 0; col < width; col++)
+ read_shorts(image[row * width + col], colors);
+ maximum = (1 << (thumb_misc & 31)) - 1;
+}
diff --git a/libkdcraw/libraw/src/decoders/load_mfbacks.cpp b/libkdcraw/libraw/src/decoders/load_mfbacks.cpp
new file mode 100644
index 0000000..493c785
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/load_mfbacks.cpp
@@ -0,0 +1,915 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+inline uint32_t abs32(int32_t x)
+{
+ // Branchless version.
+ uint32_t sm = x >> 31;
+ return (uint32_t) ((x + sm) ^ sm);
+}
+
+inline uint32_t min32(uint32_t x, uint32_t y)
+{
+ return x < y ? x : y;
+}
+
+inline uint32_t max32(uint32_t x, uint32_t y)
+{
+ return x > y ? x : y;
+}
+
+inline uint32_t constain32(uint32_t x, uint32_t l, uint32_t u)
+{
+ return x < l ? l : (x > u ? u : x);
+}
+
+int unsigned_cmp(const void *a, const void *b)
+{
+ if (!a || !b)
+ return 0;
+
+ return *(unsigned *)a > *(unsigned *)b ? 1 : (*(unsigned *)a < *(unsigned *)b ? -1 : 0);
+}
+
+int LibRaw::p1rawc(unsigned row, unsigned col, unsigned& count)
+{
+ return (row < raw_height && col < raw_width) ? (++count, RAW(row, col)) : 0;
+}
+
+int LibRaw::p1raw(unsigned row, unsigned col)
+{
+ return (row < raw_height && col < raw_width) ? RAW(row, col) : 0;
+}
+
+
+// DNG SDK version of fixing pixels in bad column using averages sets
+// corrected not to use pixels in the same column
+void LibRaw::phase_one_fix_col_pixel_avg(unsigned row, unsigned col)
+{
+ static const int8_t dir[3][8][2] = {
+ { {-2,-2}, {-2, 2}, {2,-2}, {2, 2}, { 0, 0}, { 0, 0}, {0, 0}, {0, 0} },
+ { {-2,-4}, {-4,-2}, {2,-4}, {4,-2}, {-2, 4}, {-4, 2}, {2, 4}, {4, 2} },
+ { {-4,-4}, {-4, 4}, {4,-4}, {4, 4}, { 0, 0}, { 0, 0}, {0, 0}, {0, 0} } };
+
+ for (int set=0; set < 3; ++set)
+ {
+ uint32_t total = 0;
+ uint32_t count = 0;
+ for (int i = 0; i < 8; ++i)
+ {
+ if (!dir[set][i][0] && !dir[set][i][1])
+ break;
+
+ total += p1rawc(row+dir[set][i][0], col+dir[set][i][1], count);
+ }
+
+ if (count)
+ {
+ RAW(row,col) = (uint16_t)((total + (count >> 1)) / count);
+ break;
+ }
+ }
+}
+
+// DNG SDK version of fixing pixels in bad column using gradient prediction
+void LibRaw::phase_one_fix_pixel_grad(unsigned row, unsigned col)
+{
+ static const int8_t grad_sets[7][12][2] = {
+ { {-4,-2}, { 4, 2}, {-3,-1}, { 1, 1}, {-1,-1}, { 3, 1},
+ {-4,-1}, { 0, 1}, {-2,-1}, { 2, 1}, { 0,-1}, { 4, 1} },
+ { {-2,-2}, { 2, 2}, {-3,-1}, {-1, 1}, {-1,-1}, { 1, 1},
+ { 1,-1}, { 3, 1}, {-2,-1}, { 0, 1}, { 0,-1}, { 2, 1} },
+ { {-2,-4}, { 2, 4}, {-1,-3}, { 1, 1}, {-1,-1}, { 1, 3},
+ {-2,-1}, { 0, 3}, {-1,-2}, { 1, 2}, { 0,-3}, { 2, 1} },
+ { { 0,-2}, { 0, 2}, {-1,-1}, {-1, 1}, { 1,-1}, { 1, 1},
+ {-1,-2}, {-1, 2}, { 0,-1}, { 0,-1}, { 1,-2}, { 1, 2} },
+ { {-2, 4}, { 2,-4}, {-1, 3}, { 1,-1}, {-1, 1}, { 1,-3},
+ {-2, 1}, { 0,-3}, {-1, 2}, { 1,-2}, { 0, 3}, { 2,-1} },
+ { {-2, 2}, { 2,-2}, {-3, 1}, {-1,-1}, {-1, 1}, { 1,-1},
+ { 1, 1}, { 3,-1}, {-2, 1}, { 0,-1}, { 0, 1}, { 2,-1} },
+ { {-4, 2}, { 4,-2}, {-3, 1}, { 1,-1}, {-1, 1}, { 3,-1},
+ {-4, 1}, { 0,-1}, {-2, 1}, { 2,-1}, { 0, 1}, { 4,-1} } };
+
+ uint32_t est[7], grad[7];
+ uint32_t lower = min32(p1raw(row,col-2), p1raw(row, col+2));
+ uint32_t upper = max32(p1raw(row,col-2), p1raw(row, col+2));
+ uint32_t minGrad = 0xFFFFFFFF;
+ for (int i = 0; i<7; ++i)
+ {
+ est[i] = p1raw(row+grad_sets[i][0][0], col+grad_sets[i][0][1]) +
+ p1raw(row+grad_sets[i][1][0], col+grad_sets[i][1][1]);
+ grad[i] = 0;
+ for (int j=0; j<12; j+=2)
+ grad[i] += abs32(p1raw(row+grad_sets[i][j][0], col+grad_sets[i][j][1]) -
+ p1raw(row+grad_sets[i][j+1][0], col+grad_sets[i][j+1][1]));
+ minGrad = min32(minGrad, grad[i]);
+ }
+
+ uint32_t limit = (minGrad * 3) >> 1;
+ uint32_t total = 0;
+ uint32_t count = 0;
+ for (int i = 0; i<7; ++i)
+ if (grad[i] <= limit)
+ {
+ total += est[i];
+ count += 2;
+ }
+ RAW(row, col) = constain32((total + (count >> 1)) / count, lower, upper);
+}
+
+void LibRaw::phase_one_flat_field(int is_float, int nc)
+{
+ ushort head[8];
+ unsigned wide, high, y, x, c, rend, cend, row, col;
+ float *mrow, num, mult[4];
+
+ read_shorts(head, 8);
+ if (head[2] == 0 || head[3] == 0 || head[4] == 0 || head[5] == 0)
+ return;
+ wide = head[2] / head[4] + (head[2] % head[4] != 0);
+ high = head[3] / head[5] + (head[3] % head[5] != 0);
+ mrow = (float *)calloc(nc * wide, sizeof *mrow);
+ for (y = 0; y < high; y++)
+ {
+ checkCancel();
+ for (x = 0; x < wide; x++)
+ for (c = 0; c < (unsigned)nc; c += 2)
+ {
+ num = is_float ? getreal(LIBRAW_EXIFTAG_TYPE_FLOAT) : get2() / 32768.0;
+ if (y == 0)
+ mrow[c * wide + x] = num;
+ else
+ mrow[(c + 1) * wide + x] = (num - mrow[c * wide + x]) / head[5];
+ }
+ if (y == 0)
+ continue;
+ rend = head[1] + y * head[5];
+ for (row = rend - head[5];
+ row < raw_height && row < rend && row < unsigned(head[1] + head[3] - head[5]);
+ row++)
+ {
+ for (x = 1; x < wide; x++)
+ {
+ for (c = 0; c < (unsigned)nc; c += 2)
+ {
+ mult[c] = mrow[c * wide + x - 1];
+ mult[c + 1] = (mrow[c * wide + x] - mult[c]) / head[4];
+ }
+ cend = head[0] + x * head[4];
+ for (col = cend - head[4];
+ col < raw_width && col < cend && col < unsigned(head[0] + head[2] - head[4]);
+ col++)
+ {
+ c = nc > 2 ? FC(row - top_margin, col - left_margin) : 0;
+ if (!(c & 1))
+ {
+ c = RAW(row, col) * mult[c];
+ RAW(row, col) = LIM(c, 0, 65535);
+ }
+ for (c = 0; c < (unsigned)nc; c += 2)
+ mult[c] += mult[c + 1];
+ }
+ }
+ for (x = 0; x < wide; x++)
+ for (c = 0; c < (unsigned)nc; c += 2)
+ mrow[c * wide + x] += mrow[(c + 1) * wide + x];
+ }
+ }
+ free(mrow);
+}
+
+int LibRaw::phase_one_correct()
+{
+ unsigned entries, tag, data, save, col, row, type;
+ int len, i, j, k, cip, sum;
+#if 0
+ int val[4], dev[4], max;
+#endif
+ int head[9], diff, mindiff = INT_MAX, off_412 = 0;
+ /* static */ const signed char dir[12][2] = {
+ {-1, -1}, {-1, 1}, {1, -1}, {1, 1}, {-2, 0}, {0, -2},
+ {0, 2}, {2, 0}, {-2, -2}, {-2, 2}, {2, -2}, {2, 2}};
+ float poly[8], num, cfrac, frac, mult[2], *yval[2] = {NULL, NULL};
+ ushort *xval[2];
+ int qmult_applied = 0, qlin_applied = 0;
+ std::vector<unsigned> badCols;
+
+ if (!meta_length)
+ return 0;
+ fseek(ifp, meta_offset, SEEK_SET);
+ order = get2();
+ fseek(ifp, 6, SEEK_CUR);
+ fseek(ifp, meta_offset + get4(), SEEK_SET);
+ entries = get4();
+ get4();
+
+ try
+ {
+ while (entries--)
+ {
+ checkCancel();
+ tag = get4();
+ len = get4();
+ data = get4();
+ save = ftell(ifp);
+ fseek(ifp, meta_offset + data, SEEK_SET);
+#if 1
+ if (ifp->eof())
+ {
+ // skip bad or unknown tag
+ fseek(ifp, save, SEEK_SET);
+ continue;
+ }
+#endif
+ if (tag == 0x0400)
+ { /* Sensor defects */
+ while ((len -= 8) >= 0)
+ {
+ col = get2();
+ row = get2();
+ type = get2();
+ get2();
+ if (col >= raw_width)
+ continue;
+ if (type == 131 || type == 137) /* Bad column */
+#if 0
+ // Original code by Dave Coffin - it works better by
+ // not employing special logic for G1 channel below.
+ // Alternatively this column remap (including G1 channel
+ // logic) should be called prior to black subtraction
+ // unlike other corrections
+ for (row = 0; row < raw_height; row++)
+ {
+ if (FC(row - top_margin, col - left_margin)==1)
+ {
+ for (sum = i = 0; i < 4; i++)
+ sum += val[i] = p1raw(row + dir[i][0], col + dir[i][1]);
+ for (max = i = 0; i < 4; i++)
+ {
+ dev[i] = abs((val[i] << 2) - sum);
+ if (dev[max] < dev[i])
+ max = i;
+ }
+ RAW(row, col) = (sum - val[max]) / 3.0 + 0.5;
+ }
+ else
+ {
+ for (sum = 0, i = 8; i < 12; i++)
+ sum += p1raw(row + dir[i][0], col + dir[i][1]);
+ RAW(row, col) =
+ 0.5 + sum * 0.0732233 +
+ (p1raw(row, col - 2) + p1raw(row, col + 2)) * 0.3535534;
+ }
+ }
+#else
+ // accumulae bad columns to be sorted later
+ badCols.push_back(col);
+#endif
+ else if (type == 129)
+ { /* Bad pixel */
+ if (row >= raw_height)
+ continue;
+ j = (FC(row - top_margin, col - left_margin) != 1) * 4;
+ unsigned count = 0;
+ for (sum = 0, i = j; i < j + 8; i++)
+ sum += p1rawc(row + dir[i][0], col + dir[i][1], count);
+ if (count)
+ RAW(row, col) = (sum + (count >> 1)) / count;
+ }
+ }
+ }
+ else if (tag == 0x0419)
+ { /* Polynomial curve - output calibraion */
+ for (get4(), i = 0; i < 8; i++)
+ poly[i] = getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1;
+ for (i = 0; i < 0x10000; i++)
+ {
+ num = (poly[5] * i + poly[3]) * i + poly[1];
+ curve[i] = LIM(num, 0, 65535);
+ }
+ goto apply; /* apply to right half */
+ }
+ else if (tag == 0x041a)
+ { /* Polynomial curve */
+ for (i = 0; i < 4; i++)
+ poly[i] = getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ for (i = 0; i < 0x10000; i++)
+ {
+ for (num = 0, j = 4; j--;)
+ num = num * i + poly[j];
+ curve[i] = LIM(num + i, 0, 65535);
+ }
+ apply: /* apply to whole image */
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ for (col = (tag & 1) * ph1.split_col; col < raw_width; col++)
+ RAW(row, col) = curve[RAW(row, col)];
+ }
+ }
+ else if (tag == 0x0401)
+ { /* All-color flat fields - luma calibration*/
+ phase_one_flat_field(1, 2);
+ }
+ else if (tag == 0x0416 || tag == 0x0410)
+ {
+ // 0x410 - luma calibration
+ phase_one_flat_field(0, 2);
+ }
+ else if (tag == 0x040b)
+ { /* Red+blue flat field - croma calibration */
+ phase_one_flat_field(0, 4);
+ }
+ else if (tag == 0x0412)
+ {
+ fseek(ifp, 36, SEEK_CUR);
+ diff = abs(get2() - ph1.tag_21a);
+ if (mindiff > diff)
+ {
+ mindiff = diff;
+ off_412 = ftell(ifp) - 38;
+ }
+ }
+ else if (tag == 0x041f && !qlin_applied)
+ { /* Quadrant linearization */
+ ushort lc[2][2][16], ref[16];
+ int qr, qc;
+ for (qr = 0; qr < 2; qr++)
+ for (qc = 0; qc < 2; qc++)
+ for (i = 0; i < 16; i++)
+ lc[qr][qc][i] = get4();
+ for (i = 0; i < 16; i++)
+ {
+ int v = 0;
+ for (qr = 0; qr < 2; qr++)
+ for (qc = 0; qc < 2; qc++)
+ v += lc[qr][qc][i];
+ ref[i] = (v + 2) >> 2;
+ }
+ for (qr = 0; qr < 2; qr++)
+ {
+ for (qc = 0; qc < 2; qc++)
+ {
+ int cx[19], cf[19];
+ for (i = 0; i < 16; i++)
+ {
+ cx[1 + i] = lc[qr][qc][i];
+ cf[1 + i] = ref[i];
+ }
+ cx[0] = cf[0] = 0;
+ cx[17] = cf[17] = ((unsigned int)ref[15] * 65535) / lc[qr][qc][15];
+ cf[18] = cx[18] = 65535;
+ cubic_spline(cx, cf, 19);
+
+ for (row = (qr ? ph1.split_row : 0);
+ row < unsigned(qr ? raw_height : ph1.split_row); row++)
+ {
+ checkCancel();
+ for (col = (qc ? ph1.split_col : 0);
+ col < unsigned(qc ? raw_width : ph1.split_col); col++)
+ RAW(row, col) = curve[RAW(row, col)];
+ }
+ }
+ }
+ qlin_applied = 1;
+ }
+ else if (tag == 0x041e && !qmult_applied)
+ { /* Quadrant multipliers - output calibraion */
+ float qmult[2][2] = {{1, 1}, {1, 1}};
+ get4();
+ get4();
+ get4();
+ get4();
+ qmult[0][0] = 1.0 + getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ get4();
+ get4();
+ get4();
+ get4();
+ get4();
+ qmult[0][1] = 1.0 + getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ get4();
+ get4();
+ get4();
+ qmult[1][0] = 1.0 + getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ get4();
+ get4();
+ get4();
+ qmult[1][1] = 1.0 + getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < raw_width; col++)
+ {
+ i = qmult[row >= (unsigned)ph1.split_row][col >= (unsigned)ph1.split_col] *
+ RAW(row, col);
+ RAW(row, col) = LIM(i, 0, 65535);
+ }
+ }
+ qmult_applied = 1;
+ }
+ else if (tag == 0x0431 && !qmult_applied)
+ { /* Quadrant combined - four tile gain calibration */
+ ushort lc[2][2][7], ref[7];
+ int qr, qc;
+ for (i = 0; i < 7; i++)
+ ref[i] = get4();
+ for (qr = 0; qr < 2; qr++)
+ for (qc = 0; qc < 2; qc++)
+ for (i = 0; i < 7; i++)
+ lc[qr][qc][i] = get4();
+ for (qr = 0; qr < 2; qr++)
+ {
+ for (qc = 0; qc < 2; qc++)
+ {
+ int cx[9], cf[9];
+ for (i = 0; i < 7; i++)
+ {
+ cx[1 + i] = ref[i];
+ cf[1 + i] = ((unsigned)ref[i] * lc[qr][qc][i]) / 10000;
+ }
+ cx[0] = cf[0] = 0;
+ cx[8] = cf[8] = 65535;
+ cubic_spline(cx, cf, 9);
+ for (row = (qr ? ph1.split_row : 0);
+ row < unsigned(qr ? raw_height : ph1.split_row); row++)
+ {
+ checkCancel();
+ for (col = (qc ? ph1.split_col : 0);
+ col < unsigned(qc ? raw_width : ph1.split_col); col++)
+ RAW(row, col) = curve[RAW(row, col)];
+ }
+ }
+ }
+ qmult_applied = 1;
+ qlin_applied = 1;
+ }
+ fseek(ifp, save, SEEK_SET);
+ }
+ if (!badCols.empty())
+ {
+ qsort(badCols.data(), badCols.size(), sizeof(unsigned), unsigned_cmp);
+ bool prevIsolated = true;
+ for (i = 0; i < (int)badCols.size(); ++i)
+ {
+ bool nextIsolated = i == ((int)(badCols.size()-1)) || badCols[i+1]>badCols[i]+4;
+ for (row = 0; row < raw_height; ++row)
+ if (prevIsolated && nextIsolated)
+ phase_one_fix_pixel_grad(row,badCols[i]);
+ else
+ phase_one_fix_col_pixel_avg(row,badCols[i]);
+ prevIsolated = nextIsolated;
+ }
+ }
+ if (off_412)
+ {
+ fseek(ifp, off_412, SEEK_SET);
+ for (i = 0; i < 9; i++)
+ head[i] = get4() & 0x7fff;
+ yval[0] = (float *)calloc(head[1] * head[3] + head[2] * head[4], 6);
+ yval[1] = (float *)(yval[0] + head[1] * head[3]);
+ xval[0] = (ushort *)(yval[1] + head[2] * head[4]);
+ xval[1] = (ushort *)(xval[0] + head[1] * head[3]);
+ get2();
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < head[i + 1] * head[i + 3]; j++)
+ yval[i][j] = getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < head[i + 1] * head[i + 3]; j++)
+ xval[i][j] = get2();
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ for (col = 0; col < raw_width; col++)
+ {
+ cfrac = (float)col * head[3] / raw_width;
+ cfrac -= cip = cfrac;
+ num = RAW(row, col) * 0.5;
+ for (i = cip; i < cip + 2; i++)
+ {
+ for (k = j = 0; j < head[1]; j++)
+ if (num < xval[0][k = head[1] * i + j])
+ break;
+ frac = (j == 0 || j == head[1])
+ ? 0
+ : (xval[0][k] - num) / (xval[0][k] - xval[0][k - 1]);
+ mult[i - cip] = yval[0][k - 1] * frac + yval[0][k] * (1 - frac);
+ }
+ i = ((mult[0] * (1 - cfrac) + mult[1] * cfrac) * row + num) * 2;
+ RAW(row, col) = LIM(i, 0, 65535);
+ }
+ }
+ free(yval[0]);
+ }
+ }
+ catch (...)
+ {
+ if (yval[0])
+ free(yval[0]);
+ return LIBRAW_CANCELLED_BY_CALLBACK;
+ }
+ return 0;
+}
+
+void LibRaw::phase_one_load_raw()
+{
+ int a, b, i;
+ ushort akey, bkey, t_mask;
+
+ fseek(ifp, ph1.key_off, SEEK_SET);
+ akey = get2();
+ bkey = get2();
+ t_mask = ph1.format == 1 ? 0x5555 : 0x1354;
+ if (ph1.black_col || ph1.black_row)
+ {
+ imgdata.rawdata.ph1_cblack =
+ (short(*)[2])calloc(raw_height * 2, sizeof(ushort));
+ imgdata.rawdata.ph1_rblack =
+ (short(*)[2])calloc(raw_width * 2, sizeof(ushort));
+ if (ph1.black_col)
+ {
+ fseek(ifp, ph1.black_col, SEEK_SET);
+ read_shorts((ushort *)imgdata.rawdata.ph1_cblack[0], raw_height * 2);
+ }
+ if (ph1.black_row)
+ {
+ fseek(ifp, ph1.black_row, SEEK_SET);
+ read_shorts((ushort *)imgdata.rawdata.ph1_rblack[0], raw_width * 2);
+ }
+ }
+ fseek(ifp, data_offset, SEEK_SET);
+ read_shorts(raw_image, raw_width * raw_height);
+ if (ph1.format)
+ for (i = 0; i < raw_width * raw_height; i += 2)
+ {
+ a = raw_image[i + 0] ^ akey;
+ b = raw_image[i + 1] ^ bkey;
+ raw_image[i + 0] = (a & t_mask) | (b & ~t_mask);
+ raw_image[i + 1] = (b & t_mask) | (a & ~t_mask);
+ }
+}
+
+unsigned LibRaw::ph1_bithuff(int nbits, ushort *huff)
+{
+#ifndef LIBRAW_NOTHREADS
+#define bitbuf tls->ph1_bits.bitbuf
+#define vbits tls->ph1_bits.vbits
+#else
+ static UINT64 bitbuf = 0;
+ static int vbits = 0;
+#endif
+ unsigned c;
+
+ if (nbits == -1)
+ return bitbuf = vbits = 0;
+ if (nbits == 0)
+ return 0;
+ if (vbits < nbits)
+ {
+ bitbuf = bitbuf << 32 | get4();
+ vbits += 32;
+ }
+ c = bitbuf << (64 - vbits) >> (64 - nbits);
+ if (huff)
+ {
+ vbits -= huff[c] >> 8;
+ return (uchar)huff[c];
+ }
+ vbits -= nbits;
+ return c;
+#ifndef LIBRAW_NOTHREADS
+#undef bitbuf
+#undef vbits
+#endif
+}
+
+void LibRaw::phase_one_load_raw_c()
+{
+ static const int length[] = {8, 7, 6, 9, 11, 10, 5, 12, 14, 13};
+ int *offset, len[2], pred[2], row, col, i, j;
+ ushort *pixel;
+ short(*c_black)[2], (*r_black)[2];
+ if (ph1.format == 6)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ pixel = (ushort *)calloc(raw_width * 3 + raw_height * 4, 2);
+ offset = (int *)(pixel + raw_width);
+ fseek(ifp, strip_offset, SEEK_SET);
+ for (row = 0; row < raw_height; row++)
+ offset[row] = get4();
+ c_black = (short(*)[2])(offset + raw_height);
+ fseek(ifp, ph1.black_col, SEEK_SET);
+ if (ph1.black_col)
+ read_shorts((ushort *)c_black[0], raw_height * 2);
+ r_black = c_black + raw_height;
+ fseek(ifp, ph1.black_row, SEEK_SET);
+ if (ph1.black_row)
+ read_shorts((ushort *)r_black[0], raw_width * 2);
+
+ // Copy data to internal copy (ever if not read)
+ if (ph1.black_col || ph1.black_row)
+ {
+ imgdata.rawdata.ph1_cblack =
+ (short(*)[2])calloc(raw_height * 2, sizeof(ushort));
+ memmove(imgdata.rawdata.ph1_cblack, (ushort *)c_black[0],
+ raw_height * 2 * sizeof(ushort));
+ imgdata.rawdata.ph1_rblack =
+ (short(*)[2])calloc(raw_width * 2, sizeof(ushort));
+ memmove(imgdata.rawdata.ph1_rblack, (ushort *)r_black[0],
+ raw_width * 2 * sizeof(ushort));
+ }
+
+ for (i = 0; i < 256; i++)
+ curve[i] = i * i / 3.969 + 0.5;
+ try
+ {
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ fseek(ifp, data_offset + offset[row], SEEK_SET);
+ ph1_bits(-1);
+ pred[0] = pred[1] = 0;
+ for (col = 0; col < raw_width; col++)
+ {
+ if (col >= (raw_width & -8))
+ len[0] = len[1] = 14;
+ else if ((col & 7) == 0)
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 5 && !ph1_bits(1); j++)
+ ;
+ if (j--)
+ len[i] = length[j * 2 + ph1_bits(1)];
+ }
+ if ((i = len[col & 1]) == 14)
+ pixel[col] = pred[col & 1] = ph1_bits(16);
+ else
+ pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1));
+ if (pred[col & 1] >> 16)
+ derror();
+ if (ph1.format == 5 && pixel[col] < 256)
+ pixel[col] = curve[pixel[col]];
+ }
+ if (ph1.format == 8)
+ memmove(&RAW(row, 0), &pixel[0], raw_width * 2);
+ else
+ for (col = 0; col < raw_width; col++)
+ RAW(row, col) = pixel[col] << 2;
+ }
+ }
+ catch (...)
+ {
+ free(pixel);
+ throw;
+ }
+ free(pixel);
+ maximum = 0xfffc - ph1.t_black;
+}
+
+void LibRaw::hasselblad_load_raw()
+{
+ struct jhead jh;
+ int shot, row, col, *back[5]={0,0,0,0,0},
+ len[2], diff[12], pred, sh, f, c;
+ unsigned s;
+ unsigned upix, urow, ucol;
+ ushort *ip;
+
+ if (!ljpeg_start(&jh, 0))
+ return;
+ order = 0x4949;
+ ph1_bits(-1);
+ try
+ {
+ back[4] = (int *)calloc(raw_width, 3 * sizeof **back);
+ FORC3 back[c] = back[4] + c * raw_width;
+ cblack[6] >>= sh = tiff_samples > 1;
+ shot = LIM(shot_select, 1, tiff_samples) - 1;
+ for (row = 0; row < raw_height; row++)
+ {
+ checkCancel();
+ FORC4 back[(c + 3) & 3] = back[c];
+ for (col = 0; col < raw_width; col += 2)
+ {
+ for (s = 0; s < tiff_samples * 2; s += 2)
+ {
+ FORC(2) len[c] = ph1_huff(jh.huff[0]);
+ FORC(2)
+ {
+ diff[s + c] = ph1_bits(len[c]);
+ if (len[c] > 0 && (diff[s + c] & (1 << (len[c] - 1))) == 0)
+ diff[s + c] -= (1 << len[c]) - 1;
+ if (diff[s + c] == 65535)
+ diff[s + c] = -32768;
+ }
+ }
+ for (s = col; s < unsigned(col + 2); s++)
+ {
+ pred = 0x8000 + load_flags;
+ if (col)
+ pred = back[2][s - 2];
+ if (col && row > 1)
+ switch (jh.psv)
+ {
+ case 11:
+ pred += back[0][s] / 2 - back[0][s - 2] / 2;
+ break;
+ }
+ f = (row & 1) * 3 ^ ((col + s) & 1);
+ FORC(int(tiff_samples))
+ {
+ pred += diff[(s & 1) * tiff_samples + c];
+ upix = pred >> sh & 0xffff;
+ if (raw_image && c == shot)
+ RAW(row, s) = upix;
+ if (image)
+ {
+ urow = row - top_margin + (c & 1);
+ ucol = col - left_margin - ((c >> 1) & 1);
+ ip = &image[urow * width + ucol][f];
+ if (urow < height && ucol < width)
+ *ip = c < 4 ? upix : (*ip + upix) >> 1;
+ }
+ }
+ back[2][s] = pred;
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ if(back[4])
+ free(back[4]);
+ ljpeg_end(&jh);
+ throw;
+ }
+ if(back[4])
+ free(back[4]);
+ ljpeg_end(&jh);
+ if (image)
+ mix_green = 1;
+}
+
+void LibRaw::leaf_hdr_load_raw()
+{
+ ushort *pixel = 0;
+ unsigned tile = 0, r, c, row, col;
+
+ if (!filters || !raw_image)
+ {
+ if (!image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ pixel = (ushort *)calloc(raw_width, sizeof *pixel);
+ }
+ try
+ {
+ FORC(tiff_samples)
+ for (r = 0; r < raw_height; r++)
+ {
+ checkCancel();
+ if (r % tile_length == 0)
+ {
+ fseek(ifp, data_offset + 4 * tile++, SEEK_SET);
+ fseek(ifp, get4(), SEEK_SET);
+ }
+ if (filters && c != shot_select)
+ continue;
+ if (filters && raw_image)
+ pixel = raw_image + r * raw_width;
+ read_shorts(pixel, raw_width);
+ if (!filters && image && (row = r - top_margin) < height)
+ for (col = 0; col < width && col + left_margin < raw_width; col++)
+ image[row * width + col][c] = pixel[col + left_margin];
+ }
+ }
+ catch (...)
+ {
+ if (!filters)
+ free(pixel);
+ throw;
+ }
+ if (!filters)
+ {
+ maximum = 0xffff;
+ raw_color = 1;
+ free(pixel);
+ }
+}
+
+void LibRaw::unpacked_load_raw_FujiDBP()
+/*
+for Fuji DBP for GX680, aka DX-2000
+ DBP_tile_width = 688;
+ DBP_tile_height = 3856;
+ DBP_n_tiles = 8;
+*/
+{
+ int scan_line, tile_n;
+ int nTiles;
+
+ nTiles = 8;
+ tile_width = raw_width / nTiles;
+
+ ushort *tile;
+ tile = (ushort *)calloc(raw_height, tile_width * 2);
+
+ for (tile_n = 0; tile_n < nTiles; tile_n++)
+ {
+ read_shorts(tile, tile_width * raw_height);
+ for (scan_line = 0; scan_line < raw_height; scan_line++)
+ {
+ memcpy(&raw_image[scan_line * raw_width + tile_n * tile_width],
+ &tile[scan_line * tile_width], tile_width * 2);
+ }
+ }
+ free(tile);
+ fseek(ifp, -2, SEEK_CUR); // avoid EOF error
+}
+
+void LibRaw::sinar_4shot_load_raw()
+{
+ ushort *pixel;
+ unsigned shot, row, col, r, c;
+
+ if (raw_image)
+ {
+ shot = LIM(shot_select, 1, 4) - 1;
+ fseek(ifp, data_offset + shot * 4, SEEK_SET);
+ fseek(ifp, get4(), SEEK_SET);
+ unpacked_load_raw();
+ return;
+ }
+ if (!image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ pixel = (ushort *)calloc(raw_width, sizeof *pixel);
+ try
+ {
+ for (shot = 0; shot < 4; shot++)
+ {
+ checkCancel();
+ fseek(ifp, data_offset + shot * 4, SEEK_SET);
+ fseek(ifp, get4(), SEEK_SET);
+ for (row = 0; row < raw_height; row++)
+ {
+ read_shorts(pixel, raw_width);
+ if ((r = row - top_margin - (shot >> 1 & 1)) >= height)
+ continue;
+ for (col = 0; col < raw_width; col++)
+ {
+ if ((c = col - left_margin - (shot & 1)) >= width)
+ continue;
+ image[r * width + c][(row & 1) * 3 ^ (~col & 1)] = pixel[col];
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ free(pixel);
+ throw;
+ }
+ free(pixel);
+ mix_green = 1;
+}
+
+void LibRaw::imacon_full_load_raw()
+{
+ if (!image)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ int row, col;
+
+ unsigned short *buf =
+ (unsigned short *)malloc(width * 3 * sizeof(unsigned short));
+
+ for (row = 0; row < height; row++)
+ {
+ checkCancel();
+ read_shorts(buf, width * 3);
+ unsigned short(*rowp)[4] = &image[row * width];
+ for (col = 0; col < width; col++)
+ {
+ rowp[col][0] = buf[col * 3];
+ rowp[col][1] = buf[col * 3 + 1];
+ rowp[col][2] = buf[col * 3 + 2];
+ rowp[col][3] = 0;
+ }
+ }
+ free(buf);
+}
diff --git a/libkdcraw/libraw/src/decoders/smal.cpp b/libkdcraw/libraw/src/decoders/smal.cpp
new file mode 100644
index 0000000..2e54990
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/smal.cpp
@@ -0,0 +1,181 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+#define HOLE(row) ((holes >> (((row)-raw_height) & 7)) & 1)
+
+/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
+void LibRaw::smal_decode_segment(unsigned seg[2][2], int holes)
+{
+ uchar hist[3][13] = {{7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0},
+ {7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0},
+ {3, 3, 0, 0, 63, 47, 31, 15, 0}};
+ int low, high = 0xff, carry = 0, nbits = 8;
+ int s, count, bin, next, i, sym[3];
+ unsigned pix;
+ uchar diff, pred[] = {0, 0};
+ ushort data = 0, range = 0;
+
+ fseek(ifp, seg[0][1] + 1, SEEK_SET);
+ getbits(-1);
+ if (seg[1][0] > unsigned(raw_width * raw_height))
+ seg[1][0] = raw_width * raw_height;
+ for (pix = seg[0][0]; pix < seg[1][0]; pix++)
+ {
+ for (s = 0; s < 3; s++)
+ {
+ data = data << nbits | getbits(nbits);
+ if (carry < 0)
+ carry = (nbits += carry + 1) < 1 ? nbits - 1 : 0;
+ while (--nbits >= 0)
+ if ((data >> nbits & 0xff) == 0xff)
+ break;
+ if (nbits > 0)
+ data =
+ ((data & ((1 << (nbits - 1)) - 1)) << 1) |
+ ((data + (((data & (1 << (nbits - 1)))) << 1)) & ((~0u) << nbits));
+ if (nbits >= 0)
+ {
+ data += getbits(1);
+ carry = nbits - 8;
+ }
+ count = ((((data - range + 1) & 0xffff) << 2) - 1) / (high >> 4);
+ for (bin = 0; hist[s][bin + 5] > count; bin++)
+ ;
+ low = hist[s][bin + 5] * (high >> 4) >> 2;
+ if (bin)
+ high = hist[s][bin + 4] * (high >> 4) >> 2;
+ high -= low;
+ for (nbits = 0; high << nbits < 128; nbits++)
+ ;
+ range = (range + low) << nbits;
+ high <<= nbits;
+ next = hist[s][1];
+ if (++hist[s][2] > hist[s][3])
+ {
+ next = (next + 1) & hist[s][0];
+ hist[s][3] = (hist[s][next + 4] - hist[s][next + 5]) >> 2;
+ hist[s][2] = 1;
+ }
+ if (hist[s][hist[s][1] + 4] - hist[s][hist[s][1] + 5] > 1)
+ {
+ if (bin < hist[s][1])
+ for (i = bin; i < hist[s][1]; i++)
+ hist[s][i + 5]--;
+ else if (next <= bin)
+ for (i = hist[s][1]; i < bin; i++)
+ hist[s][i + 5]++;
+ }
+ hist[s][1] = next;
+ sym[s] = bin;
+ }
+ diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
+ if (sym[0] & 4)
+ diff = diff ? -diff : 0x80;
+ if (ftell(ifp) + 12 >= seg[1][1])
+ diff = 0;
+ if (pix >= unsigned(raw_width * raw_height))
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ raw_image[pix] = pred[pix & 1] += diff;
+ if (!(pix & 1) && HOLE(pix / raw_width))
+ pix += 2;
+ }
+ maximum = 0xff;
+}
+
+void LibRaw::smal_v6_load_raw()
+{
+ unsigned seg[2][2];
+
+ fseek(ifp, 16, SEEK_SET);
+ seg[0][0] = 0;
+ seg[0][1] = get2();
+ seg[1][0] = raw_width * raw_height;
+ seg[1][1] = INT_MAX;
+ smal_decode_segment(seg, 0);
+}
+
+int LibRaw::median4(int *p)
+{
+ int min, max, sum, i;
+
+ min = max = sum = p[0];
+ for (i = 1; i < 4; i++)
+ {
+ sum += p[i];
+ if (min > p[i])
+ min = p[i];
+ if (max < p[i])
+ max = p[i];
+ }
+ return (sum - min - max) >> 1;
+}
+
+void LibRaw::fill_holes(int holes)
+{
+ int row, col, val[4];
+
+ for (row = 2; row < height - 2; row++)
+ {
+ if (!HOLE(row))
+ continue;
+ for (col = 1; col < width - 1; col += 4)
+ {
+ val[0] = RAW(row - 1, col - 1);
+ val[1] = RAW(row - 1, col + 1);
+ val[2] = RAW(row + 1, col - 1);
+ val[3] = RAW(row + 1, col + 1);
+ RAW(row, col) = median4(val);
+ }
+ for (col = 2; col < width - 2; col += 4)
+ if (HOLE(row - 2) || HOLE(row + 2))
+ RAW(row, col) = (RAW(row, col - 2) + RAW(row, col + 2)) >> 1;
+ else
+ {
+ val[0] = RAW(row, col - 2);
+ val[1] = RAW(row, col + 2);
+ val[2] = RAW(row - 2, col);
+ val[3] = RAW(row + 2, col);
+ RAW(row, col) = median4(val);
+ }
+ }
+}
+
+void LibRaw::smal_v9_load_raw()
+{
+ unsigned seg[256][2], offset, nseg, holes, i;
+
+ fseek(ifp, 67, SEEK_SET);
+ offset = get4();
+ nseg = (uchar)fgetc(ifp);
+ fseek(ifp, offset, SEEK_SET);
+ for (i = 0; i < nseg * 2; i++)
+ ((unsigned *)seg)[i] = get4() + data_offset * (i & 1);
+ fseek(ifp, 78, SEEK_SET);
+ holes = fgetc(ifp);
+ fseek(ifp, 88, SEEK_SET);
+ seg[nseg][0] = raw_height * raw_width;
+ seg[nseg][1] = get4() + data_offset;
+ for (i = 0; i < nseg; i++)
+ smal_decode_segment(seg + i, holes);
+ if (holes)
+ fill_holes(holes);
+}
+
+#undef HOLE
diff --git a/libkdcraw/libraw/src/decoders/unpack.cpp b/libkdcraw/libraw/src/decoders/unpack.cpp
new file mode 100644
index 0000000..38adba4
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/unpack.cpp
@@ -0,0 +1,493 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_cameraids.h"
+#include "../../internal/libraw_cxx_defs.h"
+
+#ifdef USE_RAWSPEED3
+#include "rawspeed3_capi.h"
+#include <array>
+#endif
+
+int LibRaw::unpack(void)
+{
+ CHECK_ORDER_HIGH(LIBRAW_PROGRESS_LOAD_RAW);
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+ try
+ {
+
+ if (!libraw_internal_data.internal_data.input)
+ return LIBRAW_INPUT_CLOSED;
+
+ RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW, 0, 2);
+ if (imgdata.rawparams.shot_select >= P1.raw_count)
+ return LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE;
+
+ if (!load_raw)
+ return LIBRAW_UNSPECIFIED_ERROR;
+
+ // already allocated ?
+ if (imgdata.image)
+ {
+ free(imgdata.image);
+ imgdata.image = 0;
+ }
+ if (imgdata.rawdata.raw_alloc)
+ {
+ free(imgdata.rawdata.raw_alloc);
+ imgdata.rawdata.raw_alloc = 0;
+ }
+ if (libraw_internal_data.unpacker_data.meta_length)
+ {
+ if (libraw_internal_data.unpacker_data.meta_length >
+ INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ libraw_internal_data.internal_data.meta_data =
+ (char *)malloc(libraw_internal_data.unpacker_data.meta_length);
+ }
+
+ libraw_decoder_info_t decoder_info;
+ get_decoder_info(&decoder_info);
+
+ int save_iwidth = S.iwidth, save_iheight = S.iheight,
+ save_shrink = IO.shrink;
+
+ int rwidth = S.raw_width, rheight = S.raw_height;
+ if (!IO.fuji_width)
+ {
+ // adjust non-Fuji allocation
+ if (rwidth < S.width + S.left_margin)
+ rwidth = S.width + S.left_margin;
+ if (rheight < S.height + S.top_margin)
+ rheight = S.height + S.top_margin;
+ }
+ if (rwidth > 65535 ||
+ rheight > 65535) // No way to make image larger than 64k pix
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ imgdata.rawdata.raw_image = 0;
+ imgdata.rawdata.color4_image = 0;
+ imgdata.rawdata.color3_image = 0;
+ imgdata.rawdata.float_image = 0;
+ imgdata.rawdata.float3_image = 0;
+
+#ifdef USE_DNGSDK
+ if (imgdata.idata.dng_version && dnghost
+ && libraw_internal_data.unpacker_data.tiff_samples != 2 // Fuji SuperCCD; it is better to detect is more rigid way
+ && valid_for_dngsdk() && load_raw != &LibRaw::pentax_4shot_load_raw)
+ {
+ // Data size check
+ INT64 pixcount =
+ INT64(MAX(S.width, S.raw_width)) * INT64(MAX(S.height, S.raw_height));
+ INT64 planecount =
+ (imgdata.idata.filters || P1.colors == 1) ? 1 : LIM(P1.colors, 3, 4);
+ INT64 samplesize = is_floating_point() ? 4 : 2;
+ INT64 bytes = pixcount * planecount * samplesize;
+ if (bytes + INT64(libraw_internal_data.unpacker_data.meta_length )
+ > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ // find ifd to check sample
+ try_dngsdk();
+ if (raw_was_read())
+ imgdata.process_warnings |= LIBRAW_WARN_DNGSDK_PROCESSED;
+ }
+#endif
+#ifdef USE_RAWSPEED3
+ if (!raw_was_read()
+ && (!IO.fuji_width) // Do not use for fuji rotated
+ && ((imgdata.idata.raw_count == 1)
+ // Canon dual pixel, 1st frame
+ || (makeIs(LIBRAW_CAMERAMAKER_Canon) && imgdata.idata.raw_count == 2 && imgdata.rawparams.shot_select==0)
+ )
+#ifdef USE_RAWSPEED_BITS
+ && (imgdata.rawparams.use_rawspeed & LIBRAW_RAWSPEEDV3_USE)
+#else
+ && imgdata.rawparams.use_rawspeed
+#endif
+ && (decoder_info.decoder_flags & LIBRAW_DECODER_TRYRAWSPEED3)
+ )
+ {
+ INT64 pixcount = INT64(MAX(S.width, S.raw_width)) * INT64(MAX(S.height, S.raw_height));
+ INT64 planecount = (imgdata.idata.filters || P1.colors == 1) ? 1 : LIM(P1.colors, 3, 4);
+ INT64 bytes = pixcount * planecount * 2; // sample size is always 2 for rawspeed
+ if (bytes + INT64(libraw_internal_data.unpacker_data.meta_length)
+ > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ if (!_rawspeed3_handle)
+ _rawspeed3_handle = rawspeed3_initdefault();
+
+ if (_rawspeed3_handle && ID.input->size() > 0) // large bound is checked at identify
+ {
+ void *_rawspeed_buffer = 0;
+ try {
+ ID.input->seek(0, SEEK_SET);
+ INT64 _rawspeed_buffer_sz = ID.input->size() + 32;
+ _rawspeed_buffer = malloc(_rawspeed_buffer_sz);
+ if (!_rawspeed_buffer)
+ throw LIBRAW_EXCEPTION_ALLOC;
+ ID.input->read(_rawspeed_buffer, ID.input->size(), 1);
+
+ rawspeed3_ret_t rs3ret;
+ rawspeed3_clearresult(&rs3ret);
+ int status = rawspeed3_decodefile(_rawspeed3_handle, &rs3ret, _rawspeed_buffer, ID.input->size(),
+#ifdef USE_RAWSPEED_BITS
+ !(imgdata.rawparams.use_rawspeed & LIBRAW_RAWSPEEDV3_FAILONUNKNOWN)
+#else
+ false
+#endif
+ );
+ if (status != rawspeed3_ok)
+ imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_UNSUPPORTED;
+
+ if (status == rawspeed3_not_supported)
+ imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED3_NOTLISTED;
+
+ if (status == rawspeed3_ok
+#ifdef USE_RAWSPEED_BITS
+ ||
+ (status == rawspeed3_ok_warnings && (imgdata.rawparams.use_rawspeed & LIBRAW_RAWSPEEDV3_IGNOREERRORS))
+#endif
+ )
+ {
+
+ if ((S.raw_width != rs3ret.width) || (S.raw_height != rs3ret.height))
+ throw "Size mismatch";
+
+ // DECODED w/ success
+ if (rs3ret.filters>1) // Fuji or bayer
+ imgdata.rawdata.raw_image = (ushort*)rs3ret.pixeldata;
+ else if (rs3ret.cpp == 4)
+ {
+ imgdata.rawdata.color4_image = (ushort(*)[4])rs3ret.pixeldata;
+ //if (r->whitePoint > 0 && r->whitePoint < 65536)
+ // C.maximum = r->whitePoint;
+ }
+ else if (rs3ret.cpp == 3)
+ {
+ imgdata.rawdata.color3_image = (ushort(*)[3])rs3ret.pixeldata;
+ //if (r->whitePoint > 0 && r->whitePoint < 65536)
+ // C.maximum = r->whitePoint;
+ }
+
+ if (raw_was_read()) // buffers are assigned above
+ {
+ // set sizes
+ S.raw_pitch = rs3ret.pitch;
+ S.raw_width = rs3ret.width;
+ S.raw_height = rs3ret.height;
+ imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED3_PROCESSED;
+ // if (r->whitePoint > 0 && r->whitePoint < 65536)
+ // C.maximum = r->whitePoint;
+ }
+ }
+ free(_rawspeed_buffer);
+ }
+ catch (...)
+ {
+ imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED3_PROBLEM;
+ if (_rawspeed_buffer)
+ free(_rawspeed_buffer);
+ }
+ }
+ }
+#endif
+#ifdef USE_RAWSPEED
+ if (!raw_was_read())
+ {
+ int rawspeed_enabled = 1;
+
+ if (imgdata.idata.dng_version && (libraw_internal_data.unpacker_data.tiff_samples == 2 || imgdata.idata.raw_count > 1))
+ rawspeed_enabled = 0;
+
+ if (libraw_internal_data.unpacker_data.is_NikonTransfer)
+ rawspeed_enabled = 0;
+
+ if (libraw_internal_data.unpacker_data.pana_encoding == 5)
+ rawspeed_enabled = 0;
+
+ if (imgdata.idata.raw_count > 1)
+ rawspeed_enabled = 0;
+ if (!strncasecmp(imgdata.idata.software, "Magic", 5))
+ rawspeed_enabled = 0;
+ // Disable rawspeed for double-sized Oly files
+ if (makeIs(LIBRAW_CAMERAMAKER_Olympus) &&
+ ((imgdata.sizes.raw_width > 6000) ||
+ !strncasecmp(imgdata.idata.model, "SH-", 3) ||
+ !strncasecmp(imgdata.idata.model, "TG-", 3) ))
+ rawspeed_enabled = 0;
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Canon) &&
+ (libraw_internal_data.identify_data.unique_id == CanonID_EOS_6D_Mark_II))
+ rawspeed_enabled = 0;
+
+ if (imgdata.idata.dng_version && imgdata.idata.filters == 0 &&
+ libraw_internal_data.unpacker_data.tiff_bps == 8) // Disable for 8 bit
+ rawspeed_enabled = 0;
+
+ if (load_raw == &LibRaw::packed_load_raw &&
+ makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
+ (!strncasecmp(imgdata.idata.model, "E", 1) ||
+ !strncasecmp(imgdata.idata.model, "COOLPIX B", 9) ||
+ !strncasecmp(imgdata.idata.model, "COOLPIX P9", 10) ||
+ !strncasecmp(imgdata.idata.model, "COOLPIX P1000", 13)))
+ rawspeed_enabled = 0;
+
+ if (load_raw == &LibRaw::nikon_load_raw && makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
+ !strcasecmp(imgdata.idata.model, "D6"))
+ rawspeed_enabled = 0;
+
+ if (load_raw == &LibRaw::lossless_jpeg_load_raw &&
+ MN.canon.RecordMode && makeIs(LIBRAW_CAMERAMAKER_Kodak) &&
+ /* Not normalized models here, it is intentional */
+ (!strncasecmp(imgdata.idata.model, "EOS D2000", 9) ||
+ !strncasecmp(imgdata.idata.model, "EOS D6000", 9)))
+ rawspeed_enabled = 0;
+
+ if (load_raw == &LibRaw::nikon_load_raw &&
+ makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
+ (!strncasecmp(imgdata.idata.model, "Z", 1) || !strncasecmp(imgdata.idata.model,"D780",4)))
+ rawspeed_enabled = 0;
+
+ if (load_raw == &LibRaw::panasonic_load_raw &&
+ libraw_internal_data.unpacker_data.pana_encoding > 4)
+ rawspeed_enabled = 0;
+
+ // RawSpeed Supported,
+ if (
+#ifdef USE_RAWSPEED_BITS
+ (imgdata.rawparams.use_rawspeed & LIBRAW_RAWSPEEDV1_USE)
+#else
+ imgdata.rawparams.use_rawspeed
+#endif
+ && rawspeed_enabled &&
+ !(is_sraw() && (imgdata.rawparams.specials &
+ (LIBRAW_RAWSPECIAL_SRAW_NO_RGB |
+ LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE))) &&
+ (decoder_info.decoder_flags & LIBRAW_DECODER_TRYRAWSPEED) &&
+ _rawspeed_camerameta)
+ {
+ INT64 pixcount = INT64(MAX(S.width, S.raw_width)) *
+ INT64(MAX(S.height, S.raw_height));
+ INT64 planecount = (imgdata.idata.filters || P1.colors == 1)
+ ? 1
+ : LIM(P1.colors, 3, 4);
+ INT64 bytes =
+ pixcount * planecount * 2; // sample size is always 2 for rawspeed
+ if (bytes + +INT64(libraw_internal_data.unpacker_data.meta_length) >
+ INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ /*int rr = */ try_rawspeed();
+
+ }
+ }
+#endif
+ if (!raw_was_read()) // RawSpeed failed or not run
+ {
+ // Not allocated on RawSpeed call, try call LibRaow
+ int zero_rawimage = 0;
+ if (decoder_info.decoder_flags & LIBRAW_DECODER_OWNALLOC)
+ {
+ // x3f foveon decoder and DNG float
+ // Do nothing! Decoder will allocate data internally
+ }
+ if (decoder_info.decoder_flags & LIBRAW_DECODER_SINAR4SHOT)
+ {
+ if (imgdata.rawparams.shot_select) // single image extract
+ {
+ if (INT64(rwidth) * INT64(rheight + 8) *
+ INT64(sizeof(imgdata.rawdata.raw_image[0]))
+ + +INT64(libraw_internal_data.unpacker_data.meta_length) >
+ INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+ imgdata.rawdata.raw_alloc = malloc(
+ rwidth * (rheight + 8) * sizeof(imgdata.rawdata.raw_image[0]));
+ imgdata.rawdata.raw_image = (ushort *)imgdata.rawdata.raw_alloc;
+ if (!S.raw_pitch)
+ S.raw_pitch = S.raw_width * 2; // Bayer case, not set before
+ }
+ else // Full image extract
+ {
+ if (INT64(rwidth) * INT64(rheight + 8) *
+ INT64(sizeof(imgdata.rawdata.raw_image[0])) * 4
+ +INT64(libraw_internal_data.unpacker_data.meta_length) >
+ INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+ S.raw_pitch = S.raw_width * 8;
+ imgdata.rawdata.raw_alloc = 0;
+ imgdata.image = (ushort(*)[4])calloc(
+ unsigned(MAX(S.width, S.raw_width)) *
+ unsigned(MAX(S.height, S.raw_height) + 8),
+ sizeof(*imgdata.image));
+ }
+ }
+ else if (decoder_info.decoder_flags & LIBRAW_DECODER_3CHANNEL)
+ {
+ if (INT64(rwidth) * INT64(rheight + 8) *
+ INT64(sizeof(imgdata.rawdata.raw_image[0])) * 3
+ + INT64(libraw_internal_data.unpacker_data.meta_length) >
+ INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ imgdata.rawdata.raw_alloc = malloc(
+ rwidth * (rheight + 8) * sizeof(imgdata.rawdata.raw_image[0]) * 3);
+ imgdata.rawdata.color3_image = (ushort(*)[3])imgdata.rawdata.raw_alloc;
+ if (!S.raw_pitch)
+ S.raw_pitch = S.raw_width * 6;
+ }
+ else if (imgdata.idata.filters ||
+ P1.colors ==
+ 1) // Bayer image or single color -> decode to raw_image
+ {
+ if (INT64(rwidth) * INT64(rheight + 8) *
+ INT64(sizeof(imgdata.rawdata.raw_image[0]))
+ + INT64(libraw_internal_data.unpacker_data.meta_length) >
+ INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+ imgdata.rawdata.raw_alloc = malloc(
+ rwidth * (rheight + 8) * sizeof(imgdata.rawdata.raw_image[0]));
+ imgdata.rawdata.raw_image = (ushort *)imgdata.rawdata.raw_alloc;
+ if (!S.raw_pitch)
+ S.raw_pitch = S.raw_width * 2; // Bayer case, not set before
+ }
+ else // NO LEGACY FLAG if (decoder_info.decoder_flags &
+ // LIBRAW_DECODER_LEGACY)
+ {
+ if (decoder_info.decoder_flags & LIBRAW_DECODER_ADOBECOPYPIXEL)
+ {
+ S.raw_pitch = S.raw_width * 8;
+ }
+ else
+ {
+ S.iwidth = S.width;
+ S.iheight = S.height;
+ IO.shrink = 0;
+ if (!S.raw_pitch)
+ S.raw_pitch = (decoder_info.decoder_flags &
+ LIBRAW_DECODER_LEGACY_WITH_MARGINS)
+ ? S.raw_width * 8
+ : S.width * 8;
+ }
+ // sRAW and old Foveon decoders only, so extra buffer size is just 1/4
+ // allocate image as temporary buffer, size
+ if (INT64(MAX(S.width, S.raw_width)) *
+ INT64(MAX(S.height, S.raw_height) + 8) *
+ INT64(sizeof(*imgdata.image))
+ + INT64(libraw_internal_data.unpacker_data.meta_length) >
+ INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ imgdata.rawdata.raw_alloc = 0;
+ imgdata.image =
+ (ushort(*)[4])calloc(unsigned(MAX(S.width, S.raw_width)) *
+ unsigned(MAX(S.height, S.raw_height) + 8),
+ sizeof(*imgdata.image));
+ if (!(decoder_info.decoder_flags & LIBRAW_DECODER_ADOBECOPYPIXEL))
+ {
+ imgdata.rawdata.raw_image = (ushort *)imgdata.image;
+ zero_rawimage = 1;
+ }
+ }
+ ID.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
+
+ unsigned m_save = C.maximum;
+ if (load_raw == &LibRaw::unpacked_load_raw &&
+ (!strcasecmp(imgdata.idata.make, "Nikon") || !strcasecmp(imgdata.idata.make, "Hasselblad"))
+ )
+ C.maximum = 65535;
+ (this->*load_raw)();
+ if (zero_rawimage)
+ imgdata.rawdata.raw_image = 0;
+ if (load_raw == &LibRaw::unpacked_load_raw &&
+ (!strcasecmp(imgdata.idata.make, "Nikon") || !strcasecmp(imgdata.idata.make, "Hasselblad"))
+ )
+ C.maximum = m_save;
+ if (decoder_info.decoder_flags & LIBRAW_DECODER_OWNALLOC)
+ {
+ // x3f foveon decoder only: do nothing
+ }
+ else if (decoder_info.decoder_flags & LIBRAW_DECODER_SINAR4SHOT &&
+ imgdata.rawparams.shot_select == 0)
+ {
+ imgdata.rawdata.raw_alloc = imgdata.image;
+ imgdata.rawdata.color4_image = (ushort(*)[4])imgdata.rawdata.raw_alloc;
+ imgdata.image = 0;
+ }
+ else if (!(imgdata.idata.filters ||
+ P1.colors == 1)) // legacy decoder, ownalloc handled above
+ {
+ // successfully decoded legacy image, attach image to raw_alloc
+ imgdata.rawdata.raw_alloc = imgdata.image;
+ imgdata.rawdata.color4_image = (ushort(*)[4])imgdata.rawdata.raw_alloc;
+ imgdata.image = 0;
+ // Restore saved values. Note: Foveon have masked frame
+ // Other 4-color legacy data: no borders
+ if (!(libraw_internal_data.unpacker_data.load_flags & 256) &&
+ !(decoder_info.decoder_flags & LIBRAW_DECODER_ADOBECOPYPIXEL) &&
+ !(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY_WITH_MARGINS))
+ {
+ S.raw_width = S.width;
+ S.left_margin = 0;
+ S.raw_height = S.height;
+ S.top_margin = 0;
+ }
+ }
+ }
+
+ if (imgdata.rawdata.raw_image)
+ crop_masked_pixels(); // calculate black levels
+
+ // recover image sizes
+ S.iwidth = save_iwidth;
+ S.iheight = save_iheight;
+ IO.shrink = save_shrink;
+
+ // adjust black to possible maximum
+ unsigned int i = C.cblack[3];
+ unsigned int c;
+ for (c = 0; c < 3; c++)
+ if (i > C.cblack[c])
+ i = C.cblack[c];
+ for (c = 0; c < 4; c++)
+ C.cblack[c] -= i;
+ C.black += i;
+
+ // Save color,sizes and internal data into raw_image fields
+ memmove(&imgdata.rawdata.color, &imgdata.color, sizeof(imgdata.color));
+ memmove(&imgdata.rawdata.sizes, &imgdata.sizes, sizeof(imgdata.sizes));
+ memmove(&imgdata.rawdata.iparams, &imgdata.idata, sizeof(imgdata.idata));
+ memmove(&imgdata.rawdata.ioparams,
+ &libraw_internal_data.internal_output_params,
+ sizeof(libraw_internal_data.internal_output_params));
+
+ SET_PROC_FLAG(LIBRAW_PROGRESS_LOAD_RAW);
+ RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW, 1, 2);
+
+ return 0;
+ }
+ catch (const std::bad_alloc&)
+ {
+ EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC);
+ }
+ catch (const LibRaw_exceptions& err)
+ {
+ EXCEPTION_HANDLER(err);
+ }
+ catch (const std::exception& )
+ {
+ EXCEPTION_HANDLER(LIBRAW_EXCEPTION_IO_CORRUPT);
+ }
+}
diff --git a/libkdcraw/libraw/src/decoders/unpack_thumb.cpp b/libkdcraw/libraw/src/decoders/unpack_thumb.cpp
new file mode 100644
index 0000000..1f01ddc
--- /dev/null
+++ b/libkdcraw/libraw/src/decoders/unpack_thumb.cpp
@@ -0,0 +1,385 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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"
+
+#ifndef NO_JPEG
+struct jpegErrorManager
+{
+ struct jpeg_error_mgr pub;
+ jmp_buf setjmp_buffer;
+};
+
+static void jpegErrorExit(j_common_ptr cinfo)
+{
+ jpegErrorManager *myerr = (jpegErrorManager *)cinfo->err;
+ longjmp(myerr->setjmp_buffer, 1);
+}
+#endif
+
+int LibRaw::unpack_thumb_ex(int idx)
+{
+ if (idx < 0 || idx >= imgdata.thumbs_list.thumbcount || idx >= LIBRAW_THUMBNAIL_MAXCOUNT)
+ return LIBRAW_REQUEST_FOR_NONEXISTENT_THUMBNAIL;
+
+ // Set from thumb-list
+ libraw_internal_data.internal_data.toffset = imgdata.thumbs_list.thumblist[idx].toffset;
+ imgdata.thumbnail.tlength = imgdata.thumbs_list.thumblist[idx].tlength;
+ libraw_internal_data.unpacker_data.thumb_format = imgdata.thumbs_list.thumblist[idx].tformat;
+ imgdata.thumbnail.twidth = imgdata.thumbs_list.thumblist[idx].twidth;
+ imgdata.thumbnail.theight = imgdata.thumbs_list.thumblist[idx].theight;
+ libraw_internal_data.unpacker_data.thumb_misc = imgdata.thumbs_list.thumblist[idx].tmisc;
+ int rc = unpack_thumb();
+ imgdata.progress_flags &= ~LIBRAW_PROGRESS_THUMB_LOAD;
+
+ return rc;
+}
+
+
+int LibRaw::unpack_thumb(void)
+{
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+ CHECK_ORDER_BIT(LIBRAW_PROGRESS_THUMB_LOAD);
+
+#define THUMB_SIZE_CHECKT(A) \
+ do { \
+ if (INT64(A) > 1024LL * 1024LL * LIBRAW_MAX_THUMBNAIL_MB) return LIBRAW_UNSUPPORTED_THUMBNAIL; \
+ if (INT64(A) > 0 && INT64(A) < 64LL) return LIBRAW_NO_THUMBNAIL; \
+ } while (0)
+
+#define THUMB_SIZE_CHECKTNZ(A) \
+ do { \
+ if (INT64(A) > 1024LL * 1024LL * LIBRAW_MAX_THUMBNAIL_MB) return LIBRAW_UNSUPPORTED_THUMBNAIL; \
+ if (INT64(A) < 64LL) return LIBRAW_NO_THUMBNAIL; \
+ } while (0)
+
+
+#define THUMB_SIZE_CHECKWH(W,H) \
+ do { \
+ if (INT64(W)*INT64(H) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB) return LIBRAW_UNSUPPORTED_THUMBNAIL; \
+ if (INT64(W)*INT64(H) < 64ULL) return LIBRAW_NO_THUMBNAIL; \
+ } while (0)
+
+#define Tformat libraw_internal_data.unpacker_data.thumb_format
+
+ try
+ {
+ if (!libraw_internal_data.internal_data.input)
+ return LIBRAW_INPUT_CLOSED;
+
+ int t_colors = libraw_internal_data.unpacker_data.thumb_misc >> 5 & 7;
+ int t_bytesps = (libraw_internal_data.unpacker_data.thumb_misc & 31) / 8;
+
+ if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 &&
+ load_raw == &LibRaw::broadcom_load_raw) // RPi
+#ifdef USE_6BY9RPI
+ && !(imgdata.thumbnail.tlength > 0 && libraw_internal_data.unpacker_data.load_flags & 0x4000
+ && (load_raw == &LibRaw::rpi_load_raw8 || load_raw == &LibRaw::nokia_load_raw ||
+ load_raw == &LibRaw::rpi_load_raw12 || load_raw == &LibRaw::rpi_load_raw14))
+#endif
+ )
+ {
+ return LIBRAW_NO_THUMBNAIL;
+ }
+ else if ((Tformat >= LIBRAW_INTERNAL_THUMBNAIL_KODAK_THUMB)
+ && ((Tformat <= LIBRAW_INTERNAL_THUMBNAIL_KODAK_RGB)))
+ {
+ kodak_thumb_loader();
+ T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+ else
+ {
+#ifdef USE_X3FTOOLS
+ if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_X3F)
+ {
+ INT64 tsize = x3f_thumb_size();
+ if (tsize < 2048 || INT64(ID.toffset) + tsize < 1)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ if (INT64(ID.toffset) + tsize > ID.input->size() + THUMB_READ_BEYOND)
+ throw LIBRAW_EXCEPTION_IO_EOF;
+ THUMB_SIZE_CHECKT(tsize);
+ }
+#else
+ if (0) {}
+#endif
+ else
+ {
+ if (INT64(ID.toffset) + INT64(T.tlength) < 1)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ if (INT64(ID.toffset) + INT64(T.tlength) >
+ ID.input->size() + THUMB_READ_BEYOND)
+ throw LIBRAW_EXCEPTION_IO_EOF;
+ }
+
+ ID.input->seek(ID.toffset, SEEK_SET);
+ if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_JPEG)
+ {
+ THUMB_SIZE_CHECKTNZ(T.tlength);
+ if (T.thumb)
+ free(T.thumb);
+ T.thumb = (char *)malloc(T.tlength);
+ ID.input->read(T.thumb, 1, T.tlength);
+ unsigned char *tthumb = (unsigned char *)T.thumb;
+ if (load_raw == &LibRaw::crxLoadRaw && T.tlength > 0xE0)
+ {
+ // Check if it is canon H.265 preview: CISZ at bytes 4-6, CISZ prefix is 000n
+ if (tthumb[0] == 0 && tthumb[1] == 0 && tthumb[2] == 0 && !memcmp(tthumb + 4, "CISZ", 4))
+ {
+ T.tformat = LIBRAW_THUMBNAIL_H265;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+ }
+ tthumb[0] = 0xff;
+ tthumb[1] = 0xd8;
+#ifdef NO_JPEG
+ T.tcolors = 3;
+#else
+ {
+ jpegErrorManager jerr;
+ struct jpeg_decompress_struct cinfo;
+ cinfo.err = jpeg_std_error(&jerr.pub);
+ jerr.pub.error_exit = jpegErrorExit;
+ if (setjmp(jerr.setjmp_buffer))
+ {
+ err2:
+ // Error in original JPEG thumb, read it again because
+ // original bytes 0-1 was damaged above
+ jpeg_destroy_decompress(&cinfo);
+ T.tcolors = 3;
+ T.tformat = LIBRAW_THUMBNAIL_UNKNOWN;
+ ID.input->seek(ID.toffset, SEEK_SET);
+ ID.input->read(T.thumb, 1, T.tlength);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+ jpeg_create_decompress(&cinfo);
+ jpeg_mem_src(&cinfo, (unsigned char *)T.thumb, T.tlength);
+ int rc = jpeg_read_header(&cinfo, TRUE);
+ if (rc != 1)
+ goto err2;
+ T.tcolors = (cinfo.num_components > 0 && cinfo.num_components <= 3)
+ ? cinfo.num_components
+ : 3;
+ jpeg_destroy_decompress(&cinfo);
+ }
+#endif
+ T.tformat = LIBRAW_THUMBNAIL_JPEG;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+ else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_LAYER)
+ {
+ int colors = libraw_internal_data.unpacker_data.thumb_misc >> 5 & 7;
+ if (colors != 1 && colors != 3)
+ return LIBRAW_UNSUPPORTED_THUMBNAIL;
+
+ THUMB_SIZE_CHECKWH(T.twidth, T.theight);
+
+ int tlength = T.twidth * T.theight;
+ if (T.thumb)
+ free(T.thumb);
+ T.thumb = (char *)calloc(colors, tlength);
+ unsigned char *tbuf = (unsigned char *)calloc(colors, tlength);
+ // Avoid OOB of tbuf, should use tlength
+ ID.input->read(tbuf, colors, tlength);
+ if (libraw_internal_data.unpacker_data.thumb_misc >> 8 &&
+ colors == 3) // GRB order
+ for (int i = 0; i < tlength; i++)
+ {
+ T.thumb[i * 3] = tbuf[i + tlength];
+ T.thumb[i * 3 + 1] = tbuf[i];
+ T.thumb[i * 3 + 2] = tbuf[i + 2 * tlength];
+ }
+ else if (colors == 3) // RGB or 1-channel
+ for (int i = 0; i < tlength; i++)
+ {
+ T.thumb[i * 3] = tbuf[i];
+ T.thumb[i * 3 + 1] = tbuf[i + tlength];
+ T.thumb[i * 3 + 2] = tbuf[i + 2 * tlength];
+ }
+ else if (colors == 1)
+ {
+ free(T.thumb);
+ T.thumb = (char *)tbuf;
+ tbuf = 0;
+ }
+ if (tbuf)
+ free(tbuf);
+ T.tcolors = colors;
+ T.tlength = colors * tlength;
+ T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+ else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_ROLLEI)
+ {
+ int i;
+ THUMB_SIZE_CHECKWH(T.twidth, T.theight);
+ int tlength = T.twidth * T.theight;
+ if (T.thumb)
+ free(T.thumb);
+ T.tcolors = 3;
+ T.thumb = (char *)calloc(T.tcolors, tlength);
+ unsigned short *tbuf = (unsigned short *)calloc(2, tlength);
+ read_shorts(tbuf, tlength);
+ for (i = 0; i < tlength; i++)
+ {
+ T.thumb[i * 3] = (tbuf[i] << 3) & 0xff;
+ T.thumb[i * 3 + 1] = (tbuf[i] >> 5 << 2) & 0xff;
+ T.thumb[i * 3 + 2] = (tbuf[i] >> 11 << 3) & 0xff;
+ }
+ free(tbuf);
+ T.tlength = T.tcolors * tlength;
+ T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+ else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_PPM)
+ {
+ if (t_bytesps > 1)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT; // 8-bit thumb, but parsed for more
+ // bits
+ THUMB_SIZE_CHECKWH(T.twidth, T.theight);
+ int t_length = T.twidth * T.theight * t_colors;
+
+ if (T.tlength &&
+ (int)T.tlength < t_length) // try to find tiff ifd with needed offset
+ {
+ int pifd = find_ifd_by_offset(libraw_internal_data.internal_data.toffset);
+ if (pifd >= 0 && tiff_ifd[pifd].strip_offsets_count &&
+ tiff_ifd[pifd].strip_byte_counts_count)
+ {
+ // We found it, calculate final size
+ unsigned total_size = 0;
+ for (int i = 0; i < tiff_ifd[pifd].strip_byte_counts_count; i++)
+ total_size += tiff_ifd[pifd].strip_byte_counts[i];
+ if (total_size != (unsigned)t_length) // recalculate colors
+ {
+ if (total_size == T.twidth * T.tlength * 3)
+ T.tcolors = 3;
+ else if (total_size == T.twidth * T.tlength)
+ T.tcolors = 1;
+ }
+ T.tlength = total_size;
+ THUMB_SIZE_CHECKTNZ(T.tlength);
+ if (T.thumb)
+ free(T.thumb);
+ T.thumb = (char *)malloc(T.tlength);
+
+ char *dest = T.thumb;
+ INT64 pos = ID.input->tell();
+
+ for (int i = 0; i < tiff_ifd[pifd].strip_byte_counts_count &&
+ i < tiff_ifd[pifd].strip_offsets_count;
+ i++)
+ {
+ int remain = T.tlength;
+ int sz = tiff_ifd[pifd].strip_byte_counts[i];
+ int off = tiff_ifd[pifd].strip_offsets[i];
+ if (off >= 0 && off + sz <= ID.input->size() && sz <= remain)
+ {
+ ID.input->seek(off, SEEK_SET);
+ ID.input->read(dest, sz, 1);
+ remain -= sz;
+ dest += sz;
+ }
+ }
+ ID.input->seek(pos, SEEK_SET);
+ T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+ }
+
+ if (!T.tlength)
+ T.tlength = t_length;
+ if (T.thumb)
+ free(T.thumb);
+
+ THUMB_SIZE_CHECKTNZ(T.tlength);
+
+ T.thumb = (char *)malloc(T.tlength);
+ if (!T.tcolors)
+ T.tcolors = t_colors;
+
+ ID.input->read(T.thumb, 1, T.tlength);
+
+ T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+ else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_PPM16)
+ {
+ if (t_bytesps > 2)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT; // 16-bit thumb, but parsed for
+ // more bits
+ int o_bps = (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_USE_PPM16_THUMBS) ? 2 : 1;
+ int o_length = T.twidth * T.theight * t_colors * o_bps;
+ int i_length = T.twidth * T.theight * t_colors * 2;
+ if (!T.tlength)
+ T.tlength = o_length;
+ THUMB_SIZE_CHECKTNZ(o_length);
+ THUMB_SIZE_CHECKTNZ(i_length);
+ THUMB_SIZE_CHECKTNZ(T.tlength);
+
+ ushort *t_thumb = (ushort *)calloc(i_length, 1);
+ ID.input->read(t_thumb, 1, i_length);
+ if ((libraw_internal_data.unpacker_data.order == 0x4949) ==
+ (ntohs(0x1234) == 0x1234))
+ libraw_swab(t_thumb, i_length);
+
+ if (T.thumb)
+ free(T.thumb);
+ if ((imgdata.rawparams.options & LIBRAW_RAWOPTIONS_USE_PPM16_THUMBS))
+ {
+ T.thumb = (char *)t_thumb;
+ T.tformat = LIBRAW_THUMBNAIL_BITMAP16;
+ }
+ else
+ {
+ T.thumb = (char *)malloc(o_length);
+ for (int i = 0; i < o_length; i++)
+ T.thumb[i] = t_thumb[i] >> 8;
+ free(t_thumb);
+ T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+ }
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+#ifdef USE_X3FTOOLS
+ else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_X3F)
+ {
+ x3f_thumb_loader();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+#endif
+ else
+ {
+ return LIBRAW_UNSUPPORTED_THUMBNAIL;
+ }
+ }
+ // last resort
+ return LIBRAW_UNSUPPORTED_THUMBNAIL; /* warned as unreachable*/
+ }
+ catch (const LibRaw_exceptions& err)
+ {
+ EXCEPTION_HANDLER(err);
+ }
+}
diff --git a/libkdcraw/libraw/src/demosaic/aahd_demosaic.cpp b/libkdcraw/libraw/src/demosaic/aahd_demosaic.cpp
new file mode 100644
index 0000000..9421765
--- /dev/null
+++ b/libkdcraw/libraw/src/demosaic/aahd_demosaic.cpp
@@ -0,0 +1,781 @@
+/* -*- C++ -*-
+ * File: aahd_demosaic.cpp
+ * Copyright 2013 Anton Petrusevich
+ * Created: Wed May 15, 2013
+ *
+ * This code is licensed under 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/dmp_include.h"
+
+typedef ushort ushort3[3];
+typedef int int3[3];
+
+#ifndef Pnw
+#define Pnw (-1 - nr_width)
+#define Pn (-nr_width)
+#define Pne (+1 - nr_width)
+#define Pe (+1)
+#define Pse (+1 + nr_width)
+#define Ps (+nr_width)
+#define Psw (-1 + nr_width)
+#define Pw (-1)
+#endif
+
+struct AAHD
+{
+ int nr_height, nr_width;
+ static const int nr_margin = 4;
+ static const int Thot = 4;
+ static const int Tdead = 4;
+ static const int OverFraction = 8;
+ ushort3 *rgb_ahd[2];
+ int3 *yuv[2];
+ char *ndir, *homo[2];
+ ushort channel_maximum[3], channels_max;
+ ushort channel_minimum[3];
+ static const float yuv_coeff[3][3];
+ static float gammaLUT[0x10000];
+ float yuv_cam[3][3];
+ LibRaw &libraw;
+ enum
+ {
+ HVSH = 1,
+ HOR = 2,
+ VER = 4,
+ HORSH = HOR | HVSH,
+ VERSH = VER | HVSH,
+ HOT = 8
+ };
+
+ static inline float calc_dist(int c1, int c2) throw()
+ {
+ return c1 > c2 ? (float)c1 / c2 : (float)c2 / c1;
+ }
+ int inline Y(ushort3 &rgb) throw()
+ {
+ return yuv_cam[0][0] * rgb[0] + yuv_cam[0][1] * rgb[1] +
+ yuv_cam[0][2] * rgb[2];
+ }
+ int inline U(ushort3 &rgb) throw()
+ {
+ return yuv_cam[1][0] * rgb[0] + yuv_cam[1][1] * rgb[1] +
+ yuv_cam[1][2] * rgb[2];
+ }
+ int inline V(ushort3 &rgb) throw()
+ {
+ return yuv_cam[2][0] * rgb[0] + yuv_cam[2][1] * rgb[1] +
+ yuv_cam[2][2] * rgb[2];
+ }
+ inline int nr_offset(int row, int col) throw()
+ {
+ return (row * nr_width + col);
+ }
+ ~AAHD();
+ AAHD(LibRaw &_libraw);
+ void make_ahd_greens();
+ void make_ahd_gline(int i);
+ void make_ahd_rb();
+ void make_ahd_rb_hv(int i);
+ void make_ahd_rb_last(int i);
+ void evaluate_ahd();
+ void combine_image();
+ void hide_hots();
+ void refine_hv_dirs();
+ void refine_hv_dirs(int i, int js);
+ void refine_ihv_dirs(int i);
+ void illustrate_dirs();
+ void illustrate_dline(int i);
+};
+
+const float AAHD::yuv_coeff[3][3] = {
+ // YPbPr
+ // {
+ // 0.299f,
+ // 0.587f,
+ // 0.114f },
+ // {
+ // -0.168736,
+ // -0.331264f,
+ // 0.5f },
+ // {
+ // 0.5f,
+ // -0.418688f,
+ // -0.081312f }
+ //
+ // Rec. 2020
+ // Y'= 0,2627R' + 0,6780G' + 0,0593B'
+ // U = (B-Y)/1.8814 = (-0,2627R' - 0,6780G' + 0.9407B) / 1.8814 =
+ //-0.13963R - 0.36037G + 0.5B
+ // V = (R-Y)/1.4647 = (0.7373R - 0,6780G - 0,0593B) / 1.4647 = 0.5R -
+ //0.4629G - 0.04049B
+ {+0.2627f, +0.6780f, +0.0593f},
+ {-0.13963f, -0.36037f, +0.5f},
+ {+0.5034f, -0.4629f, -0.0405f}
+
+};
+
+float AAHD::gammaLUT[0x10000] = {-1.f};
+
+AAHD::AAHD(LibRaw &_libraw) : libraw(_libraw)
+{
+ nr_height = libraw.imgdata.sizes.iheight + nr_margin * 2;
+ nr_width = libraw.imgdata.sizes.iwidth + nr_margin * 2;
+ rgb_ahd[0] = (ushort3 *)calloc(nr_height * nr_width,
+ (sizeof(ushort3) * 2 + sizeof(int3) * 2 + 3));
+ if (!rgb_ahd[0])
+ throw LIBRAW_EXCEPTION_ALLOC;
+
+ rgb_ahd[1] = rgb_ahd[0] + nr_height * nr_width;
+ yuv[0] = (int3 *)(rgb_ahd[1] + nr_height * nr_width);
+ yuv[1] = yuv[0] + nr_height * nr_width;
+ ndir = (char *)(yuv[1] + nr_height * nr_width);
+ homo[0] = ndir + nr_height * nr_width;
+ homo[1] = homo[0] + nr_height * nr_width;
+ channel_maximum[0] = channel_maximum[1] = channel_maximum[2] = 0;
+ channel_minimum[0] = libraw.imgdata.image[0][0];
+ channel_minimum[1] = libraw.imgdata.image[0][1];
+ channel_minimum[2] = libraw.imgdata.image[0][2];
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ for (int i = 0; i < 3; ++i)
+ for (int j = 0; j < 3; ++j)
+ {
+ yuv_cam[i][j] = 0;
+ for (int k = 0; k < 3; ++k)
+ yuv_cam[i][j] += yuv_coeff[i][k] * libraw.imgdata.color.rgb_cam[k][j];
+ }
+ if (gammaLUT[0] < -0.1f)
+ {
+ float r;
+ for (int i = 0; i < 0x10000; i++)
+ {
+ r = (float)i / 0x10000;
+ gammaLUT[i] =
+ 0x10000 * (r < 0.0181 ? 4.5f * r : 1.0993f * pow(r, 0.45f) - .0993f);
+ }
+ }
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ int col_cache[48];
+ for (int j = 0; j < 48; ++j)
+ {
+ int c = libraw.COLOR(i, j);
+ if (c == 3)
+ c = 1;
+ col_cache[j] = c;
+ }
+ int moff = nr_offset(i + nr_margin, nr_margin);
+ for (int j = 0; j < iwidth; ++j, ++moff)
+ {
+ int c = col_cache[j % 48];
+ unsigned short d = libraw.imgdata.image[i * iwidth + j][c];
+ if (d != 0)
+ {
+ if (channel_maximum[c] < d)
+ channel_maximum[c] = d;
+ if (channel_minimum[c] > d)
+ channel_minimum[c] = d;
+ rgb_ahd[1][moff][c] = rgb_ahd[0][moff][c] = d;
+ }
+ }
+ }
+ channels_max =
+ MAX(MAX(channel_maximum[0], channel_maximum[1]), channel_maximum[2]);
+}
+
+void AAHD::hide_hots()
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ int js = libraw.COLOR(i, 0) & 1;
+ int kc = libraw.COLOR(i, js);
+ /*
+ * js -- начальная х-координата, которая попадает мимо известного зелёного
+ * kc -- известный цвет в точке интерполирования
+ */
+ int moff = nr_offset(i + nr_margin, nr_margin + js);
+ for (int j = js; j < iwidth; j += 2, moff += 2)
+ {
+ ushort3 *rgb = &rgb_ahd[0][moff];
+ int c = rgb[0][kc];
+ if ((c > rgb[2 * Pe][kc] && c > rgb[2 * Pw][kc] && c > rgb[2 * Pn][kc] &&
+ c > rgb[2 * Ps][kc] && c > rgb[Pe][1] && c > rgb[Pw][1] &&
+ c > rgb[Pn][1] && c > rgb[Ps][1]) ||
+ (c < rgb[2 * Pe][kc] && c < rgb[2 * Pw][kc] && c < rgb[2 * Pn][kc] &&
+ c < rgb[2 * Ps][kc] && c < rgb[Pe][1] && c < rgb[Pw][1] &&
+ c < rgb[Pn][1] && c < rgb[Ps][1]))
+ {
+ int chot = c >> Thot;
+ int cdead = c << Tdead;
+ int avg = 0;
+ for (int k = -2; k < 3; k += 2)
+ for (int m = -2; m < 3; m += 2)
+ if (m == 0 && k == 0)
+ continue;
+ else
+ avg += rgb[nr_offset(k, m)][kc];
+ avg /= 8;
+ if (chot > avg || cdead < avg)
+ {
+ ndir[moff] |= HOT;
+ int dh =
+ ABS(rgb[2 * Pw][kc] - rgb[2 * Pe][kc]) +
+ ABS(rgb[Pw][1] - rgb[Pe][1]) +
+ ABS(rgb[Pw][1] - rgb[Pe][1] + rgb[2 * Pe][kc] - rgb[2 * Pw][kc]);
+ int dv =
+ ABS(rgb[2 * Pn][kc] - rgb[2 * Ps][kc]) +
+ ABS(rgb[Pn][1] - rgb[Ps][1]) +
+ ABS(rgb[Pn][1] - rgb[Ps][1] + rgb[2 * Ps][kc] - rgb[2 * Pn][kc]);
+ int d;
+ if (dv > dh)
+ d = Pw;
+ else
+ d = Pn;
+ rgb_ahd[1][moff][kc] = rgb[0][kc] =
+ (rgb[+2 * d][kc] + rgb[-2 * d][kc]) / 2;
+ }
+ }
+ }
+ js ^= 1;
+ moff = nr_offset(i + nr_margin, nr_margin + js);
+ for (int j = js; j < iwidth; j += 2, moff += 2)
+ {
+ ushort3 *rgb = &rgb_ahd[0][moff];
+ int c = rgb[0][1];
+ if ((c > rgb[2 * Pe][1] && c > rgb[2 * Pw][1] && c > rgb[2 * Pn][1] &&
+ c > rgb[2 * Ps][1] && c > rgb[Pe][kc] && c > rgb[Pw][kc] &&
+ c > rgb[Pn][kc ^ 2] && c > rgb[Ps][kc ^ 2]) ||
+ (c < rgb[2 * Pe][1] && c < rgb[2 * Pw][1] && c < rgb[2 * Pn][1] &&
+ c < rgb[2 * Ps][1] && c < rgb[Pe][kc] && c < rgb[Pw][kc] &&
+ c < rgb[Pn][kc ^ 2] && c < rgb[Ps][kc ^ 2]))
+ {
+ int chot = c >> Thot;
+ int cdead = c << Tdead;
+ int avg = 0;
+ for (int k = -2; k < 3; k += 2)
+ for (int m = -2; m < 3; m += 2)
+ if (k == 0 && m == 0)
+ continue;
+ else
+ avg += rgb[nr_offset(k, m)][1];
+ avg /= 8;
+ if (chot > avg || cdead < avg)
+ {
+ ndir[moff] |= HOT;
+ int dh =
+ ABS(rgb[2 * Pw][1] - rgb[2 * Pe][1]) +
+ ABS(rgb[Pw][kc] - rgb[Pe][kc]) +
+ ABS(rgb[Pw][kc] - rgb[Pe][kc] + rgb[2 * Pe][1] - rgb[2 * Pw][1]);
+ int dv = ABS(rgb[2 * Pn][1] - rgb[2 * Ps][1]) +
+ ABS(rgb[Pn][kc ^ 2] - rgb[Ps][kc ^ 2]) +
+ ABS(rgb[Pn][kc ^ 2] - rgb[Ps][kc ^ 2] + rgb[2 * Ps][1] -
+ rgb[2 * Pn][1]);
+ int d;
+ if (dv > dh)
+ d = Pw;
+ else
+ d = Pn;
+ rgb_ahd[1][moff][1] = rgb[0][1] =
+ (rgb[+2 * d][1] + rgb[-2 * d][1]) / 2;
+ }
+ }
+ }
+ }
+}
+
+void AAHD::evaluate_ahd()
+{
+ int hvdir[4] = {Pw, Pe, Pn, Ps};
+ /*
+ * YUV
+ *
+ */
+ for (int d = 0; d < 2; ++d)
+ {
+ for (int i = 0; i < nr_width * nr_height; ++i)
+ {
+ ushort3 rgb;
+ for (int c = 0; c < 3; ++c)
+ {
+ rgb[c] = gammaLUT[rgb_ahd[d][i][c]];
+ }
+ yuv[d][i][0] = Y(rgb);
+ yuv[d][i][1] = U(rgb);
+ yuv[d][i][2] = V(rgb);
+ }
+ }
+ /* */
+ /*
+ * Lab
+ *
+ float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
+ for (int i = 0; i < 0x10000; i++) {
+ r = i / 65535.0;
+ cbrt[i] = r > 0.008856 ? pow((double) r, (double) (1 / 3.0)) : 7.787 * r + 16
+ / 116.0;
+ }
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++) {
+ xyz_cam[i][j] = 0;
+ for (int k = 0; k < 3; k++)
+ xyz_cam[i][j] += xyz_rgb[i][k] * libraw.imgdata.color.rgb_cam[k][j] /
+ d65_white[i];
+ }
+ for (int d = 0; d < 2; ++d)
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) {
+ int moff = nr_offset(i + nr_margin, nr_margin);
+ for (int j = 0; j < libraw.imgdata.sizes.iwidth; j++, ++moff) {
+ xyz[0] = xyz[1] = xyz[2] = 0.5;
+ for (int c = 0; c < 3; c++) {
+ xyz[0] += xyz_cam[0][c] * rgb_ahd[d][moff][c];
+ xyz[1] += xyz_cam[1][c] * rgb_ahd[d][moff][c];
+ xyz[2] += xyz_cam[2][c] * rgb_ahd[d][moff][c];
+ }
+ xyz[0] = cbrt[CLIP((int) xyz[0])];
+ xyz[1] = cbrt[CLIP((int) xyz[1])];
+ xyz[2] = cbrt[CLIP((int) xyz[2])];
+ yuv[d][moff][0] = 64 * (116 * xyz[1] - 16);
+ yuv[d][moff][1] = 64 * 500 * (xyz[0] - xyz[1]);
+ yuv[d][moff][2] = 64 * 200 * (xyz[1] - xyz[2]);
+ }
+ }
+ * Lab */
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ int moff = nr_offset(i + nr_margin, nr_margin);
+ for (int j = 0; j < libraw.imgdata.sizes.iwidth; j++, ++moff)
+ {
+ int3 *ynr;
+ float ydiff[2][4];
+ int uvdiff[2][4];
+ for (int d = 0; d < 2; ++d)
+ {
+ ynr = &yuv[d][moff];
+ for (int k = 0; k < 4; k++)
+ {
+ ydiff[d][k] = ABS(ynr[0][0] - ynr[hvdir[k]][0]);
+ uvdiff[d][k] = SQR(ynr[0][1] - ynr[hvdir[k]][1]) +
+ SQR(ynr[0][2] - ynr[hvdir[k]][2]);
+ }
+ }
+ float yeps =
+ MIN(MAX(ydiff[0][0], ydiff[0][1]), MAX(ydiff[1][2], ydiff[1][3]));
+ int uveps =
+ MIN(MAX(uvdiff[0][0], uvdiff[0][1]), MAX(uvdiff[1][2], uvdiff[1][3]));
+ for (int d = 0; d < 2; d++)
+ {
+ ynr = &yuv[d][moff];
+ for (int k = 0; k < 4; k++)
+ if (ydiff[d][k] <= yeps && uvdiff[d][k] <= uveps)
+ {
+ homo[d][moff + hvdir[k]]++;
+ if (k / 2 == d)
+ {
+ // если в сонаправленном направлении интеполяции следующие точки
+ // так же гомогенны, учтём их тоже
+ for (int m = 2; m < 4; ++m)
+ {
+ int hvd = m * hvdir[k];
+ if (ABS(ynr[0][0] - ynr[hvd][0]) < yeps &&
+ SQR(ynr[0][1] - ynr[hvd][1]) +
+ SQR(ynr[0][2] - ynr[hvd][2]) <
+ uveps)
+ {
+ homo[d][moff + hvd]++;
+ }
+ else
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ int moff = nr_offset(i + nr_margin, nr_margin);
+ for (int j = 0; j < libraw.imgdata.sizes.iwidth; j++, ++moff)
+ {
+ char hm[2];
+ for (int d = 0; d < 2; d++)
+ {
+ hm[d] = 0;
+ char *hh = &homo[d][moff];
+ for (int hx = -1; hx < 2; hx++)
+ for (int hy = -1; hy < 2; hy++)
+ hm[d] += hh[nr_offset(hy, hx)];
+ }
+ char d = 0;
+ if (hm[0] != hm[1])
+ {
+ if (hm[1] > hm[0])
+ {
+ d = VERSH;
+ }
+ else
+ {
+ d = HORSH;
+ }
+ }
+ else
+ {
+ int3 *ynr = &yuv[1][moff];
+ int gv = SQR(2 * ynr[0][0] - ynr[Pn][0] - ynr[Ps][0]);
+ gv += SQR(2 * ynr[0][1] - ynr[Pn][1] - ynr[Ps][1]) +
+ SQR(2 * ynr[0][2] - ynr[Pn][2] - ynr[Ps][2]);
+ ynr = &yuv[1][moff + Pn];
+ gv += (SQR(2 * ynr[0][0] - ynr[Pn][0] - ynr[Ps][0]) +
+ SQR(2 * ynr[0][1] - ynr[Pn][1] - ynr[Ps][1]) +
+ SQR(2 * ynr[0][2] - ynr[Pn][2] - ynr[Ps][2])) /
+ 2;
+ ynr = &yuv[1][moff + Ps];
+ gv += (SQR(2 * ynr[0][0] - ynr[Pn][0] - ynr[Ps][0]) +
+ SQR(2 * ynr[0][1] - ynr[Pn][1] - ynr[Ps][1]) +
+ SQR(2 * ynr[0][2] - ynr[Pn][2] - ynr[Ps][2])) /
+ 2;
+ ynr = &yuv[0][moff];
+ int gh = SQR(2 * ynr[0][0] - ynr[Pw][0] - ynr[Pe][0]);
+ gh += SQR(2 * ynr[0][1] - ynr[Pw][1] - ynr[Pe][1]) +
+ SQR(2 * ynr[0][2] - ynr[Pw][2] - ynr[Pe][2]);
+ ynr = &yuv[0][moff + Pw];
+ gh += (SQR(2 * ynr[0][0] - ynr[Pw][0] - ynr[Pe][0]) +
+ SQR(2 * ynr[0][1] - ynr[Pw][1] - ynr[Pe][1]) +
+ SQR(2 * ynr[0][2] - ynr[Pw][2] - ynr[Pe][2])) /
+ 2;
+ ynr = &yuv[0][moff + Pe];
+ gh += (SQR(2 * ynr[0][0] - ynr[Pw][0] - ynr[Pe][0]) +
+ SQR(2 * ynr[0][1] - ynr[Pw][1] - ynr[Pe][1]) +
+ SQR(2 * ynr[0][2] - ynr[Pw][2] - ynr[Pe][2])) /
+ 2;
+ if (gv > gh)
+ d = HOR;
+ else
+ d = VER;
+ }
+ ndir[moff] |= d;
+ }
+ }
+}
+
+void AAHD::combine_image()
+{
+ for (int i = 0, i_out = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ int moff = nr_offset(i + nr_margin, nr_margin);
+ for (int j = 0; j < libraw.imgdata.sizes.iwidth; j++, ++moff, ++i_out)
+ {
+ if (ndir[moff] & HOT)
+ {
+ int c = libraw.COLOR(i, j);
+ rgb_ahd[1][moff][c] = rgb_ahd[0][moff][c] =
+ libraw.imgdata.image[i_out][c];
+ }
+ if (ndir[moff] & VER)
+ {
+ libraw.imgdata.image[i_out][0] = rgb_ahd[1][moff][0];
+ libraw.imgdata.image[i_out][3] = libraw.imgdata.image[i_out][1] =
+ rgb_ahd[1][moff][1];
+ libraw.imgdata.image[i_out][2] = rgb_ahd[1][moff][2];
+ }
+ else
+ {
+ libraw.imgdata.image[i_out][0] = rgb_ahd[0][moff][0];
+ libraw.imgdata.image[i_out][3] = libraw.imgdata.image[i_out][1] =
+ rgb_ahd[0][moff][1];
+ libraw.imgdata.image[i_out][2] = rgb_ahd[0][moff][2];
+ }
+ }
+ }
+}
+
+void AAHD::refine_hv_dirs()
+{
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ refine_hv_dirs(i, i & 1);
+ }
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ refine_hv_dirs(i, (i & 1) ^ 1);
+ }
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ refine_ihv_dirs(i);
+ }
+}
+
+void AAHD::refine_ihv_dirs(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ int moff = nr_offset(i + nr_margin, nr_margin);
+ for (int j = 0; j < iwidth; j++, ++moff)
+ {
+ if (ndir[moff] & HVSH)
+ continue;
+ int nv = (ndir[moff + Pn] & VER) + (ndir[moff + Ps] & VER) +
+ (ndir[moff + Pw] & VER) + (ndir[moff + Pe] & VER);
+ int nh = (ndir[moff + Pn] & HOR) + (ndir[moff + Ps] & HOR) +
+ (ndir[moff + Pw] & HOR) + (ndir[moff + Pe] & HOR);
+ nv /= VER;
+ nh /= HOR;
+ if ((ndir[moff] & VER) && nh > 3)
+ {
+ ndir[moff] &= ~VER;
+ ndir[moff] |= HOR;
+ }
+ if ((ndir[moff] & HOR) && nv > 3)
+ {
+ ndir[moff] &= ~HOR;
+ ndir[moff] |= VER;
+ }
+ }
+}
+
+void AAHD::refine_hv_dirs(int i, int js)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ int moff = nr_offset(i + nr_margin, nr_margin + js);
+ for (int j = js; j < iwidth; j += 2, moff += 2)
+ {
+ int nv = (ndir[moff + Pn] & VER) + (ndir[moff + Ps] & VER) +
+ (ndir[moff + Pw] & VER) + (ndir[moff + Pe] & VER);
+ int nh = (ndir[moff + Pn] & HOR) + (ndir[moff + Ps] & HOR) +
+ (ndir[moff + Pw] & HOR) + (ndir[moff + Pe] & HOR);
+ bool codir = (ndir[moff] & VER)
+ ? ((ndir[moff + Pn] & VER) || (ndir[moff + Ps] & VER))
+ : ((ndir[moff + Pw] & HOR) || (ndir[moff + Pe] & HOR));
+ nv /= VER;
+ nh /= HOR;
+ if ((ndir[moff] & VER) && (nh > 2 && !codir))
+ {
+ ndir[moff] &= ~VER;
+ ndir[moff] |= HOR;
+ }
+ if ((ndir[moff] & HOR) && (nv > 2 && !codir))
+ {
+ ndir[moff] &= ~HOR;
+ ndir[moff] |= VER;
+ }
+ }
+}
+
+/*
+ * вычисление недостающих зелёных точек.
+ */
+void AAHD::make_ahd_greens()
+{
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ make_ahd_gline(i);
+ }
+}
+
+void AAHD::make_ahd_gline(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ int js = libraw.COLOR(i, 0) & 1;
+ int kc = libraw.COLOR(i, js);
+ /*
+ * js -- начальная х-координата, которая попадает мимо известного зелёного
+ * kc -- известный цвет в точке интерполирования
+ */
+ int hvdir[2] = {Pe, Ps};
+ for (int d = 0; d < 2; ++d)
+ {
+ int moff = nr_offset(i + nr_margin, nr_margin + js);
+ for (int j = js; j < iwidth; j += 2, moff += 2)
+ {
+ ushort3 *cnr;
+ cnr = &rgb_ahd[d][moff];
+ int h1 = 2 * cnr[-hvdir[d]][1] - int(cnr[-2 * hvdir[d]][kc] + cnr[0][kc]);
+ int h2 = 2 * cnr[+hvdir[d]][1] - int(cnr[+2 * hvdir[d]][kc] + cnr[0][kc]);
+ int h0 = (h1 + h2) / 4;
+ int eg = cnr[0][kc] + h0;
+ int min = MIN(cnr[-hvdir[d]][1], cnr[+hvdir[d]][1]);
+ int max = MAX(cnr[-hvdir[d]][1], cnr[+hvdir[d]][1]);
+ min -= min / OverFraction;
+ max += max / OverFraction;
+ if (eg < min)
+ eg = min - sqrt(float(min - eg));
+ else if (eg > max)
+ eg = max + sqrt(float(eg - max));
+ if (eg > channel_maximum[1])
+ eg = channel_maximum[1];
+ else if (eg < channel_minimum[1])
+ eg = channel_minimum[1];
+ cnr[0][1] = eg;
+ }
+ }
+}
+
+/*
+ * отладочная функция
+ */
+
+void AAHD::illustrate_dirs()
+{
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ illustrate_dline(i);
+ }
+}
+
+void AAHD::illustrate_dline(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ for (int j = 0; j < iwidth; j++)
+ {
+ int x = j + nr_margin;
+ int y = i + nr_margin;
+ rgb_ahd[1][nr_offset(y, x)][0] = rgb_ahd[1][nr_offset(y, x)][1] =
+ rgb_ahd[1][nr_offset(y, x)][2] = rgb_ahd[0][nr_offset(y, x)][0] =
+ rgb_ahd[0][nr_offset(y, x)][1] = rgb_ahd[0][nr_offset(y, x)][2] = 0;
+ int l = ndir[nr_offset(y, x)] & HVSH;
+ l /= HVSH;
+ if (ndir[nr_offset(y, x)] & VER)
+ rgb_ahd[1][nr_offset(y, x)][0] =
+ l * channel_maximum[0] / 4 + channel_maximum[0] / 4;
+ else
+ rgb_ahd[0][nr_offset(y, x)][2] =
+ l * channel_maximum[2] / 4 + channel_maximum[2] / 4;
+ }
+}
+
+void AAHD::make_ahd_rb_hv(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ int js = libraw.COLOR(i, 0) & 1;
+ int kc = libraw.COLOR(i, js);
+ js ^= 1; // начальная координата зелёного
+ int hvdir[2] = {Pe, Ps};
+ // интерполяция вертикальных вертикально и горизонтальных горизонтально
+ for (int j = js; j < iwidth; j += 2)
+ {
+ int x = j + nr_margin;
+ int y = i + nr_margin;
+ int moff = nr_offset(y, x);
+ for (int d = 0; d < 2; ++d)
+ {
+ ushort3 *cnr;
+ cnr = &rgb_ahd[d][moff];
+ int c = kc ^ (d << 1); // цвет соответсвенного направления, для
+ // горизонтального c = kc, для вертикального c=kc^2
+ int h1 = cnr[-hvdir[d]][c] - cnr[-hvdir[d]][1];
+ int h2 = cnr[+hvdir[d]][c] - cnr[+hvdir[d]][1];
+ int h0 = (h1 + h2) / 2;
+ int eg = cnr[0][1] + h0;
+ // int min = MIN(cnr[-hvdir[d]][c], cnr[+hvdir[d]][c]);
+ // int max = MAX(cnr[-hvdir[d]][c], cnr[+hvdir[d]][c]);
+ // min -= min / OverFraction;
+ // max += max / OverFraction;
+ // if (eg < min)
+ // eg = min - sqrt(min - eg);
+ // else if (eg > max)
+ // eg = max + sqrt(eg - max);
+ if (eg > channel_maximum[c])
+ eg = channel_maximum[c];
+ else if (eg < channel_minimum[c])
+ eg = channel_minimum[c];
+ cnr[0][c] = eg;
+ }
+ }
+}
+
+void AAHD::make_ahd_rb()
+{
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ make_ahd_rb_hv(i);
+ }
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ make_ahd_rb_last(i);
+ }
+}
+
+void AAHD::make_ahd_rb_last(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ int js = libraw.COLOR(i, 0) & 1;
+ int kc = libraw.COLOR(i, js);
+ /*
+ * js -- начальная х-координата, которая попадает мимо известного зелёного
+ * kc -- известный цвет в точке интерполирования
+ */
+ int dirs[2][3] = {{Pnw, Pn, Pne}, {Pnw, Pw, Psw}};
+ int moff = nr_offset(i + nr_margin, nr_margin);
+ for (int j = 0; j < iwidth; j++)
+ {
+ for (int d = 0; d < 2; ++d)
+ {
+ ushort3 *cnr;
+ cnr = &rgb_ahd[d][moff + j];
+ int c = kc ^ 2;
+ if ((j & 1) != js)
+ {
+ // точка зелёного, для вертикального направления нужен альтернативный
+ // строчному цвет
+ c ^= d << 1;
+ }
+ int bh = 0, bk = 0;
+ int bgd = 0;
+ for (int k = 0; k < 3; ++k)
+ for (int h = 0; h < 3; ++h)
+ {
+ // градиент зелёного плюс градиент {r,b}
+ int gd =
+ ABS(2 * cnr[0][1] - (cnr[+dirs[d][k]][1] + cnr[-dirs[d][h]][1])) +
+ ABS(cnr[+dirs[d][k]][c] - cnr[-dirs[d][h]][c]) / 4 +
+ ABS(cnr[+dirs[d][k]][c] - cnr[+dirs[d][k]][1] +
+ cnr[-dirs[d][h]][1] - cnr[-dirs[d][h]][c]) /
+ 4;
+ if (bgd == 0 || gd < bgd)
+ {
+ bgd = gd;
+ bh = h;
+ bk = k;
+ }
+ }
+ int h1 = cnr[+dirs[d][bk]][c] - cnr[+dirs[d][bk]][1];
+ int h2 = cnr[-dirs[d][bh]][c] - cnr[-dirs[d][bh]][1];
+ int eg = cnr[0][1] + (h1 + h2) / 2;
+ // int min = MIN(cnr[+dirs[d][bk]][c], cnr[-dirs[d][bh]][c]);
+ // int max = MAX(cnr[+dirs[d][bk]][c], cnr[-dirs[d][bh]][c]);
+ // min -= min / OverFraction;
+ // max += max / OverFraction;
+ // if (eg < min)
+ // eg = min - sqrt(min - eg);
+ // else if (eg > max)
+ // eg = max + sqrt(eg - max);
+ if (eg > channel_maximum[c])
+ eg = channel_maximum[c];
+ else if (eg < channel_minimum[c])
+ eg = channel_minimum[c];
+ cnr[0][c] = eg;
+ }
+ }
+}
+
+AAHD::~AAHD() { free(rgb_ahd[0]); }
+
+void LibRaw::aahd_interpolate()
+{
+ AAHD aahd(*this);
+ aahd.hide_hots();
+ aahd.make_ahd_greens();
+ aahd.make_ahd_rb();
+ aahd.evaluate_ahd();
+ aahd.refine_hv_dirs();
+ // aahd.illustrate_dirs();
+ aahd.combine_image();
+}
diff --git a/libkdcraw/libraw/src/demosaic/ahd_demosaic.cpp b/libkdcraw/libraw/src/demosaic/ahd_demosaic.cpp
new file mode 100644
index 0000000..e743c96
--- /dev/null
+++ b/libkdcraw/libraw/src/demosaic/ahd_demosaic.cpp
@@ -0,0 +1,355 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+/*
+ Adaptive Homogeneity-Directed interpolation is based on
+ the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
+ */
+
+void LibRaw::cielab(ushort rgb[3], short lab[3])
+{
+ int c, i, j, k;
+ float r, xyz[3];
+#ifdef LIBRAW_NOTHREADS
+ static float cbrt[0x10000], xyz_cam[3][4];
+#else
+#define cbrt tls->ahd_data.cbrt
+#define xyz_cam tls->ahd_data.xyz_cam
+#endif
+
+ if (!rgb)
+ {
+#ifndef LIBRAW_NOTHREADS
+ if (cbrt[0] < -1.0f)
+#endif
+ for (i = 0; i < 0x10000; i++)
+ {
+ r = i / 65535.0;
+ cbrt[i] =
+ r > 0.008856 ? pow(r, 1.f / 3.0f) : 7.787f * r + 16.f / 116.0f;
+ }
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < colors; j++)
+ for (xyz_cam[i][j] = k = 0; k < 3; k++)
+ xyz_cam[i][j] += LibRaw_constants::xyz_rgb[i][k] * rgb_cam[k][j] /
+ LibRaw_constants::d65_white[i];
+ return;
+ }
+ xyz[0] = xyz[1] = xyz[2] = 0.5;
+ FORCC
+ {
+ xyz[0] += xyz_cam[0][c] * rgb[c];
+ xyz[1] += xyz_cam[1][c] * rgb[c];
+ xyz[2] += xyz_cam[2][c] * rgb[c];
+ }
+ xyz[0] = cbrt[CLIP((int)xyz[0])];
+ xyz[1] = cbrt[CLIP((int)xyz[1])];
+ xyz[2] = cbrt[CLIP((int)xyz[2])];
+ lab[0] = 64 * (116 * xyz[1] - 16);
+ lab[1] = 64 * 500 * (xyz[0] - xyz[1]);
+ lab[2] = 64 * 200 * (xyz[1] - xyz[2]);
+#ifndef LIBRAW_NOTHREADS
+#undef cbrt
+#undef xyz_cam
+#endif
+}
+
+void LibRaw::ahd_interpolate_green_h_and_v(
+ int top, int left, ushort (*out_rgb)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3])
+{
+ int row, col;
+ int c, val;
+ ushort(*pix)[4];
+ const int rowlimit = MIN(top + LIBRAW_AHD_TILE, height - 2);
+ const int collimit = MIN(left + LIBRAW_AHD_TILE, width - 2);
+
+ for (row = top; row < rowlimit; row++)
+ {
+ col = left + (FC(row, left) & 1);
+ for (c = FC(row, col); col < collimit; col += 2)
+ {
+ pix = image + row * width + col;
+ val =
+ ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 - pix[-2][c] - pix[2][c]) >>
+ 2;
+ out_rgb[0][row - top][col - left][1] = ULIM(val, pix[-1][1], pix[1][1]);
+ val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 -
+ pix[-2 * width][c] - pix[2 * width][c]) >>
+ 2;
+ out_rgb[1][row - top][col - left][1] =
+ ULIM(val, pix[-width][1], pix[width][1]);
+ }
+ }
+}
+void LibRaw::ahd_interpolate_r_and_b_in_rgb_and_convert_to_cielab(
+ int top, int left, ushort (*inout_rgb)[LIBRAW_AHD_TILE][3],
+ short (*out_lab)[LIBRAW_AHD_TILE][3])
+{
+ unsigned row, col;
+ int c, val;
+ ushort(*pix)[4];
+ ushort(*rix)[3];
+ short(*lix)[3];
+ const unsigned num_pix_per_row = 4 * width;
+ const unsigned rowlimit = MIN(top + LIBRAW_AHD_TILE - 1, height - 3);
+ const unsigned collimit = MIN(left + LIBRAW_AHD_TILE - 1, width - 3);
+ ushort *pix_above;
+ ushort *pix_below;
+ int t1, t2;
+
+ for (row = top + 1; row < rowlimit; row++)
+ {
+ pix = image + row * width + left;
+ rix = &inout_rgb[row - top][0];
+ lix = &out_lab[row - top][0];
+
+ for (col = left + 1; col < collimit; col++)
+ {
+ pix++;
+ pix_above = &pix[0][0] - num_pix_per_row;
+ pix_below = &pix[0][0] + num_pix_per_row;
+ rix++;
+ lix++;
+
+ c = 2 - FC(row, col);
+
+ if (c == 1)
+ {
+ c = FC(row + 1, col);
+ t1 = 2 - c;
+ val = pix[0][1] +
+ ((pix[-1][t1] + pix[1][t1] - rix[-1][1] - rix[1][1]) >> 1);
+ rix[0][t1] = CLIP(val);
+ val =
+ pix[0][1] + ((pix_above[c] + pix_below[c] -
+ rix[-LIBRAW_AHD_TILE][1] - rix[LIBRAW_AHD_TILE][1]) >>
+ 1);
+ }
+ else
+ {
+ t1 = -4 + c; /* -4+c: pixel of color c to the left */
+ t2 = 4 + c; /* 4+c: pixel of color c to the right */
+ val = rix[0][1] +
+ ((pix_above[t1] + pix_above[t2] + pix_below[t1] + pix_below[t2] -
+ rix[-LIBRAW_AHD_TILE - 1][1] - rix[-LIBRAW_AHD_TILE + 1][1] -
+ rix[+LIBRAW_AHD_TILE - 1][1] - rix[+LIBRAW_AHD_TILE + 1][1] +
+ 1) >>
+ 2);
+ }
+ rix[0][c] = CLIP(val);
+ c = FC(row, col);
+ rix[0][c] = pix[0][c];
+ cielab(rix[0], lix[0]);
+ }
+ }
+}
+void LibRaw::ahd_interpolate_r_and_b_and_convert_to_cielab(
+ int top, int left, ushort (*inout_rgb)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3],
+ short (*out_lab)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3])
+{
+ int direction;
+ for (direction = 0; direction < 2; direction++)
+ {
+ ahd_interpolate_r_and_b_in_rgb_and_convert_to_cielab(
+ top, left, inout_rgb[direction], out_lab[direction]);
+ }
+}
+
+void LibRaw::ahd_interpolate_build_homogeneity_map(
+ int top, int left, short (*lab)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3],
+ char (*out_homogeneity_map)[LIBRAW_AHD_TILE][2])
+{
+ int row, col;
+ int tr;
+ int direction;
+ int i;
+ short(*lix)[3];
+ short(*lixs[2])[3];
+ short *adjacent_lix;
+ unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
+ static const int dir[4] = {-1, 1, -LIBRAW_AHD_TILE, LIBRAW_AHD_TILE};
+ const int rowlimit = MIN(top + LIBRAW_AHD_TILE - 2, height - 4);
+ const int collimit = MIN(left + LIBRAW_AHD_TILE - 2, width - 4);
+ int homogeneity;
+ char(*homogeneity_map_p)[2];
+
+ memset(out_homogeneity_map, 0, 2 * LIBRAW_AHD_TILE * LIBRAW_AHD_TILE);
+
+ for (row = top + 2; row < rowlimit; row++)
+ {
+ tr = row - top;
+ homogeneity_map_p = &out_homogeneity_map[tr][1];
+ for (direction = 0; direction < 2; direction++)
+ {
+ lixs[direction] = &lab[direction][tr][1];
+ }
+
+ for (col = left + 2; col < collimit; col++)
+ {
+ homogeneity_map_p++;
+
+ for (direction = 0; direction < 2; direction++)
+ {
+ lix = ++lixs[direction];
+ for (i = 0; i < 4; i++)
+ {
+ adjacent_lix = lix[dir[i]];
+ ldiff[direction][i] = ABS(lix[0][0] - adjacent_lix[0]);
+ abdiff[direction][i] = SQR(lix[0][1] - adjacent_lix[1]) +
+ SQR(lix[0][2] - adjacent_lix[2]);
+ }
+ }
+ leps = MIN(MAX(ldiff[0][0], ldiff[0][1]), MAX(ldiff[1][2], ldiff[1][3]));
+ abeps =
+ MIN(MAX(abdiff[0][0], abdiff[0][1]), MAX(abdiff[1][2], abdiff[1][3]));
+ for (direction = 0; direction < 2; direction++)
+ {
+ homogeneity = 0;
+ for (i = 0; i < 4; i++)
+ {
+ if (ldiff[direction][i] <= leps && abdiff[direction][i] <= abeps)
+ {
+ homogeneity++;
+ }
+ }
+ homogeneity_map_p[0][direction] = homogeneity;
+ }
+ }
+ }
+}
+void LibRaw::ahd_interpolate_combine_homogeneous_pixels(
+ int top, int left, ushort (*rgb)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3],
+ char (*homogeneity_map)[LIBRAW_AHD_TILE][2])
+{
+ int row, col;
+ int tr, tc;
+ int i, j;
+ int direction;
+ int hm[2];
+ int c;
+ const int rowlimit = MIN(top + LIBRAW_AHD_TILE - 3, height - 5);
+ const int collimit = MIN(left + LIBRAW_AHD_TILE - 3, width - 5);
+
+ ushort(*pix)[4];
+ ushort(*rix[2])[3];
+
+ for (row = top + 3; row < rowlimit; row++)
+ {
+ tr = row - top;
+ pix = &image[row * width + left + 2];
+ for (direction = 0; direction < 2; direction++)
+ {
+ rix[direction] = &rgb[direction][tr][2];
+ }
+
+ for (col = left + 3; col < collimit; col++)
+ {
+ tc = col - left;
+ pix++;
+ for (direction = 0; direction < 2; direction++)
+ {
+ rix[direction]++;
+ }
+
+ for (direction = 0; direction < 2; direction++)
+ {
+ hm[direction] = 0;
+ for (i = tr - 1; i <= tr + 1; i++)
+ {
+ for (j = tc - 1; j <= tc + 1; j++)
+ {
+ hm[direction] += homogeneity_map[i][j][direction];
+ }
+ }
+ }
+ if (hm[0] != hm[1])
+ {
+ memcpy(pix[0], rix[hm[1] > hm[0]][0], 3 * sizeof(ushort));
+ }
+ else
+ {
+ FORC3 { pix[0][c] = (rix[0][0][c] + rix[1][0][c]) >> 1; }
+ }
+ }
+ }
+}
+void LibRaw::ahd_interpolate()
+{
+ int terminate_flag = 0;
+ cielab(0, 0);
+ border_interpolate(5);
+
+#ifdef LIBRAW_USE_OPENMP
+ int buffer_count = omp_get_max_threads();
+#else
+ int buffer_count = 1;
+#endif
+
+ size_t buffer_size = 26 * LIBRAW_AHD_TILE * LIBRAW_AHD_TILE; /* 1664 kB */
+ char** buffers = malloc_omp_buffers(buffer_count, buffer_size);
+
+#ifdef LIBRAW_USE_OPENMP
+#pragma omp parallel for schedule(dynamic) default(none) shared(terminate_flag) firstprivate(buffers)
+#endif
+ for (int top = 2; top < height - 5; top += LIBRAW_AHD_TILE - 6)
+ {
+#ifdef LIBRAW_USE_OPENMP
+ if (0 == omp_get_thread_num())
+#endif
+ if (callbacks.progress_cb)
+ {
+ int rr = (*callbacks.progress_cb)(callbacks.progresscb_data,
+ LIBRAW_PROGRESS_INTERPOLATE,
+ top - 2, height - 7);
+ if (rr)
+ terminate_flag = 1;
+ }
+
+#if defined(LIBRAW_USE_OPENMP)
+ char* buffer = buffers[omp_get_thread_num()];
+#else
+ char* buffer = buffers[0];
+#endif
+
+ ushort(*rgb)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3];
+ short(*lab)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3];
+ char(*homo)[LIBRAW_AHD_TILE][2];
+
+ rgb = (ushort(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3])buffer;
+ lab = (short(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3])(
+ buffer + 12 * LIBRAW_AHD_TILE * LIBRAW_AHD_TILE);
+ homo = (char(*)[LIBRAW_AHD_TILE][2])(buffer + 24 * LIBRAW_AHD_TILE *
+ LIBRAW_AHD_TILE);
+
+ for (int left = 2; !terminate_flag && (left < width - 5);
+ left += LIBRAW_AHD_TILE - 6)
+ {
+ ahd_interpolate_green_h_and_v(top, left, rgb);
+ ahd_interpolate_r_and_b_and_convert_to_cielab(top, left, rgb, lab);
+ ahd_interpolate_build_homogeneity_map(top, left, lab, homo);
+ ahd_interpolate_combine_homogeneous_pixels(top, left, rgb, homo);
+ }
+ }
+
+ free_omp_buffers(buffers, buffer_count);
+
+ if (terminate_flag)
+ throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK;
+}
diff --git a/libkdcraw/libraw/src/demosaic/dcb_demosaic.cpp b/libkdcraw/libraw/src/demosaic/dcb_demosaic.cpp
new file mode 100644
index 0000000..f25292b
--- /dev/null
+++ b/libkdcraw/libraw/src/demosaic/dcb_demosaic.cpp
@@ -0,0 +1,900 @@
+/*
+ * Copyright (C) 2010, Jacek Gozdz ([email protected])
+ *
+ * This code is licensed under a (3-clause) BSD license as follows :
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the author nor the names of its
+ * contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+// DCB demosaicing by Jacek Gozdz ([email protected])
+
+// FBDD denoising by Jacek Gozdz ([email protected]) and
+// Luis Sanz Rodríguez ([email protected])
+
+// last modification: 11.07.2010
+
+#include "../../internal/dcraw_defs.h"
+
+// interpolates green vertically and saves it to image3
+void LibRaw::dcb_ver(float (*image3)[3])
+{
+ int row, col, u = width, indx;
+
+ for (row = 2; row < height - 2; row++)
+ for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
+ col += 2, indx += 2)
+ {
+
+ image3[indx][1] = CLIP((image[indx + u][1] + image[indx - u][1]) / 2.0);
+ }
+}
+
+// interpolates green horizontally and saves it to image2
+void LibRaw::dcb_hor(float (*image2)[3])
+{
+ int row, col, u = width, indx;
+
+ for (row = 2; row < height - 2; row++)
+ for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
+ col += 2, indx += 2)
+ {
+
+ image2[indx][1] = CLIP((image[indx + 1][1] + image[indx - 1][1]) / 2.0);
+ }
+}
+
+// missing colors are interpolated
+void LibRaw::dcb_color()
+{
+ int row, col, c, d, u = width, indx;
+
+ for (row = 1; row < height - 1; row++)
+ for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
+ c = 2 - FC(row, col);
+ col < u - 1; col += 2, indx += 2)
+ {
+
+ image[indx][c] = CLIP((4 * image[indx][1] - image[indx + u + 1][1] -
+ image[indx + u - 1][1] - image[indx - u + 1][1] -
+ image[indx - u - 1][1] + image[indx + u + 1][c] +
+ image[indx + u - 1][c] + image[indx - u + 1][c] +
+ image[indx - u - 1][c]) /
+ 4.0);
+ }
+
+ for (row = 1; row < height - 1; row++)
+ for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
+ c = FC(row, col + 1), d = 2 - c;
+ col < width - 1; col += 2, indx += 2)
+ {
+
+ image[indx][c] =
+ CLIP((2 * image[indx][1] - image[indx + 1][1] - image[indx - 1][1] +
+ image[indx + 1][c] + image[indx - 1][c]) /
+ 2.0);
+ image[indx][d] =
+ CLIP((2 * image[indx][1] - image[indx + u][1] - image[indx - u][1] +
+ image[indx + u][d] + image[indx - u][d]) /
+ 2.0);
+ }
+}
+
+// missing R and B are interpolated horizontally and saved in image2
+void LibRaw::dcb_color2(float (*image2)[3])
+{
+ int row, col, c, d, u = width, indx;
+
+ for (row = 1; row < height - 1; row++)
+ for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
+ c = 2 - FC(row, col);
+ col < u - 1; col += 2, indx += 2)
+ {
+
+ image2[indx][c] =
+ CLIP((4 * image2[indx][1] - image2[indx + u + 1][1] -
+ image2[indx + u - 1][1] - image2[indx - u + 1][1] -
+ image2[indx - u - 1][1] + image[indx + u + 1][c] +
+ image[indx + u - 1][c] + image[indx - u + 1][c] +
+ image[indx - u - 1][c]) /
+ 4.0);
+ }
+
+ for (row = 1; row < height - 1; row++)
+ for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
+ c = FC(row, col + 1), d = 2 - c;
+ col < width - 1; col += 2, indx += 2)
+ {
+
+ image2[indx][c] = CLIP((image[indx + 1][c] + image[indx - 1][c]) / 2.0);
+ image2[indx][d] =
+ CLIP((2 * image2[indx][1] - image2[indx + u][1] -
+ image2[indx - u][1] + image[indx + u][d] + image[indx - u][d]) /
+ 2.0);
+ }
+}
+
+// missing R and B are interpolated vertically and saved in image3
+void LibRaw::dcb_color3(float (*image3)[3])
+{
+ int row, col, c, d, u = width, indx;
+
+ for (row = 1; row < height - 1; row++)
+ for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
+ c = 2 - FC(row, col);
+ col < u - 1; col += 2, indx += 2)
+ {
+
+ image3[indx][c] =
+ CLIP((4 * image3[indx][1] - image3[indx + u + 1][1] -
+ image3[indx + u - 1][1] - image3[indx - u + 1][1] -
+ image3[indx - u - 1][1] + image[indx + u + 1][c] +
+ image[indx + u - 1][c] + image[indx - u + 1][c] +
+ image[indx - u - 1][c]) /
+ 4.0);
+ }
+
+ for (row = 1; row < height - 1; row++)
+ for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
+ c = FC(row, col + 1), d = 2 - c;
+ col < width - 1; col += 2, indx += 2)
+ {
+
+ image3[indx][c] =
+ CLIP((2 * image3[indx][1] - image3[indx + 1][1] -
+ image3[indx - 1][1] + image[indx + 1][c] + image[indx - 1][c]) /
+ 2.0);
+ image3[indx][d] = CLIP((image[indx + u][d] + image[indx - u][d]) / 2.0);
+ }
+}
+
+// decides the primary green interpolation direction
+void LibRaw::dcb_decide(float (*image2)[3], float (*image3)[3])
+{
+ int row, col, c, d, u = width, v = 2 * u, indx;
+ float current, current2, current3;
+
+ for (row = 2; row < height - 2; row++)
+ for (col = 2 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
+ col < u - 2; col += 2, indx += 2)
+ {
+
+ d = ABS(c - 2);
+
+ current = MAX(image[indx + v][c],
+ MAX(image[indx - v][c],
+ MAX(image[indx - 2][c], image[indx + 2][c]))) -
+ MIN(image[indx + v][c],
+ MIN(image[indx - v][c],
+ MIN(image[indx - 2][c], image[indx + 2][c]))) +
+ MAX(image[indx + 1 + u][d],
+ MAX(image[indx + 1 - u][d],
+ MAX(image[indx - 1 + u][d], image[indx - 1 - u][d]))) -
+ MIN(image[indx + 1 + u][d],
+ MIN(image[indx + 1 - u][d],
+ MIN(image[indx - 1 + u][d], image[indx - 1 - u][d])));
+
+ current2 =
+ MAX(image2[indx + v][d],
+ MAX(image2[indx - v][d],
+ MAX(image2[indx - 2][d], image2[indx + 2][d]))) -
+ MIN(image2[indx + v][d],
+ MIN(image2[indx - v][d],
+ MIN(image2[indx - 2][d], image2[indx + 2][d]))) +
+ MAX(image2[indx + 1 + u][c],
+ MAX(image2[indx + 1 - u][c],
+ MAX(image2[indx - 1 + u][c], image2[indx - 1 - u][c]))) -
+ MIN(image2[indx + 1 + u][c],
+ MIN(image2[indx + 1 - u][c],
+ MIN(image2[indx - 1 + u][c], image2[indx - 1 - u][c])));
+
+ current3 =
+ MAX(image3[indx + v][d],
+ MAX(image3[indx - v][d],
+ MAX(image3[indx - 2][d], image3[indx + 2][d]))) -
+ MIN(image3[indx + v][d],
+ MIN(image3[indx - v][d],
+ MIN(image3[indx - 2][d], image3[indx + 2][d]))) +
+ MAX(image3[indx + 1 + u][c],
+ MAX(image3[indx + 1 - u][c],
+ MAX(image3[indx - 1 + u][c], image3[indx - 1 - u][c]))) -
+ MIN(image3[indx + 1 + u][c],
+ MIN(image3[indx + 1 - u][c],
+ MIN(image3[indx - 1 + u][c], image3[indx - 1 - u][c])));
+
+ if (ABS(current - current2) < ABS(current - current3))
+ image[indx][1] = image2[indx][1];
+ else
+ image[indx][1] = image3[indx][1];
+ }
+}
+
+// saves red and blue in image2
+void LibRaw::dcb_copy_to_buffer(float (*image2)[3])
+{
+ int indx;
+
+ for (indx = 0; indx < height * width; indx++)
+ {
+ image2[indx][0] = image[indx][0]; // R
+ image2[indx][2] = image[indx][2]; // B
+ }
+}
+
+// restores red and blue from image2
+void LibRaw::dcb_restore_from_buffer(float (*image2)[3])
+{
+ int indx;
+
+ for (indx = 0; indx < height * width; indx++)
+ {
+ image[indx][0] = image2[indx][0]; // R
+ image[indx][2] = image2[indx][2]; // B
+ }
+}
+
+// R and B smoothing using green contrast, all pixels except 2 pixel wide border
+void LibRaw::dcb_pp()
+{
+ int g1, r1, b1, u = width, indx, row, col;
+
+ for (row = 2; row < height - 2; row++)
+ for (col = 2, indx = row * u + col; col < width - 2; col++, indx++)
+ {
+
+ r1 = (image[indx - 1][0] + image[indx + 1][0] + image[indx - u][0] +
+ image[indx + u][0] + image[indx - u - 1][0] +
+ image[indx + u + 1][0] + image[indx - u + 1][0] +
+ image[indx + u - 1][0]) /
+ 8.0;
+ g1 = (image[indx - 1][1] + image[indx + 1][1] + image[indx - u][1] +
+ image[indx + u][1] + image[indx - u - 1][1] +
+ image[indx + u + 1][1] + image[indx - u + 1][1] +
+ image[indx + u - 1][1]) /
+ 8.0;
+ b1 = (image[indx - 1][2] + image[indx + 1][2] + image[indx - u][2] +
+ image[indx + u][2] + image[indx - u - 1][2] +
+ image[indx + u + 1][2] + image[indx - u + 1][2] +
+ image[indx + u - 1][2]) /
+ 8.0;
+
+ image[indx][0] = CLIP(r1 + (image[indx][1] - g1));
+ image[indx][2] = CLIP(b1 + (image[indx][1] - g1));
+ }
+}
+
+// green blurring correction, helps to get the nyquist right
+void LibRaw::dcb_nyquist()
+{
+ int row, col, c, u = width, v = 2 * u, indx;
+
+ for (row = 2; row < height - 2; row++)
+ for (col = 2 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
+ col < u - 2; col += 2, indx += 2)
+ {
+
+ image[indx][1] = CLIP((image[indx + v][1] + image[indx - v][1] +
+ image[indx - 2][1] + image[indx + 2][1]) /
+ 4.0 +
+ image[indx][c] -
+ (image[indx + v][c] + image[indx - v][c] +
+ image[indx - 2][c] + image[indx + 2][c]) /
+ 4.0);
+ }
+}
+
+// missing colors are interpolated using high quality algorithm by Luis Sanz
+// Rodríguez
+void LibRaw::dcb_color_full()
+{
+ int row, col, c, d, u = width, w = 3 * u, indx, g1, g2;
+ float f[4], g[4], (*chroma)[2];
+
+ chroma = (float(*)[2])calloc(width * height, sizeof *chroma);
+
+ for (row = 1; row < height - 1; row++)
+ for (col = 1 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col),
+ d = c / 2;
+ col < u - 1; col += 2, indx += 2)
+ chroma[indx][d] = image[indx][c] - image[indx][1];
+
+ for (row = 3; row < height - 3; row++)
+ for (col = 3 + (FC(row, 1) & 1), indx = row * width + col,
+ c = 1 - FC(row, col) / 2, d = 1 - c;
+ col < u - 3; col += 2, indx += 2)
+ {
+ f[0] = 1.0 /
+ (float)(1.0 +
+ fabs(chroma[indx - u - 1][c] - chroma[indx + u + 1][c]) +
+ fabs(chroma[indx - u - 1][c] - chroma[indx - w - 3][c]) +
+ fabs(chroma[indx + u + 1][c] - chroma[indx - w - 3][c]));
+ f[1] = 1.0 /
+ (float)(1.0 +
+ fabs(chroma[indx - u + 1][c] - chroma[indx + u - 1][c]) +
+ fabs(chroma[indx - u + 1][c] - chroma[indx - w + 3][c]) +
+ fabs(chroma[indx + u - 1][c] - chroma[indx - w + 3][c]));
+ f[2] = 1.0 /
+ (float)(1.0 +
+ fabs(chroma[indx + u - 1][c] - chroma[indx - u + 1][c]) +
+ fabs(chroma[indx + u - 1][c] - chroma[indx + w + 3][c]) +
+ fabs(chroma[indx - u + 1][c] - chroma[indx + w - 3][c]));
+ f[3] = 1.0 /
+ (float)(1.0 +
+ fabs(chroma[indx + u + 1][c] - chroma[indx - u - 1][c]) +
+ fabs(chroma[indx + u + 1][c] - chroma[indx + w - 3][c]) +
+ fabs(chroma[indx - u - 1][c] - chroma[indx + w + 3][c]));
+ g[0] = 1.325 * chroma[indx - u - 1][c] - 0.175 * chroma[indx - w - 3][c] -
+ 0.075 * chroma[indx - w - 1][c] - 0.075 * chroma[indx - u - 3][c];
+ g[1] = 1.325 * chroma[indx - u + 1][c] - 0.175 * chroma[indx - w + 3][c] -
+ 0.075 * chroma[indx - w + 1][c] - 0.075 * chroma[indx - u + 3][c];
+ g[2] = 1.325 * chroma[indx + u - 1][c] - 0.175 * chroma[indx + w - 3][c] -
+ 0.075 * chroma[indx + w - 1][c] - 0.075 * chroma[indx + u - 3][c];
+ g[3] = 1.325 * chroma[indx + u + 1][c] - 0.175 * chroma[indx + w + 3][c] -
+ 0.075 * chroma[indx + w + 1][c] - 0.075 * chroma[indx + u + 3][c];
+ chroma[indx][c] =
+ (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
+ (f[0] + f[1] + f[2] + f[3]);
+ }
+ for (row = 3; row < height - 3; row++)
+ for (col = 3 + (FC(row, 2) & 1), indx = row * width + col,
+ c = FC(row, col + 1) / 2;
+ col < u - 3; col += 2, indx += 2)
+ for (d = 0; d <= 1; c = 1 - c, d++)
+ {
+ f[0] = 1.0 /
+ (float)(1.0 + fabs(chroma[indx - u][c] - chroma[indx + u][c]) +
+ fabs(chroma[indx - u][c] - chroma[indx - w][c]) +
+ fabs(chroma[indx + u][c] - chroma[indx - w][c]));
+ f[1] = 1.0 /
+ (float)(1.0 + fabs(chroma[indx + 1][c] - chroma[indx - 1][c]) +
+ fabs(chroma[indx + 1][c] - chroma[indx + 3][c]) +
+ fabs(chroma[indx - 1][c] - chroma[indx + 3][c]));
+ f[2] = 1.0 /
+ (float)(1.0 + fabs(chroma[indx - 1][c] - chroma[indx + 1][c]) +
+ fabs(chroma[indx - 1][c] - chroma[indx - 3][c]) +
+ fabs(chroma[indx + 1][c] - chroma[indx - 3][c]));
+ f[3] = 1.0 /
+ (float)(1.0 + fabs(chroma[indx + u][c] - chroma[indx - u][c]) +
+ fabs(chroma[indx + u][c] - chroma[indx + w][c]) +
+ fabs(chroma[indx - u][c] - chroma[indx + w][c]));
+
+ g[0] = 0.875 * chroma[indx - u][c] + 0.125 * chroma[indx - w][c];
+ g[1] = 0.875 * chroma[indx + 1][c] + 0.125 * chroma[indx + 3][c];
+ g[2] = 0.875 * chroma[indx - 1][c] + 0.125 * chroma[indx - 3][c];
+ g[3] = 0.875 * chroma[indx + u][c] + 0.125 * chroma[indx + w][c];
+
+ chroma[indx][c] =
+ (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
+ (f[0] + f[1] + f[2] + f[3]);
+ }
+
+ for (row = 6; row < height - 6; row++)
+ for (col = 6, indx = row * width + col; col < width - 6; col++, indx++)
+ {
+ image[indx][0] = CLIP(chroma[indx][0] + image[indx][1]);
+ image[indx][2] = CLIP(chroma[indx][1] + image[indx][1]);
+
+ g1 = MIN(
+ image[indx + 1 + u][0],
+ MIN(image[indx + 1 - u][0],
+ MIN(image[indx - 1 + u][0],
+ MIN(image[indx - 1 - u][0],
+ MIN(image[indx - 1][0],
+ MIN(image[indx + 1][0],
+ MIN(image[indx - u][0], image[indx + u][0])))))));
+
+ g2 = MAX(
+ image[indx + 1 + u][0],
+ MAX(image[indx + 1 - u][0],
+ MAX(image[indx - 1 + u][0],
+ MAX(image[indx - 1 - u][0],
+ MAX(image[indx - 1][0],
+ MAX(image[indx + 1][0],
+ MAX(image[indx - u][0], image[indx + u][0])))))));
+
+ image[indx][0] = ULIM(image[indx][0], g2, g1);
+
+ g1 = MIN(
+ image[indx + 1 + u][2],
+ MIN(image[indx + 1 - u][2],
+ MIN(image[indx - 1 + u][2],
+ MIN(image[indx - 1 - u][2],
+ MIN(image[indx - 1][2],
+ MIN(image[indx + 1][2],
+ MIN(image[indx - u][2], image[indx + u][2])))))));
+
+ g2 = MAX(
+ image[indx + 1 + u][2],
+ MAX(image[indx + 1 - u][2],
+ MAX(image[indx - 1 + u][2],
+ MAX(image[indx - 1 - u][2],
+ MAX(image[indx - 1][2],
+ MAX(image[indx + 1][2],
+ MAX(image[indx - u][2], image[indx + u][2])))))));
+
+ image[indx][2] = ULIM(image[indx][2], g2, g1);
+ }
+
+ free(chroma);
+}
+
+// green is used to create an interpolation direction map saved in image[][3]
+// 1 = vertical
+// 0 = horizontal
+void LibRaw::dcb_map()
+{
+ int row, col, u = width, indx;
+
+ for (row = 1; row < height - 1; row++)
+ {
+ for (col = 1, indx = row * width + col; col < width - 1; col++, indx++)
+ {
+
+ if (image[indx][1] > (image[indx - 1][1] + image[indx + 1][1] +
+ image[indx - u][1] + image[indx + u][1]) /
+ 4.0)
+ image[indx][3] = ((MIN(image[indx - 1][1], image[indx + 1][1]) +
+ image[indx - 1][1] + image[indx + 1][1]) <
+ (MIN(image[indx - u][1], image[indx + u][1]) +
+ image[indx - u][1] + image[indx + u][1]));
+ else
+ image[indx][3] = ((MAX(image[indx - 1][1], image[indx + 1][1]) +
+ image[indx - 1][1] + image[indx + 1][1]) >
+ (MAX(image[indx - u][1], image[indx + u][1]) +
+ image[indx - u][1] + image[indx + u][1]));
+ }
+ }
+}
+
+// interpolated green pixels are corrected using the map
+void LibRaw::dcb_correction()
+{
+ int current, row, col, u = width, v = 2 * u, indx;
+
+ for (row = 2; row < height - 2; row++)
+ for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
+ col += 2, indx += 2)
+ {
+
+ current = 4 * image[indx][3] +
+ 2 * (image[indx + u][3] + image[indx - u][3] +
+ image[indx + 1][3] + image[indx - 1][3]) +
+ image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] +
+ image[indx - 2][3];
+
+ image[indx][1] =
+ ((16 - current) * (image[indx - 1][1] + image[indx + 1][1]) / 2.0 +
+ current * (image[indx - u][1] + image[indx + u][1]) / 2.0) /
+ 16.0;
+ }
+}
+
+// interpolated green pixels are corrected using the map
+// with contrast correction
+void LibRaw::dcb_correction2()
+{
+ int current, row, col, c, u = width, v = 2 * u, indx;
+
+ for (row = 4; row < height - 4; row++)
+ for (col = 4 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
+ col < u - 4; col += 2, indx += 2)
+ {
+
+ current = 4 * image[indx][3] +
+ 2 * (image[indx + u][3] + image[indx - u][3] +
+ image[indx + 1][3] + image[indx - 1][3]) +
+ image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] +
+ image[indx - 2][3];
+
+ image[indx][1] = CLIP(
+ ((16 - current) * ((image[indx - 1][1] + image[indx + 1][1]) / 2.0 +
+ image[indx][c] -
+ (image[indx + 2][c] + image[indx - 2][c]) / 2.0) +
+ current * ((image[indx - u][1] + image[indx + u][1]) / 2.0 +
+ image[indx][c] -
+ (image[indx + v][c] + image[indx - v][c]) / 2.0)) /
+ 16.0);
+ }
+}
+
+void LibRaw::dcb_refinement()
+{
+ int row, col, c, u = width, v = 2 * u, w = 3 * u, indx, current;
+ float f[5], g1, g2;
+
+ for (row = 4; row < height - 4; row++)
+ for (col = 4 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
+ col < u - 4; col += 2, indx += 2)
+ {
+
+ current = 4 * image[indx][3] +
+ 2 * (image[indx + u][3] + image[indx - u][3] +
+ image[indx + 1][3] + image[indx - 1][3]) +
+ image[indx + v][3] + image[indx - v][3] + image[indx - 2][3] +
+ image[indx + 2][3];
+
+ if (image[indx][c] > 1)
+ {
+
+ f[0] = (float)(image[indx - u][1] + image[indx + u][1]) /
+ (2 * image[indx][c]);
+
+ if (image[indx - v][c] > 0)
+ f[1] = 2 * (float)image[indx - u][1] /
+ (image[indx - v][c] + image[indx][c]);
+ else
+ f[1] = f[0];
+
+ if (image[indx - v][c] > 0)
+ f[2] = (float)(image[indx - u][1] + image[indx - w][1]) /
+ (2 * image[indx - v][c]);
+ else
+ f[2] = f[0];
+
+ if (image[indx + v][c] > 0)
+ f[3] = 2 * (float)image[indx + u][1] /
+ (image[indx + v][c] + image[indx][c]);
+ else
+ f[3] = f[0];
+
+ if (image[indx + v][c] > 0)
+ f[4] = (float)(image[indx + u][1] + image[indx + w][1]) /
+ (2 * image[indx + v][c]);
+ else
+ f[4] = f[0];
+
+ g1 = (5 * f[0] + 3 * f[1] + f[2] + 3 * f[3] + f[4]) / 13.0;
+
+ f[0] = (float)(image[indx - 1][1] + image[indx + 1][1]) /
+ (2 * image[indx][c]);
+
+ if (image[indx - 2][c] > 0)
+ f[1] = 2 * (float)image[indx - 1][1] /
+ (image[indx - 2][c] + image[indx][c]);
+ else
+ f[1] = f[0];
+
+ if (image[indx - 2][c] > 0)
+ f[2] = (float)(image[indx - 1][1] + image[indx - 3][1]) /
+ (2 * image[indx - 2][c]);
+ else
+ f[2] = f[0];
+
+ if (image[indx + 2][c] > 0)
+ f[3] = 2 * (float)image[indx + 1][1] /
+ (image[indx + 2][c] + image[indx][c]);
+ else
+ f[3] = f[0];
+
+ if (image[indx + 2][c] > 0)
+ f[4] = (float)(image[indx + 1][1] + image[indx + 3][1]) /
+ (2 * image[indx + 2][c]);
+ else
+ f[4] = f[0];
+
+ g2 = (5 * f[0] + 3 * f[1] + f[2] + 3 * f[3] + f[4]) / 13.0;
+
+ image[indx][1] = CLIP((image[indx][c]) *
+ (current * g1 + (16 - current) * g2) / 16.0);
+ }
+ else
+ image[indx][1] = image[indx][c];
+
+ // get rid of overshooted pixels
+
+ g1 = MIN(
+ image[indx + 1 + u][1],
+ MIN(image[indx + 1 - u][1],
+ MIN(image[indx - 1 + u][1],
+ MIN(image[indx - 1 - u][1],
+ MIN(image[indx - 1][1],
+ MIN(image[indx + 1][1],
+ MIN(image[indx - u][1], image[indx + u][1])))))));
+
+ g2 = MAX(
+ image[indx + 1 + u][1],
+ MAX(image[indx + 1 - u][1],
+ MAX(image[indx - 1 + u][1],
+ MAX(image[indx - 1 - u][1],
+ MAX(image[indx - 1][1],
+ MAX(image[indx + 1][1],
+ MAX(image[indx - u][1], image[indx + u][1])))))));
+
+ image[indx][1] = ULIM(image[indx][1], g2, g1);
+ }
+}
+
+// converts RGB to LCH colorspace and saves it to image3
+void LibRaw::rgb_to_lch(double (*image2)[3])
+{
+ int indx;
+ for (indx = 0; indx < height * width; indx++)
+ {
+
+ image2[indx][0] = image[indx][0] + image[indx][1] + image[indx][2]; // L
+ image2[indx][1] = 1.732050808 * (image[indx][0] - image[indx][1]); // C
+ image2[indx][2] =
+ 2.0 * image[indx][2] - image[indx][0] - image[indx][1]; // H
+ }
+}
+
+// converts LCH to RGB colorspace and saves it back to image
+void LibRaw::lch_to_rgb(double (*image2)[3])
+{
+ int indx;
+ for (indx = 0; indx < height * width; indx++)
+ {
+
+ image[indx][0] = CLIP(image2[indx][0] / 3.0 - image2[indx][2] / 6.0 +
+ image2[indx][1] / 3.464101615);
+ image[indx][1] = CLIP(image2[indx][0] / 3.0 - image2[indx][2] / 6.0 -
+ image2[indx][1] / 3.464101615);
+ image[indx][2] = CLIP(image2[indx][0] / 3.0 + image2[indx][2] / 3.0);
+ }
+}
+
+// denoising using interpolated neighbours
+void LibRaw::fbdd_correction()
+{
+ int row, col, c, u = width, indx;
+
+ for (row = 2; row < height - 2; row++)
+ {
+ for (col = 2, indx = row * width + col; col < width - 2; col++, indx++)
+ {
+
+ c = fcol(row, col);
+
+ image[indx][c] =
+ ULIM(image[indx][c],
+ MAX(image[indx - 1][c],
+ MAX(image[indx + 1][c],
+ MAX(image[indx - u][c], image[indx + u][c]))),
+ MIN(image[indx - 1][c],
+ MIN(image[indx + 1][c],
+ MIN(image[indx - u][c], image[indx + u][c]))));
+ }
+ }
+}
+
+// corrects chroma noise
+void LibRaw::fbdd_correction2(double (*image2)[3])
+{
+ int indx, v = 2 * width;
+ int col, row;
+ double Co, Ho, ratio;
+
+ for (row = 6; row < height - 6; row++)
+ {
+ for (col = 6; col < width - 6; col++)
+ {
+ indx = row * width + col;
+
+ if (image2[indx][1] * image2[indx][2] != 0)
+ {
+ Co = (image2[indx + v][1] + image2[indx - v][1] + image2[indx - 2][1] +
+ image2[indx + 2][1] -
+ MAX(image2[indx - 2][1],
+ MAX(image2[indx + 2][1],
+ MAX(image2[indx - v][1], image2[indx + v][1]))) -
+ MIN(image2[indx - 2][1],
+ MIN(image2[indx + 2][1],
+ MIN(image2[indx - v][1], image2[indx + v][1])))) /
+ 2.0;
+ Ho = (image2[indx + v][2] + image2[indx - v][2] + image2[indx - 2][2] +
+ image2[indx + 2][2] -
+ MAX(image2[indx - 2][2],
+ MAX(image2[indx + 2][2],
+ MAX(image2[indx - v][2], image2[indx + v][2]))) -
+ MIN(image2[indx - 2][2],
+ MIN(image2[indx + 2][2],
+ MIN(image2[indx - v][2], image2[indx + v][2])))) /
+ 2.0;
+ ratio = sqrt((Co * Co + Ho * Ho) / (image2[indx][1] * image2[indx][1] +
+ image2[indx][2] * image2[indx][2]));
+
+ if (ratio < 0.85)
+ {
+ image2[indx][0] =
+ -(image2[indx][1] + image2[indx][2] - Co - Ho) + image2[indx][0];
+ image2[indx][1] = Co;
+ image2[indx][2] = Ho;
+ }
+ }
+ }
+ }
+}
+
+// Cubic Spline Interpolation by Li and Randhawa, modified by Jacek Gozdz and
+// Luis Sanz Rodríguez
+void LibRaw::fbdd_green()
+{
+ int row, col, c, u = width, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u, indx,
+ min, max;
+ float f[4], g[4];
+
+ for (row = 5; row < height - 5; row++)
+ for (col = 5 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col);
+ col < u - 5; col += 2, indx += 2)
+ {
+
+ f[0] = 1.0 / (1.0 + abs(image[indx - u][1] - image[indx - w][1]) +
+ abs(image[indx - w][1] - image[indx + y][1]));
+ f[1] = 1.0 / (1.0 + abs(image[indx + 1][1] - image[indx + 3][1]) +
+ abs(image[indx + 3][1] - image[indx - 5][1]));
+ f[2] = 1.0 / (1.0 + abs(image[indx - 1][1] - image[indx - 3][1]) +
+ abs(image[indx - 3][1] - image[indx + 5][1]));
+ f[3] = 1.0 / (1.0 + abs(image[indx + u][1] - image[indx + w][1]) +
+ abs(image[indx + w][1] - image[indx - y][1]));
+
+ g[0] = CLIP((23 * image[indx - u][1] + 23 * image[indx - w][1] +
+ 2 * image[indx - y][1] +
+ 8 * (image[indx - v][c] - image[indx - x][c]) +
+ 40 * (image[indx][c] - image[indx - v][c])) /
+ 48.0);
+ g[1] = CLIP((23 * image[indx + 1][1] + 23 * image[indx + 3][1] +
+ 2 * image[indx + 5][1] +
+ 8 * (image[indx + 2][c] - image[indx + 4][c]) +
+ 40 * (image[indx][c] - image[indx + 2][c])) /
+ 48.0);
+ g[2] = CLIP((23 * image[indx - 1][1] + 23 * image[indx - 3][1] +
+ 2 * image[indx - 5][1] +
+ 8 * (image[indx - 2][c] - image[indx - 4][c]) +
+ 40 * (image[indx][c] - image[indx - 2][c])) /
+ 48.0);
+ g[3] = CLIP((23 * image[indx + u][1] + 23 * image[indx + w][1] +
+ 2 * image[indx + y][1] +
+ 8 * (image[indx + v][c] - image[indx + x][c]) +
+ 40 * (image[indx][c] - image[indx + v][c])) /
+ 48.0);
+
+ image[indx][1] =
+ CLIP((f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
+ (f[0] + f[1] + f[2] + f[3]));
+
+ min = MIN(
+ image[indx + 1 + u][1],
+ MIN(image[indx + 1 - u][1],
+ MIN(image[indx - 1 + u][1],
+ MIN(image[indx - 1 - u][1],
+ MIN(image[indx - 1][1],
+ MIN(image[indx + 1][1],
+ MIN(image[indx - u][1], image[indx + u][1])))))));
+
+ max = MAX(
+ image[indx + 1 + u][1],
+ MAX(image[indx + 1 - u][1],
+ MAX(image[indx - 1 + u][1],
+ MAX(image[indx - 1 - u][1],
+ MAX(image[indx - 1][1],
+ MAX(image[indx + 1][1],
+ MAX(image[indx - u][1], image[indx + u][1])))))));
+
+ image[indx][1] = ULIM(image[indx][1], max, min);
+ }
+}
+
+// FBDD (Fake Before Demosaicing Denoising)
+void LibRaw::fbdd(int noiserd)
+{
+ double(*image2)[3];
+ // safety net: disable for 4-color bayer or full-color images
+ if (colors != 3 || !filters)
+ return;
+ image2 = (double(*)[3])calloc(width * height, sizeof *image2);
+
+ border_interpolate(4);
+
+ if (noiserd > 1)
+ {
+ fbdd_green();
+ // dcb_color_full(image2);
+ dcb_color_full();
+ fbdd_correction();
+
+ dcb_color();
+ rgb_to_lch(image2);
+ fbdd_correction2(image2);
+ fbdd_correction2(image2);
+ lch_to_rgb(image2);
+ }
+ else
+ {
+ fbdd_green();
+ // dcb_color_full(image2);
+ dcb_color_full();
+ fbdd_correction();
+ }
+
+ free(image2);
+}
+
+// DCB demosaicing main routine
+void LibRaw::dcb(int iterations, int dcb_enhance)
+{
+
+ int i = 1;
+
+ float(*image2)[3];
+ image2 = (float(*)[3])calloc(width * height, sizeof *image2);
+
+ float(*image3)[3];
+ image3 = (float(*)[3])calloc(width * height, sizeof *image3);
+
+ border_interpolate(6);
+
+ dcb_hor(image2);
+ dcb_color2(image2);
+
+ dcb_ver(image3);
+ dcb_color3(image3);
+
+ dcb_decide(image2, image3);
+
+ free(image3);
+
+ dcb_copy_to_buffer(image2);
+
+ while (i <= iterations)
+ {
+ dcb_nyquist();
+ dcb_nyquist();
+ dcb_nyquist();
+ dcb_map();
+ dcb_correction();
+ i++;
+ }
+
+ dcb_color();
+ dcb_pp();
+
+ dcb_map();
+ dcb_correction2();
+
+ dcb_map();
+ dcb_correction();
+
+ dcb_map();
+ dcb_correction();
+
+ dcb_map();
+ dcb_correction();
+
+ dcb_map();
+ dcb_restore_from_buffer(image2);
+ dcb_color();
+
+ if (dcb_enhance)
+ {
+ dcb_refinement();
+ // dcb_color_full(image2);
+ dcb_color_full();
+ }
+
+ free(image2);
+}
diff --git a/libkdcraw/libraw/src/demosaic/dht_demosaic.cpp b/libkdcraw/libraw/src/demosaic/dht_demosaic.cpp
new file mode 100644
index 0000000..bff8f77
--- /dev/null
+++ b/libkdcraw/libraw/src/demosaic/dht_demosaic.cpp
@@ -0,0 +1,1033 @@
+/* -*- C++ -*-
+ * File: dht_demosaic.cpp
+ * Copyright 2013 Anton Petrusevich
+ * Created: Tue Apr 9, 2013
+ *
+ * This code is licensed under 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).
+ *
+ */
+
+/*
+ * функция вычисляет яркостную дистанцию.
+ * если две яркости отличаются в два раза, например 10 и 20, то они имеют такой
+ * же вес при принятии решения об интерполировании, как и 100 и 200 --
+ * фотографическая яркость между ними 1 стоп. дистанция всегда >=1
+ */
+
+#include "../../internal/dmp_include.h"
+
+static inline float calc_dist(float c1, float c2)
+{
+ return c1 > c2 ? c1 / c2 : c2 / c1;
+}
+
+struct DHT
+{
+ int nr_height, nr_width;
+ static const int nr_topmargin = 4, nr_leftmargin = 4;
+ float (*nraw)[3];
+ ushort channel_maximum[3];
+ float channel_minimum[3];
+ LibRaw &libraw;
+ enum
+ {
+ HVSH = 1,
+ HOR = 2,
+ VER = 4,
+ HORSH = HOR | HVSH,
+ VERSH = VER | HVSH,
+ DIASH = 8,
+ LURD = 16,
+ RULD = 32,
+ LURDSH = LURD | DIASH,
+ RULDSH = RULD | DIASH,
+ HOT = 64
+ };
+ static inline float Thot(void) throw() { return 64.0f; }
+ static inline float Tg(void) throw() { return 256.0f; }
+ static inline float T(void) throw() { return 1.4f; }
+ char *ndir;
+ inline int nr_offset(int row, int col) throw()
+ {
+ return (row * nr_width + col);
+ }
+ int get_hv_grb(int x, int y, int kc)
+ {
+ float hv1 = 2 * nraw[nr_offset(y - 1, x)][1] /
+ (nraw[nr_offset(y - 2, x)][kc] + nraw[nr_offset(y, x)][kc]);
+ float hv2 = 2 * nraw[nr_offset(y + 1, x)][1] /
+ (nraw[nr_offset(y + 2, x)][kc] + nraw[nr_offset(y, x)][kc]);
+ float kv = calc_dist(hv1, hv2) *
+ calc_dist(nraw[nr_offset(y, x)][kc] * nraw[nr_offset(y, x)][kc],
+ (nraw[nr_offset(y - 2, x)][kc] *
+ nraw[nr_offset(y + 2, x)][kc]));
+ kv *= kv;
+ kv *= kv;
+ kv *= kv;
+ float dv =
+ kv *
+ calc_dist(nraw[nr_offset(y - 3, x)][1] * nraw[nr_offset(y + 3, x)][1],
+ nraw[nr_offset(y - 1, x)][1] * nraw[nr_offset(y + 1, x)][1]);
+ float hh1 = 2 * nraw[nr_offset(y, x - 1)][1] /
+ (nraw[nr_offset(y, x - 2)][kc] + nraw[nr_offset(y, x)][kc]);
+ float hh2 = 2 * nraw[nr_offset(y, x + 1)][1] /
+ (nraw[nr_offset(y, x + 2)][kc] + nraw[nr_offset(y, x)][kc]);
+ float kh = calc_dist(hh1, hh2) *
+ calc_dist(nraw[nr_offset(y, x)][kc] * nraw[nr_offset(y, x)][kc],
+ (nraw[nr_offset(y, x - 2)][kc] *
+ nraw[nr_offset(y, x + 2)][kc]));
+ kh *= kh;
+ kh *= kh;
+ kh *= kh;
+ float dh =
+ kh *
+ calc_dist(nraw[nr_offset(y, x - 3)][1] * nraw[nr_offset(y, x + 3)][1],
+ nraw[nr_offset(y, x - 1)][1] * nraw[nr_offset(y, x + 1)][1]);
+ float e = calc_dist(dh, dv);
+ char d = dh < dv ? (e > Tg() ? HORSH : HOR) : (e > Tg() ? VERSH : VER);
+ return d;
+ }
+ int get_hv_rbg(int x, int y, int hc)
+ {
+ float hv1 = 2 * nraw[nr_offset(y - 1, x)][hc ^ 2] /
+ (nraw[nr_offset(y - 2, x)][1] + nraw[nr_offset(y, x)][1]);
+ float hv2 = 2 * nraw[nr_offset(y + 1, x)][hc ^ 2] /
+ (nraw[nr_offset(y + 2, x)][1] + nraw[nr_offset(y, x)][1]);
+ float kv = calc_dist(hv1, hv2) *
+ calc_dist(nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1],
+ (nraw[nr_offset(y - 2, x)][1] *
+ nraw[nr_offset(y + 2, x)][1]));
+ kv *= kv;
+ kv *= kv;
+ kv *= kv;
+ float dv = kv * calc_dist(nraw[nr_offset(y - 3, x)][hc ^ 2] *
+ nraw[nr_offset(y + 3, x)][hc ^ 2],
+ nraw[nr_offset(y - 1, x)][hc ^ 2] *
+ nraw[nr_offset(y + 1, x)][hc ^ 2]);
+ float hh1 = 2 * nraw[nr_offset(y, x - 1)][hc] /
+ (nraw[nr_offset(y, x - 2)][1] + nraw[nr_offset(y, x)][1]);
+ float hh2 = 2 * nraw[nr_offset(y, x + 1)][hc] /
+ (nraw[nr_offset(y, x + 2)][1] + nraw[nr_offset(y, x)][1]);
+ float kh = calc_dist(hh1, hh2) *
+ calc_dist(nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1],
+ (nraw[nr_offset(y, x - 2)][1] *
+ nraw[nr_offset(y, x + 2)][1]));
+ kh *= kh;
+ kh *= kh;
+ kh *= kh;
+ float dh =
+ kh * calc_dist(
+ nraw[nr_offset(y, x - 3)][hc] * nraw[nr_offset(y, x + 3)][hc],
+ nraw[nr_offset(y, x - 1)][hc] * nraw[nr_offset(y, x + 1)][hc]);
+ float e = calc_dist(dh, dv);
+ char d = dh < dv ? (e > Tg() ? HORSH : HOR) : (e > Tg() ? VERSH : VER);
+ return d;
+ }
+ int get_diag_grb(int x, int y, int kc)
+ {
+ float hlu =
+ nraw[nr_offset(y - 1, x - 1)][1] / nraw[nr_offset(y - 1, x - 1)][kc];
+ float hrd =
+ nraw[nr_offset(y + 1, x + 1)][1] / nraw[nr_offset(y + 1, x + 1)][kc];
+ float dlurd =
+ calc_dist(hlu, hrd) *
+ calc_dist(nraw[nr_offset(y - 1, x - 1)][1] *
+ nraw[nr_offset(y + 1, x + 1)][1],
+ nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]);
+ float druld =
+ calc_dist(hlu, hrd) *
+ calc_dist(nraw[nr_offset(y - 1, x + 1)][1] *
+ nraw[nr_offset(y + 1, x - 1)][1],
+ nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]);
+ float e = calc_dist(dlurd, druld);
+ char d =
+ druld < dlurd ? (e > T() ? RULDSH : RULD) : (e > T() ? LURDSH : LURD);
+ return d;
+ }
+ int get_diag_rbg(int x, int y, int /* hc */)
+ {
+ float dlurd = calc_dist(
+ nraw[nr_offset(y - 1, x - 1)][1] * nraw[nr_offset(y + 1, x + 1)][1],
+ nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]);
+ float druld = calc_dist(
+ nraw[nr_offset(y - 1, x + 1)][1] * nraw[nr_offset(y + 1, x - 1)][1],
+ nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]);
+ float e = calc_dist(dlurd, druld);
+ char d =
+ druld < dlurd ? (e > T() ? RULDSH : RULD) : (e > T() ? LURDSH : LURD);
+ return d;
+ }
+ static inline float scale_over(float ec, float base)
+ {
+ float s = base * .4;
+ float o = ec - base;
+ return base + sqrt(s * (o + s)) - s;
+ }
+ static inline float scale_under(float ec, float base)
+ {
+ float s = base * .6;
+ float o = base - ec;
+ return base - sqrt(s * (o + s)) + s;
+ }
+ ~DHT();
+ DHT(LibRaw &_libraw);
+ void copy_to_image();
+ void make_greens();
+ void make_diag_dirs();
+ void make_hv_dirs();
+ void refine_hv_dirs(int i, int js);
+ void refine_diag_dirs(int i, int js);
+ void refine_ihv_dirs(int i);
+ void refine_idiag_dirs(int i);
+ void illustrate_dirs();
+ void illustrate_dline(int i);
+ void make_hv_dline(int i);
+ void make_diag_dline(int i);
+ void make_gline(int i);
+ void make_rbdiag(int i);
+ void make_rbhv(int i);
+ void make_rb();
+ void hide_hots();
+ void restore_hots();
+};
+
+typedef float float3[3];
+
+/*
+ * информация о цветах копируется во float в общем то с одной целью -- чтобы
+ * вместо 0 можно было писать 0.5, что больше подходит для вычисления яркостной
+ * разницы. причина: в целых числах разница в 1 стоп составляет ряд 8,4,2,1,0 --
+ * последнее число должно быть 0.5, которое непредствамио в целых числах. так же
+ * это изменение позволяет не думать о специальных случаях деления на ноль.
+ *
+ * альтернативное решение: умножить все данные на 2 и в младший бит внести 1.
+ * правда, всё равно придётся следить, чтобы при интерпретации зелёного цвета не
+ * получился 0 при округлении, иначе проблема при интерпретации синих и красных.
+ *
+ */
+DHT::DHT(LibRaw &_libraw) : libraw(_libraw)
+{
+ nr_height = libraw.imgdata.sizes.iheight + nr_topmargin * 2;
+ nr_width = libraw.imgdata.sizes.iwidth + nr_leftmargin * 2;
+ nraw = (float3 *)malloc(nr_height * nr_width * sizeof(float3));
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ ndir = (char *)calloc(nr_height * nr_width, 1);
+ channel_maximum[0] = channel_maximum[1] = channel_maximum[2] = 0;
+ channel_minimum[0] = libraw.imgdata.image[0][0];
+ channel_minimum[1] = libraw.imgdata.image[0][1];
+ channel_minimum[2] = libraw.imgdata.image[0][2];
+ for (int i = 0; i < nr_height * nr_width; ++i)
+ nraw[i][0] = nraw[i][1] = nraw[i][2] = 0.5;
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ int col_cache[48];
+ for (int j = 0; j < 48; ++j)
+ {
+ int l = libraw.COLOR(i, j);
+ if (l == 3)
+ l = 1;
+ col_cache[j] = l;
+ }
+ for (int j = 0; j < iwidth; ++j)
+ {
+ int l = col_cache[j % 48];
+ unsigned short c = libraw.imgdata.image[i * iwidth + j][l];
+ if (c != 0)
+ {
+ if (channel_maximum[l] < c)
+ channel_maximum[l] = c;
+ if (channel_minimum[l] > c)
+ channel_minimum[l] = c;
+ nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)][l] = (float)c;
+ }
+ }
+ }
+ channel_minimum[0] += .5;
+ channel_minimum[1] += .5;
+ channel_minimum[2] += .5;
+}
+
+void DHT::hide_hots()
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp parallel for schedule(guided) firstprivate(iwidth)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ int js = libraw.COLOR(i, 0) & 1;
+ int kc = libraw.COLOR(i, js);
+ /*
+ * js -- начальная х-координата, которая попадает мимо известного зелёного
+ * kc -- известный цвет в точке интерполирования
+ */
+ for (int j = js; j < iwidth; j += 2)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ float c = nraw[nr_offset(y, x)][kc];
+ if ((c > nraw[nr_offset(y, x + 2)][kc] &&
+ c > nraw[nr_offset(y, x - 2)][kc] &&
+ c > nraw[nr_offset(y - 2, x)][kc] &&
+ c > nraw[nr_offset(y + 2, x)][kc] &&
+ c > nraw[nr_offset(y, x + 1)][1] &&
+ c > nraw[nr_offset(y, x - 1)][1] &&
+ c > nraw[nr_offset(y - 1, x)][1] &&
+ c > nraw[nr_offset(y + 1, x)][1]) ||
+ (c < nraw[nr_offset(y, x + 2)][kc] &&
+ c < nraw[nr_offset(y, x - 2)][kc] &&
+ c < nraw[nr_offset(y - 2, x)][kc] &&
+ c < nraw[nr_offset(y + 2, x)][kc] &&
+ c < nraw[nr_offset(y, x + 1)][1] &&
+ c < nraw[nr_offset(y, x - 1)][1] &&
+ c < nraw[nr_offset(y - 1, x)][1] &&
+ c < nraw[nr_offset(y + 1, x)][1]))
+ {
+ float avg = 0;
+ for (int k = -2; k < 3; k += 2)
+ for (int m = -2; m < 3; m += 2)
+ if (m == 0 && k == 0)
+ continue;
+ else
+ avg += nraw[nr_offset(y + k, x + m)][kc];
+ avg /= 8;
+ // float dev = 0;
+ // for (int k = -2; k < 3; k += 2)
+ // for (int l = -2; l < 3; l += 2)
+ // if (k == 0 && l == 0)
+ // continue;
+ // else {
+ // float t = nraw[nr_offset(y + k, x + l)][kc] -
+ //avg; dev += t * t;
+ // }
+ // dev /= 8;
+ // dev = sqrt(dev);
+ if (calc_dist(c, avg) > Thot())
+ {
+ ndir[nr_offset(y, x)] |= HOT;
+ float dv = calc_dist(
+ nraw[nr_offset(y - 2, x)][kc] * nraw[nr_offset(y - 1, x)][1],
+ nraw[nr_offset(y + 2, x)][kc] * nraw[nr_offset(y + 1, x)][1]);
+ float dh = calc_dist(
+ nraw[nr_offset(y, x - 2)][kc] * nraw[nr_offset(y, x - 1)][1],
+ nraw[nr_offset(y, x + 2)][kc] * nraw[nr_offset(y, x + 1)][1]);
+ if (dv > dh)
+ nraw[nr_offset(y, x)][kc] = (nraw[nr_offset(y, x + 2)][kc] +
+ nraw[nr_offset(y, x - 2)][kc]) /
+ 2;
+ else
+ nraw[nr_offset(y, x)][kc] = (nraw[nr_offset(y - 2, x)][kc] +
+ nraw[nr_offset(y + 2, x)][kc]) /
+ 2;
+ }
+ }
+ }
+ for (int j = js ^ 1; j < iwidth; j += 2)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ float c = nraw[nr_offset(y, x)][1];
+ if ((c > nraw[nr_offset(y, x + 2)][1] &&
+ c > nraw[nr_offset(y, x - 2)][1] &&
+ c > nraw[nr_offset(y - 2, x)][1] &&
+ c > nraw[nr_offset(y + 2, x)][1] &&
+ c > nraw[nr_offset(y, x + 1)][kc] &&
+ c > nraw[nr_offset(y, x - 1)][kc] &&
+ c > nraw[nr_offset(y - 1, x)][kc ^ 2] &&
+ c > nraw[nr_offset(y + 1, x)][kc ^ 2]) ||
+ (c < nraw[nr_offset(y, x + 2)][1] &&
+ c < nraw[nr_offset(y, x - 2)][1] &&
+ c < nraw[nr_offset(y - 2, x)][1] &&
+ c < nraw[nr_offset(y + 2, x)][1] &&
+ c < nraw[nr_offset(y, x + 1)][kc] &&
+ c < nraw[nr_offset(y, x - 1)][kc] &&
+ c < nraw[nr_offset(y - 1, x)][kc ^ 2] &&
+ c < nraw[nr_offset(y + 1, x)][kc ^ 2]))
+ {
+ float avg = 0;
+ for (int k = -2; k < 3; k += 2)
+ for (int m = -2; m < 3; m += 2)
+ if (k == 0 && m == 0)
+ continue;
+ else
+ avg += nraw[nr_offset(y + k, x + m)][1];
+ avg /= 8;
+ // float dev = 0;
+ // for (int k = -2; k < 3; k += 2)
+ // for (int l = -2; l < 3; l += 2)
+ // if (k == 0 && l == 0)
+ // continue;
+ // else {
+ // float t = nraw[nr_offset(y + k, x + l)][1] -
+ //avg; dev += t * t;
+ // }
+ // dev /= 8;
+ // dev = sqrt(dev);
+ if (calc_dist(c, avg) > Thot())
+ {
+ ndir[nr_offset(y, x)] |= HOT;
+ float dv = calc_dist(
+ nraw[nr_offset(y - 2, x)][1] * nraw[nr_offset(y - 1, x)][kc ^ 2],
+ nraw[nr_offset(y + 2, x)][1] * nraw[nr_offset(y + 1, x)][kc ^ 2]);
+ float dh = calc_dist(
+ nraw[nr_offset(y, x - 2)][1] * nraw[nr_offset(y, x - 1)][kc],
+ nraw[nr_offset(y, x + 2)][1] * nraw[nr_offset(y, x + 1)][kc]);
+ if (dv > dh)
+ nraw[nr_offset(y, x)][1] =
+ (nraw[nr_offset(y, x + 2)][1] + nraw[nr_offset(y, x - 2)][1]) /
+ 2;
+ else
+ nraw[nr_offset(y, x)][1] =
+ (nraw[nr_offset(y - 2, x)][1] + nraw[nr_offset(y + 2, x)][1]) /
+ 2;
+ }
+ }
+ }
+ }
+}
+
+void DHT::restore_hots()
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+#if defined(LIBRAW_USE_OPENMP)
+#ifdef _MSC_VER
+#pragma omp parallel for firstprivate(iwidth)
+#else
+#pragma omp parallel for schedule(guided) firstprivate(iwidth) collapse(2)
+#endif
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ for (int j = 0; j < iwidth; ++j)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ if (ndir[nr_offset(y, x)] & HOT)
+ {
+ int l = libraw.COLOR(i, j);
+ nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)][l] =
+ libraw.imgdata.image[i * iwidth + j][l];
+ }
+ }
+ }
+}
+
+void DHT::make_diag_dirs()
+{
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp parallel for schedule(guided)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ make_diag_dline(i);
+ }
+//#if defined(LIBRAW_USE_OPENMP)
+//#pragma omp parallel for schedule(guided)
+//#endif
+// for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) {
+// refine_diag_dirs(i, i & 1);
+// }
+//#if defined(LIBRAW_USE_OPENMP)
+//#pragma omp parallel for schedule(guided)
+//#endif
+// for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) {
+// refine_diag_dirs(i, (i & 1) ^ 1);
+// }
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp parallel for schedule(guided)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ refine_idiag_dirs(i);
+ }
+}
+
+void DHT::make_hv_dirs()
+{
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp parallel for schedule(guided)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ make_hv_dline(i);
+ }
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp parallel for schedule(guided)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ refine_hv_dirs(i, i & 1);
+ }
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp parallel for schedule(guided)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ refine_hv_dirs(i, (i & 1) ^ 1);
+ }
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp parallel for schedule(guided)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ refine_ihv_dirs(i);
+ }
+}
+
+void DHT::refine_hv_dirs(int i, int js)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ for (int j = js; j < iwidth; j += 2)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ if (ndir[nr_offset(y, x)] & HVSH)
+ continue;
+ int nv =
+ (ndir[nr_offset(y - 1, x)] & VER) + (ndir[nr_offset(y + 1, x)] & VER) +
+ (ndir[nr_offset(y, x - 1)] & VER) + (ndir[nr_offset(y, x + 1)] & VER);
+ int nh =
+ (ndir[nr_offset(y - 1, x)] & HOR) + (ndir[nr_offset(y + 1, x)] & HOR) +
+ (ndir[nr_offset(y, x - 1)] & HOR) + (ndir[nr_offset(y, x + 1)] & HOR);
+ bool codir = (ndir[nr_offset(y, x)] & VER)
+ ? ((ndir[nr_offset(y - 1, x)] & VER) ||
+ (ndir[nr_offset(y + 1, x)] & VER))
+ : ((ndir[nr_offset(y, x - 1)] & HOR) ||
+ (ndir[nr_offset(y, x + 1)] & HOR));
+ nv /= VER;
+ nh /= HOR;
+ if ((ndir[nr_offset(y, x)] & VER) && (nh > 2 && !codir))
+ {
+ ndir[nr_offset(y, x)] &= ~VER;
+ ndir[nr_offset(y, x)] |= HOR;
+ }
+ if ((ndir[nr_offset(y, x)] & HOR) && (nv > 2 && !codir))
+ {
+ ndir[nr_offset(y, x)] &= ~HOR;
+ ndir[nr_offset(y, x)] |= VER;
+ }
+ }
+}
+
+void DHT::refine_ihv_dirs(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ for (int j = 0; j < iwidth; j++)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ if (ndir[nr_offset(y, x)] & HVSH)
+ continue;
+ int nv =
+ (ndir[nr_offset(y - 1, x)] & VER) + (ndir[nr_offset(y + 1, x)] & VER) +
+ (ndir[nr_offset(y, x - 1)] & VER) + (ndir[nr_offset(y, x + 1)] & VER);
+ int nh =
+ (ndir[nr_offset(y - 1, x)] & HOR) + (ndir[nr_offset(y + 1, x)] & HOR) +
+ (ndir[nr_offset(y, x - 1)] & HOR) + (ndir[nr_offset(y, x + 1)] & HOR);
+ nv /= VER;
+ nh /= HOR;
+ if ((ndir[nr_offset(y, x)] & VER) && nh > 3)
+ {
+ ndir[nr_offset(y, x)] &= ~VER;
+ ndir[nr_offset(y, x)] |= HOR;
+ }
+ if ((ndir[nr_offset(y, x)] & HOR) && nv > 3)
+ {
+ ndir[nr_offset(y, x)] &= ~HOR;
+ ndir[nr_offset(y, x)] |= VER;
+ }
+ }
+}
+void DHT::make_hv_dline(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ int js = libraw.COLOR(i, 0) & 1;
+ int kc = libraw.COLOR(i, js);
+ /*
+ * js -- начальная х-координата, которая попадает мимо известного зелёного
+ * kc -- известный цвет в точке интерполирования
+ */
+ for (int j = 0; j < iwidth; j++)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ char d = 0;
+ if ((j & 1) == js)
+ {
+ d = get_hv_grb(x, y, kc);
+ }
+ else
+ {
+ d = get_hv_rbg(x, y, kc);
+ }
+ ndir[nr_offset(y, x)] |= d;
+ }
+}
+
+void DHT::make_diag_dline(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ int js = libraw.COLOR(i, 0) & 1;
+ int kc = libraw.COLOR(i, js);
+ /*
+ * js -- начальная х-координата, которая попадает мимо известного зелёного
+ * kc -- известный цвет в точке интерполирования
+ */
+ for (int j = 0; j < iwidth; j++)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ char d = 0;
+ if ((j & 1) == js)
+ {
+ d = get_diag_grb(x, y, kc);
+ }
+ else
+ {
+ d = get_diag_rbg(x, y, kc);
+ }
+ ndir[nr_offset(y, x)] |= d;
+ }
+}
+
+void DHT::refine_diag_dirs(int i, int js)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ for (int j = js; j < iwidth; j += 2)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ if (ndir[nr_offset(y, x)] & DIASH)
+ continue;
+ int nv = (ndir[nr_offset(y - 1, x)] & LURD) +
+ (ndir[nr_offset(y + 1, x)] & LURD) +
+ (ndir[nr_offset(y, x - 1)] & LURD) +
+ (ndir[nr_offset(y, x + 1)] & LURD) +
+ (ndir[nr_offset(y - 1, x - 1)] & LURD) +
+ (ndir[nr_offset(y - 1, x + 1)] & LURD) +
+ (ndir[nr_offset(y + 1, x - 1)] & LURD) +
+ (ndir[nr_offset(y + 1, x + 1)] & LURD);
+ int nh = (ndir[nr_offset(y - 1, x)] & RULD) +
+ (ndir[nr_offset(y + 1, x)] & RULD) +
+ (ndir[nr_offset(y, x - 1)] & RULD) +
+ (ndir[nr_offset(y, x + 1)] & RULD) +
+ (ndir[nr_offset(y - 1, x - 1)] & RULD) +
+ (ndir[nr_offset(y - 1, x + 1)] & RULD) +
+ (ndir[nr_offset(y + 1, x - 1)] & RULD) +
+ (ndir[nr_offset(y + 1, x + 1)] & RULD);
+ bool codir = (ndir[nr_offset(y, x)] & LURD)
+ ? ((ndir[nr_offset(y - 1, x - 1)] & LURD) ||
+ (ndir[nr_offset(y + 1, x + 1)] & LURD))
+ : ((ndir[nr_offset(y - 1, x + 1)] & RULD) ||
+ (ndir[nr_offset(y + 1, x - 1)] & RULD));
+ nv /= LURD;
+ nh /= RULD;
+ if ((ndir[nr_offset(y, x)] & LURD) && (nh > 4 && !codir))
+ {
+ ndir[nr_offset(y, x)] &= ~LURD;
+ ndir[nr_offset(y, x)] |= RULD;
+ }
+ if ((ndir[nr_offset(y, x)] & RULD) && (nv > 4 && !codir))
+ {
+ ndir[nr_offset(y, x)] &= ~RULD;
+ ndir[nr_offset(y, x)] |= LURD;
+ }
+ }
+}
+
+void DHT::refine_idiag_dirs(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ for (int j = 0; j < iwidth; j++)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ if (ndir[nr_offset(y, x)] & DIASH)
+ continue;
+ int nv = (ndir[nr_offset(y - 1, x)] & LURD) +
+ (ndir[nr_offset(y + 1, x)] & LURD) +
+ (ndir[nr_offset(y, x - 1)] & LURD) +
+ (ndir[nr_offset(y, x + 1)] & LURD) +
+ (ndir[nr_offset(y - 1, x - 1)] & LURD) +
+ (ndir[nr_offset(y - 1, x + 1)] & LURD) +
+ (ndir[nr_offset(y + 1, x - 1)] & LURD) +
+ (ndir[nr_offset(y + 1, x + 1)] & LURD);
+ int nh = (ndir[nr_offset(y - 1, x)] & RULD) +
+ (ndir[nr_offset(y + 1, x)] & RULD) +
+ (ndir[nr_offset(y, x - 1)] & RULD) +
+ (ndir[nr_offset(y, x + 1)] & RULD) +
+ (ndir[nr_offset(y - 1, x - 1)] & RULD) +
+ (ndir[nr_offset(y - 1, x + 1)] & RULD) +
+ (ndir[nr_offset(y + 1, x - 1)] & RULD) +
+ (ndir[nr_offset(y + 1, x + 1)] & RULD);
+ nv /= LURD;
+ nh /= RULD;
+ if ((ndir[nr_offset(y, x)] & LURD) && nh > 7)
+ {
+ ndir[nr_offset(y, x)] &= ~LURD;
+ ndir[nr_offset(y, x)] |= RULD;
+ }
+ if ((ndir[nr_offset(y, x)] & RULD) && nv > 7)
+ {
+ ndir[nr_offset(y, x)] &= ~RULD;
+ ndir[nr_offset(y, x)] |= LURD;
+ }
+ }
+}
+
+/*
+ * вычисление недостающих зелёных точек.
+ */
+void DHT::make_greens()
+{
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp parallel for schedule(guided)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ make_gline(i);
+ }
+}
+
+void DHT::make_gline(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ int js = libraw.COLOR(i, 0) & 1;
+ int kc = libraw.COLOR(i, js);
+ /*
+ * js -- начальная х-координата, которая попадает мимо известного зелёного
+ * kc -- известный цвет в точке интерполирования
+ */
+ for (int j = js; j < iwidth; j += 2)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ int dx, dy, dx2, dy2;
+ float h1, h2;
+ if (ndir[nr_offset(y, x)] & VER)
+ {
+ dx = dx2 = 0;
+ dy = -1;
+ dy2 = 1;
+ h1 = 2 * nraw[nr_offset(y - 1, x)][1] /
+ (nraw[nr_offset(y - 2, x)][kc] + nraw[nr_offset(y, x)][kc]);
+ h2 = 2 * nraw[nr_offset(y + 1, x)][1] /
+ (nraw[nr_offset(y + 2, x)][kc] + nraw[nr_offset(y, x)][kc]);
+ }
+ else
+ {
+ dy = dy2 = 0;
+ dx = 1;
+ dx2 = -1;
+ h1 = 2 * nraw[nr_offset(y, x + 1)][1] /
+ (nraw[nr_offset(y, x + 2)][kc] + nraw[nr_offset(y, x)][kc]);
+ h2 = 2 * nraw[nr_offset(y, x - 1)][1] /
+ (nraw[nr_offset(y, x - 2)][kc] + nraw[nr_offset(y, x)][kc]);
+ }
+ float b1 = 1 / calc_dist(nraw[nr_offset(y, x)][kc],
+ nraw[nr_offset(y + dy * 2, x + dx * 2)][kc]);
+ float b2 = 1 / calc_dist(nraw[nr_offset(y, x)][kc],
+ nraw[nr_offset(y + dy2 * 2, x + dx2 * 2)][kc]);
+ b1 *= b1;
+ b2 *= b2;
+ float eg = nraw[nr_offset(y, x)][kc] * (b1 * h1 + b2 * h2) / (b1 + b2);
+ float min, max;
+ min = MIN(nraw[nr_offset(y + dy, x + dx)][1],
+ nraw[nr_offset(y + dy2, x + dx2)][1]);
+ max = MAX(nraw[nr_offset(y + dy, x + dx)][1],
+ nraw[nr_offset(y + dy2, x + dx2)][1]);
+ min /= 1.2f;
+ max *= 1.2f;
+ if (eg < min)
+ eg = scale_under(eg, min);
+ else if (eg > max)
+ eg = scale_over(eg, max);
+ if (eg > channel_maximum[1])
+ eg = channel_maximum[1];
+ else if (eg < channel_minimum[1])
+ eg = channel_minimum[1];
+ nraw[nr_offset(y, x)][1] = eg;
+ }
+}
+
+/*
+ * отладочная функция
+ */
+
+void DHT::illustrate_dirs()
+{
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp parallel for schedule(guided)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ illustrate_dline(i);
+ }
+}
+
+void DHT::illustrate_dline(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ for (int j = 0; j < iwidth; j++)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ nraw[nr_offset(y, x)][0] = nraw[nr_offset(y, x)][1] =
+ nraw[nr_offset(y, x)][2] = 0.5;
+ int l = ndir[nr_offset(y, x)] & 8;
+ // l >>= 3; // WTF?
+ l = 1;
+ if (ndir[nr_offset(y, x)] & HOT)
+ nraw[nr_offset(y, x)][0] =
+ l * channel_maximum[0] / 4 + channel_maximum[0] / 4;
+ else
+ nraw[nr_offset(y, x)][2] =
+ l * channel_maximum[2] / 4 + channel_maximum[2] / 4;
+ }
+}
+
+/*
+ * интерполяция красных и синих.
+ *
+ * сначала интерполируются недостающие цвета, по диагональным направлениям от
+ * которых находятся известные, затем ситуация сводится к тому как
+ * интерполировались зелёные.
+ */
+
+void DHT::make_rbdiag(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ int js = libraw.COLOR(i, 0) & 1;
+ int uc = libraw.COLOR(i, js);
+ int cl = uc ^ 2;
+ /*
+ * js -- начальная х-координата, которая попадает на уже интерполированный
+ * зелёный al -- известный цвет (кроме зелёного) в точке интерполирования cl
+ * -- неизвестный цвет
+ */
+ for (int j = js; j < iwidth; j += 2)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ int dx, dy, dx2, dy2;
+ if (ndir[nr_offset(y, x)] & LURD)
+ {
+ dx = -1;
+ dx2 = 1;
+ dy = -1;
+ dy2 = 1;
+ }
+ else
+ {
+ dx = -1;
+ dx2 = 1;
+ dy = 1;
+ dy2 = -1;
+ }
+ float g1 = 1 / calc_dist(nraw[nr_offset(y, x)][1],
+ nraw[nr_offset(y + dy, x + dx)][1]);
+ float g2 = 1 / calc_dist(nraw[nr_offset(y, x)][1],
+ nraw[nr_offset(y + dy2, x + dx2)][1]);
+ g1 *= g1 * g1;
+ g2 *= g2 * g2;
+
+ float eg;
+ eg = nraw[nr_offset(y, x)][1] *
+ (g1 * nraw[nr_offset(y + dy, x + dx)][cl] /
+ nraw[nr_offset(y + dy, x + dx)][1] +
+ g2 * nraw[nr_offset(y + dy2, x + dx2)][cl] /
+ nraw[nr_offset(y + dy2, x + dx2)][1]) /
+ (g1 + g2);
+ float min, max;
+ min = MIN(nraw[nr_offset(y + dy, x + dx)][cl],
+ nraw[nr_offset(y + dy2, x + dx2)][cl]);
+ max = MAX(nraw[nr_offset(y + dy, x + dx)][cl],
+ nraw[nr_offset(y + dy2, x + dx2)][cl]);
+ min /= 1.2f;
+ max *= 1.2f;
+ if (eg < min)
+ eg = scale_under(eg, min);
+ else if (eg > max)
+ eg = scale_over(eg, max);
+ if (eg > channel_maximum[cl])
+ eg = channel_maximum[cl];
+ else if (eg < channel_minimum[cl])
+ eg = channel_minimum[cl];
+ nraw[nr_offset(y, x)][cl] = eg;
+ }
+}
+
+/*
+ * интерполяция красных и синих в точках где был известен только зелёный,
+ * направления горизонтальные или вертикальные
+ */
+
+void DHT::make_rbhv(int i)
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+ int js = (libraw.COLOR(i, 0) & 1) ^ 1;
+ for (int j = js; j < iwidth; j += 2)
+ {
+ int x = j + nr_leftmargin;
+ int y = i + nr_topmargin;
+ /*
+ * поскольку сверху-снизу и справа-слева уже есть все необходимые красные и
+ * синие, то можно выбрать наилучшее направление исходя из информации по
+ * обоим цветам.
+ */
+ int dx, dy, dx2, dy2;
+ if (ndir[nr_offset(y, x)] & VER)
+ {
+ dx = dx2 = 0;
+ dy = -1;
+ dy2 = 1;
+ }
+ else
+ {
+ dy = dy2 = 0;
+ dx = 1;
+ dx2 = -1;
+ }
+ float g1 = 1 / calc_dist(nraw[nr_offset(y, x)][1],
+ nraw[nr_offset(y + dy, x + dx)][1]);
+ float g2 = 1 / calc_dist(nraw[nr_offset(y, x)][1],
+ nraw[nr_offset(y + dy2, x + dx2)][1]);
+ g1 *= g1;
+ g2 *= g2;
+ float eg_r, eg_b;
+ eg_r = nraw[nr_offset(y, x)][1] *
+ (g1 * nraw[nr_offset(y + dy, x + dx)][0] /
+ nraw[nr_offset(y + dy, x + dx)][1] +
+ g2 * nraw[nr_offset(y + dy2, x + dx2)][0] /
+ nraw[nr_offset(y + dy2, x + dx2)][1]) /
+ (g1 + g2);
+ eg_b = nraw[nr_offset(y, x)][1] *
+ (g1 * nraw[nr_offset(y + dy, x + dx)][2] /
+ nraw[nr_offset(y + dy, x + dx)][1] +
+ g2 * nraw[nr_offset(y + dy2, x + dx2)][2] /
+ nraw[nr_offset(y + dy2, x + dx2)][1]) /
+ (g1 + g2);
+ float min_r, max_r;
+ min_r = MIN(nraw[nr_offset(y + dy, x + dx)][0],
+ nraw[nr_offset(y + dy2, x + dx2)][0]);
+ max_r = MAX(nraw[nr_offset(y + dy, x + dx)][0],
+ nraw[nr_offset(y + dy2, x + dx2)][0]);
+ float min_b, max_b;
+ min_b = MIN(nraw[nr_offset(y + dy, x + dx)][2],
+ nraw[nr_offset(y + dy2, x + dx2)][2]);
+ max_b = MAX(nraw[nr_offset(y + dy, x + dx)][2],
+ nraw[nr_offset(y + dy2, x + dx2)][2]);
+ min_r /= 1.2f;
+ max_r *= 1.2f;
+ min_b /= 1.2f;
+ max_b *= 1.2f;
+
+ if (eg_r < min_r)
+ eg_r = scale_under(eg_r, min_r);
+ else if (eg_r > max_r)
+ eg_r = scale_over(eg_r, max_r);
+ if (eg_b < min_b)
+ eg_b = scale_under(eg_b, min_b);
+ else if (eg_b > max_b)
+ eg_b = scale_over(eg_b, max_b);
+
+ if (eg_r > channel_maximum[0])
+ eg_r = channel_maximum[0];
+ else if (eg_r < channel_minimum[0])
+ eg_r = channel_minimum[0];
+ if (eg_b > channel_maximum[2])
+ eg_b = channel_maximum[2];
+ else if (eg_b < channel_minimum[2])
+ eg_b = channel_minimum[2];
+ nraw[nr_offset(y, x)][0] = eg_r;
+ nraw[nr_offset(y, x)][2] = eg_b;
+ }
+}
+
+void DHT::make_rb()
+{
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp barrier
+#pragma omp parallel for schedule(guided)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ make_rbdiag(i);
+ }
+#if defined(LIBRAW_USE_OPENMP)
+#pragma omp barrier
+#pragma omp parallel for schedule(guided)
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ make_rbhv(i);
+ }
+}
+
+/*
+ * перенос изображения в выходной массив
+ */
+void DHT::copy_to_image()
+{
+ int iwidth = libraw.imgdata.sizes.iwidth;
+#if defined(LIBRAW_USE_OPENMP)
+#ifdef _MSC_VER
+#pragma omp parallel for
+#else
+#pragma omp parallel for schedule(guided) collapse(2)
+#endif
+#endif
+ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
+ {
+ for (int j = 0; j < iwidth; ++j)
+ {
+ libraw.imgdata.image[i * iwidth + j][0] =
+ (unsigned short)(nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)]
+ [0]);
+ libraw.imgdata.image[i * iwidth + j][2] =
+ (unsigned short)(nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)]
+ [2]);
+ libraw.imgdata.image[i * iwidth + j][1] =
+ libraw.imgdata.image[i * iwidth + j][3] =
+ (unsigned short)(nraw[nr_offset(i + nr_topmargin,
+ j + nr_leftmargin)][1]);
+ }
+ }
+}
+
+DHT::~DHT()
+{
+ free(nraw);
+ free(ndir);
+}
+
+void LibRaw::dht_interpolate()
+{
+ if (imgdata.idata.filters != 0x16161616
+ && imgdata.idata.filters != 0x61616161
+ && imgdata.idata.filters != 0x49494949
+ && imgdata.idata.filters != 0x94949494
+ )
+ {
+ ahd_interpolate();
+ return;
+ }
+ DHT dht(*this);
+ dht.hide_hots();
+ dht.make_hv_dirs();
+ // dht.illustrate_dirs();
+ dht.make_greens();
+ dht.make_diag_dirs();
+ // dht.illustrate_dirs();
+ dht.make_rb();
+ dht.restore_hots();
+ dht.copy_to_image();
+}
diff --git a/libkdcraw/libraw/src/demosaic/misc_demosaic.cpp b/libkdcraw/libraw/src/demosaic/misc_demosaic.cpp
new file mode 100644
index 0000000..d23e494
--- /dev/null
+++ b/libkdcraw/libraw/src/demosaic/misc_demosaic.cpp
@@ -0,0 +1,420 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::pre_interpolate()
+{
+ ushort(*img)[4];
+ int row, col, c;
+ RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE, 0, 2);
+ if (shrink)
+ {
+ if (half_size)
+ {
+ height = iheight;
+ width = iwidth;
+ if (filters == 9)
+ {
+ for (row = 0; row < 3; row++)
+ for (col = 1; col < 4; col++)
+ if (!(image[row * width + col][0] | image[row * width + col][2]))
+ goto break2;
+ break2:
+ for (; row < height; row += 3)
+ for (col = (col - 1) % 3 + 1; col < width - 1; col += 3)
+ {
+ img = image + row * width + col;
+ for (c = 0; c < 3; c += 2)
+ img[0][c] = (img[-1][c] + img[1][c]) >> 1;
+ }
+ }
+ }
+ else
+ {
+ img = (ushort(*)[4])calloc(height, width * sizeof *img);
+ for (row = 0; row < height; row++)
+ for (col = 0; col < width; col++)
+ {
+ c = fcol(row, col);
+ img[row * width + col][c] =
+ image[(row >> 1) * iwidth + (col >> 1)][c];
+ }
+ free(image);
+ image = img;
+ shrink = 0;
+ }
+ }
+ if (filters > 1000 && colors == 3)
+ {
+ mix_green = four_color_rgb ^ half_size;
+ if (four_color_rgb | half_size)
+ colors++;
+ else
+ {
+ for (row = FC(1, 0) >> 1; row < height; row += 2)
+ for (col = FC(row, 1) & 1; col < width; col += 2)
+ image[row * width + col][1] = image[row * width + col][3];
+ filters &= ~((filters & 0x55555555U) << 1);
+ }
+ }
+ if (half_size)
+ filters = 0;
+ RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE, 1, 2);
+}
+
+void LibRaw::border_interpolate(int border)
+{
+ unsigned row, col, y, x, f, c, sum[8];
+
+ for (row = 0; row < height; row++)
+ for (col = 0; col < width; col++)
+ {
+ if (col == (unsigned)border && row >= (unsigned)border && row < (unsigned)(height - border))
+ col = width - border;
+ memset(sum, 0, sizeof sum);
+ for (y = row - 1; y != row + 2; y++)
+ for (x = col - 1; x != col + 2; x++)
+ if (y < height && x < width)
+ {
+ f = fcol(y, x);
+ sum[f] += image[y * width + x][f];
+ sum[f + 4]++;
+ }
+ f = fcol(row, col);
+ FORC(unsigned(colors)) if (c != f && sum[c + 4]) image[row * width + col][c] =
+ sum[c] / sum[c + 4];
+ }
+}
+
+void LibRaw::lin_interpolate_loop(int *code, int size)
+{
+ int row;
+ for (row = 1; row < height - 1; row++)
+ {
+ int col, *ip;
+ ushort *pix;
+ for (col = 1; col < width - 1; col++)
+ {
+ int i;
+ int sum[4];
+ pix = image[row * width + col];
+ ip = code + ((((row % size) * 16) + (col % size)) * 32);
+ memset(sum, 0, sizeof sum);
+ for (i = *ip++; i--; ip += 3)
+ sum[ip[2]] += pix[ip[0]] << ip[1];
+ for (i = colors; --i; ip += 2)
+ pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
+ }
+ }
+}
+
+void LibRaw::lin_interpolate()
+{
+ std::vector<int> code_buffer(16 * 16 * 32);
+ int* code = &code_buffer[0], size = 16, *ip, sum[4];
+ int f, c, x, y, row, col, shift, color;
+
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 0, 3);
+
+ if (filters == 9)
+ size = 6;
+ border_interpolate(1);
+ for (row = 0; row < size; row++)
+ for (col = 0; col < size; col++)
+ {
+ ip = code + (((row * 16) + col) * 32) + 1;
+ f = fcol(row, col);
+ memset(sum, 0, sizeof sum);
+ for (y = -1; y <= 1; y++)
+ for (x = -1; x <= 1; x++)
+ {
+ shift = (y == 0) + (x == 0);
+ color = fcol(row + y + 48, col + x + 48);
+ if (color == f)
+ continue;
+ *ip++ = (width * y + x) * 4 + color;
+ *ip++ = shift;
+ *ip++ = color;
+ sum[color] += 1 << shift;
+ }
+ code[(row * 16 + col) * 32] = (ip - (code + ((row * 16) + col) * 32)) / 3;
+ FORCC
+ if (c != f)
+ {
+ *ip++ = c;
+ *ip++ = sum[c] > 0 ? 256 / sum[c] : 0;
+ }
+ }
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 1, 3);
+ lin_interpolate_loop(code, size);
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 2, 3);
+}
+
+/*
+ This algorithm is officially called:
+
+ "Interpolation using a Threshold-based variable number of gradients"
+
+ described in
+ http://scien.stanford.edu/pages/labsite/1999/psych221/projects/99/tingchen/algodep/vargra.html
+
+ I've extended the basic idea to work with non-Bayer filter arrays.
+ Gradients are numbered clockwise from NW=0 to W=7.
+ */
+void LibRaw::vng_interpolate()
+{
+ static const signed char *cp,
+ terms[] =
+ {-2, -2, +0, -1, 0, 0x01, -2, -2, +0, +0, 1, 0x01, -2, -1, -1,
+ +0, 0, 0x01, -2, -1, +0, -1, 0, 0x02, -2, -1, +0, +0, 0, 0x03,
+ -2, -1, +0, +1, 1, 0x01, -2, +0, +0, -1, 0, 0x06, -2, +0, +0,
+ +0, 1, 0x02, -2, +0, +0, +1, 0, 0x03, -2, +1, -1, +0, 0, 0x04,
+ -2, +1, +0, -1, 1, 0x04, -2, +1, +0, +0, 0, 0x06, -2, +1, +0,
+ +1, 0, 0x02, -2, +2, +0, +0, 1, 0x04, -2, +2, +0, +1, 0, 0x04,
+ -1, -2, -1, +0, 0, -128, -1, -2, +0, -1, 0, 0x01, -1, -2, +1,
+ -1, 0, 0x01, -1, -2, +1, +0, 1, 0x01, -1, -1, -1, +1, 0, -120,
+ -1, -1, +1, -2, 0, 0x40, -1, -1, +1, -1, 0, 0x22, -1, -1, +1,
+ +0, 0, 0x33, -1, -1, +1, +1, 1, 0x11, -1, +0, -1, +2, 0, 0x08,
+ -1, +0, +0, -1, 0, 0x44, -1, +0, +0, +1, 0, 0x11, -1, +0, +1,
+ -2, 1, 0x40, -1, +0, +1, -1, 0, 0x66, -1, +0, +1, +0, 1, 0x22,
+ -1, +0, +1, +1, 0, 0x33, -1, +0, +1, +2, 1, 0x10, -1, +1, +1,
+ -1, 1, 0x44, -1, +1, +1, +0, 0, 0x66, -1, +1, +1, +1, 0, 0x22,
+ -1, +1, +1, +2, 0, 0x10, -1, +2, +0, +1, 0, 0x04, -1, +2, +1,
+ +0, 1, 0x04, -1, +2, +1, +1, 0, 0x04, +0, -2, +0, +0, 1, -128,
+ +0, -1, +0, +1, 1, -120, +0, -1, +1, -2, 0, 0x40, +0, -1, +1,
+ +0, 0, 0x11, +0, -1, +2, -2, 0, 0x40, +0, -1, +2, -1, 0, 0x20,
+ +0, -1, +2, +0, 0, 0x30, +0, -1, +2, +1, 1, 0x10, +0, +0, +0,
+ +2, 1, 0x08, +0, +0, +2, -2, 1, 0x40, +0, +0, +2, -1, 0, 0x60,
+ +0, +0, +2, +0, 1, 0x20, +0, +0, +2, +1, 0, 0x30, +0, +0, +2,
+ +2, 1, 0x10, +0, +1, +1, +0, 0, 0x44, +0, +1, +1, +2, 0, 0x10,
+ +0, +1, +2, -1, 1, 0x40, +0, +1, +2, +0, 0, 0x60, +0, +1, +2,
+ +1, 0, 0x20, +0, +1, +2, +2, 0, 0x10, +1, -2, +1, +0, 0, -128,
+ +1, -1, +1, +1, 0, -120, +1, +0, +1, +2, 0, 0x08, +1, +0, +2,
+ -1, 0, 0x40, +1, +0, +2, +1, 0, 0x10},
+ chood[] = {-1, -1, -1, 0, -1, +1, 0, +1, +1, +1, +1, 0, +1, -1, 0, -1};
+ ushort(*brow[5])[4], *pix;
+ int prow = 8, pcol = 2, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
+ int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
+ int g, diff, thold, num, c;
+
+ lin_interpolate();
+
+ if (filters == 1)
+ prow = pcol = 16;
+ if (filters == 9)
+ prow = pcol = 6;
+ ip = (int *)calloc(prow * pcol, 1280);
+ for (row = 0; row < prow; row++) /* Precalculate for VNG */
+ for (col = 0; col < pcol; col++)
+ {
+ code[row][col] = ip;
+ for (cp = terms, t = 0; t < 64; t++)
+ {
+ y1 = *cp++;
+ x1 = *cp++;
+ y2 = *cp++;
+ x2 = *cp++;
+ weight = *cp++;
+ grads = *cp++;
+ color = fcol(row + y1 + 144, col + x1 + 144);
+ if (fcol(row + y2 + 144, col + x2 + 144) != color)
+ continue;
+ diag = (fcol(row, col + 1) == color && fcol(row + 1, col) == color) ? 2
+ : 1;
+ if (abs(y1 - y2) == diag && abs(x1 - x2) == diag)
+ continue;
+ *ip++ = (y1 * width + x1) * 4 + color;
+ *ip++ = (y2 * width + x2) * 4 + color;
+ *ip++ = weight;
+ for (g = 0; g < 8; g++)
+ if (grads & 1 << g)
+ *ip++ = g;
+ *ip++ = -1;
+ }
+ *ip++ = INT_MAX;
+ for (cp = chood, g = 0; g < 8; g++)
+ {
+ y = *cp++;
+ x = *cp++;
+ *ip++ = (y * width + x) * 4;
+ color = fcol(row, col);
+ if (fcol(row + y + 144, col + x + 144) != color &&
+ fcol(row + y * 2 + 144, col + x * 2 + 144) == color)
+ *ip++ = (y * width + x) * 8 + color;
+ else
+ *ip++ = 0;
+ }
+ }
+ brow[4] = (ushort(*)[4])calloc(width * 3, sizeof **brow);
+ for (row = 0; row < 3; row++)
+ brow[row] = brow[4] + row * width;
+ for (row = 2; row < height - 2; row++)
+ { /* Do VNG interpolation */
+ if (!((row - 2) % 256))
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, (row - 2) / 256 + 1,
+ ((height - 3) / 256) + 1);
+ for (col = 2; col < width - 2; col++)
+ {
+ pix = image[row * width + col];
+ ip = code[row % prow][col % pcol];
+ memset(gval, 0, sizeof gval);
+ while ((g = ip[0]) != INT_MAX)
+ { /* Calculate gradients */
+ diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
+ gval[ip[3]] += diff;
+ ip += 5;
+ if ((g = ip[-1]) == -1)
+ continue;
+ gval[g] += diff;
+ while ((g = *ip++) != -1)
+ gval[g] += diff;
+ }
+ ip++;
+ gmin = gmax = gval[0]; /* Choose a threshold */
+ for (g = 1; g < 8; g++)
+ {
+ if (gmin > gval[g])
+ gmin = gval[g];
+ if (gmax < gval[g])
+ gmax = gval[g];
+ }
+ if (gmax == 0)
+ {
+ memcpy(brow[2][col], pix, sizeof *image);
+ continue;
+ }
+ thold = gmin + (gmax >> 1);
+ memset(sum, 0, sizeof sum);
+ color = fcol(row, col);
+ for (num = g = 0; g < 8; g++, ip += 2)
+ { /* Average the neighbors */
+ if (gval[g] <= thold)
+ {
+ FORCC
+ if (c == color && ip[1])
+ sum[c] += (pix[c] + pix[ip[1]]) >> 1;
+ else
+ sum[c] += pix[ip[0] + c];
+ num++;
+ }
+ }
+ FORCC
+ { /* Save to buffer */
+ t = pix[color];
+ if (c != color)
+ t += (sum[c] - sum[color]) / num;
+ brow[2][col][c] = CLIP(t);
+ }
+ }
+ if (row > 3) /* Write buffer to image */
+ memcpy(image[(row - 2) * width + 2], brow[0] + 2,
+ (width - 4) * sizeof *image);
+ for (g = 0; g < 4; g++)
+ brow[(g - 1) & 3] = brow[g];
+ }
+ memcpy(image[(row - 2) * width + 2], brow[0] + 2,
+ (width - 4) * sizeof *image);
+ memcpy(image[(row - 1) * width + 2], brow[1] + 2,
+ (width - 4) * sizeof *image);
+ free(brow[4]);
+ free(code[0][0]);
+}
+
+/*
+ Patterned Pixel Grouping Interpolation by Alain Desbiolles
+*/
+void LibRaw::ppg_interpolate()
+{
+ int dir[5] = {1, width, -1, -width, 1};
+ int row, col, diff[2], guess[2], c, d, i;
+ ushort(*pix)[4];
+
+ border_interpolate(3);
+
+ /* Fill in the green layer with gradients and pattern recognition: */
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 0, 3);
+#ifdef LIBRAW_USE_OPENMP
+#pragma omp parallel for default(shared) private(guess, diff, row, col, d, c, \
+ i, pix) schedule(static)
+#endif
+ for (row = 3; row < height - 3; row++)
+ for (col = 3 + (FC(row, 3) & 1), c = FC(row, col); col < width - 3;
+ col += 2)
+ {
+ pix = image + row * width + col;
+ for (i = 0; i < 2; i++)
+ {
+ d = dir[i];
+ guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 - pix[-2 * d][c] -
+ pix[2 * d][c];
+ diff[i] =
+ (ABS(pix[-2 * d][c] - pix[0][c]) + ABS(pix[2 * d][c] - pix[0][c]) +
+ ABS(pix[-d][1] - pix[d][1])) *
+ 3 +
+ (ABS(pix[3 * d][1] - pix[d][1]) +
+ ABS(pix[-3 * d][1] - pix[-d][1])) *
+ 2;
+ }
+ d = dir[i = diff[0] > diff[1]];
+ pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
+ }
+ /* Calculate red and blue for each green pixel: */
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 1, 3);
+#ifdef LIBRAW_USE_OPENMP
+#pragma omp parallel for default(shared) private(guess, diff, row, col, d, c, \
+ i, pix) schedule(static)
+#endif
+ for (row = 1; row < height - 1; row++)
+ for (col = 1 + (FC(row, 2) & 1), c = FC(row, col + 1); col < width - 1;
+ col += 2)
+ {
+ pix = image + row * width + col;
+ for (i = 0; i < 2; c = 2 - c, i++)
+ {
+ d = dir[i];
+ pix[0][c] = CLIP(
+ (pix[-d][c] + pix[d][c] + 2 * pix[0][1] - pix[-d][1] - pix[d][1]) >>
+ 1);
+ }
+ }
+ /* Calculate blue for red pixels and vice versa: */
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 2, 3);
+#ifdef LIBRAW_USE_OPENMP
+#pragma omp parallel for default(shared) private(guess, diff, row, col, d, c, \
+ i, pix) schedule(static)
+#endif
+ for (row = 1; row < height - 1; row++)
+ for (col = 1 + (FC(row, 1) & 1), c = 2 - FC(row, col); col < width - 1;
+ col += 2)
+ {
+ pix = image + row * width + col;
+ for (i = 0; i < 2; i++)
+ {
+ d = dir[i] + dir[i+1];
+ diff[i] = ABS(pix[-d][c] - pix[d][c]) + ABS(pix[-d][1] - pix[0][1]) +
+ ABS(pix[d][1] - pix[0][1]);
+ guess[i] =
+ pix[-d][c] + pix[d][c] + 2 * pix[0][1] - pix[-d][1] - pix[d][1];
+ }
+ if (diff[0] != diff[1])
+ pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
+ else
+ pix[0][c] = CLIP((guess[0] + guess[1]) >> 2);
+ }
+}
diff --git a/libkdcraw/libraw/src/demosaic/xtrans_demosaic.cpp b/libkdcraw/libraw/src/demosaic/xtrans_demosaic.cpp
new file mode 100644
index 0000000..5dbc3c3
--- /dev/null
+++ b/libkdcraw/libraw/src/demosaic/xtrans_demosaic.cpp
@@ -0,0 +1,430 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+#define fcol(row, col) xtrans[(row + 6) % 6][(col + 6) % 6]
+/*
+ Frank Markesteijn's algorithm for Fuji X-Trans sensors
+ */
+void LibRaw::xtrans_interpolate(int passes)
+{
+ int cstat[4] = {0, 0, 0, 0};
+ int ndir;
+ static const short orth[12] = {1, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, 1},
+ patt[2][16] = {{0, 1, 0, -1, 2, 0, -1, 0, 1, 1, 1, -1, 0,
+ 0, 0, 0},
+ {0, 1, 0, -2, 1, 0, -2, 0, 1, 1, -2, -2, 1,
+ -1, -1, 1}},
+ dir[4] = {1, LIBRAW_AHD_TILE, LIBRAW_AHD_TILE + 1,
+ LIBRAW_AHD_TILE - 1};
+ short allhex[3][3][2][8];
+ ushort sgrow = 0, sgcol = 0;
+
+ if (width < LIBRAW_AHD_TILE || height < LIBRAW_AHD_TILE)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT; // too small image
+ /* Check against right pattern */
+ for (int row = 0; row < 6; row++)
+ for (int col = 0; col < 6; col++)
+ cstat[(unsigned)fcol(row, col)]++;
+
+ if (cstat[0] < 6 || cstat[0] > 10 || cstat[1] < 16 || cstat[1] > 24 ||
+ cstat[2] < 6 || cstat[2] > 10 || cstat[3])
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ // Init allhex table to unreasonable values
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ for (int k = 0; k < 2; k++)
+ for (int l = 0; l < 8; l++)
+ allhex[i][j][k][l] = 32700;
+
+ cielab(0, 0);
+ ndir = 4 << int(passes > 1);
+
+ int minv = 0, maxv = 0, minh = 0, maxh = 0;
+ /* Map a green hexagon around each non-green pixel and vice versa: */
+ for (int row = 0; row < 3; row++)
+ for (int col = 0; col < 3; col++)
+ for (int ng = 0, d = 0; d < 10; d += 2)
+ {
+ int g = fcol(row, col) == 1;
+ if (fcol(row + orth[d], col + orth[d + 2]) == 1)
+ ng = 0;
+ else
+ ng++;
+ if (ng == 4)
+ {
+ sgrow = row;
+ sgcol = col;
+ }
+ if (ng == g + 1)
+ {
+ int c;
+ FORC(8)
+ {
+ int v = orth[d] * patt[g][c * 2] + orth[d + 1] * patt[g][c * 2 + 1];
+ int h = orth[d + 2] * patt[g][c * 2] + orth[d + 3] * patt[g][c * 2 + 1];
+ minv = MIN(v, minv);
+ maxv = MAX(v, maxv);
+ minh = MIN(v, minh);
+ maxh = MAX(v, maxh);
+ allhex[row][col][0][c ^ (g * 2 & d)] = h + v * width;
+ allhex[row][col][1][c ^ (g * 2 & d)] = h + v * LIBRAW_AHD_TILE;
+ }
+ }
+ }
+
+ // Check allhex table initialization
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ for (int k = 0; k < 2; k++)
+ for (int l = 0; l < 8; l++)
+ if (allhex[i][j][k][l] > maxh + maxv * width + 1 ||
+ allhex[i][j][k][l] < minh + minv * width - 1)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ int retrycount = 0;
+
+ /* Set green1 and green3 to the minimum and maximum allowed values: */
+ for (int row = 2; row < height - 2; row++)
+ {
+ int col;
+ ushort min, max;
+ for (col = 2, max = 0u, min = 0xffffu; col < int(width) - 2; col++)
+ {
+ if (fcol(row, col) == 1 && (min = ~(max = 0)))
+ continue;
+ ushort(*pix)[4];
+ pix = image + row * width + col;
+ short* hex = allhex[row % 3][col % 3][0];
+ if (!max)
+ {
+ int c;
+ FORC(6)
+ {
+ int val = pix[hex[c]][1];
+ if (min > val)
+ min = val;
+ if (max < val)
+ max = val;
+ }
+ }
+ pix[0][1] = min;
+ pix[0][3] = max;
+ switch ((row - sgrow) % 3)
+ {
+ case 1:
+ if (row < height - 3)
+ {
+ row++;
+ col--;
+ }
+ break;
+ case 2:
+ if ((min = ~(max = 0)) && (col += 2) < width - 3 && row > 2)
+ {
+ row--;
+ if (retrycount++ > width * height)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+ }
+ }
+ }
+
+ for (int row = 3; row < 9 && row < height - 3; row++)
+ for (int col = 3; col < 9 && col < width - 3; col++)
+ {
+ if ((fcol(row, col)) == 1)
+ continue;
+ short* hex = allhex[row % 3][col % 3][0];
+ int c;
+ FORC(2)
+ {
+ int idx3 = 3 * hex[4 + c] + row * width + col;
+ int idx4 = -3 * hex[4 + c] + row * width + col;
+ int maxidx = width * height;
+ if (idx3 < 0 || idx3 >= maxidx)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ if (idx4 < 0 || idx4 >= maxidx)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+ }
+
+#if defined(LIBRAW_USE_OPENMP)
+ int buffer_count = omp_get_max_threads();
+#else
+ int buffer_count = 1;
+#endif
+
+ size_t buffer_size = LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 11 + 6);
+ char** buffers = malloc_omp_buffers(buffer_count, buffer_size);
+
+#if defined(LIBRAW_USE_OPENMP)
+# pragma omp parallel for schedule(dynamic) default(none) firstprivate(buffers, allhex, passes, sgrow, sgcol, ndir) shared(dir)
+#endif
+ for (int top = 3; top < height - 19; top += LIBRAW_AHD_TILE - 16)
+ {
+#if defined(LIBRAW_USE_OPENMP)
+ char* buffer = buffers[omp_get_thread_num()];
+#else
+ char* buffer = buffers[0];
+#endif
+
+ ushort(*rgb)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3], (*rix)[3];
+ short(*lab)[LIBRAW_AHD_TILE][3], (*lix)[3];
+ float(*drv)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE];
+ char(*homo)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE];
+
+ rgb = (ushort(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3])buffer;
+ lab = (short(*)[LIBRAW_AHD_TILE][3])(
+ buffer + LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 6));
+ drv = (float(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE])(
+ buffer + LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 6 + 6));
+ homo = (char(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE])(
+ buffer + LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 10 + 6));
+
+ for (int left = 3; left < width - 19; left += LIBRAW_AHD_TILE - 16)
+ {
+ int mrow = MIN(top + LIBRAW_AHD_TILE, height - 3);
+ int mcol = MIN(left + LIBRAW_AHD_TILE, width - 3);
+ for (int row = top; row < mrow; row++)
+ for (int col = left; col < mcol; col++)
+ memcpy(rgb[0][row - top][col - left], image[row * width + col], 6);
+ int c;
+ FORC3 memcpy(rgb[c + 1], rgb[0], sizeof * rgb);
+
+ /* Interpolate green horizontally, vertically, and along both diagonals:
+ */
+ int color[3][8];
+ for (int row = top; row < mrow; row++)
+ for (int col = left; col < mcol; col++)
+ {
+ int f;
+ if ((f = fcol(row, col)) == 1)
+ continue;
+ ushort (*pix)[4] = image + row * width + col;
+ short* hex = allhex[row % 3][col % 3][0];
+ color[1][0] = 174 * (pix[hex[1]][1] + pix[hex[0]][1]) -
+ 46 * (pix[2 * hex[1]][1] + pix[2 * hex[0]][1]);
+ color[1][1] = 223 * pix[hex[3]][1] + pix[hex[2]][1] * 33 +
+ 92 * (pix[0][f] - pix[-hex[2]][f]);
+ FORC(2)
+ color[1][2 + c] = 164 * pix[hex[4 + c]][1] +
+ 92 * pix[-2 * hex[4 + c]][1] +
+ 33 * (2 * pix[0][f] - pix[3 * hex[4 + c]][f] -
+ pix[-3 * hex[4 + c]][f]);
+ FORC4 rgb[c ^ !((row - sgrow) % 3)][row - top][col - left][1] =
+ LIM(color[1][c] >> 8, pix[0][1], pix[0][3]);
+ }
+
+ for (int pass = 0; pass < passes; pass++)
+ {
+ if (pass == 1)
+ memcpy(rgb += 4, buffer, 4 * sizeof * rgb);
+
+ /* Recalculate green from interpolated values of closer pixels: */
+ if (pass)
+ {
+ for (int row = top + 2; row < mrow - 2; row++)
+ for (int col = left + 2; col < mcol - 2; col++)
+ {
+ int f;
+ if ((f = fcol(row, col)) == 1)
+ continue;
+ ushort(*pix)[4] = image + row * width + col;
+ short* hex = allhex[row % 3][col % 3][1];
+ for (int d = 3; d < 6; d++)
+ {
+ rix =
+ &rgb[(d - 2) ^ !((row - sgrow) % 3)][row - top][col - left];
+ int val = rix[-2 * hex[d]][1] + 2 * rix[hex[d]][1] -
+ rix[-2 * hex[d]][f] - 2 * rix[hex[d]][f] + 3 * rix[0][f];
+ rix[0][1] = LIM(val / 3, pix[0][1], pix[0][3]);
+ }
+ }
+ }
+
+ /* Interpolate red and blue values for solitary green pixels: */
+ for (int row = (top - sgrow + 4) / 3 * 3 + sgrow; row < mrow - 2; row += 3)
+ for (int col = (left - sgcol + 4) / 3 * 3 + sgcol; col < mcol - 2; col += 3)
+ {
+ rix = &rgb[0][row - top][col - left];
+ int h = fcol(row, col + 1);
+ float diff[6];
+ memset(diff, 0, sizeof diff);
+ for (int i = 1, d = 0; d < 6; d++, i ^= LIBRAW_AHD_TILE ^ 1, h ^= 2)
+ {
+ for (c = 0; c < 2; c++, h ^= 2)
+ {
+ int g = 2 * rix[0][1] - rix[i << c][1] - rix[-i << c][1];
+ color[h][d] = g + rix[i << c][h] + rix[-i << c][h];
+ if (d > 1)
+ diff[d] += SQR((float)rix[i << c][1] - (float)rix[-i << c][1] -
+ (float)rix[i << c][h] + (float)rix[-i << c][h]) + SQR((float)g);
+ }
+ if (d > 1 && (d & 1))
+ if (diff[d - 1] < diff[d])
+ FORC(2) color[c * 2][d] = color[c * 2][d - 1];
+ if (d < 2 || (d & 1))
+ {
+ FORC(2) rix[0][c * 2] = CLIP(color[c * 2][d] / 2);
+ rix += LIBRAW_AHD_TILE * LIBRAW_AHD_TILE;
+ }
+ }
+ }
+
+ /* Interpolate red for blue pixels and vice versa: */
+ for (int row = top + 3; row < mrow - 3; row++)
+ for (int col = left + 3; col < mcol - 3; col++)
+ {
+ int f;
+ if ((f = 2 - fcol(row, col)) == 1)
+ continue;
+ rix = &rgb[0][row - top][col - left];
+ c = (row - sgrow) % 3 ? LIBRAW_AHD_TILE : 1;
+ int h = 3 * (c ^ LIBRAW_AHD_TILE ^ 1);
+ for (int d = 0; d < 4; d++, rix += LIBRAW_AHD_TILE * LIBRAW_AHD_TILE)
+ {
+ int i = d > 1 || ((d ^ c) & 1) ||
+ ((ABS(rix[0][1] - rix[c][1]) +
+ ABS(rix[0][1] - rix[-c][1])) <
+ 2 * (ABS(rix[0][1] - rix[h][1]) +
+ ABS(rix[0][1] - rix[-h][1])))
+ ? c
+ : h;
+ rix[0][f] = CLIP((rix[i][f] + rix[-i][f] + 2 * rix[0][1] -
+ rix[i][1] - rix[-i][1]) /
+ 2);
+ }
+ }
+
+ /* Fill in red and blue for 2x2 blocks of green: */
+ for (int row = top + 2; row < mrow - 2; row++)
+ if ((row - sgrow) % 3)
+ for (int col = left + 2; col < mcol - 2; col++)
+ if ((col - sgcol) % 3)
+ {
+ rix = &rgb[0][row - top][col - left];
+ short* hex = allhex[row % 3][col % 3][1];
+ for (int d = 0; d < 8;
+ d += 2, rix += LIBRAW_AHD_TILE * LIBRAW_AHD_TILE)
+ if (hex[d] + hex[d + 1])
+ {
+ int g = 3 * rix[0][1] - 2 * rix[hex[d]][1] - rix[hex[d + 1]][1];
+ for (c = 0; c < 4; c += 2)
+ rix[0][c] = CLIP(
+ (g + 2 * rix[hex[d]][c] + rix[hex[d + 1]][c]) / 3);
+ }
+ else
+ {
+ int g = 2 * rix[0][1] - rix[hex[d]][1] - rix[hex[d + 1]][1];
+ for (c = 0; c < 4; c += 2)
+ rix[0][c] =
+ CLIP((g + rix[hex[d]][c] + rix[hex[d + 1]][c]) / 2);
+ }
+ }
+ }
+ rgb = (ushort(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3])buffer;
+ mrow -= top;
+ mcol -= left;
+
+ /* Convert to CIELab and differentiate in all directions: */
+ // no effect
+ for (int d = 0; d < ndir; d++)
+ {
+ for (int row = 2; row < mrow - 2; row++)
+ for (int col = 2; col < mcol - 2; col++)
+ cielab(rgb[d][row][col], lab[row][col]);
+ for (int f = dir[d & 3], row = 3; row < mrow - 3; row++)
+ for (int col = 3; col < mcol - 3; col++)
+ {
+ lix = &lab[row][col];
+ int g = 2 * lix[0][0] - lix[f][0] - lix[-f][0];
+ drv[d][row][col] =
+ SQR(g) +
+ SQR((2 * lix[0][1] - lix[f][1] - lix[-f][1] + g * 500 / 232)) +
+ SQR((2 * lix[0][2] - lix[f][2] - lix[-f][2] - g * 500 / 580));
+ }
+ }
+
+ /* Build homogeneity maps from the derivatives: */
+ memset(homo, 0, ndir * LIBRAW_AHD_TILE * LIBRAW_AHD_TILE);
+ for (int row = 4; row < mrow - 4; row++)
+ for (int col = 4; col < mcol - 4; col++)
+ {
+ int d;
+ float tr;
+ for (tr = FLT_MAX, d = 0; d < ndir; d++)
+ if (tr > drv[d][row][col])
+ tr = drv[d][row][col];
+ tr *= 8;
+ for (int dd = 0; dd < ndir; dd++)
+ for (int v = -1; v <= 1; v++)
+ for (int h = -1; h <= 1; h++)
+ if (drv[dd][row + v][col + h] <= tr)
+ homo[dd][row][col]++;
+ }
+
+ /* Average the most homogeneous pixels for the final result: */
+ if (height - top < LIBRAW_AHD_TILE + 4)
+ mrow = height - top + 2;
+ if (width - left < LIBRAW_AHD_TILE + 4)
+ mcol = width - left + 2;
+ for (int row = MIN(top, 8); row < mrow - 8; row++)
+ for (int col = MIN(left, 8); col < mcol - 8; col++)
+ {
+ int v;
+ int hm[8];
+ for (int d = 0; d < ndir; d++)
+ for (v = -2, hm[d] = 0; v <= 2; v++)
+ for (int h = -2; h <= 2; h++)
+ hm[d] += homo[d][row + v][col + h];
+ for (int d = 0; d < ndir - 4; d++)
+ if (hm[d] < hm[d + 4])
+ hm[d] = 0;
+ else if (hm[d] > hm[d + 4])
+ hm[d + 4] = 0;
+ ushort max;
+ int d;
+ for (d = 1, max = hm[0]; d < ndir; d++)
+ if (max < hm[d])
+ max = hm[d];
+ max -= max >> 3;
+
+ int avg[4];
+ memset(avg, 0, sizeof avg);
+ for (int dd = 0; dd < ndir; dd++)
+ if (hm[dd] >= max)
+ {
+ FORC3 avg[c] += rgb[dd][row][col][c];
+ avg[3]++;
+ }
+ FORC3 image[(row + top) * width + col + left][c] = avg[c] / avg[3];
+ }
+ }
+ }
+
+#ifdef LIBRAW_USE_OPENMP
+#pragma omp barrier
+#endif
+
+ free_omp_buffers(buffers, buffer_count);
+
+ border_interpolate(8);
+}
+#undef fcol
diff --git a/libkdcraw/libraw/src/integration/dngsdk_glue.cpp b/libkdcraw/libraw/src/integration/dngsdk_glue.cpp
new file mode 100644
index 0000000..4943836
--- /dev/null
+++ b/libkdcraw/libraw/src/integration/dngsdk_glue.cpp
@@ -0,0 +1,414 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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"
+
+#if defined (USE_GPRSDK) && !defined(USE_DNGSDK)
+#error GPR (GoPro) SDK should be used with Adobe DNG SDK
+#endif
+#ifdef USE_DNGSDK
+#include "dng_read_image.h"
+#endif
+#ifdef USE_GPRSDK
+#include "gpr_read_image.h"
+#endif
+
+#ifdef USE_DNGSDK
+static dng_ifd* search_single_ifd(const std::vector <dng_ifd *>& v, uint64 offset, int& idx, dng_stream& stream)
+{
+ idx = -1;
+ for (int i = 0; i < v.size(); i++)
+ {
+ if (!v[i]) continue;
+ if (v[i]->fTileOffsetsOffset == offset)
+ {
+ idx = i;
+ return v[i];
+ }
+ else if (v[i]->fTileOffsetsCount == 1 && v[i]->fTileOffset[0] == offset)
+ {
+ idx = i;
+ return v[i];
+ }
+ else if (v[i]->fTileOffsetsCount > dng_ifd::kMaxTileInfo)
+ {
+ uint64 p = stream.Position();
+ stream.SetReadPosition(v[i]->fTileOffsetsOffset);
+ int32 oo = stream.TagValue_uint32(v[i]->fTileOffsetsType);
+ stream.SetReadPosition(p);
+ if (oo == offset)
+ {
+ idx = i;
+ return v[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+static dng_ifd* search_for_ifd(const dng_info& info, uint64 offset, ushort w, ushort h, int& ifdIndex, dng_stream& stream)
+{
+ dng_ifd *ret = 0;
+ ret = search_single_ifd(info.fIFD, offset, ifdIndex, stream);
+ int dummy;
+ if (!ret) ret = search_single_ifd(info.fChainedIFD, offset, dummy, stream);
+ if (!ret)
+ {
+ for (int c = 0; !ret && c < info.fChainedSubIFD.size(); c++)
+ ret = search_single_ifd(info.fChainedSubIFD[c], offset, dummy, stream);
+ }
+ if (ret && (ret->fImageLength == h) && ret->fImageWidth == w)
+ return ret;
+ ifdIndex = -1;
+ return 0;
+}
+#endif
+
+int LibRaw::valid_for_dngsdk()
+{
+#ifndef USE_DNGSDK
+ return 0;
+#else
+ if (!imgdata.idata.dng_version)
+ return 0;
+
+ // All DNG larger than 2GB - to DNG SDK
+ if (libraw_internal_data.internal_data.input->size() > 2147483647ULL)
+ return 1;
+
+ if (!strcasecmp(imgdata.idata.make, "Blackmagic")
+ && (libraw_internal_data.unpacker_data.tiff_compress == 7)
+ && (libraw_internal_data.unpacker_data.tiff_bps > 8)
+ )
+ return 0;
+
+ if (libraw_internal_data.unpacker_data.tiff_compress == 34892
+ && libraw_internal_data.unpacker_data.tiff_bps == 8
+ && libraw_internal_data.unpacker_data.tiff_samples == 3
+ && load_raw == &LibRaw::lossy_dng_load_raw
+ )
+ {
+ if (!dnghost)
+ return 0;
+ dng_host *host = static_cast<dng_host *>(dnghost);
+ libraw_dng_stream stream(libraw_internal_data.internal_data.input);
+ AutoPtr<dng_negative> negative;
+ negative.Reset(host->Make_dng_negative());
+ dng_info info;
+ info.Parse(*host, stream);
+ info.PostParse(*host);
+ if (!info.IsValidDNG())
+ return 0;
+ negative->Parse(*host, stream, info);
+ negative->PostParse(*host, stream, info);
+ int ifdindex = -1;
+ dng_ifd *rawIFD = search_for_ifd(info, libraw_internal_data.unpacker_data.data_offset, imgdata.sizes.raw_width, imgdata.sizes.raw_height, ifdindex,stream);
+ if (rawIFD && ifdindex >= 0 && ifdindex == info.fMainIndex)
+ return 1;
+ return 0;
+ }
+
+#ifdef USE_GPRSDK
+ if (load_raw == &LibRaw::vc5_dng_load_raw_placeholder) // regardless of flags or use_dngsdk value!
+ return 1;
+#endif
+ if (!imgdata.rawparams.use_dngsdk)
+ return 0;
+ if (load_raw == &LibRaw::lossy_dng_load_raw) // WHY??
+ return 0;
+ if (is_floating_point() && (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_FLOAT))
+ return 1;
+ if (!imgdata.idata.filters && (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_LINEAR))
+ return 1;
+ if (libraw_internal_data.unpacker_data.tiff_bps == 8 &&
+ (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_8BIT))
+ return 1;
+ if (libraw_internal_data.unpacker_data.tiff_compress == 8 &&
+ (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_DEFLATE))
+ return 1;
+ if (libraw_internal_data.unpacker_data.tiff_samples == 2)
+ return 0; // Always deny 2-samples (old fuji superccd)
+ if (imgdata.idata.filters == 9 &&
+ (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_XTRANS))
+ return 1;
+ if (is_fuji_rotated())
+ return 0; // refuse
+ if (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_OTHER)
+ return 1;
+ return 0;
+#endif
+}
+
+
+
+
+int LibRaw::try_dngsdk()
+{
+#ifdef USE_DNGSDK
+ if (!dnghost)
+ return LIBRAW_UNSPECIFIED_ERROR;
+
+ dng_host *host = static_cast<dng_host *>(dnghost);
+
+ try
+ {
+ libraw_dng_stream stream(libraw_internal_data.internal_data.input);
+
+ AutoPtr<dng_negative> negative;
+ negative.Reset(host->Make_dng_negative());
+
+ dng_info info;
+ info.Parse(*host, stream);
+ info.PostParse(*host);
+
+ if (!info.IsValidDNG())
+ {
+ return LIBRAW_DATA_ERROR;
+ }
+ negative->Parse(*host, stream, info);
+ negative->PostParse(*host, stream, info);
+ int ifdindex;
+ dng_ifd *rawIFD = search_for_ifd(info,libraw_internal_data.unpacker_data.data_offset,imgdata.sizes.raw_width,imgdata.sizes.raw_height,ifdindex,stream);
+ if(!rawIFD)
+ return LIBRAW_DATA_ERROR;
+
+ AutoPtr<dng_simple_image> stage2;
+ bool stage23used = false;
+ bool zerocopy = false;
+
+ //(new dng_simple_image(rawIFD->Bounds(), rawIFD->fSamplesPerPixel, rawIFD->PixelType(), host->Allocator()));
+
+ if (((libraw_internal_data.unpacker_data.tiff_compress == 34892
+ && libraw_internal_data.unpacker_data.tiff_bps == 8
+ && libraw_internal_data.unpacker_data.tiff_samples == 3
+ && load_raw == &LibRaw::lossy_dng_load_raw)
+ || (imgdata.rawparams.options & (LIBRAW_RAWOPTIONS_DNG_STAGE2| LIBRAW_RAWOPTIONS_DNG_STAGE3))
+ || ((tiff_ifd[ifdindex].dng_levels.parsedfields & (LIBRAW_DNGFM_OPCODE2| LIBRAW_DNGFM_OPCODE3))
+ && (imgdata.rawparams.options & (LIBRAW_RAWOPTIONS_DNG_STAGE2_IFPRESENT | LIBRAW_RAWOPTIONS_DNG_STAGE3_IFPRESENT)))
+ )
+ && ifdindex >= 0)
+ {
+ if (info.fMainIndex != ifdindex)
+ info.fMainIndex = ifdindex;
+
+ negative->ReadStage1Image(*host, stream, info);
+ negative->BuildStage2Image(*host);
+ imgdata.process_warnings |= LIBRAW_WARN_DNG_STAGE2_APPLIED;
+ if ( (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_STAGE3) ||
+ ((tiff_ifd[ifdindex].dng_levels.parsedfields & LIBRAW_DNGFM_OPCODE3) &&
+ (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_STAGE3_IFPRESENT))
+ )
+ {
+ negative->BuildStage3Image(*host);
+ stage2.Reset((dng_simple_image*)negative->Stage3Image());
+ imgdata.process_warnings |= LIBRAW_WARN_DNG_STAGE3_APPLIED;
+ }
+ else
+ stage2.Reset((dng_simple_image*)negative->Stage2Image());
+ stage23used = true;
+ }
+ else
+ {
+ stage2.Reset(new dng_simple_image(rawIFD->Bounds(), rawIFD->fSamplesPerPixel, rawIFD->PixelType(), host->Allocator()));
+#ifdef USE_GPRSDK
+ if (libraw_internal_data.unpacker_data.tiff_compress == 9)
+ {
+ gpr_allocator allocator;
+ allocator.Alloc = ::malloc;
+ allocator.Free = ::free;
+ gpr_buffer_auto vc5_image_obj(allocator.Alloc, allocator.Free);
+
+ gpr_read_image reader(&vc5_image_obj);
+ reader.Read(*host, *rawIFD, stream, *stage2.Get(), NULL, NULL);
+ }
+ else
+#endif
+ {
+ dng_read_image reader;
+ reader.Read(*host, *rawIFD, stream, *stage2.Get(), NULL, NULL);
+ }
+ }
+
+ if (stage2->Bounds().W() != S.raw_width ||
+ stage2->Bounds().H() != S.raw_height)
+ {
+ if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_ALLOWSIZECHANGE)
+ {
+ S.raw_width = S.width = stage2->Bounds().W();
+ S.left_margin = 0;
+ S.raw_height = S.height = stage2->Bounds().H();
+ S.top_margin = 0;
+ }
+ else
+ {
+ stage2.Release(); // It holds copy to internal dngnegative
+ return LIBRAW_DATA_ERROR;
+ }
+ }
+ if (stage23used)
+ {
+ if (stage2->Planes() > 1)
+ {
+ imgdata.idata.filters = 0;
+ imgdata.idata.colors = stage2->Planes();
+ }
+ // reset BL and whitepoint
+ imgdata.color.black = 0;
+ memset(imgdata.color.cblack, 0, sizeof(imgdata.color.cblack));
+ imgdata.color.maximum = 0xffff;
+ }
+
+ int pplanes = stage2->Planes();
+ int ptype = stage2->PixelType();
+
+ dng_pixel_buffer buffer;
+ stage2->GetPixelBuffer(buffer);
+
+ int pixels = stage2->Bounds().H() * stage2->Bounds().W() * pplanes;
+
+ if (ptype == ttShort && !stage23used && !is_curve_linear())
+ {
+ imgdata.rawdata.raw_alloc = malloc(pixels * TagTypeSize(ptype));
+ ushort *src = (ushort *)buffer.fData;
+ ushort *dst = (ushort *)imgdata.rawdata.raw_alloc;
+ for (int i = 0; i < pixels; i++)
+ dst[i] = imgdata.color.curve[src[i]];
+ S.raw_pitch = S.raw_width * pplanes * TagTypeSize(ptype);
+
+ }
+ else if (ptype == ttByte)
+ {
+ imgdata.rawdata.raw_alloc = malloc(pixels * TagTypeSize(ttShort));
+ unsigned char *src = (unsigned char *)buffer.fData;
+ ushort *dst = (ushort *)imgdata.rawdata.raw_alloc;
+ if (is_curve_linear())
+ {
+ for (int i = 0; i < pixels; i++)
+ dst[i] = src[i];
+ }
+ else
+ {
+ for (int i = 0; i < pixels; i++)
+ dst[i] = imgdata.color.curve[src[i]];
+ }
+ S.raw_pitch = S.raw_width * pplanes * TagTypeSize(ttShort);
+ }
+ else
+ {
+ // Alloc
+ if ((imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNGSDK_ZEROCOPY) && !stage23used)
+ {
+ zerocopy = true;
+ }
+ else
+ {
+ imgdata.rawdata.raw_alloc = malloc(pixels * TagTypeSize(ptype));
+ memmove(imgdata.rawdata.raw_alloc, buffer.fData,
+ pixels * TagTypeSize(ptype));
+ }
+ S.raw_pitch = S.raw_width * pplanes * TagTypeSize(ptype);
+ }
+
+ if (stage23used)
+ stage2.Release();
+
+ if ((ptype == ttFloat) && (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT))
+ zerocopy = true;
+
+ if (zerocopy)
+ {
+ switch (ptype)
+ {
+ case ttFloat:
+ if (pplanes == 1)
+ imgdata.rawdata.float_image = (float *)buffer.fData;
+ else if (pplanes == 3)
+ imgdata.rawdata.float3_image = (float(*)[3])buffer.fData;
+ else if (pplanes == 4)
+ imgdata.rawdata.float4_image = (float(*)[4])buffer.fData;
+ break;
+
+ case ttShort:
+ if (pplanes == 1)
+ imgdata.rawdata.raw_image = (ushort *)buffer.fData;
+ else if (pplanes == 3)
+ imgdata.rawdata.color3_image = (ushort(*)[3])buffer.fData;
+ else if (pplanes == 4)
+ imgdata.rawdata.color4_image = (ushort(*)[4])buffer.fData;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+ else
+ {
+ switch (ptype)
+ {
+ case ttFloat:
+ if (pplanes == 1)
+ imgdata.rawdata.float_image = (float *)imgdata.rawdata.raw_alloc;
+ else if (pplanes == 3)
+ imgdata.rawdata.float3_image = (float(*)[3])imgdata.rawdata.raw_alloc;
+ else if (pplanes == 4)
+ imgdata.rawdata.float4_image = (float(*)[4])imgdata.rawdata.raw_alloc;
+ break;
+
+ case ttByte:
+ case ttShort:
+ if (pplanes == 1)
+ imgdata.rawdata.raw_image = (ushort *)imgdata.rawdata.raw_alloc;
+ else if (pplanes == 3)
+ imgdata.rawdata.color3_image =
+ (ushort(*)[3])imgdata.rawdata.raw_alloc;
+ else if (pplanes == 4)
+ imgdata.rawdata.color4_image =
+ (ushort(*)[4])imgdata.rawdata.raw_alloc;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ if ((ptype == ttFloat) && (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT))
+ {
+ convertFloatToInt();
+ zerocopy = false;
+ }
+
+ if (zerocopy)
+ {
+ dng_negative *stolen = negative.Release();
+ dngnegative = stolen;
+ dng_simple_image *simage = stage2.Release();
+ dngimage = simage;
+ }
+ }
+ catch (...)
+ {
+ return LIBRAW_UNSPECIFIED_ERROR;
+ }
+
+ return (dngnegative || imgdata.rawdata.raw_alloc) ? LIBRAW_SUCCESS : LIBRAW_UNSPECIFIED_ERROR;
+#else
+ return LIBRAW_UNSPECIFIED_ERROR;
+#endif
+}
+void LibRaw::set_dng_host(void *p)
+{
+#ifdef USE_DNGSDK
+ dnghost = p;
+#endif
+}
diff --git a/libkdcraw/libraw/src/integration/rawspeed_glue.cpp b/libkdcraw/libraw/src/integration/rawspeed_glue.cpp
new file mode 100644
index 0000000..42561e7
--- /dev/null
+++ b/libkdcraw/libraw/src/integration/rawspeed_glue.cpp
@@ -0,0 +1,286 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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"
+
+#ifdef USE_RAWSPEED
+using namespace RawSpeed;
+
+CameraMetaDataLR::CameraMetaDataLR(char *data, int sz) : CameraMetaData()
+{
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL)
+ {
+ ThrowCME("CameraMetaData:Could not initialize context.");
+ }
+
+ xmlResetLastError();
+ doc = xmlCtxtReadMemory(ctxt, data, sz, "", NULL, XML_PARSE_DTDVALID);
+
+ if (doc == NULL)
+ {
+ ThrowCME("CameraMetaData: XML Document could not be parsed successfully. "
+ "Error was: %s",
+ ctxt->lastError.message);
+ }
+
+ if (ctxt->valid == 0)
+ {
+ if (ctxt->lastError.code == 0x5e)
+ {
+ // ignore this error code
+ }
+ else
+ {
+ ThrowCME("CameraMetaData: XML file does not validate. DTD Error was: %s",
+ ctxt->lastError.message);
+ }
+ }
+
+ xmlNodePtr cur;
+ cur = xmlDocGetRootElement(doc);
+ if (xmlStrcmp(cur->name, (const xmlChar *)"Cameras"))
+ {
+ ThrowCME("CameraMetaData: XML document of the wrong type, root node is not "
+ "cameras.");
+ return;
+ }
+
+ cur = cur->xmlChildrenNode;
+ while (cur != NULL)
+ {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *)"Camera")))
+ {
+ Camera *camera = new Camera(doc, cur);
+ addCamera(camera);
+
+ // Create cameras for aliases.
+ for (unsigned int i = 0; i < camera->aliases.size(); i++)
+ {
+ addCamera(new Camera(camera, i));
+ }
+ }
+ cur = cur->next;
+ }
+ if (doc)
+ xmlFreeDoc(doc);
+ doc = 0;
+ if (ctxt)
+ xmlFreeParserCtxt(ctxt);
+ ctxt = 0;
+}
+
+CameraMetaDataLR *make_camera_metadata()
+{
+ int len = 0, i;
+ for (i = 0; i < RAWSPEED_DATA_COUNT; i++)
+ if (_rawspeed_data_xml[i])
+ {
+ len += int(strlen(_rawspeed_data_xml[i]));
+ }
+ char *rawspeed_xml =
+ (char *)calloc(len + 1, sizeof(_rawspeed_data_xml[0][0]));
+ if (!rawspeed_xml)
+ return NULL;
+ int offt = 0;
+ for (i = 0; i < RAWSPEED_DATA_COUNT; i++)
+ if (_rawspeed_data_xml[i])
+ {
+ int ll = int(strlen(_rawspeed_data_xml[i]));
+ if (offt + ll > len)
+ break;
+ memmove(rawspeed_xml + offt, _rawspeed_data_xml[i], ll);
+ offt += ll;
+ }
+ rawspeed_xml[offt] = 0;
+ CameraMetaDataLR *ret = NULL;
+ try
+ {
+ ret = new CameraMetaDataLR(rawspeed_xml, offt);
+ }
+ catch (...)
+ {
+ // Mask all exceptions
+ }
+ free(rawspeed_xml);
+ return ret;
+}
+
+#endif
+
+int LibRaw::set_rawspeed_camerafile(char * filename)
+{
+#ifdef USE_RAWSPEED
+ try
+ {
+ CameraMetaDataLR *camerameta = new CameraMetaDataLR(filename);
+ if (_rawspeed_camerameta)
+ {
+ CameraMetaDataLR *d =
+ static_cast<CameraMetaDataLR *>(_rawspeed_camerameta);
+ delete d;
+ }
+ _rawspeed_camerameta = static_cast<void *>(camerameta);
+ }
+ catch (...)
+ {
+ // just return error code
+ return -1;
+ }
+#else
+ (void)filename;
+#endif
+ return 0;
+}
+#ifdef USE_RAWSPEED
+void LibRaw::fix_after_rawspeed(int /*bl*/)
+{
+ if (load_raw == &LibRaw::lossy_dng_load_raw)
+ C.maximum = 0xffff;
+ else if (load_raw == &LibRaw::sony_load_raw)
+ C.maximum = 0x3ff0;
+}
+#else
+void LibRaw::fix_after_rawspeed(int) {}
+#endif
+
+int LibRaw::try_rawspeed()
+{
+#ifdef USE_RAWSPEED
+ int ret = LIBRAW_SUCCESS;
+
+#ifdef USE_RAWSPEED_BITS
+ int rawspeed_ignore_errors = (imgdata.rawparams.use_rawspeed & LIBRAW_RAWSPEEDV1_IGNOREERRORS);
+#else
+ int rawspeed_ignore_errors = 0;
+#endif
+ if (imgdata.idata.dng_version && imgdata.idata.colors == 3 &&
+ !strcasecmp(imgdata.idata.software,
+ "Adobe Photoshop Lightroom 6.1.1 (Windows)"))
+ rawspeed_ignore_errors = 1;
+
+ // RawSpeed Supported,
+ INT64 spos = ID.input->tell();
+ void *_rawspeed_buffer = 0;
+ try
+ {
+ ID.input->seek(0, SEEK_SET);
+ INT64 _rawspeed_buffer_sz = ID.input->size() + 32;
+ _rawspeed_buffer = malloc(_rawspeed_buffer_sz);
+ if (!_rawspeed_buffer)
+ throw LIBRAW_EXCEPTION_ALLOC;
+ ID.input->read(_rawspeed_buffer, _rawspeed_buffer_sz, 1);
+ FileMap map((uchar8 *)_rawspeed_buffer, _rawspeed_buffer_sz);
+ RawParser t(&map);
+ RawDecoder *d = 0;
+ CameraMetaDataLR *meta =
+ static_cast<CameraMetaDataLR *>(_rawspeed_camerameta);
+ d = t.getDecoder();
+ if (!d)
+ throw "Unable to find decoder";
+
+#ifdef USE_RAWSPEED_BITS
+ if (imgdata.rawparams.use_rawspeed & LIBRAW_RAWSPEEDV1_FAILONUNKNOWN)
+ d->failOnUnknown = TRUE;
+ else
+ d->failOnUnknown = FALSE;
+#endif
+ d->interpolateBadPixels = FALSE;
+ d->applyStage1DngOpcodes = FALSE;
+
+ try
+ {
+ d->checkSupport(meta);
+ }
+ catch (const RawDecoderException &e)
+ {
+ imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_UNSUPPORTED;
+ throw e;
+ }
+ _rawspeed_decoder = static_cast<void *>(d);
+ d->decodeRaw();
+ d->decodeMetaData(meta);
+ RawImage r = d->mRaw;
+ if (r->errors.size() > 0 && !rawspeed_ignore_errors)
+ {
+ delete d;
+ _rawspeed_decoder = 0;
+ throw 1;
+ }
+ if (r->isCFA)
+ {
+ imgdata.rawdata.raw_image = (ushort *)r->getDataUncropped(0, 0);
+ }
+ else if (r->getCpp() == 4)
+ {
+ imgdata.rawdata.color4_image = (ushort(*)[4])r->getDataUncropped(0, 0);
+ if (r->whitePoint > 0 && r->whitePoint < 65536)
+ C.maximum = r->whitePoint;
+ }
+ else if (r->getCpp() == 3)
+ {
+ imgdata.rawdata.color3_image = (ushort(*)[3])r->getDataUncropped(0, 0);
+ if (r->whitePoint > 0 && r->whitePoint < 65536)
+ C.maximum = r->whitePoint;
+ }
+ else
+ {
+ delete d;
+ _rawspeed_decoder = 0;
+ ret = LIBRAW_UNSPECIFIED_ERROR;
+ }
+ if (_rawspeed_decoder)
+ {
+ // set sizes
+ iPoint2D rsdim = r->getUncroppedDim();
+ S.raw_pitch = r->pitch;
+ S.raw_width = rsdim.x;
+ S.raw_height = rsdim.y;
+ // C.maximum = r->whitePoint;
+ fix_after_rawspeed(r->blackLevel);
+ }
+ free(_rawspeed_buffer);
+ _rawspeed_buffer = 0;
+ imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROCESSED;
+ }
+ catch (const RawDecoderException &RDE)
+ {
+ imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROBLEM;
+ if (_rawspeed_buffer)
+ {
+ free(_rawspeed_buffer);
+ _rawspeed_buffer = 0;
+ }
+ if (!strncmp(RDE.what(), "Decoder canceled", strlen("Decoder canceled")))
+ throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK;
+ ret = LIBRAW_UNSPECIFIED_ERROR;
+ }
+ catch (...)
+ {
+ // We may get here due to cancellation flag
+ imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROBLEM;
+ if (_rawspeed_buffer)
+ {
+ free(_rawspeed_buffer);
+ _rawspeed_buffer = 0;
+ }
+ ret = LIBRAW_UNSPECIFIED_ERROR;
+ }
+ ID.input->seek(spos, SEEK_SET);
+
+ return ret;
+#else
+ return LIBRAW_NOT_IMPLEMENTED;
+#endif
+}
diff --git a/libkdcraw/libraw/src/libraw_c_api.cpp b/libkdcraw/libraw/src/libraw_c_api.cpp
index f966e9e..4e85ec2 100644
--- a/libkdcraw/libraw/src/libraw_c_api.cpp
+++ b/libkdcraw/libraw/src/libraw_c_api.cpp
@@ -1,142 +1,456 @@
-/*
+/* -*- C++ -*-
* File: libraw_c_api.cpp
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
* Created: Sat Mar 8 , 2008
*
- * LibRaw C++ interface (implementation)
+ * LibRaw C interface
+
+
+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 <math.h>
#include <errno.h>
#include "libraw/libraw.h"
#ifdef __cplusplus
-extern "C"
+#include <new>
+extern "C"
{
#endif
- libraw_data_t *libraw_init(unsigned int flags)
- {
- LibRaw *ret = new LibRaw(flags);
- return &(ret->imgdata);
- }
-
- const char* libraw_version() { return LibRaw::version();}
- const char* libraw_strprogress(enum LibRaw_progress p) { return LibRaw::strprogress(p);}
- int libraw_versionNumber() { return LibRaw::versionNumber();}
- const char** libraw_cameraList() { return LibRaw::cameraList();}
- int libraw_cameraCount() { return LibRaw::cameraCount(); }
- const char* libraw_unpack_function_name(libraw_data_t* lr)
+ libraw_data_t *libraw_init(unsigned int flags)
+ {
+ LibRaw *ret;
+ try
{
- if(!lr) return "NULL parameter passed";
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->unpack_function_name();
+ ret = new LibRaw(flags);
}
- int libraw_rotate_fuji_raw(libraw_data_t* lr)
+ catch (const std::bad_alloc& )
{
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->rotate_fuji_raw();
+ return NULL;
}
+ return &(ret->imgdata);
+ }
- int libraw_add_masked_borders_to_bitmap(libraw_data_t* lr)
- {
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->add_masked_borders_to_bitmap();
- }
+ unsigned libraw_capabilities() { return LibRaw::capabilities(); }
+ const char *libraw_version() { return LibRaw::version(); }
+ const char *libraw_strprogress(enum LibRaw_progress p)
+ {
+ return LibRaw::strprogress(p);
+ }
+ int libraw_versionNumber() { return LibRaw::versionNumber(); }
+ const char **libraw_cameraList() { return LibRaw::cameraList(); }
+ int libraw_cameraCount() { return LibRaw::cameraCount(); }
+ const char *libraw_unpack_function_name(libraw_data_t *lr)
+ {
+ if (!lr)
+ return "NULL parameter passed";
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->unpack_function_name();
+ }
- int libraw_open_file(libraw_data_t* lr, const char *file)
- {
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->open_file(file);
- }
- int libraw_open_buffer(libraw_data_t* lr, void *buffer, size_t size)
- {
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->open_buffer(buffer,size);
- }
- int libraw_unpack(libraw_data_t* lr)
- {
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->unpack();
- }
- int libraw_unpack_thumb(libraw_data_t* lr)
- {
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->unpack_thumb();
- }
- void libraw_recycle(libraw_data_t* lr)
+ void libraw_subtract_black(libraw_data_t *lr)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->subtract_black();
+ }
+
+ int libraw_open_file(libraw_data_t *lr, const char *file)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->open_file(file);
+ }
+
+ libraw_iparams_t *libraw_get_iparams(libraw_data_t *lr)
+ {
+ if (!lr)
+ return NULL;
+ return &(lr->idata);
+ }
+
+ libraw_lensinfo_t *libraw_get_lensinfo(libraw_data_t *lr)
+ {
+ if (!lr)
+ return NULL;
+ return &(lr->lens);
+ }
+
+ libraw_imgother_t *libraw_get_imgother(libraw_data_t *lr)
+ {
+ if (!lr)
+ return NULL;
+ return &(lr->other);
+ }
+
+#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
+ int libraw_open_file_ex(libraw_data_t *lr, const char *file, INT64 sz)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->open_file(file, sz);
+ }
+#endif
+
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ int libraw_open_wfile(libraw_data_t *lr, const wchar_t *file)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->open_file(file);
+ }
+
+#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
+ int libraw_open_wfile_ex(libraw_data_t *lr, const wchar_t *file, INT64 sz)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->open_file(file, sz);
+ }
+#endif
+#endif
+ int libraw_open_buffer(libraw_data_t *lr, const void *buffer, size_t size)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->open_buffer(buffer, size);
+ }
+ int libraw_open_bayer(libraw_data_t *lr, unsigned char *data,
+ unsigned datalen, ushort _raw_width, ushort _raw_height,
+ ushort _left_margin, ushort _top_margin,
+ ushort _right_margin, ushort _bottom_margin,
+ unsigned char procflags, unsigned char bayer_pattern,
+ unsigned unused_bits, unsigned otherflags,
+ unsigned black_level)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->open_bayer(data, datalen, _raw_width, _raw_height, _left_margin,
+ _top_margin, _right_margin, _bottom_margin, procflags,
+ bayer_pattern, unused_bits, otherflags, black_level);
+ }
+ int libraw_unpack(libraw_data_t *lr)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->unpack();
+ }
+ int libraw_unpack_thumb(libraw_data_t *lr)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->unpack_thumb();
+ }
+ int libraw_unpack_thumb_ex(libraw_data_t *lr, int i)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->unpack_thumb_ex(i);
+ }
+ void libraw_recycle_datastream(libraw_data_t *lr)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->recycle_datastream();
+ }
+ void libraw_recycle(libraw_data_t *lr)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->recycle();
+ }
+ void libraw_close(libraw_data_t *lr)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ delete ip;
+ }
+
+ void libraw_set_exifparser_handler(libraw_data_t *lr, exif_parser_callback cb,
+ void *data)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->set_exifparser_handler(cb, data);
+ }
+
+ void libraw_set_dataerror_handler(libraw_data_t *lr, data_callback func,
+ void *data)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->set_dataerror_handler(func, data);
+ }
+ void libraw_set_progress_handler(libraw_data_t *lr, progress_callback cb,
+ void *data)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->set_progress_handler(cb, data);
+ }
+
+ // DCRAW
+ int libraw_adjust_sizes_info_only(libraw_data_t *lr)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->adjust_sizes_info_only();
+ }
+ int libraw_dcraw_ppm_tiff_writer(libraw_data_t *lr, const char *filename)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->dcraw_ppm_tiff_writer(filename);
+ }
+ int libraw_dcraw_thumb_writer(libraw_data_t *lr, const char *fname)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->dcraw_thumb_writer(fname);
+ }
+ int libraw_dcraw_process(libraw_data_t *lr)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->dcraw_process();
+ }
+ libraw_processed_image_t *libraw_dcraw_make_mem_image(libraw_data_t *lr,
+ int *errc)
+ {
+ if (!lr)
{
- if(!lr) return;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- ip->recycle();
+ if (errc)
+ *errc = EINVAL;
+ return NULL;
}
- void libraw_close(libraw_data_t* lr)
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->dcraw_make_mem_image(errc);
+ }
+ libraw_processed_image_t *libraw_dcraw_make_mem_thumb(libraw_data_t *lr,
+ int *errc)
+ {
+ if (!lr)
{
- if(!lr) return;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- delete ip;
+ if (errc)
+ *errc = EINVAL;
+ return NULL;
}
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->dcraw_make_mem_thumb(errc);
+ }
- void libraw_set_memerror_handler(libraw_data_t* lr, memory_callback cb,void *data)
- {
- if(!lr) return;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- ip->set_memerror_handler(cb,data);
+ void libraw_dcraw_clear_mem(libraw_processed_image_t *p)
+ {
+ LibRaw::dcraw_clear_mem(p);
+ }
- }
- void libraw_set_dataerror_handler(libraw_data_t* lr,data_callback func,void *data)
- {
- if(!lr) return;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- ip->set_dataerror_handler(func,data);
+ int libraw_raw2image(libraw_data_t *lr)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->raw2image();
+ }
+ void libraw_free_image(libraw_data_t *lr)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->free_image();
+ }
+ int libraw_get_decoder_info(libraw_data_t *lr, libraw_decoder_info_t *d)
+ {
+ if (!lr || !d)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->get_decoder_info(d);
+ }
+ int libraw_COLOR(libraw_data_t *lr, int row, int col)
+ {
+ if (!lr)
+ return EINVAL;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ return ip->COLOR(row, col);
+ }
- }
- void libraw_set_progress_handler(libraw_data_t* lr, progress_callback cb,void *data)
- {
- if(!lr) return;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- ip->set_progress_handler(cb,data);
+ /* getters/setters used by 3DLut Creator */
+ DllDef void libraw_set_demosaic(libraw_data_t *lr, int value)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.user_qual = value;
+ }
- }
+ DllDef void libraw_set_output_color(libraw_data_t *lr, int value)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.output_color = value;
+ }
- // DCRAW
- int libraw_adjust_sizes_info_only(libraw_data_t* lr)
- {
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->adjust_sizes_info_only();
- }
+ DllDef void libraw_set_adjust_maximum_thr(libraw_data_t *lr, float value)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.adjust_maximum_thr = value;
+ }
- int libraw_dcraw_document_mode_processing(libraw_data_t* lr)
- {
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->dcraw_document_mode_processing();
+ DllDef void libraw_set_output_bps(libraw_data_t *lr, int value)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.output_bps = value;
+ }
- }
- int libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename)
- {
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->dcraw_ppm_tiff_writer(filename);
- }
- int libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname)
- {
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->dcraw_thumb_writer(fname);
+ DllDef void libraw_set_output_tif(libraw_data_t *lr, int value)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.output_tiff = value;
+ }
- }
- int libraw_dcraw_process(libraw_data_t* lr)
- {
- if(!lr) return EINVAL;
- LibRaw *ip = (LibRaw*) lr->parent_class;
- return ip->dcraw_process();
- }
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define LIM(x, min, max) MAX(min, MIN(x, max))
+
+ DllDef void libraw_set_user_mul(libraw_data_t *lr, int index, float val)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.user_mul[LIM(index, 0, 3)] = val;
+ }
+
+ DllDef void libraw_set_gamma(libraw_data_t *lr, int index, float value)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.gamm[LIM(index, 0, 5)] = value;
+ }
+
+ DllDef void libraw_set_no_auto_bright(libraw_data_t *lr, int value)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.no_auto_bright = value;
+ }
+
+ DllDef void libraw_set_bright(libraw_data_t *lr, float value)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.bright = value;
+ }
+
+ DllDef void libraw_set_highlight(libraw_data_t *lr, int value)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.highlight = value;
+ }
+
+ DllDef void libraw_set_fbdd_noiserd(libraw_data_t *lr, int value)
+ {
+ if (!lr)
+ return;
+ LibRaw *ip = (LibRaw *)lr->parent_class;
+ ip->imgdata.params.fbdd_noiserd = value;
+ }
+
+ DllDef int libraw_get_raw_height(libraw_data_t *lr)
+ {
+ if (!lr)
+ return EINVAL;
+ return lr->sizes.raw_height;
+ }
+
+ DllDef int libraw_get_raw_width(libraw_data_t *lr)
+ {
+ if (!lr)
+ return EINVAL;
+ return lr->sizes.raw_width;
+ }
+
+ DllDef int libraw_get_iheight(libraw_data_t *lr)
+ {
+ if (!lr)
+ return EINVAL;
+ return lr->sizes.iheight;
+ }
+
+ DllDef int libraw_get_iwidth(libraw_data_t *lr)
+ {
+ if (!lr)
+ return EINVAL;
+ return lr->sizes.iwidth;
+ }
+
+ DllDef float libraw_get_cam_mul(libraw_data_t *lr, int index)
+ {
+ if (!lr)
+ return EINVAL;
+ return lr->color.cam_mul[LIM(index, 0, 3)];
+ }
+
+ DllDef float libraw_get_pre_mul(libraw_data_t *lr, int index)
+ {
+ if (!lr)
+ return EINVAL;
+ return lr->color.pre_mul[LIM(index, 0, 3)];
+ }
+
+ DllDef float libraw_get_rgb_cam(libraw_data_t *lr, int index1, int index2)
+ {
+ if (!lr)
+ return EINVAL;
+ return lr->color.rgb_cam[LIM(index1, 0, 2)][LIM(index2, 0, 3)];
+ }
+
+ DllDef int libraw_get_color_maximum(libraw_data_t *lr)
+ {
+ if (!lr)
+ return EINVAL;
+ return lr->color.maximum;
+ }
#ifdef __cplusplus
}
diff --git a/libkdcraw/libraw/src/libraw_cxx.cpp b/libkdcraw/libraw/src/libraw_cxx.cpp
index 457d4f9..468f4d0 100644
--- a/libkdcraw/libraw/src/libraw_cxx.cpp
+++ b/libkdcraw/libraw/src/libraw_cxx.cpp
@@ -1,1940 +1,55 @@
-/*
+/* -*- C++ -*-
* File: libraw_cxx.cpp
- * Copyright 2008-2009 Alex Tutubalin <[email protected]>
+ * Copyright 2008-2020 LibRaw LLC ([email protected])
* Created: Sat Mar 8 , 2008
*
- * LibRaw C++ interface (implementation)
- */
-
-#include <errno.h>
-#include <float.h>
-#include <math.h>
-#ifndef WIN32
-#include <netinet/in.h>
-#else
-#include <winsock2.h>
-#endif
-#define LIBRAW_LIBRARY_BUILD
-#include "libraw/libraw.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
- void default_memory_callback(void *,const char *file,const char *where)
- {
- fprintf (stderr,"%s: Out of memory in %s\n", file?file:"unknown file", where);
- }
-
- void default_data_callback(void*,const char *file, const int offset)
- {
- if(offset < 0)
- fprintf (stderr,"%s: Unexpected end of file\n", file?file:"unknown file");
- else
- fprintf (stderr,"%s: data corrupted at %d\n",file?file:"unknown file",offset);
- }
- const char *libraw_strerror(int e)
- {
- enum LibRaw_errors errorcode = (LibRaw_errors)e;
- switch(errorcode)
- {
- case LIBRAW_SUCCESS:
- return "No error";
- case LIBRAW_UNSPECIFIED_ERROR:
- return "Unspecified error";
- case LIBRAW_FILE_UNSUPPORTED:
- return "Unsupported file format or not RAW file";
- case LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE:
- return "Request for nonexisting image number";
- case LIBRAW_OUT_OF_ORDER_CALL:
- return "Out of order call of libraw function";
- case LIBRAW_NO_THUMBNAIL:
- return "No thumbnail in file";
- case LIBRAW_UNSUPPORTED_THUMBNAIL:
- return "Unsupported thumbnail format";
- case LIBRAW_CANNOT_ADDMASK:
- return "Cannot add masked pixels to resized image";
- case LIBRAW_UNSUFFICIENT_MEMORY:
- return "Unsufficient memory";
- case LIBRAW_DATA_ERROR:
- return "Corrupted data or unexpected EOF";
- case LIBRAW_IO_ERROR:
- return "Input/output error";
- case LIBRAW_CANCELLED_BY_CALLBACK:
- return "Cancelled by user callback";
- default:
- return "Unknown error code";
- }
- }
-
-#ifdef __cplusplus
-}
-#endif
-
-
-const double LibRaw_constants::xyz_rgb[3][3] =
-{
- { 0.412453, 0.357580, 0.180423 },
- { 0.212671, 0.715160, 0.072169 },
- { 0.019334, 0.119193, 0.950227 }
-};
-
-const float LibRaw_constants::d65_white[3] = { 0.950456, 1, 1.088754 };
-
-#define P1 imgdata.idata
-#define S imgdata.sizes
-#define O imgdata.params
-#define C imgdata.color
-#define M imgdata.masked_pixels
-#define T imgdata.thumbnail
-#define IO libraw_internal_data.internal_output_params
-#define ID libraw_internal_data.internal_data
-
-#define EXCEPTION_HANDLER(e) do{ \
- fprintf(stderr,"Exception %d caught\n",e); \
- switch(e) \
- { \
- case LIBRAW_EXCEPTION_ALLOC: \
- recycle(); \
- return LIBRAW_UNSUFFICIENT_MEMORY; \
- case LIBRAW_EXCEPTION_DECODE_RAW: \
- case LIBRAW_EXCEPTION_DECODE_JPEG: \
- recycle(); \
- return LIBRAW_DATA_ERROR; \
- case LIBRAW_EXCEPTION_IO_EOF: \
- case LIBRAW_EXCEPTION_IO_CORRUPT: \
- recycle(); \
- return LIBRAW_IO_ERROR; \
- case LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK:\
- recycle(); \
- return LIBRAW_CANCELLED_BY_CALLBACK; \
- default: \
- return LIBRAW_UNSPECIFIED_ERROR; \
- } \
- }while(0)
-
-void LibRaw::derror()
-{
- if (!libraw_internal_data.unpacker_data.data_error && libraw_internal_data.internal_data.input)
- {
- if (libraw_internal_data.internal_data.input->eof())
- {
- if(callbacks.data_cb)(*callbacks.data_cb)(callbacks.datacb_data,
- libraw_internal_data.internal_data.input->fname(),-1);
- throw LIBRAW_EXCEPTION_IO_EOF;
- }
- else
- {
- if(callbacks.data_cb)(*callbacks.data_cb)(callbacks.datacb_data,
- libraw_internal_data.internal_data.input->fname(),
- libraw_internal_data.internal_data.input->tell());
- throw LIBRAW_EXCEPTION_IO_CORRUPT;
- }
- }
- libraw_internal_data.unpacker_data.data_error = 1;
-}
-LibRaw:: LibRaw(unsigned int flags)
-{
- double aber[4] = {1,1,1,1};
- double gamm[5] = { 0.45,4.5,0,0,0 };
- unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX };
-#ifdef DCRAW_VERBOSE
- verbose = 1;
-#else
- verbose = 0;
-#endif
- bzero(&imgdata,sizeof(imgdata));
- bzero(&libraw_internal_data,sizeof(libraw_internal_data));
- bzero(&callbacks,sizeof(callbacks));
- callbacks.mem_cb = (flags & LIBRAW_OPIONS_NO_MEMERR_CALLBACK) ? NULL: &default_memory_callback;
- callbacks.data_cb = (flags & LIBRAW_OPIONS_NO_DATAERR_CALLBACK)? NULL : &default_data_callback;
- memmove(&imgdata.params.aber,&aber,sizeof(aber));
- memmove(&imgdata.params.gamm,&gamm,sizeof(gamm));
- memmove(&imgdata.params.greybox,&greybox,sizeof(greybox));
-
- imgdata.params.bright=1;
- imgdata.params.use_camera_matrix=-1;
- imgdata.params.user_flip=-1;
- imgdata.params.user_black=-1;
- imgdata.params.user_sat=-1;
- imgdata.params.user_qual=-1;
- imgdata.params.output_color=1;
- imgdata.params.output_bps=8;
- imgdata.params.use_fuji_rotate=1;
- imgdata.params.auto_bright_thr = 0.01;
- imgdata.parent_class = this;
- imgdata.progress_flags = 0;
- tls = new LibRaw_TLS;
- tls->init();
-}
-
-
-void* LibRaw:: malloc(size_t t)
-{
- void *p = memmgr.malloc(t);
- return p;
-}
-void* LibRaw:: calloc(size_t n,size_t t)
-{
- void *p = memmgr.calloc(n,t);
- return p;
-}
-void LibRaw:: free(void *p)
-{
- memmgr.free(p);
-}
-
-
-int LibRaw:: fc (int row, int col)
-{
- static const char filter[16][16] =
- { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
- { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
- { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
- { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
- { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
- { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
- { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
- { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
- { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
- { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
- { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
- { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
- { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
- { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
- { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
- { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
-
- if (imgdata.idata.filters != 1) return FC(row,col);
- return filter[(row+imgdata.sizes.top_margin) & 15][(col+imgdata.sizes.left_margin) & 15];
-}
-
-void LibRaw:: recycle()
-{
- if(libraw_internal_data.internal_data.input && libraw_internal_data.internal_data.input_internal)
- {
- delete libraw_internal_data.internal_data.input;
- libraw_internal_data.internal_data.input = NULL;
- }
- libraw_internal_data.internal_data.input_internal = 0;
-#define FREE(a) do { if(a) { free(a); a = NULL;} }while(0)
-
- FREE(imgdata.image);
- FREE(imgdata.thumbnail.thumb);
- FREE(libraw_internal_data.internal_data.meta_data);
- FREE(libraw_internal_data.output_data.histogram);
- FREE(libraw_internal_data.output_data.oprof);
- FREE(imgdata.color.profile);
- FREE(imgdata.masked_pixels.buffer);
- FREE(imgdata.masked_pixels.ph1_black);
-#undef FREE
-#define ZERO(a) bzero(&a,sizeof(a))
- ZERO(imgdata.masked_pixels);
- ZERO(imgdata.sizes);
- ZERO(libraw_internal_data.internal_output_params);
-#undef ZERO
- memmgr.cleanup();
- imgdata.thumbnail.tformat = LIBRAW_THUMBNAIL_UNKNOWN;
- imgdata.progress_flags = 0;
-
- tls->init();
-}
-
-const char * LibRaw::unpack_function_name()
-{
- if(!load_raw) return "Function not set";
-
- // sorted names order
- if (load_raw == &LibRaw::adobe_dng_load_raw_lj) return "adobe_dng_load_raw_lj()";
- if (load_raw == &LibRaw::adobe_dng_load_raw_nc) return "adobe_dng_load_raw_nc()";
- if (load_raw == &LibRaw::canon_600_load_raw) return "canon_600_load_raw()";
-
- if (load_raw == &LibRaw::canon_a5_load_raw) return "canon_a5_load_raw()";
- if (load_raw == &LibRaw::canon_compressed_load_raw) return "canon_compressed_load_raw()";
- if (load_raw == &LibRaw::canon_sraw_load_raw) return "canon_sraw_load_raw()";
-
- if (load_raw == &LibRaw::casio_qv5700_load_raw ) return "casio_qv5700_load_raw()";
- if (load_raw == &LibRaw::eight_bit_load_raw ) return "eight_bit_load_raw()";
- if (load_raw == &LibRaw::foveon_load_raw ) return "foveon_load_raw()";
- if (load_raw == &LibRaw::fuji_load_raw ) return "fuji_load_raw()";
- // 10
- if (load_raw == &LibRaw::hasselblad_load_raw ) return "hasselblad_load_raw()";
- if (load_raw == &LibRaw::imacon_full_load_raw ) return "imacon_full_load_raw()";
- if (load_raw == &LibRaw::kodak_262_load_raw ) return "kodak_262_load_raw()";
-
- if (load_raw == &LibRaw::kodak_65000_load_raw ) return "kodak_65000_load_raw()";
- if (load_raw == &LibRaw::kodak_dc120_load_raw ) return "kodak_dc120_load_raw()";
- if (load_raw == &LibRaw::kodak_jpeg_load_raw ) return "kodak_jpeg_load_raw()";
-
- if (load_raw == &LibRaw::kodak_radc_load_raw ) return "kodak_radc_load_raw()";
- if (load_raw == &LibRaw::kodak_rgb_load_raw ) return "kodak_rgb_load_raw()";
- if (load_raw == &LibRaw::kodak_yrgb_load_raw ) return "kodak_yrgb_load_raw()";
- if (load_raw == &LibRaw::kodak_ycbcr_load_raw ) return "kodak_ycbcr_load_raw()";
- // 20
- if (load_raw == &LibRaw::leaf_hdr_load_raw ) return "leaf_hdr_load_raw()";
- if (load_raw == &LibRaw::lossless_jpeg_load_raw) return "lossless_jpeg_load_raw()";
- if (load_raw == &LibRaw::minolta_rd175_load_raw ) return "minolta_rd175_load_raw()";
-
- if (load_raw == &LibRaw::nikon_compressed_load_raw) return "nikon_compressed_load_raw()";
- if (load_raw == &LibRaw::nikon_e900_load_raw ) return "nikon_e900_load_raw()";
- if (load_raw == &LibRaw::nokia_load_raw ) return "nokia_load_raw()";
-
- if (load_raw == &LibRaw::olympus_e300_load_raw ) return "olympus_e300_load_raw()";
- if (load_raw == &LibRaw::olympus_e410_load_raw ) return "olympus_e410_load_raw()";
- if (load_raw == &LibRaw::packed_12_load_raw ) return "packed_12_load_raw()";
- if (load_raw == &LibRaw::panasonic_load_raw ) return "panasonic_load_raw()";
- // 30
- if (load_raw == &LibRaw::pentax_k10_load_raw ) return "pentax_k10_load_raw()";
- if (load_raw == &LibRaw::phase_one_load_raw ) return "phase_one_load_raw()";
- if (load_raw == &LibRaw::phase_one_load_raw_c ) return "phase_one_load_raw_c()";
-
- if (load_raw == &LibRaw::quicktake_100_load_raw ) return "quicktake_100_load_raw()";
- if (load_raw == &LibRaw::rollei_load_raw ) return "rollei_load_raw()";
- if (load_raw == &LibRaw::sinar_4shot_load_raw ) return "sinar_4shot_load_raw()";
-
- if (load_raw == &LibRaw::smal_v6_load_raw ) return "smal_v6_load_raw()";
- if (load_raw == &LibRaw::smal_v9_load_raw ) return "smal_v9_load_raw()";
- if (load_raw == &LibRaw::sony_load_raw ) return "sony_load_raw()";
- if (load_raw == &LibRaw::sony_arw_load_raw ) return "sony_arw_load_raw()";
- // 40
- if (load_raw == &LibRaw::sony_arw2_load_raw ) return "sony_arw2_load_raw()";
- if (load_raw == &LibRaw::unpacked_load_raw ) return "unpacked_load_raw()";
- // 42 total
-
- return "Unknown unpack function";
-}
-
-
-void LibRaw:: merror (void *ptr, const char *where)
-{
- if (ptr) return;
- if(callbacks.mem_cb)(*callbacks.mem_cb)(callbacks.memcb_data,
- libraw_internal_data.internal_data.input
- ?libraw_internal_data.internal_data.input->fname()
- :NULL,
- where);
- throw LIBRAW_EXCEPTION_ALLOC;
-}
-
-ushort * LibRaw::get_masked_pointer(int row, int col)
-{
- if(row<0 || col < 0) return NULL;
- if(!M.buffer) return NULL;
- if(row < S.top_margin)
- {
- // top band
- if(col < S.left_margin)
- {
- return &(M.tl[row*S.left_margin+col]);
- }
- else if (col < S.left_margin + S.width)
- {
- int icol = col - S.left_margin;
- return &(M.top[row*S.width+icol]);
- }
- else if (col < S.raw_width)
- {
- int icol = col - S.left_margin - S.width;
- return &(M.tr[row*S.right_margin+icol]);
- }
- else
- return NULL; // out of bounds
- }
- else if (row < S.top_margin + S.height)
- {
- //normal image height
- int irow = row - S.top_margin;
- if(col < S.left_margin)
- {
- return &M.left[irow*S.left_margin + col];
- }
- else if (col < S.left_margin + S.width)
- {
- // central image
- return NULL;
- }
- else if (col < S.raw_width)
- {
- int icol = col - S.left_margin - S.width;
- return &M.right[irow*S.right_margin+icol];
- }
- else
- return NULL; // out of bounds
- }
- else if (row < S.raw_height)
- {
- int irow = row - S.top_margin - S.height;
- // bottom band
- if(col < S.left_margin)
- {
- return &M.bl[irow*S.left_margin+col];
- }
- else if (col < S.left_margin + S.width)
- {
- int icol = col - S.left_margin;
- return &M.bottom[irow*S.width + icol];
- }
- else if (col < S.raw_width)
- {
- int icol = col - S.left_margin - S.width;
- return &M.br[irow*S.right_margin + icol];
- }
- else
- return NULL; // out of bounds
- }
- else
- {
- // out of bounds
- return NULL;
- }
- // fallback
- return NULL;
-}
-
-void LibRaw:: init_masked_ptrs()
-{
- if(!M.buffer) return;
-
- // top band
- M.tl = M.buffer;
- M.top = M.tl +(S.top_margin*S.left_margin);
- M.tr = M.top + (S.top_margin*S.width);
-
- // left-right
- M.left = M.tr + (S.top_margin * S.right_margin);
- M.right = M.left + (S.left_margin * S.height);
-
- // bottom band
- M.bl = M.right + (S.right_margin * S.height);
- M.bottom = M.bl + (S.left_margin * S.bottom_margin);
- M.br = M.bottom + (S.width * S.bottom_margin);
-
-}
-
-int LibRaw::add_masked_borders_to_bitmap()
-{
- CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
- CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
-
- if(S.width != S.iwidth || S.height!=S.iheight)
- return LIBRAW_CANNOT_ADDMASK;
-
- if(P1.is_foveon || !P1.filters)
- return LIBRAW_CANNOT_ADDMASK;
-
- if(!imgdata.image)
- return LIBRAW_OUT_OF_ORDER_CALL;
-
- if(S.raw_width < S.width || S.raw_height < S.height)
- return LIBRAW_SUCCESS; // nothing to do or already called
-
- if(S.width == S.raw_width && S.height == S.raw_height)
- return LIBRAW_SUCCESS; // nothing to do or already called
-
- ushort (*newimage)[4];
-
- newimage = (ushort (*)[4]) calloc (S.raw_height*S.raw_width, sizeof (*newimage));
- merror (newimage, "add_masked_borders_to_bitmap()");
-
- int r,c;
- // top rows
- for (r=0; r<S.top_margin;r++)
- for(c=0;c<S.raw_width;c++)
- {
- ushort *p = get_masked_pointer(r,c);
- if(p)
- newimage[r*S.raw_width+c][FC(r,c)] = *p;
- }
- // middle rows
- for (r=S.top_margin; r<S.top_margin+S.height;r++)
- {
- int row = r-S.top_margin;
- for(c=0;c<S.left_margin;c++)
- {
- ushort *p = get_masked_pointer(r,c);
- if(p)
- newimage[r*S.raw_width+c][FC(r,c)] = *p;
- }
- for(c=S.left_margin; c<S.left_margin+S.iwidth;c++)
- {
- int col = c - S.left_margin;
- newimage[r*S.raw_width+c][FC(r,c)] = imgdata.image[row*S.iwidth+col][FC(row,col)];
- }
- for(c=S.left_margin+S.iwidth;c<S.raw_width;c++)
- {
- ushort *p = get_masked_pointer(r,c);
- if(p)
- newimage[r*S.raw_width+c][FC(r,c)] = *p;
- }
- }
- // bottom rows
- for (r=S.top_margin+S.height; r<S.raw_height;r++)
- for(c=0;c<S.raw_width;c++)
- {
- ushort *p = get_masked_pointer(r,c);
- if(p)
- newimage[r*S.raw_width+c][FC(r,c)] = *p;
- }
- free(imgdata.image);
- imgdata.image=newimage;
- S.iwidth = S.width = S.raw_width;
- S.iheight = S.height = S.raw_height;
- return LIBRAW_SUCCESS;
-}
-
-int LibRaw::open_file(const char *fname)
-{
- // this stream will close on recycle()
- LibRaw_file_datastream *stream = new LibRaw_file_datastream(fname);
- if(!stream->valid())
- {
- delete stream;
- return LIBRAW_IO_ERROR;
- }
- ID.input_internal = 0; // preserve from deletion on error
- int ret = open_datastream(stream);
- if (ret == LIBRAW_SUCCESS)
- {
- ID.input_internal =1 ; // flag to delete datastream on recycle
- }
- else
- {
- delete stream;
- ID.input_internal = 0;
- }
- return ret;
-}
-
-int LibRaw::open_buffer(void *buffer, size_t size)
-{
- // this stream will close on recycle()
- if(!buffer || buffer==(void*)-1)
- return LIBRAW_IO_ERROR;
-
- LibRaw_buffer_datastream *stream = new LibRaw_buffer_datastream(buffer,size);
- if(!stream->valid())
- {
- delete stream;
- return LIBRAW_IO_ERROR;
- }
- ID.input_internal = 0; // preserve from deletion on error
- int ret = open_datastream(stream);
- if (ret == LIBRAW_SUCCESS)
- {
- ID.input_internal =1 ; // flag to delete datastream on recycle
- }
- else
- {
- delete stream;
- ID.input_internal = 0;
- }
- return ret;
-}
-
-
-int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
-{
-
- if(!stream)
- return ENOENT;
- if(!stream->valid())
- return LIBRAW_IO_ERROR;
- recycle();
-
- try {
- ID.input = stream;
- SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);
-
- if (O.use_camera_matrix < 0)
- O.use_camera_matrix = O.use_camera_wb;
-
- identify();
-
- if(IO.fuji_width)
- {
- IO.fwidth = S.width;
- IO.fheight = S.height;
- S.iwidth = S.width = IO.fuji_width << !libraw_internal_data.unpacker_data.fuji_layout;
- S.iheight = S.height = S.raw_height;
- S.raw_height += 2*S.top_margin;
- }
-
- int saved_raw_width = S.raw_width;
- int saved_width = S.width;
- // from packed_12_load_raw
- if ((load_raw == &LibRaw:: packed_12_load_raw) && (S.raw_width * 2 >= S.width * 3))
- {
- // raw_width is in bytes!
- S.raw_width = S.raw_width * 2 / 3;
- }
- else if (S.pixel_aspect < 0.95 || S.pixel_aspect > 1.05)
- {
- S.width*=S.pixel_aspect;
- }
-
- if(S.raw_width>S.width + S.left_margin)
- S.right_margin = S.raw_width - S.width - S.left_margin;
-
- if(S.raw_height > S.height + S.top_margin)
- S.bottom_margin = S.raw_height - S.height - S.top_margin;
-
- S.raw_width = saved_raw_width;
- S.width = saved_width;
-
- if(C.profile_length)
- {
- if(C.profile) free(C.profile);
- C.profile = malloc(C.profile_length);
- merror(C.profile,"LibRaw::open_file()");
- ID.input->seek(ID.profile_offset,SEEK_SET);
- ID.input->read(C.profile,C.profile_length,1);
- }
-
- SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
- }
- catch ( LibRaw_exceptions err) {
- EXCEPTION_HANDLER(err);
- }
-
- if(P1.raw_count < 1)
- return LIBRAW_FILE_UNSUPPORTED;
-
- 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;
- }
-
- write_fun = &LibRaw::write_ppm_tiff;
-
- if (load_raw == &LibRaw::kodak_ycbcr_load_raw)
- {
- S.height += S.height & 1;
- S.width += S.width & 1;
- }
-
- 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;
-
- SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST);
-
-
- return LIBRAW_SUCCESS;
-}
-
-int LibRaw::unpack(void)
-{
- CHECK_ORDER_HIGH(LIBRAW_PROGRESS_LOAD_RAW);
- CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
- try {
-
- RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW,0,2);
- if (O.shot_select >= P1.raw_count)
- return LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE;
-
- if(!load_raw)
- return LIBRAW_UNSPECIFIED_ERROR;
-
- if (O.use_camera_matrix && C.cmatrix[0][0] > 0.25)
- {
- memcpy (C.rgb_cam, C.cmatrix, sizeof (C.cmatrix));
- IO.raw_color = 0;
- }
- // already allocated ?
- if(imgdata.image) free(imgdata.image);
-
- imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image));
- merror (imgdata.image, "unpack()");
-
-
- if(S.top_margin || S.left_margin || S.right_margin || S.bottom_margin)
- {
- unsigned sz = S.raw_height*(S.left_margin+S.right_margin)
- + S.width*(S.top_margin+S.bottom_margin);
- imgdata.masked_pixels.buffer = (ushort*) calloc(sz, sizeof(ushort));
- merror (imgdata.masked_pixels.buffer, "unpack()");
- init_masked_ptrs();
- }
- if (libraw_internal_data.unpacker_data.meta_length)
- {
- libraw_internal_data.internal_data.meta_data =
- (char *) malloc (libraw_internal_data.unpacker_data.meta_length);
- merror (libraw_internal_data.internal_data.meta_data, "LibRaw::unpack()");
- }
- ID.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
- // foveon_load_raw produces different data for document_mode, we'll
- // deal with it in dcraw_document_mode_processing
- int save_document_mode = O.document_mode;
- O.document_mode = 0;
-
- if(!own_filtering_supported() && (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT))
- O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC_BIT; // turn on black and zeroes filtering
-
- (this->*load_raw)();
-
- O.document_mode = save_document_mode;
-
- if (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT)
- O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC; // restore automated mode
-
- SET_PROC_FLAG(LIBRAW_PROGRESS_LOAD_RAW);
- RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW,1,2);
-
- return 0;
- }
- catch ( LibRaw_exceptions err) {
- EXCEPTION_HANDLER(err);
- }
-}
-
-int LibRaw::dcraw_document_mode_processing(void)
-{
- CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
- CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
-
- try {
-
- if(IO.fwidth)
- rotate_fuji_raw();
-
- if(!own_filtering_supported() && (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT))
- O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC_BIT; // turn on black and zeroes filtering
-
- O.document_mode = 2;
- if(P1.is_foveon)
- {
- // filter image data for foveon document mode
- short *iptr = (short *)imgdata.image;
- for (int i=0; i < S.height*S.width*4; i++)
- {
- if ((short) iptr[i] < 0)
- iptr[i] = 0;
- }
- SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE);
- }
-
- O.use_fuji_rotate = 0;
- if (!(O.filtering_mode & LIBRAW_FILTERING_NOZEROES) && IO.zero_is_bad)
- {
- remove_zeroes();
- SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
- }
- if(O.bad_pixels)
- {
- bad_pixels(O.bad_pixels);
- SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
- }
- if (O.dark_frame)
- {
- subtract (O.dark_frame);
- SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
- }
- if(O.filtering_mode & LIBRAW_FILTERING_NOBLACKS)
- C.black=0;
-
- if (O.user_black >= 0)
- C.black = O.user_black;
-
- if (O.user_sat > 0)
- C.maximum = O.user_sat;
-
- pre_interpolate();
- SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
-
- if (libraw_internal_data.internal_output_params.mix_green)
- {
- int i;
- for (P1.colors=3, i=0; i < S.height*S.width; i++)
- imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
- }
- SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
-
- if (!P1.is_foveon && P1.colors == 3)
- median_filter();
- SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
-
- if (!P1.is_foveon && O.highlight == 2)
- blend_highlights();
-
- if (!P1.is_foveon && O.highlight > 2)
- recover_highlights();
- SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
-
- if (O.use_fuji_rotate)
- fuji_rotate();
- SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
-#ifndef NO_LCMS
- if(O.camera_profile)
- {
- apply_profile(O.camera_profile,O.output_profile);
- SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
- }
-#endif
- if(!libraw_internal_data.output_data.histogram)
- {
- libraw_internal_data.output_data.histogram = (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
- merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_document_mode_processing()");
- }
- convert_to_rgb();
- SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
-
- if (O.use_fuji_rotate)
- stretch();
- SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
-
- if (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT)
- O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC; // restore automated mode
-
- return 0;
- }
- catch ( LibRaw_exceptions err) {
- EXCEPTION_HANDLER(err);
- }
-
-}
-
-#if 1
-#define FORC(cnt) for (c=0; c < cnt; c++)
-#define FORCC FORC(ret->colors)
-#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
-
-libraw_processed_image_t * LibRaw::dcraw_make_mem_thumb(int *errcode)
-{
- if(!T.thumb)
- {
- if ( !ID.toffset)
- {
- if(errcode) *errcode= LIBRAW_NO_THUMBNAIL;
- }
- else
- {
- if(errcode) *errcode= LIBRAW_OUT_OF_ORDER_CALL;
- }
- return NULL;
- }
-
- if (T.tformat == LIBRAW_THUMBNAIL_BITMAP)
- {
- libraw_processed_image_t * ret =
- (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t)+T.tlength);
+ * This file is provided for compatibility w/ old build scripts/tools:
+ * It includes multiple separate files that should be built separately
+ * if new build tools are used
- if(!ret)
- {
- if(errcode) *errcode= ENOMEM;
- return NULL;
- }
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of two licenses as you choose:
- bzero(ret,sizeof(libraw_processed_image_t));
- ret->type = LIBRAW_IMAGE_BITMAP;
- ret->height = T.theight;
- ret->width = T.twidth;
- ret->colors = 3;
- ret->bits = 8;
- ret->gamma_corrected = 1;
- ret->data_size = T.tlength;
- memmove(ret->data,T.thumb,T.tlength);
- if(errcode) *errcode= 0;
- return ret;
- }
- else if (T.tformat == LIBRAW_THUMBNAIL_JPEG)
- {
- ushort exif[5];
- int mk_exif = 0;
- if(strcmp(T.thumb+6,"Exif")) mk_exif = 1;
-
- int dsize = T.tlength + mk_exif * (sizeof(exif)+sizeof(tiff_hdr));
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+ (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
- libraw_processed_image_t * ret =
- (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t)+dsize);
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
- if(!ret)
- {
- if(errcode) *errcode= ENOMEM;
- return NULL;
- }
-
- bzero(ret,sizeof(libraw_processed_image_t));
-
- ret->type = LIBRAW_IMAGE_JPEG;
- ret->data_size = dsize;
-
- ret->data[0] = 0xff;
- ret->data[1] = 0xd8;
- if(mk_exif)
- {
- struct tiff_hdr th;
- memcpy (exif, "\xff\xe1 Exif\0\0", 10);
- exif[1] = htons (8 + sizeof th);
- memmove(ret->data+2,exif,sizeof(exif));
- tiff_head (&th, 0);
- memmove(ret->data+(2+sizeof(exif)),&th,sizeof(th));
- memmove(ret->data+(2+sizeof(exif)+sizeof(th)),T.thumb+2,T.tlength-2);
- }
- else
- {
- memmove(ret->data+2,T.thumb+2,T.tlength-2);
- }
- if(errcode) *errcode= 0;
- return ret;
-
- }
- else
- {
- if(errcode) *errcode= LIBRAW_UNSUPPORTED_THUMBNAIL;
- return NULL;
-
- }
-}
-
-
-
-libraw_processed_image_t *LibRaw::dcraw_make_mem_image(int *errcode)
-{
- if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < LIBRAW_PROGRESS_PRE_INTERPOLATE)
- {
- if(errcode) *errcode= LIBRAW_OUT_OF_ORDER_CALL;
- return NULL;
- }
-
- if(!libraw_internal_data.output_data.histogram)
- {
- libraw_internal_data.output_data.histogram =
- (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
- merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_make_mem_image()");
- }
-
- unsigned ds = S.height * S.width * (O.output_bps/8) * P1.colors;
- libraw_processed_image_t *ret = (libraw_processed_image_t*)::malloc(sizeof(libraw_processed_image_t)+ds);
- if(!ret)
- {
- if(errcode) *errcode= ENOMEM;
- return NULL;
- }
- bzero(ret,sizeof(libraw_processed_image_t));
- // metadata init
-
- int s_iheight = S.iheight;
- int s_iwidth = S.iwidth;
- int s_width = S.width;
- int s_hwight = S.height;
-
- S.iheight = S.height;
- S.iwidth = S.width;
-
-
- if (S.flip & 4) SWAP(S.height,S.width);
-
-
- ret->type = LIBRAW_IMAGE_BITMAP;
- ret->height = S.height;
- ret->width = S.width;
- ret->colors = P1.colors;
- ret->bits = O.output_bps;
- ret->gamma_corrected = (O.output_bps == 8)?1:O.gamma_16bit;
-
- ret->data_size = ds;
-
- // Cut'n'paste from write_tiff_ppm, should be generalized later
- uchar *bufp = ret->data;
- uchar *ppm;
- ushort *ppm2,lut16[0x10000];
- int c, row, col, soff, rstep, cstep;
-
-
- if (ret->bits == 8 || ret->gamma_corrected ) gamma_lut (lut16);
- soff = flip_index (0, 0);
- cstep = flip_index (0, 1) - soff;
- rstep = flip_index (1, 0) - flip_index (0, S.width);
-
-
- for (row=0; row < ret->height; row++, soff += rstep)
- {
- ppm2 = (ushort*) (ppm = bufp);
- for (col=0; col < ret->width; col++, soff += cstep)
- if (ret->bits == 8)
- FORCC ppm [col*ret->colors+c] = lut16[imgdata.image[soff][c]]/256;
- else if(ret->gamma_corrected)
- FORCC ppm2[col*ret->colors+c] = lut16[imgdata.image[soff][c]];
- else
- FORCC ppm2[col*ret->colors+c] = imgdata.image[soff][c];
- bufp+=ret->colors*(ret->bits/8)*ret->width;
- }
- if(errcode) *errcode= 0;
-
- S.iheight = s_iheight;
- S.iwidth = s_iwidth;
- S.width = s_width;
- S.height = s_hwight;
-
- return ret;
-}
-
-#undef FORC
-#undef FORCC
-#undef SWAP
-#endif
-
-
-int LibRaw::dcraw_ppm_tiff_writer(const char *filename)
-{
- CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
-
- if(!imgdata.image)
- return LIBRAW_OUT_OF_ORDER_CALL;
-
- if(!filename)
- return ENOENT;
- FILE *f = fopen(filename,"wb");
-
- if(!f)
- return errno;
-
- try {
- if(!libraw_internal_data.output_data.histogram)
- {
- libraw_internal_data.output_data.histogram =
- (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
- merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_ppm_tiff_writer()");
- }
- write_ppm_tiff(f);
- SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP);
- fclose(f);
- return 0;
- }
- catch ( LibRaw_exceptions err) {
- fclose(f);
- EXCEPTION_HANDLER(err);
- }
-}
-
-void LibRaw::kodak_thumb_loader()
-{
- // some kodak cameras
- ushort s_height = S.height, s_width = S.width,s_iwidth = S.iwidth,s_iheight=S.iheight;
- int s_colors = P1.colors;
- unsigned s_filters = P1.filters;
- ushort (*s_image)[4] = imgdata.image;
-
-
- S.height = T.theight;
- S.width = T.twidth;
- P1.filters = 0;
-
- if (thumb_load_raw == &CLASS kodak_ycbcr_load_raw)
- {
- S.height += S.height & 1;
- S.width += S.width & 1;
- }
-
- imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image));
- merror (imgdata.image, "LibRaw::kodak_thumb_loader()");
-
- ID.input->seek(ID.toffset, SEEK_SET);
- // read kodak thumbnail into T.image[]
- (this->*thumb_load_raw)();
-
- // copy-n-paste from image pipe
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#define LIM(x,min,max) MAX(min,MIN(x,max))
-#define CLIP(x) LIM(x,0,65535)
-#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
-
- // from scale_colors
- {
- double dmax;
- float scale_mul[4];
- int c,val;
- for (dmax=DBL_MAX, c=0; c < 3; c++)
- if (dmax > C.pre_mul[c])
- dmax = C.pre_mul[c];
-
- for( c=0; c< 3; c++)
- scale_mul[c] = (C.pre_mul[c] / dmax) * 65535.0 / C.maximum;
- scale_mul[3] = scale_mul[1];
-
- size_t size = S.height * S.width;
- for (int i=0; i < size*4 ; i++)
- {
- val = imgdata.image[0][i];
- if(!val) continue;
- val *= scale_mul[i & 3];
- imgdata.image[0][i] = CLIP(val);
- }
- }
-
- // from convert_to_rgb
- ushort *img;
- int row,col;
-
- int (*t_hist)[LIBRAW_HISTOGRAM_SIZE] = (int (*)[LIBRAW_HISTOGRAM_SIZE]) calloc(sizeof(*t_hist),4);
- merror (t_hist, "LibRaw::kodak_thumb_loader()");
-
- float out[3],
- out_cam[3][4] =
- {
- {2.81761312, -1.98369181, 0.166078627, 0},
- {-0.111855984, 1.73688626, -0.625030339, 0},
- {-0.0379119813, -0.891268849, 1.92918086, 0}
- };
-
- for (img=imgdata.image[0], row=0; row < S.height; row++)
- for (col=0; col < S.width; col++, img+=4)
- {
- out[0] = out[1] = out[2] = 0;
- for(int c=0;c<3;c++)
- {
- out[0] += out_cam[0][c] * img[c];
- out[1] += out_cam[1][c] * img[c];
- out[2] += out_cam[2][c] * img[c];
- }
- for(int c=0; c<3; c++)
- img[c] = CLIP((int) out[c]);
- for(int c=0; c<P1.colors;c++)
- t_hist[c][img[c] >> 3]++;
-
- }
-
- // from gamma_lut
- int (*save_hist)[LIBRAW_HISTOGRAM_SIZE] = libraw_internal_data.output_data.histogram;
- libraw_internal_data.output_data.histogram = t_hist;
-
- ushort *lut16 = (ushort*)calloc(0x10000,sizeof(ushort));
- merror(lut16,"LibRaw::kodak_thumb_loader()");
- gamma_lut(lut16);
-
- libraw_internal_data.output_data.histogram = save_hist;
-
- free(t_hist);
-
- // from write_ppm_tiff - copy pixels into bitmap
-
- S.iheight = S.height;
- S.iwidth = S.width;
- if (S.flip & 4) SWAP(S.height,S.width);
-
- if(T.thumb) free(T.thumb);
- T.thumb = (char*) calloc (S.width * S.height, P1.colors);
- merror (T.thumb, "LibRaw::kodak_thumb_loader()");
- T.tlength = S.width * S.height * P1.colors;
-
- // from write_tiff_ppm
- {
- int soff = flip_index (0, 0);
- int cstep = flip_index (0, 1) - soff;
- int rstep = flip_index (1, 0) - flip_index (0, S.width);
-
- for (int row=0; row < S.height; row++, soff += rstep)
- {
- char *ppm = T.thumb + row*S.width*P1.colors;
- for (int col=0; col < S.width; col++, soff += cstep)
- for(int c = 0; c < P1.colors; c++)
- ppm [col*P1.colors+c] = lut16[imgdata.image[soff][c]]/256;
- }
- }
- free(lut16);
- // restore variables
- free(imgdata.image);
- imgdata.image = s_image;
-
- T.twidth = S.width;
- S.width = s_width;
-
- S.iwidth = s_iwidth;
- S.iheight = s_iheight;
-
- T.theight = S.height;
- S.height = s_height;
-
- T.tcolors = P1.colors;
- P1.colors = s_colors;
-
- P1.filters = s_filters;
-}
-#undef MIN
-#undef MAX
-#undef LIM
-#undef CLIP
-#undef SWAP
-
-
-void LibRaw::foveon_thumb_loader (void)
-{
- unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
- struct decode *dindex;
- short pred[3];
-
- if(T.thumb) free(T.thumb);
- T.thumb = NULL;
-
- bwide = get4();
- if (bwide > 0)
- {
- if (bwide < T.twidth*3) return;
- T.thumb = (char*)malloc(3*T.twidth * T.theight);
- merror (T.thumb, "foveon_thumb()");
- char *buf = (char*)malloc(bwide);
- merror (buf, "foveon_thumb()");
- for (row=0; row < T.theight; row++)
- {
- ID.input->read(buf, 1, bwide);
- memmove(T.thumb+(row*T.twidth*3),buf,T.twidth*3);
- }
- free(buf);
- T.tlength = 3*T.twidth * T.theight;
- T.tformat = LIBRAW_THUMBNAIL_BITMAP;
- return;
- }
- else
- {
- foveon_decoder (256, 0);
- T.thumb = (char*)malloc(3*T.twidth * T.theight);
- char *bufp = T.thumb;
- merror (T.thumb, "foveon_thumb()");
- for (row=0; row < T.theight; row++)
- {
- memset (pred, 0, sizeof pred);
- if (!bit) get4();
- for (bit=col=0; col < T.twidth; col++)
- for(c=0;c<3;c++)
- {
- for (dindex=first_decode; dindex->branch[0]; )
- {
- if ((bit = (bit-1) & 31) == 31)
- for (i=0; i < 4; i++)
- bitbuf = (bitbuf << 8) + ID.input->get_char();
- dindex = dindex->branch[bitbuf >> bit & 1];
- }
- pred[c] += dindex->leaf;
- (*bufp++)=pred[c];
- }
- }
- T.tformat = LIBRAW_THUMBNAIL_BITMAP;
- T.tlength = 3*T.twidth * T.theight;
- }
- return;
-}
-
-
-// ������� thumbnail �� �����, ������ thumb_format � ������������ � ��������
-int LibRaw::unpack_thumb(void)
-{
- CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
- CHECK_ORDER_BIT(LIBRAW_PROGRESS_THUMB_LOAD);
-
- try {
- if ( !ID.toffset)
- {
- return LIBRAW_NO_THUMBNAIL;
- }
- else if (thumb_load_raw)
- {
- kodak_thumb_loader();
- T.tformat = LIBRAW_THUMBNAIL_BITMAP;
- SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
- return 0;
- }
- else
- {
- ID.input->seek(ID.toffset, SEEK_SET);
- if ( write_thumb == &LibRaw::jpeg_thumb)
- {
- if(T.thumb) free(T.thumb);
- T.thumb = (char *) malloc (T.tlength);
- merror (T.thumb, "jpeg_thumb()");
- ID.input->read (T.thumb, 1, T.tlength);
- T.tcolors = 3;
- T.tformat = LIBRAW_THUMBNAIL_JPEG;
- SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
- return 0;
- }
- else if (write_thumb == &LibRaw::ppm_thumb)
- {
- T.tlength = T.twidth * T.theight*3;
- if(T.thumb) free(T.thumb);
-
- T.thumb = (char *) malloc (T.tlength);
- merror (T.thumb, "ppm_thumb()");
-
- ID.input->read(T.thumb, 1, T.tlength);
-
- T.tformat = LIBRAW_THUMBNAIL_BITMAP;
- SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
- return 0;
-
- }
- else if (write_thumb == &LibRaw::foveon_thumb)
- {
- foveon_thumb_loader();
- // may return with error, so format is set in
- // foveon thumb loader itself
- SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
- return 0;
- }
- // else if -- all other write_thumb cases!
- else
- {
- return LIBRAW_UNSUPPORTED_THUMBNAIL;
- }
- }
- // last resort
- return LIBRAW_UNSUPPORTED_THUMBNAIL;
- }
- catch ( LibRaw_exceptions err) {
- EXCEPTION_HANDLER(err);
- }
-
-}
-
-int LibRaw::dcraw_thumb_writer(const char *fname)
-{
-// CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD);
-
- if(!fname)
- return ENOENT;
-
- FILE *tfp = fopen(fname,"wb");
-
- if(!tfp)
- return errno;
-
- if(!T.thumb)
- {
- fclose(tfp);
- return LIBRAW_OUT_OF_ORDER_CALL;
- }
-
- try {
- switch (T.tformat)
- {
- case LIBRAW_THUMBNAIL_JPEG:
- jpeg_thumb_writer (tfp,T.thumb,T.tlength);
- break;
- case LIBRAW_THUMBNAIL_BITMAP:
- fprintf (tfp, "P6\n%d %d\n255\n", T.twidth, T.theight);
- fwrite (T.thumb, 1, T.tlength, tfp);
- break;
- default:
- fclose(tfp);
- return LIBRAW_UNSUPPORTED_THUMBNAIL;
- }
- fclose(tfp);
- return 0;
- }
- catch ( LibRaw_exceptions err) {
- fclose(tfp);
- EXCEPTION_HANDLER(err);
- }
-}
-
-int LibRaw::adjust_sizes_info_only(void)
-{
- CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
- CHECK_ORDER_HIGH(LIBRAW_PROGRESS_FUJI_ROTATE);
- if (O.use_fuji_rotate)
- {
- if (IO.fuji_width)
- {
- // restore saved values
- if(IO.fheight)
- {
- 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;
- IO.fheight = IO.fwidth = 0; // prevent repeated calls
- }
- // dcraw code
- IO.fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink;
- S.iwidth = (ushort)(IO.fuji_width / sqrt(0.5));
- S.iheight = (ushort)( (S.iheight - IO.fuji_width) / sqrt(0.5));
- }
- else
- {
- if (S.pixel_aspect < 1) S.iheight = (ushort)( S.iheight / S.pixel_aspect + 0.5);
- if (S.pixel_aspect > 1) S.iwidth = (ushort) (S.iwidth * S.pixel_aspect + 0.5);
- }
- }
- SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
- if (S.flip & 4)
- {
- unsigned short t = S.iheight;
- S.iheight=S.iwidth;
- S.iwidth = t;
- SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP);
- }
- return 0;
-}
-
-int LibRaw::rotate_fuji_raw(void)
-{
- CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
- CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
-
-
- if(!IO.fwidth) return LIBRAW_SUCCESS;
- int row,col,r,c;
- ushort (*newimage)[4];
- ushort fiwidth,fiheight;
-
- fiheight = (IO.fheight + IO.shrink) >> IO.shrink;
- fiwidth = (IO.fwidth + IO.shrink) >> IO.shrink;
-
- newimage = (ushort (*)[4]) calloc (fiheight*fiwidth, sizeof (*newimage));
- merror(newimage,"rotate_fuji_raw()");
- for(row=0;row<S.height;row++)
- {
- for(col=0;col<S.width;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);
- }
- newimage[((r) >> IO.shrink)*fiwidth + ((c) >> IO.shrink)][FC(r,c)] =
- imgdata.image[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][FC(r,c)];
- }
- }
- // restore fuji sizes!
- 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;
- IO.fheight = IO.fwidth = 0; // prevent repeated calls
-
- free(imgdata.image);
- imgdata.image = newimage;
- return LIBRAW_SUCCESS;
-
-}
-
-
-int LibRaw::dcraw_process(void)
-{
- int quality,i;
-
-
- CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
- CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
-
- try {
-
- if(IO.fwidth)
- rotate_fuji_raw();
-
-
- if(!own_filtering_supported() && (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT))
- O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC_BIT; // turn on black and zeroes filtering
-
- if(O.half_size)
- O.four_color_rgb = 1;
-
- if (!(O.filtering_mode & LIBRAW_FILTERING_NOZEROES) && IO.zero_is_bad)
- {
- remove_zeroes();
- SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
- }
- if(O.bad_pixels)
- {
- bad_pixels(O.bad_pixels);
- SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
- }
- if (O.dark_frame)
- {
- subtract (O.dark_frame);
- SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
- }
-
- quality = 2 + !IO.fuji_width;
-
- if(O.filtering_mode & LIBRAW_FILTERING_NOBLACKS)
- C.black=0;
-
- if (O.user_qual >= 0) quality = O.user_qual;
- if (O.user_black >= 0) C.black = O.user_black;
- if (O.user_sat > 0) C.maximum = O.user_sat;
-
- if (P1.is_foveon && !O.document_mode)
- {
- foveon_interpolate();
- SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE);
- }
-
- if (!P1.is_foveon && O.document_mode < 2)
- {
- scale_colors();
- SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS);
- }
-
- pre_interpolate();
- SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
-
- if (P1.filters && !O.document_mode)
- {
- if (quality == 0)
- lin_interpolate();
- else if (quality == 1 || P1.colors > 3)
- vng_interpolate();
- else if (quality == 2)
- ppg_interpolate();
- else
- ahd_interpolate();
- SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE);
- }
- if (IO.mix_green)
- {
- for (P1.colors=3, i=0; i < S.height * S.width; i++)
- imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
- SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
- }
+ */
- if(!P1.is_foveon)
- {
- if (P1.colors == 3)
- {
- median_filter();
- SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
- }
-
- if (O.highlight == 2)
- {
- blend_highlights();
- SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
- }
-
- if (O.highlight > 2)
- {
- recover_highlights();
- SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
- }
- }
- if (O.use_fuji_rotate)
- {
- fuji_rotate();
- SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
- }
-
- if(!libraw_internal_data.output_data.histogram)
- {
- libraw_internal_data.output_data.histogram = (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
- merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_process()");
- }
-#ifndef NO_LCMS
- if(O.camera_profile)
- {
- apply_profile(O.camera_profile,O.output_profile);
- SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
- }
+#include "../internal/libraw_cxx_defs.h"
+
+#include "tables/cameralist.cpp"
+#include "decoders/fuji_compressed.cpp"
+#include "decoders/crx.cpp"
+#include "decoders/fp_dng.cpp"
+#include "decoders/decoders_libraw.cpp"
+#include "decoders/unpack.cpp"
+#include "decoders/unpack_thumb.cpp"
+
+#include "integration/dngsdk_glue.cpp"
+#include "integration/rawspeed_glue.cpp"
+
+#include "tables/colorconst.cpp"
+#include "utils/utils_libraw.cpp"
+#include "utils/init_close_utils.cpp"
+#include "utils/decoder_info.cpp"
+#include "utils/open.cpp"
+#include "utils/phaseone_processing.cpp"
+#include "utils/thumb_utils.cpp"
+
+#include "write/tiff_writer.cpp"
+#include "preprocessing/subtract_black.cpp"
+#include "preprocessing/raw2image.cpp"
+#include "postprocessing/postprocessing_utils.cpp"
+#include "postprocessing/dcraw_process.cpp"
+#include "postprocessing/mem_image.cpp"
+
+/* DS conflicts with a define in /usr/include/sys/regset.h on Solaris */
+#if defined __sun && defined DS
+#undef DS
#endif
-
- convert_to_rgb();
- SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
-
- if (O.use_fuji_rotate)
- {
- stretch();
- SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
- }
- if (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT)
- O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC; // restore automated mode
- return 0;
- }
- catch ( LibRaw_exceptions err) {
- EXCEPTION_HANDLER(err);
- }
-}
-
-// Supported cameras:
-static const char *static_camera_list[] =
-{
-"Adobe Digital Negative (DNG)",
-"Apple QuickTake 100",
-"Apple QuickTake 150",
-"Apple QuickTake 200",
-"AVT F-080C",
-"AVT F-145C",
-"AVT F-201C",
-"AVT F-510C",
-"AVT F-810C",
-"Canon PowerShot 600",
-"Canon PowerShot A5",
-"Canon PowerShot A5 Zoom",
-"Canon PowerShot A50",
-"Canon PowerShot A460 (CHDK hack)",
-"Canon PowerShot A530 (CHDK hack)",
-"Canon PowerShot A610 (CHDK hack)",
-"Canon PowerShot A620 (CHDK hack)",
-"Canon PowerShot A630 (CHDK hack)",
-"Canon PowerShot A640 (CHDK hack)",
-"Canon PowerShot A650 (CHDK hack)",
-"Canon PowerShot A710 IS (CHDK hack)",
-"Canon PowerShot A720 IS (CHDK hack)",
-"Canon PowerShot Pro70",
-"Canon PowerShot Pro90 IS",
-"Canon PowerShot G1",
-"Canon PowerShot G2",
-"Canon PowerShot G3",
-"Canon PowerShot G5",
-"Canon PowerShot G6",
-"Canon PowerShot G7 (CHDK hack)",
-"Canon PowerShot G9",
-"Canon PowerShot G10",
-"Canon PowerShot S2 IS (CHDK hack)",
-"Canon PowerShot S3 IS (CHDK hack)",
-"Canon PowerShot S5 IS (CHDK hack)",
-"Canon PowerShot SD300 (CHDK hack)",
-"Canon PowerShot S30",
-"Canon PowerShot S40",
-"Canon PowerShot S45",
-"Canon PowerShot S50",
-"Canon PowerShot S60",
-"Canon PowerShot S70",
-"Canon PowerShot Pro1",
-"Canon EOS D30",
-"Canon EOS D60",
-"Canon EOS 5D",
-"Canon EOS 5D Mark II",
-"Canon EOS 10D",
-"Canon EOS 20D",
-"Canon EOS 30D",
-"Canon EOS 40D",
-"Canon EOS 50D",
-"Canon EOS 300D / Digital Rebel / Kiss Digital",
-"Canon EOS 350D / Digital Rebel XT / Kiss Digital N",
-"Canon EOS 400D / Digital Rebel XTi / Kiss Digital X",
-"Canon EOS 450D / Digital Rebel XSi / Kiss Digital X2",
-"Canon EOS 1000D / Digital Rebel XS / Kiss Digital F",
-"Canon EOS D2000C",
-"Canon EOS-1D",
-"Canon EOS-1DS",
-"Canon EOS-1D Mark II",
-"Canon EOS-1D Mark III",
-"Canon EOS-1D Mark II N",
-"Canon EOS-1Ds Mark II",
-"Canon EOS-1Ds Mark III",
-"Casio QV-2000UX",
-"Casio QV-3000EX",
-"Casio QV-3500EX",
-"Casio QV-4000",
-"Casio QV-5700",
-"Casio QV-R41",
-"Casio QV-R51",
-"Casio QV-R61",
-"Casio EX-S100",
-"Casio EX-Z4",
-"Casio EX-Z50",
-"Casio EX-Z55",
-"Casio Exlim Pro 505",
-"Casio Exlim Pro 600",
-"Casio Exlim Pro 700",
-"Contax N Digital",
-"Creative PC-CAM 600",
-"Epson R-D1",
-"Foculus 531C",
-"Fuji FinePix E550",
-"Fuji FinePix E900",
-"Fuji FinePix F700",
-"Fuji FinePix F710",
-"Fuji FinePix F800",
-"Fuji FinePix F810",
-"Fuji FinePix S2Pro",
-"Fuji FinePix S3Pro",
-"Fuji FinePix S5Pro",
-"Fuji FinePix S20Pro",
-"Fuji FinePix S100FS",
-"Fuji FinePix S5000",
-"Fuji FinePix S5100/S5500",
-"Fuji FinePix S5200/S5600",
-"Fuji FinePix S6000fd",
-"Fuji FinePix S7000",
-"Fuji FinePix S9000/S9500",
-"Fuji FinePix S9100/S9600",
-"Fuji IS-1",
-"Hasselblad CFV",
-"Hasselblad H3D",
-"Hasselblad V96C",
-"Imacon Ixpress 16-megapixel",
-"Imacon Ixpress 22-megapixel",
-"Imacon Ixpress 39-megapixel",
-"ISG 2020x1520",
-"Kodak DC20 (see Oliver Hartman's page)",
-"Kodak DC25 (see Jun-ichiro Itoh's page)",
-"Kodak DC40",
-"Kodak DC50",
-"Kodak DC120 (also try kdc2tiff)",
-"Kodak DCS200",
-"Kodak DCS315C",
-"Kodak DCS330C",
-"Kodak DCS420",
-"Kodak DCS460",
-"Kodak DCS460A",
-"Kodak DCS520C",
-"Kodak DCS560C",
-"Kodak DCS620C",
-"Kodak DCS620X",
-"Kodak DCS660C",
-"Kodak DCS660M",
-"Kodak DCS720X",
-"Kodak DCS760C",
-"Kodak DCS760M",
-"Kodak EOSDCS1",
-"Kodak EOSDCS3B",
-"Kodak NC2000F",
-"Kodak ProBack",
-"Kodak PB645C",
-"Kodak PB645H",
-"Kodak PB645M",
-"Kodak DCS Pro 14n",
-"Kodak DCS Pro 14nx",
-"Kodak DCS Pro SLR/c",
-"Kodak DCS Pro SLR/n",
-"Kodak C330",
-"Kodak C603",
-"Kodak P850",
-"Kodak P880",
-"Kodak KAI-0340",
-"Konica KD-400Z",
-"Konica KD-510Z",
-"Leaf AFi 7",
-"Leaf Aptus 17",
-"Leaf Aptus 22",
-"Leaf Aptus 54S",
-"Leaf Aptus 65",
-"Leaf Aptus 75",
-"Leaf Aptus 75S",
-"Leaf Cantare",
-"Leaf CatchLight",
-"Leaf CMost",
-"Leaf DCB2",
-"Leaf Valeo 6",
-"Leaf Valeo 11",
-"Leaf Valeo 17",
-"Leaf Valeo 22",
-"Leaf Volare",
-"Leica Digilux 2",
-"Leica Digilux 3",
-"Leica D-LUX2",
-"Leica D-LUX3",
-"Leica D-LUX4",
-"Leica V-LUX1",
-"Logitech Fotoman Pixtura",
-"Mamiya ZD",
-"Micron 2010",
-"Minolta RD175",
-"Minolta DiMAGE 5",
-"Minolta DiMAGE 7",
-"Minolta DiMAGE 7i",
-"Minolta DiMAGE 7Hi",
-"Minolta DiMAGE A1",
-"Minolta DiMAGE A2",
-"Minolta DiMAGE A200",
-"Minolta DiMAGE G400",
-"Minolta DiMAGE G500",
-"Minolta DiMAGE G530",
-"Minolta DiMAGE G600",
-"Minolta DiMAGE Z2",
-"Minolta Alpha/Dynax/Maxxum 5D",
-"Minolta Alpha/Dynax/Maxxum 7D",
-"Nikon D1",
-"Nikon D1H",
-"Nikon D1X",
-"Nikon D2H",
-"Nikon D2Hs",
-"Nikon D2X",
-"Nikon D2Xs",
-"Nikon D3",
-"Nikon D3X",
-"Nikon D40",
-"Nikon D40X",
-"Nikon D50",
-"Nikon D60",
-"Nikon D70",
-"Nikon D70s",
-"Nikon D80",
-"Nikon D90",
-"Nikon D100",
-"Nikon D200",
-"Nikon D300",
-"Nikon D700",
-"Nikon E700 (\"DIAG RAW\" hack)",
-"Nikon E800 (\"DIAG RAW\" hack)",
-"Nikon E880 (\"DIAG RAW\" hack)",
-"Nikon E900 (\"DIAG RAW\" hack)",
-"Nikon E950 (\"DIAG RAW\" hack)",
-"Nikon E990 (\"DIAG RAW\" hack)",
-"Nikon E995 (\"DIAG RAW\" hack)",
-"Nikon E2100 (\"DIAG RAW\" hack)",
-"Nikon E2500 (\"DIAG RAW\" hack)",
-"Nikon E3200 (\"DIAG RAW\" hack)",
-"Nikon E3700 (\"DIAG RAW\" hack)",
-"Nikon E4300 (\"DIAG RAW\" hack)",
-"Nikon E4500 (\"DIAG RAW\" hack)",
-"Nikon E5000",
-"Nikon E5400",
-"Nikon E5700",
-"Nikon E8400",
-"Nikon E8700",
-"Nikon E8800",
-"Nikon Coolpix P6000",
-"Nikon Coolpix S6 (\"DIAG RAW\" hack)",
-"Nokia N95",
-"Olympus C3030Z",
-"Olympus C5050Z",
-"Olympus C5060WZ",
-"Olympus C7070WZ",
-"Olympus C70Z,C7000Z",
-"Olympus C740UZ",
-"Olympus C770UZ",
-"Olympus C8080WZ",
-"Olympus E-1",
-"Olympus E-3",
-"Olympus E-10",
-"Olympus E-20",
-"Olympus E-300",
-"Olympus E-330",
-"Olympus E-400",
-"Olympus E-410",
-"Olympus E-420",
-"Olympus E-500",
-"Olympus E-510",
-"Olympus E-520",
-"Olympus SP310",
-"Olympus SP320",
-"Olympus SP350",
-"Olympus SP500UZ",
-"Olympus SP510UZ",
-"Olympus SP550UZ",
-"Olympus SP560UZ",
-"Olympus SP570UZ",
-"Panasonic DMC-FZ8",
-"Panasonic DMC-FZ18",
-"Panasonic DMC-FZ28",
-"Panasonic DMC-FZ30",
-"Panasonic DMC-FZ50",
-"Panasonic DMC-FX150",
-"Panasonic DMC-G1",
-"Panasonic DMC-L1",
-"Panasonic DMC-L10",
-"Panasonic DMC-LC1",
-"Panasonic DMC-LX1",
-"Panasonic DMC-LX2",
-"Panasonic DMC-LX3",
-"Pentax *ist D",
-"Pentax *ist DL",
-"Pentax *ist DL2",
-"Pentax *ist DS",
-"Pentax *ist DS2",
-"Pentax K10D",
-"Pentax K20D",
-"Pentax K100D",
-"Pentax K100D Super",
-"Pentax K200D",
-"Pentax K2000/K-m",
-"Pentax Optio S",
-"Pentax Optio S4",
-"Pentax Optio 33WR",
-"Pentax Optio 750Z",
-"Phase One LightPhase",
-"Phase One H 10",
-"Phase One H 20",
-"Phase One H 25",
-"Phase One P 20",
-"Phase One P 25",
-"Phase One P 30",
-"Phase One P 45",
-"Pixelink A782",
-"Polaroid x530",
-"Rollei d530flex",
-"RoverShot 3320af",
-"Samsung GX-1S",
-"Samsung GX-10",
-"Samsung S85 (hacked)",
-"Sarnoff 4096x5440",
-"Sigma SD9",
-"Sigma SD10",
-"Sigma SD14",
-"Sinar 3072x2048",
-"Sinar 4080x4080",
-"Sinar 4080x5440",
-"Sinar STI format",
-"SMaL Ultra-Pocket 3",
-"SMaL Ultra-Pocket 4",
-"SMaL Ultra-Pocket 5",
-"Sony DSC-F828",
-"Sony DSC-R1",
-"Sony DSC-V3",
-"Sony DSLR-A100",
-"Sony DSLR-A200",
-"Sony DSLR-A300",
-"Sony DSLR-A350",
-"Sony DSLR-A700",
-"Sony DSLR-A900",
-"Sony XCD-SX910CR",
-"STV680 VGA",
- NULL
-};
-
-const char** LibRaw::cameraList() { return static_camera_list;}
-int LibRaw::cameraCount() { return (sizeof(static_camera_list)/sizeof(static_camera_list[0]))-1; }
-
-
-const char * LibRaw::strprogress(enum LibRaw_progress p)
-{
- switch(p)
- {
- case LIBRAW_PROGRESS_START:
- return "Starting";
- case LIBRAW_PROGRESS_OPEN :
- return "Opening file";
- case LIBRAW_PROGRESS_IDENTIFY :
- return "Reading metadata";
- case LIBRAW_PROGRESS_SIZE_ADJUST:
- return "Adjusting size";
- case LIBRAW_PROGRESS_LOAD_RAW:
- return "Reading RAW data";
- case LIBRAW_PROGRESS_REMOVE_ZEROES:
- return "Clearing zero values";
- case LIBRAW_PROGRESS_BAD_PIXELS :
- return "Removing dead pixels";
- case LIBRAW_PROGRESS_DARK_FRAME:
- return "Subtracting dark frame data";
- case LIBRAW_PROGRESS_FOVEON_INTERPOLATE:
- return "Interpolating Foveon sensor data";
- case LIBRAW_PROGRESS_SCALE_COLORS:
- return "Scaling colors";
- case LIBRAW_PROGRESS_PRE_INTERPOLATE:
- return "Pre-interpolating";
- case LIBRAW_PROGRESS_INTERPOLATE:
- return "Interpolating";
- case LIBRAW_PROGRESS_MIX_GREEN :
- return "Mixing green channels";
- case LIBRAW_PROGRESS_MEDIAN_FILTER :
- return "Median filter";
- case LIBRAW_PROGRESS_HIGHLIGHTS:
- return "Highlight recovery";
- case LIBRAW_PROGRESS_FUJI_ROTATE :
- return "Rotating Fuji diagonal data";
- case LIBRAW_PROGRESS_FLIP :
- return "Flipping image";
- case LIBRAW_PROGRESS_APPLY_PROFILE:
- return "ICC conversion";
- case LIBRAW_PROGRESS_CONVERT_RGB:
- return "Converting to RGB";
- case LIBRAW_PROGRESS_STRETCH:
- return "Stretching image";
- case LIBRAW_PROGRESS_THUMB_LOAD:
- return "Loading thumbnail";
- default:
- return "Some strange things";
- }
-}
+#undef ID /* used in x3f utils */
+#include "x3f/x3f_utils_patched.cpp"
+#include "x3f/x3f_parse_process.cpp"
diff --git a/libkdcraw/libraw/src/libraw_datastream.cpp b/libkdcraw/libraw/src/libraw_datastream.cpp
new file mode 100644
index 0000000..898761d
--- /dev/null
+++ b/libkdcraw/libraw/src/libraw_datastream.cpp
@@ -0,0 +1,1046 @@
+/* -*- C++ -*-
+ * File: libraw_datastream.cpp
+ * Copyright 2008-2021 LibRaw LLC ([email protected])
+ *
+ * LibRaw C++ interface (implementation)
+
+ 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).
+
+*/
+
+#ifdef _WIN32
+#ifdef __MINGW32__
+#define _WIN32_WINNT 0x0500
+#include <stdexcept>
+#endif
+#endif
+
+#define LIBRAW_LIBRARY_BUILD
+#include "libraw/libraw.h"
+#include "libraw/libraw_types.h"
+#include "libraw/libraw_datastream.h"
+#include <sys/stat.h>
+#ifdef USE_JASPER
+#include <jasper/jasper.h> /* Decode RED camera movies */
+#else
+#define NO_JASPER
+#endif
+#ifdef USE_JPEG
+#include <jpeglib.h>
+#include <jerror.h>
+#else
+#define NO_JPEG
+#endif
+
+#ifdef USE_JPEG
+
+typedef struct
+{
+ struct jpeg_source_mgr pub; /* public fields */
+ LibRaw_abstract_datastream *instream; /* source stream */
+ JOCTET *buffer; /* start of buffer */
+ boolean start_of_file; /* have we gotten any data yet? */
+} lr_jpg_source_mgr;
+
+typedef lr_jpg_source_mgr *lr_jpg_src_ptr;
+
+#define LR_JPEG_INPUT_BUF_SIZE 16384
+
+static void f_init_source(j_decompress_ptr cinfo)
+{
+ lr_jpg_src_ptr src = (lr_jpg_src_ptr)cinfo->src;
+ src->start_of_file = TRUE;
+}
+
+#ifdef ERREXIT
+#undef ERREXIT
+#endif
+
+#define ERREXIT(cinfo, code) \
+ ((cinfo)->err->msg_code = (code), \
+ (*(cinfo)->err->error_exit)((j_common_ptr)(cinfo)))
+
+static boolean lr_fill_input_buffer(j_decompress_ptr cinfo)
+{
+ lr_jpg_src_ptr src = (lr_jpg_src_ptr)cinfo->src;
+ size_t nbytes;
+
+ nbytes = src->instream->read((void*)src->buffer, 1, LR_JPEG_INPUT_BUF_SIZE);
+
+ if (nbytes <= 0)
+ {
+ if (src->start_of_file) /* Treat empty input file as fatal error */
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ /* Insert a fake EOI marker */
+ src->buffer[0] = (JOCTET)0xFF;
+ src->buffer[1] = (JOCTET)JPEG_EOI;
+ nbytes = 2;
+ }
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
+ src->start_of_file = FALSE;
+ return TRUE;
+}
+
+static void lr_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+{
+ struct jpeg_source_mgr *src = cinfo->src;
+ if (num_bytes > 0)
+ {
+ while (num_bytes > (long)src->bytes_in_buffer)
+ {
+ num_bytes -= (long)src->bytes_in_buffer;
+ (void)(*src->fill_input_buffer)(cinfo);
+ /* note we assume that fill_input_buffer will never return FALSE,
+ * so suspension need not be handled.
+ */
+ }
+ src->next_input_byte += (size_t)num_bytes;
+ src->bytes_in_buffer -= (size_t)num_bytes;
+ }
+}
+
+static void lr_term_source(j_decompress_ptr /*cinfo*/) {}
+
+static void lr_jpeg_src(j_decompress_ptr cinfo, LibRaw_abstract_datastream *inf)
+{
+ lr_jpg_src_ptr src;
+ if (cinfo->src == NULL)
+ { /* first time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)(
+ (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(lr_jpg_source_mgr));
+ src = (lr_jpg_src_ptr)cinfo->src;
+ src->buffer = (JOCTET *)(*cinfo->mem->alloc_small)(
+ (j_common_ptr)cinfo, JPOOL_PERMANENT,
+ LR_JPEG_INPUT_BUF_SIZE * sizeof(JOCTET));
+ }
+ else if (cinfo->src->init_source != f_init_source)
+ {
+ ERREXIT(cinfo, JERR_BUFFER_SIZE);
+ }
+
+ src = (lr_jpg_src_ptr)cinfo->src;
+ src->pub.init_source = f_init_source;
+ src->pub.fill_input_buffer = lr_fill_input_buffer;
+ src->pub.skip_input_data = lr_skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+ src->pub.term_source = lr_term_source;
+ src->instream = inf;
+ src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+ src->pub.next_input_byte = NULL; /* until buffer loaded */
+}
+#endif
+
+int LibRaw_abstract_datastream::jpeg_src(void *jpegdata)
+{
+#ifdef NO_JPEG
+ return -1;
+#else
+ j_decompress_ptr cinfo = (j_decompress_ptr)jpegdata;
+ buffering_off();
+ lr_jpeg_src(cinfo, this);
+ return 0; // OK
+#endif
+}
+
+
+#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
+// == LibRaw_file_datastream ==
+
+LibRaw_file_datastream::~LibRaw_file_datastream()
+{
+ if (jas_file)
+ fclose(jas_file);
+}
+
+LibRaw_file_datastream::LibRaw_file_datastream(const char *fname)
+ : filename(fname), _fsize(0)
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ ,
+ wfilename()
+#endif
+ ,
+ jas_file(NULL)
+{
+ if (filename.size() > 0)
+ {
+#ifndef LIBRAW_WIN32_CALLS
+ struct stat st;
+ if (!stat(filename.c_str(), &st))
+ _fsize = st.st_size;
+#else
+ struct _stati64 st;
+ if (!_stati64(filename.c_str(), &st))
+ _fsize = st.st_size;
+#endif
+#ifdef LIBRAW_USE_AUTOPTR
+ std::auto_ptr<std::filebuf> buf(new std::filebuf());
+#else
+ std::unique_ptr<std::filebuf> buf(new std::filebuf());
+#endif
+ buf->open(filename.c_str(), std::ios_base::in | std::ios_base::binary);
+ if (buf->is_open())
+ {
+#ifdef LIBRAW_USE_AUTOPTR
+ f = buf;
+#else
+ f = std::move(buf);
+#endif
+ }
+ }
+}
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+LibRaw_file_datastream::LibRaw_file_datastream(const wchar_t *fname)
+ : filename(), wfilename(fname), jas_file(NULL), _fsize(0)
+{
+ if (wfilename.size() > 0)
+ {
+ struct _stati64 st;
+ if (!_wstati64(wfilename.c_str(), &st))
+ _fsize = st.st_size;
+#ifdef LIBRAW_USE_AUTOPTR
+ std::auto_ptr<std::filebuf> buf(new std::filebuf());
+#else
+ std::unique_ptr<std::filebuf> buf(new std::filebuf());
+#endif
+ buf->open(wfilename.c_str(), std::ios_base::in | std::ios_base::binary);
+ if (buf->is_open())
+ {
+#ifdef LIBRAW_USE_AUTOPTR
+ f = buf;
+#else
+ f = std::move(buf);
+#endif
+ }
+ }
+}
+const wchar_t *LibRaw_file_datastream::wfname()
+{
+ return wfilename.size() > 0 ? wfilename.c_str() : NULL;
+}
+#endif
+
+int LibRaw_file_datastream::valid() { return f.get() ? 1 : 0; }
+
+#define LR_STREAM_CHK() \
+ do \
+ { \
+ if (!f.get()) \
+ throw LIBRAW_EXCEPTION_IO_EOF; \
+ } while (0)
+
+int LibRaw_file_datastream::read(void *ptr, size_t size, size_t nmemb)
+{
+/* Visual Studio 2008 marks sgetn as insecure, but VS2010 does not. */
+#if defined(WIN32SECURECALLS) && (_MSC_VER < 1600)
+ LR_STREAM_CHK();
+ return int(f->_Sgetn_s(static_cast<char *>(ptr), nmemb * size, nmemb * size) /
+ (size > 0 ? size : 1));
+#else
+ LR_STREAM_CHK();
+ return int(f->sgetn(static_cast<char *>(ptr), std::streamsize(nmemb * size)) /
+ (size > 0 ? size : 1));
+#endif
+}
+
+int LibRaw_file_datastream::eof()
+{
+ LR_STREAM_CHK();
+ return f->sgetc() == EOF;
+}
+
+int LibRaw_file_datastream::seek(INT64 o, int whence)
+{
+ LR_STREAM_CHK();
+ std::ios_base::seekdir dir;
+ switch (whence)
+ {
+ case SEEK_SET:
+ dir = std::ios_base::beg;
+ break;
+ case SEEK_CUR:
+ dir = std::ios_base::cur;
+ break;
+ case SEEK_END:
+ dir = std::ios_base::end;
+ break;
+ default:
+ dir = std::ios_base::beg;
+ }
+ return f->pubseekoff((long)o, dir) < 0;
+}
+
+INT64 LibRaw_file_datastream::tell()
+{
+ LR_STREAM_CHK();
+ return f->pubseekoff(0, std::ios_base::cur);
+}
+
+char *LibRaw_file_datastream::gets(char *str, int sz)
+{
+ if(sz<1) return NULL;
+ LR_STREAM_CHK();
+ std::istream is(f.get());
+ is.getline(str, sz);
+ if (is.fail())
+ return 0;
+ return str;
+}
+
+int LibRaw_file_datastream::scanf_one(const char *fmt, void *val)
+{
+ LR_STREAM_CHK();
+
+ std::istream is(f.get());
+
+ /* HUGE ASSUMPTION: *fmt is either "%d" or "%f" */
+ if (strcmp(fmt, "%d") == 0)
+ {
+ int d;
+ is >> d;
+ if (is.fail())
+ return EOF;
+ *(static_cast<int *>(val)) = d;
+ }
+ else
+ {
+ float f;
+ is >> f;
+ if (is.fail())
+ return EOF;
+ *(static_cast<float *>(val)) = f;
+ }
+
+ return 1;
+}
+
+const char *LibRaw_file_datastream::fname()
+{
+ return filename.size() > 0 ? filename.c_str() : NULL;
+}
+
+#undef LR_STREAM_CHK
+
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+void *LibRaw_file_datastream::make_jas_stream()
+{
+#ifdef NO_JASPER
+ return NULL;
+#else
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ if (wfname())
+ {
+ jas_file = _wfopen(wfname(), L"rb");
+ return jas_stream_fdopen(fileno(jas_file), "rb");
+ }
+ else
+#endif
+ {
+ return jas_stream_fopen(fname(), "rb");
+ }
+#endif
+}
+#endif
+#endif
+
+// == LibRaw_buffer_datastream
+LibRaw_buffer_datastream::LibRaw_buffer_datastream(const void *buffer, size_t bsize)
+{
+ buf = (unsigned char *)buffer;
+ streampos = 0;
+ streamsize = bsize;
+}
+
+LibRaw_buffer_datastream::~LibRaw_buffer_datastream() {}
+
+int LibRaw_buffer_datastream::read(void *ptr, size_t sz, size_t nmemb)
+{
+ size_t to_read = sz * nmemb;
+ if (to_read > streamsize - streampos)
+ to_read = streamsize - streampos;
+ if (to_read < 1)
+ return 0;
+ memmove(ptr, buf + streampos, to_read);
+ streampos += to_read;
+ return int((to_read + sz - 1) / (sz > 0 ? sz : 1));
+}
+
+int LibRaw_buffer_datastream::seek(INT64 o, int whence)
+{
+ switch (whence)
+ {
+ case SEEK_SET:
+ if (o < 0)
+ streampos = 0;
+ else if (size_t(o) > streamsize)
+ streampos = streamsize;
+ else
+ streampos = size_t(o);
+ return 0;
+ case SEEK_CUR:
+ if (o < 0)
+ {
+ if (size_t(-o) >= streampos)
+ streampos = 0;
+ else
+ streampos += (size_t)o;
+ }
+ else if (o > 0)
+ {
+ if (o + streampos > streamsize)
+ streampos = streamsize;
+ else
+ streampos += (size_t)o;
+ }
+ return 0;
+ case SEEK_END:
+ if (o > 0)
+ streampos = streamsize;
+ else if (size_t(-o) > streamsize)
+ streampos = 0;
+ else
+ streampos = streamsize + (size_t)o;
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+INT64 LibRaw_buffer_datastream::tell()
+{
+ return INT64(streampos);
+}
+
+char *LibRaw_buffer_datastream::gets(char *s, int sz)
+{
+ if(sz<1) return NULL;
+ unsigned char *psrc, *pdest, *str;
+ str = (unsigned char *)s;
+ psrc = buf + streampos;
+ pdest = str;
+ if(streampos >= streamsize) return NULL;
+ while ((size_t(psrc - buf) < streamsize) && ((pdest - str) < (sz-1)))
+ {
+ *pdest = *psrc;
+ if (*psrc == '\n')
+ break;
+ psrc++;
+ pdest++;
+ }
+ if (size_t(psrc - buf) < streamsize)
+ psrc++;
+ if ((pdest - str) < sz-1)
+ *(++pdest) = 0;
+ else
+ s[sz - 1] = 0; // ensure trailing zero
+
+ streampos = psrc - buf;
+ return s;
+}
+
+int LibRaw_buffer_datastream::scanf_one(const char *fmt, void *val)
+{
+ int scanf_res;
+ if (streampos > streamsize)
+ return 0;
+#ifndef WIN32SECURECALLS
+ scanf_res = sscanf((char *)(buf + streampos), fmt, val);
+#else
+ scanf_res = sscanf_s((char *)(buf + streampos), fmt, val);
+#endif
+ if (scanf_res > 0)
+ {
+ int xcnt = 0;
+ while (streampos < streamsize)
+ {
+ streampos++;
+ xcnt++;
+ if (buf[streampos] == 0 || buf[streampos] == ' ' ||
+ buf[streampos] == '\t' || buf[streampos] == '\n' || xcnt > 24)
+ break;
+ }
+ }
+ return scanf_res;
+}
+
+int LibRaw_buffer_datastream::eof()
+{
+ return streampos >= streamsize;
+}
+int LibRaw_buffer_datastream::valid() { return buf ? 1 : 0; }
+
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+void *LibRaw_buffer_datastream::make_jas_stream()
+{
+#ifdef NO_JASPER
+ return NULL;
+#else
+ return jas_stream_memopen((char *)buf + streampos, streamsize - streampos);
+#endif
+}
+#endif
+
+int LibRaw_buffer_datastream::jpeg_src(void *jpegdata)
+{
+#if defined(NO_JPEG) || !defined(USE_JPEG)
+ return -1;
+#else
+ j_decompress_ptr cinfo = (j_decompress_ptr)jpegdata;
+ jpeg_mem_src(cinfo, (unsigned char *)buf + streampos,(unsigned long)(streamsize - streampos));
+ return 0;
+#endif
+}
+
+// int LibRaw_buffer_datastream
+
+// == LibRaw_bigfile_datastream
+LibRaw_bigfile_datastream::LibRaw_bigfile_datastream(const char *fname)
+ : filename(fname)
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ ,
+ wfilename()
+#endif
+{
+ if (filename.size() > 0)
+ {
+#ifndef LIBRAW_WIN32_CALLS
+ struct stat st;
+ if (!stat(filename.c_str(), &st))
+ _fsize = st.st_size;
+#else
+ struct _stati64 st;
+ if (!_stati64(filename.c_str(), &st))
+ _fsize = st.st_size;
+#endif
+
+#ifndef WIN32SECURECALLS
+ f = fopen(fname, "rb");
+#else
+ if (fopen_s(&f, fname, "rb"))
+ f = 0;
+#endif
+ }
+ else
+ {
+ filename = std::string();
+ f = 0;
+ }
+}
+
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+LibRaw_bigfile_datastream::LibRaw_bigfile_datastream(const wchar_t *fname)
+ : filename(), wfilename(fname)
+{
+ if (wfilename.size() > 0)
+ {
+ struct _stati64 st;
+ if (!_wstati64(wfilename.c_str(), &st))
+ _fsize = st.st_size;
+#ifndef WIN32SECURECALLS
+ f = _wfopen(wfilename.c_str(), L"rb");
+#else
+ if (_wfopen_s(&f, fname, L"rb"))
+ f = 0;
+#endif
+ }
+ else
+ {
+ wfilename = std::wstring();
+ f = 0;
+ }
+}
+const wchar_t *LibRaw_bigfile_datastream::wfname()
+{
+ return wfilename.size() > 0 ? wfilename.c_str() : NULL;
+}
+#endif
+
+LibRaw_bigfile_datastream::~LibRaw_bigfile_datastream()
+{
+ if (f)
+ fclose(f);
+}
+int LibRaw_bigfile_datastream::valid() { return f ? 1 : 0; }
+
+#define LR_BF_CHK() \
+ do \
+ { \
+ if (!f) \
+ throw LIBRAW_EXCEPTION_IO_EOF; \
+ } while (0)
+
+int LibRaw_bigfile_datastream::read(void *ptr, size_t size, size_t nmemb)
+{
+ LR_BF_CHK();
+ return int(fread(ptr, size, nmemb, f));
+}
+
+int LibRaw_bigfile_datastream::eof()
+{
+ LR_BF_CHK();
+ return feof(f);
+}
+
+int LibRaw_bigfile_datastream::seek(INT64 o, int whence)
+{
+ LR_BF_CHK();
+#if defined(_WIN32)
+#ifdef WIN32SECURECALLS
+ return _fseeki64(f, o, whence);
+#else
+ return fseek(f, (long)o, whence);
+#endif
+#else
+ return fseeko(f, o, whence);
+#endif
+}
+
+INT64 LibRaw_bigfile_datastream::tell()
+{
+ LR_BF_CHK();
+#if defined(_WIN32)
+#ifdef WIN32SECURECALLS
+ return _ftelli64(f);
+#else
+ return ftell(f);
+#endif
+#else
+ return ftello(f);
+#endif
+}
+
+char *LibRaw_bigfile_datastream::gets(char *str, int sz)
+{
+ if(sz<1) return NULL;
+ LR_BF_CHK();
+ return fgets(str, sz, f);
+}
+
+int LibRaw_bigfile_datastream::scanf_one(const char *fmt, void *val)
+{
+ LR_BF_CHK();
+ return
+#ifndef WIN32SECURECALLS
+ fscanf(f, fmt, val)
+#else
+ fscanf_s(f, fmt, val)
+#endif
+ ;
+}
+
+const char *LibRaw_bigfile_datastream::fname()
+{
+ return filename.size() > 0 ? filename.c_str() : NULL;
+}
+
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+void *LibRaw_bigfile_datastream::make_jas_stream()
+{
+#ifdef NO_JASPER
+ return NULL;
+#else
+ return jas_stream_fdopen(fileno(f), "rb");
+#endif
+}
+#endif
+
+// == LibRaw_windows_datastream
+#ifdef LIBRAW_WIN32_CALLS
+
+LibRaw_windows_datastream::LibRaw_windows_datastream(const TCHAR *sFile)
+ : LibRaw_buffer_datastream(NULL, 0), hMap_(0), pView_(NULL)
+{
+#if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_APP) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+ HANDLE hFile = CreateFile2(sFile, GENERIC_READ, 0, OPEN_EXISTING, 0);
+#else
+ HANDLE hFile = CreateFile(sFile, GENERIC_READ, 0, 0, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, 0);
+#endif
+ if (hFile == INVALID_HANDLE_VALUE)
+ throw std::runtime_error("failed to open the file");
+
+ try
+ {
+ Open(hFile);
+ }
+ catch (...)
+ {
+ CloseHandle(hFile);
+ throw;
+ }
+
+ CloseHandle(hFile); // windows will defer the actual closing of this handle
+ // until the hMap_ is closed
+ reconstruct_base();
+}
+
+// ctor: construct with a file handle - caller is responsible for closing the
+// file handle
+LibRaw_windows_datastream::LibRaw_windows_datastream(HANDLE hFile)
+ : LibRaw_buffer_datastream(NULL, 0), hMap_(0), pView_(NULL)
+{
+ Open(hFile);
+ reconstruct_base();
+}
+
+// dtor: unmap and close the mapping handle
+LibRaw_windows_datastream::~LibRaw_windows_datastream()
+{
+ if (pView_ != NULL)
+ ::UnmapViewOfFile(pView_);
+
+ if (hMap_ != 0)
+ ::CloseHandle(hMap_);
+}
+
+void LibRaw_windows_datastream::Open(HANDLE hFile)
+{
+ // create a file mapping handle on the file handle
+ hMap_ = ::CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, 0);
+ if (hMap_ == NULL)
+ throw std::runtime_error("failed to create file mapping");
+
+ // now map the whole file base view
+ if (!::GetFileSizeEx(hFile, (PLARGE_INTEGER)&cbView_))
+ throw std::runtime_error("failed to get the file size");
+
+ pView_ = ::MapViewOfFile(hMap_, FILE_MAP_READ, 0, 0, (size_t)cbView_);
+ if (pView_ == NULL)
+ throw std::runtime_error("failed to map the file");
+}
+
+#endif
+
+#if defined (LIBRAW_NO_IOSTREAMS_DATASTREAM) && defined (LIBRAW_WIN32_CALLS)
+
+/* LibRaw_bigfile_buffered_datastream: copypasted from LibRaw_bigfile_datastream + extra cache on read */
+
+#undef LR_BF_CHK
+#define LR_BF_CHK() \
+ do \
+ { \
+ if (fhandle ==0 || fhandle == INVALID_HANDLE_VALUE) \
+ throw LIBRAW_EXCEPTION_IO_EOF; \
+ } while (0)
+
+#define LIBRAW_BUFFER_ALIGN 4096
+
+int LibRaw_bufio_params::bufsize = 16384;
+
+void LibRaw_bufio_params::set_bufsize(int bs)
+{
+ if (bs > 0)
+ bufsize = bs;
+}
+
+
+LibRaw_bigfile_buffered_datastream::LibRaw_bigfile_buffered_datastream(const char *fname)
+ : filename(fname), _fsize(0), _fpos(0)
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ , wfilename()
+#endif
+ , iobuffers(), buffered(1)
+{
+ if (filename.size() > 0)
+ {
+ std::string fn(fname);
+ std::wstring fpath(fn.begin(), fn.end());
+#if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_APP) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+ if ((fhandle = CreateFile2(fpath.c_str(), GENERIC_READ, 0, OPEN_EXISTING, 0)) != INVALID_HANDLE_VALUE)
+#else
+ if ((fhandle = CreateFileW(fpath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE)
+#endif
+ {
+ LARGE_INTEGER fs;
+ if (GetFileSizeEx(fhandle, &fs))
+ _fsize = fs.QuadPart;
+ }
+ }
+ else
+ {
+ filename = std::string();
+ fhandle = INVALID_HANDLE_VALUE;
+ }
+}
+
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+LibRaw_bigfile_buffered_datastream::LibRaw_bigfile_buffered_datastream(const wchar_t *fname)
+ : filename(), _fsize(0), _fpos(0),
+ wfilename(fname), iobuffers(), buffered(1)
+{
+ if (wfilename.size() > 0)
+ {
+#if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_APP) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+ if ((fhandle = CreateFile2(wfilename.c_str(), GENERIC_READ, 0, OPEN_EXISTING, 0)) != INVALID_HANDLE_VALUE)
+#else
+ if ((fhandle = CreateFileW(wfilename.c_str(), GENERIC_READ, FILE_SHARE_READ, 0,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE)
+#endif
+ {
+ LARGE_INTEGER fs;
+ if (GetFileSizeEx(fhandle, &fs))
+ _fsize = fs.QuadPart;
+ }
+
+ }
+ else
+ {
+ wfilename = std::wstring();
+ fhandle = INVALID_HANDLE_VALUE;
+ }
+}
+
+const wchar_t *LibRaw_bigfile_buffered_datastream::wfname()
+{
+ return wfilename.size() > 0 ? wfilename.c_str() : NULL;
+}
+#endif
+
+LibRaw_bigfile_buffered_datastream::~LibRaw_bigfile_buffered_datastream()
+{
+ if (valid())
+ CloseHandle(fhandle);
+}
+int LibRaw_bigfile_buffered_datastream::valid() {
+ return (fhandle != NULL) && (fhandle != INVALID_HANDLE_VALUE);
+}
+
+const char *LibRaw_bigfile_buffered_datastream::fname()
+{
+ return filename.size() > 0 ? filename.c_str() : NULL;
+}
+
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+void *LibRaw_bigfile_buffered_datastream::make_jas_stream()
+{
+#ifdef NO_JASPER
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+#endif
+
+INT64 LibRaw_bigfile_buffered_datastream::readAt(void *ptr, size_t size, INT64 off)
+{
+ LR_BF_CHK();
+ DWORD NumberOfBytesRead;
+ DWORD nNumberOfBytesToRead = (DWORD)size;
+ struct _OVERLAPPED olap;
+ memset(&olap, 0, sizeof(olap));
+ olap.Offset = off & 0xffffffff;
+ olap.OffsetHigh = off >> 32;
+ if (ReadFile(fhandle, ptr, nNumberOfBytesToRead, &NumberOfBytesRead, &olap))
+ return NumberOfBytesRead;
+ else
+ return 0;
+}
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+#ifdef _MSC_VER
+#pragma intrinsic(memcpy)
+#endif
+
+int LibRaw_bigfile_buffered_datastream::read(void *data, size_t size, size_t nmemb)
+{
+ if (size < 1 || nmemb < 1)
+ return 0;
+ LR_BF_CHK();
+ INT64 count = size * nmemb;
+ INT64 partbytes = 0;
+ if (!buffered)
+ {
+ INT64 r = readAt(data, count, _fpos);
+ _fpos += r;
+ return int(r / size);
+ }
+
+ unsigned char *fBuffer = (unsigned char*)iobuffers[0].data();
+ while (count)
+ {
+ INT64 inbuffer = 0;
+ // See if the request is totally inside buffer.
+ if (iobuffers[0].contains(_fpos, inbuffer))
+ {
+ if (inbuffer >= count)
+ {
+ memcpy(data, fBuffer + (unsigned)(_fpos - iobuffers[0]._bstart), count);
+ _fpos += count;
+ return int((count + partbytes) / size);
+ }
+ memcpy(data, fBuffer + (_fpos - iobuffers[0]._bstart), inbuffer);
+ partbytes += inbuffer;
+ count -= inbuffer;
+ data = (void *)(((char *)data) + inbuffer);
+ _fpos += inbuffer;
+ }
+ if (count > (INT64) iobuffers[0].size())
+ {
+ fallback:
+ if (_fpos + count > _fsize)
+ count = MAX(0, _fsize - _fpos);
+ if (count > 0)
+ {
+ INT64 r = readAt(data, count, _fpos);
+ _fpos += r;
+ return int((r + partbytes) / size);
+ }
+ else
+ return 0;
+ }
+
+ if (!fillBufferAt(0, _fpos))
+ goto fallback;
+ }
+ return 0;
+}
+
+bool LibRaw_bigfile_buffered_datastream::fillBufferAt(int bi, INT64 off)
+{
+ if (off < 0LL) return false;
+ iobuffers[bi]._bstart = off;
+ if (iobuffers[bi].size() >= LIBRAW_BUFFER_ALIGN * 2)// Align to a file block.
+ iobuffers[bi]._bstart &= (INT64)~((INT64)(LIBRAW_BUFFER_ALIGN - 1));
+
+ iobuffers[bi]._bend = MIN(iobuffers[bi]._bstart + (INT64)iobuffers[bi].size(), _fsize);
+ if (iobuffers[bi]._bend <= off) // Buffer alignment problem, fallback
+ return false;
+ INT64 rr = readAt(iobuffers[bi].data(), (uint32_t)(iobuffers[bi]._bend - iobuffers[bi]._bstart), iobuffers[bi]._bstart);
+ if (rr > 0)
+ {
+ iobuffers[bi]._bend = iobuffers[bi]._bstart + rr;
+ return true;
+ }
+ return false;
+}
+
+
+int LibRaw_bigfile_buffered_datastream::eof()
+{
+ LR_BF_CHK();
+ return _fpos >= _fsize;
+}
+
+int LibRaw_bigfile_buffered_datastream::seek(INT64 o, int whence)
+{
+ LR_BF_CHK();
+ if (whence == SEEK_SET) _fpos = o;
+ else if (whence == SEEK_END) _fpos = o > 0 ? _fsize : _fsize + o;
+ else if (whence == SEEK_CUR) _fpos += o;
+ return 0;
+}
+
+INT64 LibRaw_bigfile_buffered_datastream::tell()
+{
+ LR_BF_CHK();
+ return _fpos;
+}
+
+char *LibRaw_bigfile_buffered_datastream::gets(char *s, int sz)
+{
+ if (sz < 1)
+ return NULL;
+ else if (sz < 2)
+ {
+ s[0] = 0;
+ return s;
+ }
+
+ LR_BF_CHK();
+ INT64 contains;
+ int bufindex = selectStringBuffer(sz, contains);
+ if (bufindex < 0) return NULL;
+ if (contains >= sz)
+ {
+ unsigned char *buf = iobuffers[bufindex].data() + (_fpos - iobuffers[bufindex]._bstart);
+ int streampos = 0;
+ int streamsize = contains;
+ unsigned char *str = (unsigned char *)s;
+ unsigned char *psrc, *pdest;
+ psrc = buf + streampos;
+ pdest = str;
+
+ while ((size_t(psrc - buf) < streamsize) && ((pdest - str) < sz-1)) // sz-1: to append \0
+ {
+ *pdest = *psrc;
+ if (*psrc == '\n')
+ break;
+ psrc++;
+ pdest++;
+ }
+ if (size_t(psrc - buf) < streamsize)
+ psrc++;
+ if ((pdest - str) < sz - 1)
+ *(++pdest) = 0;
+ else
+ s[sz - 1] = 0; // ensure trailing zero
+ streampos = psrc - buf;
+ _fpos += streampos;
+ return s;
+ }
+ return NULL;
+}
+
+int LibRaw_bigfile_buffered_datastream::selectStringBuffer(INT64 len, INT64& contains)
+{
+ if (iobuffers[0].contains(_fpos, contains) && contains >= len)
+ return 0;
+
+ if (iobuffers[1].contains(_fpos, contains) && contains >= len)
+ return 1;
+
+ fillBufferAt(1, _fpos);
+ if (iobuffers[1].contains(_fpos, contains) && contains >= len)
+ return 1;
+ return -1;
+}
+
+int LibRaw_bigfile_buffered_datastream::scanf_one(const char *fmt, void *val)
+{
+ LR_BF_CHK();
+ INT64 contains = 0;
+ int bufindex = selectStringBuffer(24, contains);
+ if (bufindex < 0) return -1;
+ if (contains >= 24)
+ {
+ unsigned char *bstart = iobuffers[bufindex].data() + (_fpos - iobuffers[bufindex]._bstart);
+ int streampos = 0;
+ int streamsize = contains;
+ int
+#ifndef WIN32SECURECALLS
+ scanf_res = sscanf((char *)(bstart), fmt, val);
+#else
+ scanf_res = sscanf_s((char *)(bstart), fmt, val);
+#endif
+ if (scanf_res > 0)
+ {
+ int xcnt = 0;
+ while (streampos < streamsize)
+ {
+ streampos++;
+ xcnt++;
+ if (bstart[streampos] == 0 || bstart[streampos] == ' ' ||
+ bstart[streampos] == '\t' || bstart[streampos] == '\n' || xcnt > 24)
+ break;
+ }
+ _fpos += streampos;
+ return scanf_res;
+ }
+ }
+ return -1;
+}
+
+#endif
+
diff --git a/libkdcraw/libraw/src/metadata/adobepano.cpp b/libkdcraw/libraw/src/metadata/adobepano.cpp
new file mode 100644
index 0000000..689c24a
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/adobepano.cpp
@@ -0,0 +1,154 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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_defs.h"
+
+void LibRaw::parseAdobePanoMakernote()
+{
+ uchar *PrivateMknBuf;
+ unsigned posPrivateMknBuf;
+ unsigned PrivateMknLength;
+ unsigned PrivateOrder;
+ unsigned PrivateEntries, PrivateTagID, PrivateTagType, PrivateTagCount;
+ unsigned PrivateTagBytes;
+ int truncated;
+
+#define CHECKSPACE(s) \
+ if (posPrivateMknBuf + (s) > PrivateMknLength) \
+ { \
+ free(PrivateMknBuf); \
+ return; \
+ }
+
+ order = 0x4d4d;
+ truncated = 0;
+ PrivateMknLength = get4();
+
+ if ((PrivateMknLength > 4) && (PrivateMknLength < 10240000) &&
+ (PrivateMknBuf = (uchar *)malloc(PrivateMknLength + 1024)))
+ { // 1024b for safety
+ fread(PrivateMknBuf, PrivateMknLength, 1, ifp);
+ PrivateOrder = sget2(PrivateMknBuf);
+ PrivateEntries = sget2(PrivateMknBuf + 2);
+ if ((PrivateEntries > 1000) ||
+ ((PrivateOrder != 0x4d4d) && (PrivateOrder != 0x4949)))
+ {
+ free(PrivateMknBuf);
+ return;
+ }
+ posPrivateMknBuf = 4;
+ while (PrivateEntries--)
+ {
+ order = 0x4d4d;
+ CHECKSPACE(8);
+ PrivateTagID = sget2(PrivateMknBuf + posPrivateMknBuf);
+ PrivateTagType = sget2(PrivateMknBuf + posPrivateMknBuf + 2);
+ PrivateTagCount = sget4(PrivateMknBuf + posPrivateMknBuf + 4);
+ posPrivateMknBuf += 8;
+ order = PrivateOrder;
+
+ if (truncated && !PrivateTagCount)
+ continue;
+
+ PrivateTagBytes = PrivateTagCount *
+ tagtype_dataunit_bytes[(PrivateTagType <= LIBRAW_EXIFTAG_TYPE_IFD8) ? PrivateTagType : 0];
+ if(PrivateTagBytes > 10240000u)
+ {
+ free(PrivateMknBuf);
+ return;
+ }
+ if (PrivateTagID == 0x0002)
+ {
+ posPrivateMknBuf += 2;
+ CHECKSPACE(2);
+ if (sget2(PrivateMknBuf + posPrivateMknBuf))
+ {
+ truncated = 1;
+ }
+ else
+ {
+ posPrivateMknBuf += 2;
+ }
+ }
+ else if (PrivateTagID == 0x0013)
+ {
+ ushort nWB, cnt, tWB;
+ CHECKSPACE(2);
+ nWB = sget2(PrivateMknBuf + posPrivateMknBuf);
+ posPrivateMknBuf += 2;
+ if (nWB > 0x100)
+ break;
+ for (cnt = 0; cnt < nWB; cnt++)
+ {
+ CHECKSPACE(2);
+ tWB = sget2(PrivateMknBuf + posPrivateMknBuf);
+ if (tWB < 0x100)
+ {
+ CHECKSPACE(4);
+ icWBC[tWB][0] = sget2(PrivateMknBuf + posPrivateMknBuf + 2);
+ icWBC[tWB][2] = sget2(PrivateMknBuf + posPrivateMknBuf + 4);
+ icWBC[tWB][1] = icWBC[tWB][3] = 0x100;
+ }
+ posPrivateMknBuf += 6;
+ }
+ }
+ else if (PrivateTagID == 0x0027)
+ {
+ ushort nWB, cnt, tWB;
+ CHECKSPACE(2);
+ nWB = sget2(PrivateMknBuf + posPrivateMknBuf);
+ posPrivateMknBuf += 2;
+ if (nWB > 0x100)
+ break;
+ for (cnt = 0; cnt < nWB; cnt++)
+ {
+ CHECKSPACE(2);
+ tWB = sget2(PrivateMknBuf + posPrivateMknBuf);
+ if (tWB < 0x100)
+ {
+ CHECKSPACE(6);
+ icWBC[tWB][0] = sget2(PrivateMknBuf + posPrivateMknBuf + 2);
+ icWBC[tWB][1] = icWBC[tWB][3] =
+ sget2(PrivateMknBuf + posPrivateMknBuf + 4);
+ icWBC[tWB][2] = sget2(PrivateMknBuf + posPrivateMknBuf + 6);
+ }
+ posPrivateMknBuf += 8;
+ }
+ }
+ else if (PrivateTagID == 0x0121)
+ {
+ CHECKSPACE(4);
+ imPana.Multishot = sget4(PrivateMknBuf + posPrivateMknBuf);
+ posPrivateMknBuf += 4;
+ }
+ else
+ {
+ if (PrivateTagBytes > 4)
+ posPrivateMknBuf += PrivateTagBytes;
+ else if (!truncated)
+ posPrivateMknBuf += 4;
+ else
+ {
+ if (PrivateTagBytes <= 2)
+ posPrivateMknBuf += 2;
+ else
+ posPrivateMknBuf += 4;
+ }
+ }
+ }
+ free(PrivateMknBuf);
+ }
+#undef CHECKSPACE
+}
diff --git a/libkdcraw/libraw/src/metadata/canon.cpp b/libkdcraw/libraw/src/metadata/canon.cpp
new file mode 100644
index 0000000..012ecb0
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/canon.cpp
@@ -0,0 +1,1335 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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_defs.h"
+#include "../../internal/libraw_cameraids.h"
+
+libraw_area_t LibRaw::get_CanonArea() {
+ libraw_area_t la = {};
+ la.l = get2();
+ la.t = get2();
+ la.r = get2();
+ la.b = get2();
+ return la;
+}
+
+float LibRaw::_CanonConvertAperture(ushort in)
+{
+ if ((in == (ushort)0xffe0) || (in == (ushort)0x7fff))
+ return 0.0f;
+ return LibRaw::libraw_powf64l(2.f, float(in) / 64.f);
+}
+
+static float _CanonConvertEV(short in)
+{
+ short EV, Sign, Frac;
+ float Frac_f;
+ EV = in;
+ if (EV < 0)
+ {
+ EV = -EV;
+ Sign = -1;
+ }
+ else
+ {
+ Sign = 1;
+ }
+ Frac = EV & 0x1f;
+ EV -= Frac; // remove fraction
+
+ if (Frac == 0x0c)
+ { // convert 1/3 and 2/3 codes
+ Frac_f = 32.0f / 3.0f;
+ }
+ else if (Frac == 0x14)
+ {
+ Frac_f = 64.0f / 3.0f;
+ }
+ else
+ Frac_f = (float)Frac;
+
+ return ((float)Sign * ((float)EV + Frac_f)) / 32.0f;
+}
+
+void LibRaw::setCanonBodyFeatures(unsigned long long id)
+{
+
+ ilm.CamID = id;
+ if ((id == CanonID_EOS_1D) ||
+ (id == CanonID_EOS_1D_Mark_II) ||
+ (id == CanonID_EOS_1D_Mark_II_N) ||
+ (id == CanonID_EOS_1D_Mark_III) ||
+ (id == CanonID_EOS_1D_Mark_IV))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_APSH;
+ ilm.CameraMount = LIBRAW_MOUNT_Canon_EF;
+ }
+ else if ((id == CanonID_EOS_1Ds) ||
+ (id == CanonID_EOS_1Ds_Mark_II) ||
+ (id == CanonID_EOS_1Ds_Mark_III) ||
+ (id == CanonID_EOS_1D_X) ||
+ (id == CanonID_EOS_1D_X_Mark_II) ||
+ (id == CanonID_EOS_1D_X_Mark_III) ||
+ (id == CanonID_EOS_1D_C) ||
+ (id == CanonID_EOS_5D) ||
+ (id == CanonID_EOS_5D_Mark_II) ||
+ (id == CanonID_EOS_5D_Mark_III) ||
+ (id == CanonID_EOS_5D_Mark_IV) ||
+ (id == CanonID_EOS_5DS) ||
+ (id == CanonID_EOS_5DS_R) ||
+ (id == CanonID_EOS_6D) ||
+ (id == CanonID_EOS_6D_Mark_II))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ ilm.CameraMount = LIBRAW_MOUNT_Canon_EF;
+ }
+ else if ((id == CanonID_EOS_M) ||
+ (id == CanonID_EOS_M2) ||
+ (id == CanonID_EOS_M3) ||
+ (id == CanonID_EOS_M5) ||
+ (id == CanonID_EOS_M10) ||
+ (id == CanonID_EOS_M50) ||
+ (id == CanonID_EOS_M50_Mark_II) ||
+ (id == CanonID_EOS_M6) ||
+ (id == CanonID_EOS_M6_Mark_II) ||
+ (id == CanonID_EOS_M100))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_Canon_EF_M;
+ }
+ else if ((id == CanonID_EOS_R) ||
+ (id == CanonID_EOS_RP) ||
+ (id == CanonID_EOS_R3) ||
+ (id == CanonID_EOS_R5) ||
+ (id == CanonID_EOS_R6))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ ilm.CameraMount = LIBRAW_MOUNT_Canon_RF;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ }
+
+ else if ((id == CanonID_EOS_R7) ||
+ (id == CanonID_EOS_R10))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_Canon_RF;
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ }
+
+ else if ((id == CanonID_EOS_D30) ||
+ (id == CanonID_EOS_D60) ||
+ (id > 0x80000000ULL))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_Canon_EF;
+ }
+}
+
+int CanonCameraInfo_checkFirmwareRecordLocation (uchar *offset) {
+// firmware record location allows
+// to determine the subversion of the CameraInfo table
+// and to adjust offsets accordingly
+ if (
+ isdigit(*offset) &&
+ isdigit(*(offset+2)) &&
+ isdigit(*(offset+4)) &&
+ (*(offset+1) == '.') &&
+ (*(offset+3) == '.') &&
+ ((*(offset+5) == 0) || isspace(*(offset+5)))
+ ) return 1;
+ else return 0; // error
+}
+
+void LibRaw::processCanonCameraInfo(unsigned long long id, uchar *CameraInfo,
+ unsigned maxlen, unsigned type, unsigned dng_writer)
+{
+ ushort iCanonLensID = 0, iCanonMaxFocal = 0, iCanonMinFocal = 0,
+ iCanonLens = 0, iCanonCurFocal = 0, iCanonFocalType = 0,
+ iMakernotesFlip = 0,
+ iHTP = 0, iALO = 0;
+ short SubVersion_offset = 0;
+ ushort SubVersion = 0, mgck = 0;
+
+ if (maxlen < 16)
+ return; // too short
+
+ mgck = sget2(CameraInfo);
+ CameraInfo[0] = 0;
+ CameraInfo[1] = 0;
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG)) {
+ if ((maxlen == 94) || (maxlen == 138) || (maxlen == 148) ||
+ (maxlen == 156) || (maxlen == 162) || (maxlen == 167) ||
+ (maxlen == 171) || (maxlen == 264) || (maxlen > 400))
+ imCommon.CameraTemperature = float(sget4(CameraInfo + ((maxlen - 3) << 2)));
+ else if (maxlen == 72)
+ imCommon.CameraTemperature = float(sget4(CameraInfo + ((maxlen - 1) << 2)));
+ else if ((maxlen == 85) || (maxlen == 93))
+ imCommon.CameraTemperature = float(sget4(CameraInfo + ((maxlen - 2) << 2)));
+ else if ((maxlen == 96) || (maxlen == 104))
+ imCommon.CameraTemperature = float(sget4(CameraInfo + ((maxlen - 4) << 2)));
+ }
+
+ switch (id)
+ {
+ case CanonID_EOS_1D:
+ case CanonID_EOS_1Ds:
+ iCanonCurFocal = 0x0a;
+ iCanonLensID = 0x0d;
+ iCanonMinFocal = 0x0e;
+ iCanonMaxFocal = 0x10;
+ if (!ilm.CurFocal)
+ ilm.CurFocal = sget2(CameraInfo + iCanonCurFocal);
+ if (!ilm.MinFocal)
+ ilm.MinFocal = sget2(CameraInfo + iCanonMinFocal);
+ if (!ilm.MaxFocal)
+ ilm.MaxFocal = sget2(CameraInfo + iCanonMaxFocal);
+ imCommon.CameraTemperature = 0.0f;
+ break;
+
+ case CanonID_EOS_1D_Mark_II:
+ case CanonID_EOS_1Ds_Mark_II:
+ iCanonCurFocal = 0x09;
+ iCanonLensID = 0x0c;
+ iCanonMinFocal = 0x11;
+ iCanonMaxFocal = 0x13;
+ iCanonFocalType = 0x2d;
+ break;
+
+ case CanonID_EOS_1D_Mark_II_N:
+ iCanonCurFocal = 0x09;
+ iCanonLensID = 0x0c;
+ iCanonMinFocal = 0x11;
+ iCanonMaxFocal = 0x13;
+ break;
+
+ case CanonID_EOS_1D_Mark_III:
+ case CanonID_EOS_1Ds_Mark_III:
+ iCanonCurFocal = 0x1d;
+ iMakernotesFlip = 0x30;
+ iCanonLensID = 0x111;
+ iCanonMinFocal = 0x113;
+ iCanonMaxFocal = 0x115;
+ break;
+
+ case CanonID_EOS_1D_Mark_IV:
+ if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x1e8))
+ SubVersion = 1;
+ else if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x1ed))
+ SubVersion = 2;
+// printf ("==>> CanonID_EOS_1D_Mark_IV, SubVersion: %d\n", SubVersion);
+ iHTP = 0x07;
+ iCanonCurFocal = 0x1e;
+ iMakernotesFlip = 0x35;
+
+ if (!SubVersion)
+ break;
+ else if (SubVersion < 2)
+ SubVersion_offset += -1;
+
+ iCanonLensID = 0x14f+SubVersion_offset;
+ iCanonMinFocal = 0x151+SubVersion_offset;
+ iCanonMaxFocal = 0x153+SubVersion_offset;
+ break;
+
+ case CanonID_EOS_1D_X:
+ if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x271))
+ SubVersion = 1;
+ else if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x279))
+ SubVersion = 2;
+ else if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x280))
+ SubVersion = 3;
+ else if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x285))
+ SubVersion = 4;
+// printf ("==>> CanonID_EOS_1D_X, SubVersion: %d\n", SubVersion);
+
+ if (SubVersion < 3)
+ SubVersion_offset += -3;
+
+ iCanonCurFocal = 0x23+SubVersion_offset;
+ iMakernotesFlip = 0x7d+SubVersion_offset;
+
+ if (SubVersion < 3)
+ SubVersion_offset += -4;
+ else if (SubVersion == 4)
+ SubVersion_offset += 5;
+
+ iCanonLensID = 0x1a7+SubVersion_offset;
+ iCanonMinFocal = 0x1a9+SubVersion_offset;
+ iCanonMaxFocal = 0x1ab+SubVersion_offset;
+ break;
+
+ case CanonID_EOS_5D:
+ iMakernotesFlip = 0x27;
+ iCanonCurFocal = 0x28;
+ iCanonLensID = 0x0c;
+ if (!sget2Rev(CameraInfo + iCanonLensID))
+ iCanonLensID = 0x97;
+ iCanonMinFocal = 0x93;
+ iCanonMaxFocal = 0x95;
+ break;
+
+ case CanonID_EOS_5D_Mark_II:
+ iHTP = 0x07;
+ iCanonCurFocal = 0x1e;
+ iMakernotesFlip = 0x31;
+ iALO = 0xbf;
+ iCanonLensID = 0xe6;
+ iCanonMinFocal = 0xe8;
+ iCanonMaxFocal = 0xea;
+ break;
+
+ case CanonID_EOS_5D_Mark_III:
+ if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x22c))
+ SubVersion = 1;
+ else if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x22d))
+ SubVersion = 2;
+ else if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x23c))
+ SubVersion = 3;
+ else if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x242))
+ SubVersion = 4;
+ else if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x247))
+ SubVersion = 5;
+// printf ("==>> CanonID_EOS_5D_Mark_III, SubVersion: %d\n", SubVersion);
+
+ if (!SubVersion)
+ break;
+ else if (SubVersion < 3)
+ SubVersion_offset += -1;
+
+ iCanonCurFocal = 0x23+SubVersion_offset;
+
+ if (SubVersion == 1)
+ SubVersion_offset += -3;
+ else if (SubVersion == 2)
+ SubVersion_offset += -2;
+ else if (SubVersion >= 4)
+ SubVersion_offset += 6;
+
+ iMakernotesFlip = 0x7d+SubVersion_offset;
+
+ if (SubVersion < 3)
+ SubVersion_offset += -4;
+ else if (SubVersion > 4)
+ SubVersion_offset += 5;
+
+ iCanonLensID = 0x153+SubVersion_offset;
+ iCanonMinFocal = 0x155+SubVersion_offset;
+ iCanonMaxFocal = 0x157+SubVersion_offset;
+ break;
+
+ case CanonID_EOS_6D:
+ iCanonCurFocal = 0x23;
+ iMakernotesFlip = 0x83;
+ iCanonLensID = 0x161;
+ iCanonMinFocal = 0x163;
+ iCanonMaxFocal = 0x165;
+ break;
+
+ case CanonID_EOS_7D:
+ if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x1a8))
+ SubVersion = 1;
+ else if (CanonCameraInfo_checkFirmwareRecordLocation(CameraInfo + 0x1ac))
+ SubVersion = 2;
+// printf ("==>> CanonID_EOS_7D, SubVersion: %d\n", SubVersion);
+ iHTP = 0x07;
+ iCanonCurFocal = 0x1e;
+
+ if (!SubVersion)
+ break;
+ else if (SubVersion < 2)
+ SubVersion_offset += -4;
+
+ iMakernotesFlip = 0x35+SubVersion_offset;
+ iCanonLensID = 0x112+SubVersion_offset;
+ iCanonMinFocal = 0x114+SubVersion_offset;
+ iCanonMaxFocal = 0x116+SubVersion_offset;
+ break;
+
+ case CanonID_EOS_40D:
+ iCanonCurFocal = 0x1d;
+ iMakernotesFlip = 0x30;
+ iCanonLensID = 0xd6;
+ iCanonMinFocal = 0xd8;
+ iCanonMaxFocal = 0xda;
+ iCanonLens = 0x92b;
+ break;
+
+ case CanonID_EOS_50D:
+ iHTP = 0x07;
+ iCanonCurFocal = 0x1e;
+ iMakernotesFlip = 0x31;
+ iALO = 0xbf;
+ iCanonLensID = 0xea;
+ iCanonMinFocal = 0xec;
+ iCanonMaxFocal = 0xee;
+ break;
+
+ case CanonID_EOS_60D:
+ case CanonID_EOS_1200D:
+ iCanonCurFocal = 0x1e;
+ if (id == CanonID_EOS_60D)
+ iMakernotesFlip = 0x36;
+ else
+ iMakernotesFlip = 0x3a;
+ iCanonLensID = 0xe8;
+ iCanonMinFocal = 0xea;
+ iCanonMaxFocal = 0xec;
+ break;
+
+ case CanonID_EOS_70D:
+ iCanonCurFocal = 0x23;
+ iMakernotesFlip = 0x84;
+ iCanonLensID = 0x166;
+ iCanonMinFocal = 0x168;
+ iCanonMaxFocal = 0x16a;
+ break;
+
+ case CanonID_EOS_80D:
+ iCanonCurFocal = 0x23;
+ iMakernotesFlip = 0x96;
+ iCanonLensID = 0x189;
+ iCanonMinFocal = 0x18b;
+ iCanonMaxFocal = 0x18d;
+ break;
+
+ case CanonID_EOS_450D:
+ iCanonCurFocal = 0x1d;
+ iMakernotesFlip = 0x30;
+ iCanonLensID = 0xde;
+ iCanonLens = 0x933;
+ break;
+
+ case CanonID_EOS_500D:
+ iHTP = 0x07;
+ iCanonCurFocal = 0x1e;
+ iMakernotesFlip = 0x31;
+ iALO = 0xbe;
+ iCanonLensID = 0xf6;
+ iCanonMinFocal = 0xf8;
+ iCanonMaxFocal = 0xfa;
+ break;
+
+ case CanonID_EOS_550D:
+ iHTP = 0x07;
+ iCanonCurFocal = 0x1e;
+ iMakernotesFlip = 0x35;
+ iCanonLensID = 0xff;
+ iCanonMinFocal = 0x101;
+ iCanonMaxFocal = 0x103;
+ break;
+
+ case CanonID_EOS_600D:
+ case CanonID_EOS_1100D:
+ iHTP = 0x07;
+ iCanonCurFocal = 0x1e;
+ iMakernotesFlip = 0x38;
+ iCanonLensID = 0xea;
+ iCanonMinFocal = 0xec;
+ iCanonMaxFocal = 0xee;
+ break;
+
+ case CanonID_EOS_650D:
+ case CanonID_EOS_700D:
+ iCanonCurFocal = 0x23;
+ iMakernotesFlip = 0x7d;
+ iCanonLensID = 0x127;
+ iCanonMinFocal = 0x129;
+ iCanonMaxFocal = 0x12b;
+ break;
+
+ case CanonID_EOS_750D:
+ case CanonID_EOS_760D:
+ iCanonCurFocal = 0x23;
+ iMakernotesFlip = 0x96;
+ iCanonLensID = 0x184;
+ iCanonMinFocal = 0x186;
+ iCanonMaxFocal = 0x188;
+ break;
+
+ case CanonID_EOS_1000D:
+ iCanonCurFocal = 0x1d;
+ iMakernotesFlip = 0x30;
+ iCanonLensID = 0xe2;
+ iCanonMinFocal = 0xe4;
+ iCanonMaxFocal = 0xe6;
+ iCanonLens = 0x937;
+ break;
+ }
+
+ if (iMakernotesFlip && (CameraInfo[iMakernotesFlip] < 3)) {
+ imCanon.MakernotesFlip = "065"[CameraInfo[iMakernotesFlip]] - '0';
+// printf ("==>> iMakernotesFlip: 0x%x, flip: %d\n", iMakernotesFlip, imCanon.MakernotesFlip);
+ } else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_UNDEFINED) &&
+ (mgck == 0xaaaa) && (dng_writer == nonDNG)) { // CameraOrientation
+ int c, i;
+ for (i = 2; (sget2(CameraInfo+i) != 0xbbbb) && i < (int)maxlen; i++);
+ i+=2;
+ while (i < int(maxlen - 5))
+ if ((sget4(CameraInfo+i) == 257) && ((c = CameraInfo[i+8]) < 3)) {
+ imCanon.MakernotesFlip = "065"[c] - '0';
+// printf ("==>> MakernotesFlip offset: 0x%x, flip: %d\n", i+8, imCanon.MakernotesFlip);
+ break;
+ } else i+=4;
+ }
+
+ if (iHTP)
+ {
+ imCanon.HighlightTonePriority = CameraInfo[iHTP];
+ if ((imCanon.HighlightTonePriority > 5) ||
+ (imCanon.HighlightTonePriority < 0))
+ imCanon.HighlightTonePriority = 0;
+ if (imCanon.HighlightTonePriority) {
+ imCommon.ExposureCalibrationShift -= float(imCanon.HighlightTonePriority);
+ }
+ }
+ if (iALO)
+ {
+ imCanon.AutoLightingOptimizer = CameraInfo[iALO];
+ if ((imCanon.AutoLightingOptimizer > 3) ||
+ (imCanon.AutoLightingOptimizer < 0))
+ imCanon.AutoLightingOptimizer = 3;
+ }
+ if (iCanonFocalType)
+ {
+ if (iCanonFocalType >= maxlen)
+ return; // broken;
+ ilm.FocalType = CameraInfo[iCanonFocalType];
+ if (!ilm.FocalType) // zero means 'prime' here, replacing with standard '1'
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ }
+ if (!ilm.CurFocal && iCanonCurFocal)
+ {
+ if (iCanonCurFocal >= maxlen)
+ return; // broken;
+ ilm.CurFocal = sget2Rev(CameraInfo + iCanonCurFocal);
+ }
+ if (!ilm.LensID && iCanonLensID)
+ {
+ if (iCanonLensID >= maxlen)
+ return; // broken;
+ ilm.LensID = sget2Rev(CameraInfo + iCanonLensID);
+ }
+ if (!ilm.MinFocal && iCanonMinFocal)
+ {
+ if (iCanonMinFocal >= maxlen)
+ return; // broken;
+ ilm.MinFocal = sget2Rev(CameraInfo + iCanonMinFocal);
+ }
+ if (!ilm.MaxFocal && iCanonMaxFocal)
+ {
+ if (iCanonMaxFocal >= maxlen)
+ return; // broken;
+ ilm.MaxFocal = sget2Rev(CameraInfo + iCanonMaxFocal);
+ }
+ if (!ilm.Lens[0] && iCanonLens)
+ {
+ if (iCanonLens + 64 >= (int)maxlen) // broken;
+ return;
+
+ char *pl = (char *)CameraInfo + iCanonLens;
+ if (!strncmp(pl, "EF-S", 4))
+ {
+ memcpy(ilm.Lens, pl, 4);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, pl, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF_S;
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ memcpy(ilm.Lens + 5, pl + 4, 60);
+ }
+ else if (!strncmp(pl, "EF-M", 4))
+ {
+ memcpy(ilm.Lens, pl, 4);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, pl, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF_M;
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ memcpy(ilm.Lens + 5, pl + 4, 60);
+ }
+ else if (!strncmp(pl, "EF", 2))
+ {
+ memcpy(ilm.Lens, pl, 2);
+ ilm.Lens[2] = ' ';
+ memcpy(ilm.LensFeatures_pre, pl, 2);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ memcpy(ilm.Lens + 3, pl + 2, 62);
+ }
+ else if (!strncmp(ilm.Lens, "CN-E", 4))
+ {
+ memmove(ilm.Lens + 5, ilm.Lens + 4, 60);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, ilm.Lens, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ }
+ else if (!strncmp(pl, "TS-E", 4))
+ {
+ memcpy(ilm.Lens, pl, 4);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, pl, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ memcpy(ilm.Lens + 5, pl + 4, 60);
+ }
+ else if (!strncmp(pl, "MP-E", 4))
+ {
+ memcpy(ilm.Lens, pl, 4);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, pl, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ memcpy(ilm.Lens + 5, pl + 4, 60);
+ }
+ else // non-Canon lens
+ memcpy(ilm.Lens, pl, 64);
+ }
+ return;
+}
+
+void LibRaw::Canon_CameraSettings(unsigned len)
+{
+ fseek(ifp, 6, SEEK_CUR);
+ imCanon.Quality = get2(); // 3
+ get2();
+ imgdata.shootinginfo.DriveMode = get2(); // 5
+ get2();
+ imgdata.shootinginfo.FocusMode = get2(); // 7
+ imCanon.RecordMode = (get2(), get2()); // 9, format
+ fseek(ifp, 14, SEEK_CUR);
+ imgdata.shootinginfo.MeteringMode = get2(); // 17
+ get2();
+ imgdata.shootinginfo.AFPoint = get2(); // 19
+ imgdata.shootinginfo.ExposureMode = get2(); // 20
+ get2();
+ ilm.LensID = get2(); // 22
+ ilm.MaxFocal = get2(); // 23
+ ilm.MinFocal = get2(); // 24
+ ilm.FocalUnits = get2(); // 25
+ if (ilm.FocalUnits > 1)
+ {
+ ilm.MaxFocal /= (float)ilm.FocalUnits;
+ ilm.MinFocal /= (float)ilm.FocalUnits;
+ }
+ ilm.MaxAp = _CanonConvertAperture(get2()); // 26
+ ilm.MinAp = _CanonConvertAperture(get2()); // 27
+ if (len >= 36)
+ {
+ fseek(ifp, 12, SEEK_CUR);
+ imgdata.shootinginfo.ImageStabilization = get2(); // 34
+ }
+ else
+ return;
+ if (len >= 48)
+ {
+ fseek(ifp, 22, SEEK_CUR);
+ imCanon.SRAWQuality = get2(); // 46
+ }
+}
+
+void LibRaw::Canon_WBpresets(int skip1, int skip2)
+{
+ int c;
+ FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][RGGB_2_RGBG(c)] = get2();
+
+ if (skip1)
+ fseek(ifp, skip1, SEEK_CUR);
+ FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][RGGB_2_RGBG(c)] = get2();
+
+ if (skip1)
+ fseek(ifp, skip1, SEEK_CUR);
+ FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][RGGB_2_RGBG(c)] = get2();
+
+ if (skip1)
+ fseek(ifp, skip1, SEEK_CUR);
+ FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][RGGB_2_RGBG(c)] = get2();
+
+ if (skip1)
+ fseek(ifp, skip1, SEEK_CUR);
+ FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][RGGB_2_RGBG(c)] = get2();
+
+ if (skip2)
+ fseek(ifp, skip2, SEEK_CUR);
+ FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][RGGB_2_RGBG(c)] = get2();
+
+ return;
+}
+
+void LibRaw::Canon_WBCTpresets(short WBCTversion)
+{
+
+ int i;
+ float norm;
+
+ if (WBCTversion == 0)
+ { // tint, as shot R, as shot B, CСT
+ for (i = 0; i < 15; i++)
+ {
+ icWBCCTC[i][2] = icWBCCTC[i][4] = 1.0f;
+ fseek(ifp, 2, SEEK_CUR);
+ icWBCCTC[i][1] = 1024.0f / fMAX(get2(), 1.f);
+ icWBCCTC[i][3] = 1024.0f / fMAX(get2(), 1.f);
+ icWBCCTC[i][0] = get2();
+ }
+ }
+ else if (WBCTversion == 1)
+ { // as shot R, as shot B, tint, CСT
+ for (i = 0; i < 15; i++)
+ {
+ icWBCCTC[i][2] = icWBCCTC[i][4] = 1.0f;
+ icWBCCTC[i][1] = 1024.0f / fMAX(get2(), 1.f);
+ icWBCCTC[i][3] = 1024.0f / fMAX(get2(), 1.f);
+ fseek(ifp, 2, SEEK_CUR);
+ icWBCCTC[i][0] = get2();
+ }
+ }
+ else if (WBCTversion == 2)
+ { // tint, offset, as shot R, as shot B, CСT
+ if ((unique_id == CanonID_EOS_M3) ||
+ (unique_id == CanonID_EOS_M10) ||
+ (imCanon.ColorDataSubVer == 0xfffc))
+ {
+ for (i = 0; i < 15; i++)
+ {
+ fseek(ifp, 4, SEEK_CUR);
+ icWBCCTC[i][2] = icWBCCTC[i][4] =
+ 1.0f;
+ icWBCCTC[i][1] = 1024.0f / fMAX(1.f, get2());
+ icWBCCTC[i][3] = 1024.0f / fMAX(1.f, get2());
+ icWBCCTC[i][0] = get2();
+ }
+ }
+ else if (imCanon.ColorDataSubVer == 0xfffd)
+ {
+ for (i = 0; i < 15; i++)
+ {
+ fseek(ifp, 2, SEEK_CUR);
+ norm = (signed short)get2();
+ norm = 512.0f + norm / 8.0f;
+ icWBCCTC[i][2] = icWBCCTC[i][4] =
+ 1.0f;
+ icWBCCTC[i][1] = (float)get2();
+ if (norm > 0.001f)
+ icWBCCTC[i][1] /= norm;
+ icWBCCTC[i][3] = (float)get2();
+ if (norm > 0.001f)
+ icWBCCTC[i][3] /= norm;
+ icWBCCTC[i][0] = get2();
+ }
+ }
+ }
+ return;
+}
+
+void LibRaw::parseCanonMakernotes(unsigned tag, unsigned /*type*/, unsigned len, unsigned dng_writer)
+{
+
+#define AsShot_Auto_MeasuredWB(offset) \
+ imCanon.ColorDataSubVer = get2(); \
+ fseek(ifp, save1 + (offset << 1), SEEK_SET); \
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = (float)get2(); \
+ get2(); \
+ FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2(); \
+ get2(); \
+ FORC4 icWBC[LIBRAW_WBI_Measured][RGGB_2_RGBG(c)] = get2();
+
+#define sRAW_WB(offset) \
+ fseek(ifp, save1 + (offset << 1), SEEK_SET); \
+ FORC4 { \
+ sraw_mul[RGGB_2_RGBG(c)] = get2(); \
+ if ((float)sraw_mul[RGGB_2_RGBG(c)] > sraw_mul_max) { \
+ sraw_mul_max = (float)sraw_mul[RGGB_2_RGBG(c)]; \
+ } \
+ } \
+ sraw_mul_max /= 1024.f; \
+ FORC4 sraw_mul[c] = (ushort)((float)sraw_mul[c] * sraw_mul_max);
+
+#define CR3_ColorData(offset) \
+ fseek(ifp, save1 + ((offset+0x0041) << 1), SEEK_SET); \
+ Canon_WBpresets(2, 12); \
+ fseek(ifp, save1 + ((offset+0x00c3) << 1), SEEK_SET); \
+ Canon_WBCTpresets(0); \
+ offsetChannelBlackLevel2 = save1 + ((offset+0x0102) << 1); \
+ offsetChannelBlackLevel = save1 + ((offset+0x02d1) << 1); \
+ offsetWhiteLevels = save1 + ((offset+0x02d5) << 1);
+
+ int c;
+ unsigned i;
+
+ if (tag == 0x0001) {
+ Canon_CameraSettings(len);
+
+ } else if (tag == 0x0002) { // focal length
+ ilm.FocalType = get2();
+ ilm.CurFocal = get2();
+ if (ilm.FocalUnits > 1) {
+ ilm.CurFocal /= (float)ilm.FocalUnits;
+ }
+
+ } else if (tag == 0x0004) { // subdir, ShotInfo
+ short tempAp;
+ if (dng_writer == nonDNG) {
+ get2();
+ imCanon.ISOgain[0] = get2();
+ imCanon.ISOgain[1] = get2();
+ if (imCanon.ISOgain[1] != 0x7fff) {
+ imCommon.real_ISO = floorf(100.f * libraw_powf64l(2.f, float(imCanon.ISOgain[0]+imCanon.ISOgain[1]) / 32.f - 5.f));
+ if (!iso_speed || (iso_speed == 65535))
+ iso_speed = imCommon.real_ISO;
+ }
+ get4();
+ if (((i = get2()) != 0xffff) && !shutter) {
+ shutter = libraw_powf64l(2.f, float((short)i) / -32.0f);
+ }
+ imCanon.wbi = (get2(), get2());
+ shot_order = (get2(), get2());
+ fseek(ifp, 4, SEEK_CUR);
+ } else
+ fseek(ifp, 24, SEEK_CUR);
+ tempAp = get2();
+ if (tempAp != 0)
+ imCommon.CameraTemperature = (float)(tempAp - 128);
+ tempAp = get2();
+ if (tempAp != -1)
+ imCommon.FlashGN = ((float)tempAp) / 32;
+ get2();
+
+ imCommon.FlashEC = _CanonConvertEV((signed short)get2());
+ fseek(ifp, 8 - 32, SEEK_CUR);
+ if ((tempAp = get2()) != 0x7fff)
+ ilm.CurAp = _CanonConvertAperture(tempAp);
+ if (ilm.CurAp < 0.7f) {
+ fseek(ifp, 32, SEEK_CUR);
+ ilm.CurAp = _CanonConvertAperture(get2());
+ }
+ if (!aperture)
+ aperture = ilm.CurAp;
+
+ } else if ((tag == 0x0007) && (dng_writer == nonDNG)) {
+ fgets(model2, 64, ifp);
+
+ } else if ((tag == 0x0008) && (dng_writer == nonDNG)) {
+ shot_order = get4();
+
+ } else if ((tag == 0x0009) && (dng_writer == nonDNG)) {
+ fread(artist, 64, 1, ifp);
+
+ } else if (tag == 0x000c) {
+ unsigned tS = get4();
+ sprintf(imgdata.shootinginfo.BodySerial, "%d", tS);
+
+ } else if ((tag == 0x0012) ||
+ (tag == 0x0026) ||
+ (tag == 0x003c)) {
+ if (!imCommon.afcount) {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ fread(imCommon.afdata[imCommon.afcount].AFInfoData, imCommon.afdata[imCommon.afcount].AFInfoData_length, 1, ifp);
+ imCommon.afcount = 1;
+ }
+
+ } else if ((tag == 0x0029) && (dng_writer == nonDNG)) { // PowerShot G9
+ int Got_AsShotWB = 0;
+ fseek(ifp, 8, SEEK_CUR);
+ for (unsigned linenum = 0; linenum < Canon_G9_linenums_2_StdWBi.size(); linenum++) {
+ if (Canon_G9_linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown ) {
+ FORC4 icWBC[Canon_G9_linenums_2_StdWBi[linenum]][GRBG_2_RGBG(c)] = get4();
+ if (Canon_wbi2std[imCanon.wbi] == Canon_G9_linenums_2_StdWBi[linenum]) {
+ FORC4 cam_mul[c] = float(icWBC[Canon_G9_linenums_2_StdWBi[linenum]][c]);
+ Got_AsShotWB = 1;
+ }
+ }
+ fseek(ifp, 16, SEEK_CUR);
+ }
+ if (!Got_AsShotWB)
+ FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
+
+ } else if ((tag == 0x0081) && (dng_writer == nonDNG)) { // -1D, -1Ds
+ data_offset = get4();
+ fseek(ifp, data_offset + 41, SEEK_SET);
+ raw_height = get2() * 2;
+ raw_width = get2();
+ filters = 0x61616161;
+
+ } else if (tag == 0x0093) {
+ if (!imCanon.RF_lensID) {
+ fseek(ifp, 0x03d<<1, SEEK_CUR);
+ imCanon.RF_lensID = get2();
+ }
+
+ } else if (tag == 0x0095 && !ilm.Lens[0])
+ { // lens model tag
+ fread(ilm.Lens, 64, 1, ifp);
+ if (!strncmp(ilm.Lens, "EF-S", 4))
+ {
+ memmove(ilm.Lens + 5, ilm.Lens + 4, 60);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, ilm.Lens, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF_S;
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ }
+ else if (!strncmp(ilm.Lens, "EF-M", 4))
+ {
+ memmove(ilm.Lens + 5, ilm.Lens + 4, 60);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, ilm.Lens, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF_M;
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ }
+ else if (!strncmp(ilm.Lens, "EF", 2))
+ {
+ memmove(ilm.Lens + 3, ilm.Lens + 2, 62);
+ ilm.Lens[2] = ' ';
+ memcpy(ilm.LensFeatures_pre, ilm.Lens, 2);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ }
+ else if (!strncmp(ilm.Lens, "CN-E", 4))
+ {
+ memmove(ilm.Lens + 5, ilm.Lens + 4, 60);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, ilm.Lens, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ }
+ else if (!strncmp(ilm.Lens, "TS-E", 4))
+ {
+ memmove(ilm.Lens + 5, ilm.Lens + 4, 60);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, ilm.Lens, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ }
+ else if (!strncmp(ilm.Lens, "MP-E", 4))
+ {
+ memmove(ilm.Lens + 5, ilm.Lens + 4, 60);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, ilm.Lens, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ }
+
+ else if (!strncmp(ilm.Lens, "RF-S", 4))
+ {
+ memmove(ilm.Lens + 5, ilm.Lens + 4, 62);
+ ilm.Lens[4] = ' ';
+ memcpy(ilm.LensFeatures_pre, ilm.Lens, 4);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_RF;
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ }
+
+ else if (!strncmp(ilm.Lens, "RF", 2))
+ {
+ memmove(ilm.Lens + 3, ilm.Lens + 2, 62);
+ ilm.Lens[2] = ' ';
+ memcpy(ilm.LensFeatures_pre, ilm.Lens, 2);
+ ilm.LensMount = LIBRAW_MOUNT_Canon_RF;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ }
+ }
+ else if (tag == 0x009a)
+ { // AspectInfo
+ i = get4();
+ switch (i)
+ {
+ case 0:
+ case 12: /* APS-H crop */
+ case 13: /* APS-C crop */
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
+ break;
+ case 1:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_1to1;
+ break;
+ case 2:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_4to3;
+ break;
+ case 7:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_16to9;
+ break;
+ case 8:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_5to4;
+ break;
+ default:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_OTHER;
+ break;
+ }
+ imgdata.sizes.raw_inset_crops[0].cwidth = get4();
+ imgdata.sizes.raw_inset_crops[0].cheight = get4();
+ imgdata.sizes.raw_inset_crops[0].cleft = get4();
+ imgdata.sizes.raw_inset_crops[0].ctop = get4();
+
+ } else if ((tag == 0x00a4) && (dng_writer == nonDNG)) { // -1D, -1Ds
+ fseek(ifp, imCanon.wbi * 48, SEEK_CUR);
+ FORC3 cam_mul[c] = get2();
+
+ } else if (tag == 0x00a9) {
+ INT64 save1 = ftell(ifp);
+ fseek(ifp, (0x1 << 1), SEEK_CUR);
+ FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2();
+ Canon_WBpresets(0, 0);
+ fseek(ifp, save1, SEEK_SET);
+ }
+ else if (tag == 0x00b4)
+ {
+ switch (get2()) {
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 2:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ }
+ else if (tag == 0x00e0) // SensorInfo
+ {
+ imCanon.SensorWidth = (get2(), get2());
+ imCanon.SensorHeight = get2();
+ fseek(ifp, 4, SEEK_CUR);
+ imCanon.DefaultCropAbsolute = get_CanonArea();
+ imCanon.LeftOpticalBlack = get_CanonArea();
+ }
+ else if (tag == 0x4001 && len > 500)
+ {
+ float sraw_mul_max = 0.f;
+ int bls = 0;
+ INT64 offsetChannelBlackLevel = 0L;
+ INT64 offsetChannelBlackLevel2 = 0L;
+ INT64 offsetWhiteLevels = 0L;
+ INT64 save1 = ftell(ifp);
+
+ switch (len)
+ {
+
+ case 582:
+ imCanon.ColorDataVer = 1; // 20D, 350D
+
+ fseek(ifp, save1 + (0x0019 << 1), SEEK_SET);
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = (float)get2();
+ fseek(ifp, save1 + (0x001e << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, save1 + (0x0041 << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Custom1][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, save1 + (0x0046 << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Custom2][RGGB_2_RGBG(c)] = get2();
+
+ fseek(ifp, save1 + (0x0023 << 1), SEEK_SET);
+ Canon_WBpresets(2, 2);
+ fseek(ifp, save1 + (0x004b << 1), SEEK_SET);
+ Canon_WBCTpresets(1); // ABCT
+ offsetChannelBlackLevel = save1 + (0x00a6 << 1);
+ break;
+
+ case 653:
+ imCanon.ColorDataVer = 2; // -1D Mark II, -1Ds Mark II
+
+ fseek(ifp, save1 + (0x0018 << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, save1 + (0x0022 << 1), SEEK_SET);
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = (float)get2();
+ fseek(ifp, save1 + (0x0090 << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Custom1][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, save1 + (0x0095 << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Custom2][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, save1 + (0x009a << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Custom3][RGGB_2_RGBG(c)] = get2();
+
+ fseek(ifp, save1 + (0x0027 << 1), SEEK_SET);
+ Canon_WBpresets(2, 12);
+ fseek(ifp, save1 + (0x00a4 << 1), SEEK_SET);
+ Canon_WBCTpresets(1); // ABCT
+ offsetChannelBlackLevel = save1 + (0x011e << 1);
+ break;
+
+ case 796:
+ imCanon.ColorDataVer = 3; // -1D Mark II N, 5D, 30D, 400D; ColorDataSubVer: 1
+ AsShot_Auto_MeasuredWB(0x003f);
+
+ fseek(ifp, save1 + (0x0071 << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Custom1][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, save1 + (0x0076 << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Custom2][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, save1 + (0x007b << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Custom3][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, save1 + (0x0080 << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Custom][RGGB_2_RGBG(c)] = get2();
+
+ fseek(ifp, save1 + (0x004e << 1), SEEK_SET);
+ Canon_WBpresets(2, 12);
+ fseek(ifp, save1 + (0x0085 << 1), SEEK_SET);
+ Canon_WBCTpresets(0); // BCAT
+ offsetChannelBlackLevel = save1 + (0x00c4 << 1);
+ break;
+
+ case 674: // -1D Mark III; ColorDataSubVer: 2
+ case 692: // 40D; ColorDataSubVer: 3
+ case 702: // -1Ds Mark III; ColorDataSubVer: 4
+ case 1227: // 450D, 1000D; ColorDataSubVer: 5
+ case 1250: // 5D Mark II, 50D; ColorDataSubVer: 6
+ case 1251: // 500D; ColorDataSubVer: 7
+ case 1337: // -1D Mark IV, 7D; ColorDataSubVer: 7
+ case 1338: // 550D; ColorDataSubVer: 7
+ case 1346: // 1100D, 60D; ColorDataSubVer: 9
+ imCanon.ColorDataVer = 4;
+ AsShot_Auto_MeasuredWB(0x003f);
+ sRAW_WB(0x004e);
+ fseek(ifp, save1 + (0x0053 << 1), SEEK_SET);
+ Canon_WBpresets(2, 12);
+ fseek(ifp, save1 + (0x00a8 << 1), SEEK_SET);
+ Canon_WBCTpresets(0); // BCAT
+
+ if ((imCanon.ColorDataSubVer == 4) ||
+ (imCanon.ColorDataSubVer == 5))
+ {
+ offsetChannelBlackLevel = save1 + (0x02b4 << 1);
+ offsetWhiteLevels = save1 + (0x02b8 << 1);
+ }
+ else if ((imCanon.ColorDataSubVer == 6) ||
+ (imCanon.ColorDataSubVer == 7))
+ {
+ offsetChannelBlackLevel = save1 + (0x02cb << 1);
+ offsetWhiteLevels = save1 + (0x02cf << 1);
+ }
+ else if (imCanon.ColorDataSubVer == 9)
+ {
+ offsetChannelBlackLevel = save1 + (0x02cf << 1);
+ offsetWhiteLevels = save1 + (0x02d3 << 1);
+ }
+ else
+ offsetChannelBlackLevel = save1 + (0x00e7 << 1);
+ break;
+
+ case 5120: // G10, G11, G12, G15, G16
+ // G1 X, G1 X Mark II, G1 X Mark III
+ // G3 X, G5 X
+ // G7 X, G7 X Mark II
+ // G9 X, G9 X Mark II
+ // S90, S95, S100, S100V, S110, S120
+ // SX1 IS, SX50 HS, SX60 HS
+ // M3, M5, M6, M10, M100
+ imCanon.ColorDataVer = 5;
+ imCanon.ColorDataSubVer = get2();
+
+ fseek(ifp, save1 + (0x0047 << 1), SEEK_SET);
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = (float)get2();
+
+ if (imCanon.ColorDataSubVer == 0xfffc) // ColorDataSubVer: 65532 (-4)
+ // G7 X Mark II, G9 X Mark II, G1 X Mark III
+ // M5, M100, M6
+ {
+ fseek(ifp, save1 + (0x004f << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, 8, SEEK_CUR);
+ FORC4 icWBC[LIBRAW_WBI_Measured][RGGB_2_RGBG(c)] =
+ get2();
+ fseek(ifp, 8, SEEK_CUR);
+ FORC4 icWBC[LIBRAW_WBI_Other][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, 8, SEEK_CUR);
+ Canon_WBpresets(8, 24);
+ fseek(ifp, 168, SEEK_CUR);
+ FORC4 icWBC[LIBRAW_WBI_FL_WW][RGGB_2_RGBG(c)] = get2();
+ fseek(ifp, 24, SEEK_CUR);
+ Canon_WBCTpresets(2); // BCADT
+ offsetChannelBlackLevel = save1 + (0x014d << 1);
+ offsetWhiteLevels = save1 + (0x0569 << 1);
+ }
+ else if (imCanon.ColorDataSubVer == 0xfffd) // ColorDataSubVer: 65533 (-3)
+ // M10, M3
+ // G1 X, G1 X Mark II
+ // G3 X, G5 X, G7 X, G9 X
+ // G10, G11, G12, G15, G16
+ // S90, S95, S100, S100V, S110, S120
+ // SX1 IS, SX50 HS, SX60 HS
+ {
+ fseek(ifp, save1 + (0x004c << 1), SEEK_SET);
+ FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2();
+ get2();
+ FORC4 icWBC[LIBRAW_WBI_Measured][RGGB_2_RGBG(c)] =
+ get2();
+ get2();
+ FORC4 icWBC[LIBRAW_WBI_Other][RGGB_2_RGBG(c)] = get2();
+ get2();
+ Canon_WBpresets(2, 12);
+ fseek(ifp, save1 + (0x00ba << 1), SEEK_SET);
+ Canon_WBCTpresets(2); // BCADT
+ offsetChannelBlackLevel = save1 + (0x0108 << 1);
+ }
+ break;
+
+ case 1273: // 600D; ColorDataSubVer: 10
+ case 1275: // 1200D; ColorDataSubVer: 10
+ imCanon.ColorDataVer = 6;
+ AsShot_Auto_MeasuredWB(0x003f);
+ sRAW_WB(0x0062);
+ fseek(ifp, save1 + (0x0067 << 1), SEEK_SET);
+ Canon_WBpresets(2, 12);
+ fseek(ifp, save1 + (0x00bc << 1), SEEK_SET);
+ Canon_WBCTpresets(0); // BCAT
+ offsetChannelBlackLevel = save1 + (0x01df << 1);
+ offsetWhiteLevels = save1 + (0x01e3 << 1);
+ break;
+
+ case 1312: // 5D Mark III, 650D, 700D, M; ColorDataSubVer: 10
+ case 1313: // 100D, 6D, 70D, EOS M2; ColorDataSubVer: 10
+ case 1316: // -1D C, -1D X; ColorDataSubVer: 10
+ case 1506: // 750D, 760D, 7D Mark II; ColorDataSubVer: 11
+ imCanon.ColorDataVer = 7;
+ AsShot_Auto_MeasuredWB(0x003f);
+ sRAW_WB(0x007b);
+ fseek(ifp, save1 + (0x0080 << 1), SEEK_SET);
+ Canon_WBpresets(2, 12);
+ fseek(ifp, save1 + (0x00d5 << 1), SEEK_SET);
+ Canon_WBCTpresets(0); // BCAT
+
+ if (imCanon.ColorDataSubVer == 10)
+ {
+ offsetChannelBlackLevel = save1 + (0x01f8 << 1);
+ offsetWhiteLevels = save1 + (0x01fc << 1);
+ }
+ else if (imCanon.ColorDataSubVer == 11)
+ {
+ offsetChannelBlackLevel = save1 + (0x02d8 << 1);
+ offsetWhiteLevels = save1 + (0x02dc << 1);
+ }
+ break;
+
+ case 1560: // 5DS, 5DS R; ColorDataSubVer: 12
+ case 1592: // 5D Mark IV, 80D, -1D X Mark II; ColorDataSubVer: 13
+ case 1353: // 1300D, 1500D, 3000D; ColorDataSubVer: 14
+ case 1602: // 200D, 6D Mark II, 77D, 800D; ColorDataSubVer: 15
+ imCanon.ColorDataVer = 8;
+ AsShot_Auto_MeasuredWB(0x003f);
+ sRAW_WB(0x0080);
+ fseek(ifp, save1 + (0x0085 << 1), SEEK_SET);
+ Canon_WBpresets(2, 12);
+ fseek(ifp, save1 + (0x0107 << 1), SEEK_SET);
+ Canon_WBCTpresets(0); // BCAT
+
+ if (imCanon.ColorDataSubVer == 14) // 1300D, 1500D, 3000D
+ {
+ offsetChannelBlackLevel = save1 + (0x022c << 1);
+ offsetWhiteLevels = save1 + (0x0230 << 1);
+ }
+ else
+ {
+ offsetChannelBlackLevel = save1 + (0x030a << 1);
+ offsetWhiteLevels = save1 + (0x030e << 1);
+ }
+ break;
+
+ case 1820: // M50; ColorDataSubVer: 16
+ case 1824: // R; ColorDataSubVer: 17
+ case 1816: // RP, 250D, SX70 HS; ColorDataSubVer: 18
+ // M6 Mark II, M200, 90D, G5 X Mark II, G7 X Mark III, 850D; ColorDataSubVer: 19
+ imCanon.ColorDataVer = 9;
+ AsShot_Auto_MeasuredWB(0x0047);
+ CR3_ColorData(0x0047);
+ break;
+
+ case 1770: // R5 CRM
+ case 2024: // -1D X Mark III; ColorDataSubVer: 32
+ case 3656: // R5, R6; ColorDataSubVer: 33
+ imCanon.ColorDataVer = 10;
+ AsShot_Auto_MeasuredWB(0x0055);
+ CR3_ColorData(0x0055);
+ break;
+
+ case 3973: // R3; ColorDataSubVer: 34
+ case 3778: // R7, R10; ColorDataSubVer: 48
+ imCanon.ColorDataVer = 11;
+ AsShot_Auto_MeasuredWB(0x0069);
+
+ fseek(ifp, save1 + ((0x0069+0x0064) << 1), SEEK_SET);
+ Canon_WBpresets(2, 12);
+ fseek(ifp, save1 + ((0x0069+0x00c3) << 1), SEEK_SET);
+ Canon_WBCTpresets(0);
+ offsetChannelBlackLevel2 = save1 + ((0x0069+0x0102) << 1);
+ offsetChannelBlackLevel = save1 + ((0x0069+0x0213) << 1);
+ offsetWhiteLevels = save1 + ((0x0069+0x0217) << 1);
+ break;
+
+ default:
+ imCanon.ColorDataSubVer = get2();
+ break;
+ }
+
+ if (offsetChannelBlackLevel)
+ {
+ fseek(ifp, offsetChannelBlackLevel, SEEK_SET);
+ FORC4
+ bls += (imCanon.ChannelBlackLevel[RGGB_2_RGBG(c)] = get2());
+ imCanon.AverageBlackLevel = bls / 4;
+ }
+ if (offsetWhiteLevels)
+ {
+ if ((offsetWhiteLevels - offsetChannelBlackLevel) != 8L)
+ fseek(ifp, offsetWhiteLevels, SEEK_SET);
+ imCanon.NormalWhiteLevel = get2();
+ imCanon.SpecularWhiteLevel = get2();
+ FORC4
+ imgdata.color.linear_max[c] = imCanon.SpecularWhiteLevel;
+ }
+
+ if(!imCanon.AverageBlackLevel && offsetChannelBlackLevel2)
+ {
+ fseek(ifp, offsetChannelBlackLevel2, SEEK_SET);
+ FORC4
+ bls += (imCanon.ChannelBlackLevel[RGGB_2_RGBG(c)] = get2());
+ imCanon.AverageBlackLevel = bls / 4;
+ }
+ fseek(ifp, save1, SEEK_SET);
+
+ } else if (tag == 0x4013) {
+ get4();
+ imCanon.AFMicroAdjMode = get4();
+ float a = float(get4());
+ float b = float(get4());
+ if (fabsf(b) > 0.001f)
+ imCanon.AFMicroAdjValue = a / b;
+
+ } else if (tag == 0x4018) {
+ fseek(ifp, 8, SEEK_CUR);
+ imCanon.AutoLightingOptimizer = get4();
+ if ((imCanon.AutoLightingOptimizer > 3) ||
+ (imCanon.AutoLightingOptimizer < 0))
+ imCanon.AutoLightingOptimizer = 3;
+ imCanon.HighlightTonePriority = get4();
+ if ((imCanon.HighlightTonePriority > 5) ||
+ (imCanon.HighlightTonePriority < 0))
+ imCanon.HighlightTonePriority = 0;
+ if (imCanon.HighlightTonePriority) {
+ imCommon.ExposureCalibrationShift -= float(imCanon.HighlightTonePriority);
+ }
+
+ } else if ((tag == 0x4021) && (dng_writer == nonDNG) &&
+ (imCanon.multishot[0] = get4()) &&
+ (imCanon.multishot[1] = get4())) {
+ if (len >= 4) {
+ imCanon.multishot[2] = get4();
+ imCanon.multishot[3] = get4();
+ }
+ FORC4 cam_mul[c] = 1024;
+ } else if (tag == 0x4026) {
+ fseek(ifp, 44, SEEK_CUR);
+ imCanon.CanonLog = get4();
+ }
+#undef CR3_ColorData
+#undef sRAW_WB
+#undef AsShot_Auto_MeasuredWB
+}
diff --git a/libkdcraw/libraw/src/metadata/ciff.cpp b/libkdcraw/libraw/src/metadata/ciff.cpp
new file mode 100644
index 0000000..2c59b11
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/ciff.cpp
@@ -0,0 +1,411 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+#ifdef _MSC_VER
+#if _MSC_VER < 1800 /* below MSVC 2013 */
+float roundf(float f)
+{
+ return floorf(f + 0.5);
+}
+
+#endif
+#endif
+
+/*
+ CIFF block 0x1030 contains an 8x8 white sample.
+ Load this into white[][] for use in scale_colors().
+ */
+void LibRaw::ciff_block_1030()
+{
+ static const ushort key[] = {0x410, 0x45f3};
+ int i, bpp, row, col, vbits = 0;
+ unsigned long bitbuf = 0;
+
+ if ((get2(), get4()) != 0x80008 || !get4())
+ return;
+ bpp = get2();
+ if (bpp != 10 && bpp != 12)
+ return;
+ for (i = row = 0; row < 8; row++)
+ for (col = 0; col < 8; col++)
+ {
+ if (vbits < bpp)
+ {
+ bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
+ vbits += 16;
+ }
+ white[row][col] = bitbuf >> (vbits -= bpp) & ~(-1 << bpp);
+ }
+}
+
+/*
+ Parse a CIFF file, better known as Canon CRW format.
+ */
+void LibRaw::parse_ciff(int offset, int length, int depth)
+{
+ int nrecs, c, type, len, wbi = -1;
+ INT64 save, tboff;
+ ushort key[] = {0x410, 0x45f3};
+ ushort CanonColorInfo1_key;
+ ushort Appendix_A = 0;
+ INT64 WB_table_offset = 0;
+ int UseWBfromTable_as_AsShot = 1;
+ int Got_AsShotWB = 0;
+ INT64 fsize = ifp->size();
+ if (metadata_blocks++ > LIBRAW_MAX_METADATA_BLOCKS)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ fseek(ifp, offset + length - 4, SEEK_SET);
+ tboff = INT64(get4()) + offset;
+ fseek(ifp, tboff, SEEK_SET);
+ nrecs = get2();
+ if (nrecs < 1)
+ return;
+ if ((nrecs | depth) > 127)
+ return;
+
+ if (nrecs * 10 + offset > fsize)
+ return;
+
+ while (nrecs--)
+ {
+ type = get2();
+ len = get4();
+ INT64 see = offset + get4();
+ save = ftell(ifp);
+
+ /* the following tags are not sub-tables
+ * they contain the value in the "len" field
+ * for such tags skip the check against filesize
+ */
+ if ((type != 0x2007) && (type != 0x580b) && (type != 0x501c) &&
+ (type != 0x5029) && (type != 0x5813) && (type != 0x5814) &&
+ (type != 0x5817) && (type != 0x5834) && (type != 0x580e))
+ {
+
+ if (see >= fsize)
+ { // At least one byte
+ fseek(ifp, save, SEEK_SET);
+ continue;
+ }
+ fseek(ifp, see, SEEK_SET);
+ if ((((type >> 8) + 8) | 8) == 0x38)
+ {
+ parse_ciff(ftell(ifp), len, depth + 1); /* Parse a sub-table */
+ }
+ }
+
+ if (type == 0x3004)
+ {
+ parse_ciff(ftell(ifp), len, depth + 1);
+ }
+ else if (type == 0x0810)
+ {
+ fread(artist, 64, 1, ifp);
+ }
+ else if (type == 0x080a)
+ {
+ fread(make, 64, 1, ifp);
+ fseek(ifp, strbuflen(make) - 63, SEEK_CUR);
+ fread(model, 64, 1, ifp);
+
+ } else if (type == 0x080b) {
+ stmread(imCommon.firmware, (unsigned)len, ifp);
+ if (!strncasecmp(imCommon.firmware, "Firmware Version", 16))
+ memmove(imCommon.firmware, imCommon.firmware + 16, strlen(imCommon.firmware) - 15);
+ trimSpaces(imCommon.firmware);
+
+ } else if (type == 0x1810)
+ {
+ width = get4();
+ height = get4();
+ pixel_aspect = int_to_float(get4());
+ flip = get4();
+ }
+ else if (type == 0x1835)
+ { /* Get the decoder table */
+ tiff_compress = get4();
+ }
+ else if (type == 0x2007)
+ {
+ thumb_offset = see;
+ thumb_length = len;
+ }
+ else if (type == 0x1818)
+ {
+ shutter = libraw_powf64l(2.0f, -int_to_float((get4(), get4())));
+ ilm.CurAp = aperture = libraw_powf64l(2.0f, int_to_float(get4()) / 2);
+ }
+ else if (type == 0x102a) // CanonShotInfo
+ {
+ // iso_speed = pow (2.0, (get4(),get2())/32.0 - 4) * 50;
+ get2(); // skip one
+ iso_speed =
+ libraw_powf64l(2.0f, (get2() + get2()) / 32.0f - 5.0f) * 100.0f;
+ ilm.CurAp = aperture = _CanonConvertAperture((get2(), get2()));
+ shutter = libraw_powf64l(2.0f, -float((short)get2()) / 32.f);
+ imCanon.wbi = wbi = (get2(), get2());
+ if (wbi >= (int)Canon_wbi2std.size())
+ wbi = 0;
+ fseek(ifp, 32, SEEK_CUR);
+ if (shutter > 1e6)
+ shutter = float(get2()) / 10.f;
+ }
+ else if (type == 0x102c) // CanonColorInfo2 / Appendix A: Pro90IS, G1, G2, S30, S40
+ {
+ int CanonColorInfo2_type = get2(); // G1 1028, G2 272, Pro90 IS 769, S30 274, S40 273, EOS D30 276
+ if (CanonColorInfo2_type > 512) { /* Pro90 IS, G1 */
+ fseek(ifp, 118, SEEK_CUR);
+ FORC4 cam_mul[BG2RG1_2_RGBG(c)] = get2();
+ }
+ else if (CanonColorInfo2_type != 276) { /* G2, S30, S40 */
+ Appendix_A = 1;
+ WB_table_offset = -14;
+ fseek(ifp, 98, SEEK_CUR);
+ FORC4 cam_mul[GRBG_2_RGBG(c)] = get2();
+ if (cam_mul[0] > 0.001f) Got_AsShotWB = 1;
+ }
+ }
+ else if (type == 0x10a9) // ColorBalance: Canon D60, 10D, 300D, and clones
+ {
+ int bls = 0;
+/*
+ int table[] = {
+ LIBRAW_WBI_Auto, // 0
+ LIBRAW_WBI_Daylight, // 1
+ LIBRAW_WBI_Cloudy, // 2
+ LIBRAW_WBI_Tungsten, // 3
+ LIBRAW_WBI_FL_W, // 4
+ LIBRAW_WBI_Flash, // 5
+ LIBRAW_WBI_Custom, // 6, absent in Canon D60
+ LIBRAW_WBI_Auto, // 7, use this if camera is set to b/w JPEG
+ LIBRAW_WBI_Shade, // 8
+ LIBRAW_WBI_Kelvin // 9, absent in Canon D60
+ };
+*/
+ int nWB =
+ ((get2() - 2) / 8) -
+ 1; // 2 bytes this, N recs 4*2bytes each, last rec is black level
+ if (nWB)
+ FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2();
+ if (nWB >= 7)
+ Canon_WBpresets(0, 0);
+ else
+ FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
+ if (nWB == 7) // mostly Canon EOS D60 + some fw#s for 300D;
+ // check for 0x1668000 is unreliable
+ {
+ if ((wbi >= 0) && (wbi < 9) && (wbi != 6))
+ {
+ FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]);
+ }
+ else
+ {
+ FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
+ }
+ }
+ else if (nWB == 9) // Canon 10D, 300D
+ {
+ FORC4 icWBC[LIBRAW_WBI_Custom][RGGB_2_RGBG(c)] = get2();
+ FORC4 icWBC[LIBRAW_WBI_Kelvin][RGGB_2_RGBG(c)] = get2();
+ if ((wbi >= 0) && (wbi < 10))
+ {
+ FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]);
+ }
+ else
+ {
+ FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
+ }
+ }
+ FORC4
+ bls += (imCanon.ChannelBlackLevel[RGGB_2_RGBG(c)] = get2());
+ imCanon.AverageBlackLevel = bls / 4;
+ }
+ else if (type == 0x102d)
+ {
+ Canon_CameraSettings(len >> 1);
+ }
+
+ else if (type == 0x10b4) {
+ switch (get2()) {
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 2:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+
+ } else if (type == 0x580b)
+ {
+ if (strcmp(model, "Canon EOS D30"))
+ sprintf(imgdata.shootinginfo.BodySerial, "%d", len);
+ else
+ sprintf(imgdata.shootinginfo.BodySerial, "%0x-%05d", len >> 16,
+ len & 0xffff);
+ }
+ else if (type == 0x0032) // CanonColorInfo1
+ {
+ if (len == 768) { // EOS D30
+
+ ushort q;
+ fseek(ifp, 4, SEEK_CUR);
+ for (unsigned linenum = 0; linenum < Canon_D30_linenums_2_StdWBi.size(); linenum++) {
+ if (Canon_D30_linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) {
+ FORC4 {
+ q = get2();
+ icWBC[Canon_D30_linenums_2_StdWBi[linenum]][RGGB_2_RGBG(c)] =
+ (int)(roundf(1024000.0f / (float)MAX(1, q)));
+ }
+// if (Canon_wbi2std[imCanon.wbi] == *(Canon_D30_linenums_2_StdWBi + linenum)) {
+// FORC4 cam_mul[c] = icWBC[*(Canon_D30_linenums_2_StdWBi + linenum)][c];
+// Got_AsShotWB = 1;
+// }
+ }
+ }
+ fseek (ifp, 68-int(Canon_D30_linenums_2_StdWBi.size())*8, SEEK_CUR);
+
+ FORC4 {
+ q = get2();
+ cam_mul[RGGB_2_RGBG(c)] = 1024.f / float(MAX(1, q));
+ }
+ if (!wbi)
+ cam_mul[0] = -1; // use my auto white balance
+
+ }
+ else if ((cam_mul[0] <= 0.001f) || // Pro1, G3, G5, G6, S45, S50, S60, S70
+ Appendix_A) // G2, S30, S40
+ {
+ libraw_static_table_t linenums_2_StdWBi;
+ unsigned AsShotWB_linenum = Canon_wbi2std.size();
+
+ CanonColorInfo1_key = get2();
+ if ((CanonColorInfo1_key == key[0]) && (len == 2048)) { // Pro1
+ linenums_2_StdWBi = Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi;
+ WB_table_offset = 8;
+
+ } else if ((CanonColorInfo1_key == key[0]) && (len == 3072)) { // S60, S70, G6
+ linenums_2_StdWBi = Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi;
+ WB_table_offset = 16;
+
+ } else if (!CanonColorInfo1_key && (len == 2048)) { // G2, S30, S40; S45, S50, G3, G5
+ key[0] = key[1] = 0;
+ linenums_2_StdWBi = Canon_KeyIsZero_Len2048_linenums_2_StdWBi;
+ if (atof(imCommon.firmware) < 1.02f)
+ UseWBfromTable_as_AsShot = 0;
+
+ } else goto next_tag;
+
+ if ((Canon_wbi2std[wbi] == LIBRAW_WBI_Auto) ||
+ (Canon_wbi2std[wbi] == LIBRAW_WBI_Unknown) ||
+ Got_AsShotWB)
+ UseWBfromTable_as_AsShot = 0;
+
+ if (UseWBfromTable_as_AsShot) {
+ int temp_wbi;
+ if (Canon_wbi2std[wbi] == LIBRAW_WBI_Custom) temp_wbi = LIBRAW_WBI_Daylight;
+ else temp_wbi = wbi;
+ for (AsShotWB_linenum = 0; AsShotWB_linenum < linenums_2_StdWBi.size(); AsShotWB_linenum++) {
+ if (Canon_wbi2std[temp_wbi] == linenums_2_StdWBi[AsShotWB_linenum]) {
+ break;
+ }
+ }
+ }
+
+ fseek (ifp, 78LL+WB_table_offset, SEEK_CUR);
+ for (unsigned linenum = 0; linenum < linenums_2_StdWBi.size(); linenum++) {
+ if (linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) {
+ FORC4 icWBC[linenums_2_StdWBi[linenum]][GRBG_2_RGBG(c)] = get2() ^ key[c & 1];
+ if (UseWBfromTable_as_AsShot && (AsShotWB_linenum == linenum)) {
+ FORC4 cam_mul[c] = float(icWBC[linenums_2_StdWBi[linenum]][c]);
+ Got_AsShotWB = 1;
+ }
+ } else {
+ fseek(ifp, 8, SEEK_CUR);
+ }
+ }
+ if (!Got_AsShotWB)
+ cam_mul[0] = -1;
+ }
+ }
+ else if (type == 0x1030 && wbi >= 0 && (0x18040 >> wbi & 1))
+ {
+ ciff_block_1030(); // all that don't have 0x10a9
+ }
+ else if (type == 0x1031)
+ {
+ raw_width = imCanon.SensorWidth = (get2(), get2());
+ raw_height = imCanon.SensorHeight = get2();
+ fseek(ifp, 4, SEEK_CUR);
+ imCanon.DefaultCropAbsolute = get_CanonArea();
+ imCanon.LeftOpticalBlack = get_CanonArea();
+ }
+ else if (type == 0x501c)
+ {
+ iso_speed = float(len & 0xffff);
+ }
+ else if (type == 0x5029)
+ {
+ ilm.CurFocal = float( len >> 16);
+ ilm.FocalType = len & 0xffff;
+ if (ilm.FocalType == LIBRAW_FT_ZOOM_LENS)
+ {
+ ilm.FocalUnits = 32;
+ if (ilm.FocalUnits > 1)
+ ilm.CurFocal /= (float)ilm.FocalUnits;
+ }
+ focal_len = ilm.CurFocal;
+ }
+ else if (type == 0x5813)
+ {
+ flash_used = int_to_float(len);
+ }
+ else if (type == 0x5814)
+ {
+ canon_ev = int_to_float(len);
+ }
+ else if (type == 0x5817)
+ {
+ shot_order = len;
+ }
+ else if (type == 0x5834)
+ {
+ unique_id = ((unsigned long long)len << 32) >> 32;
+ setCanonBodyFeatures(unique_id);
+ }
+ else if (type == 0x580e)
+ {
+ timestamp = len;
+ }
+ else if (type == 0x180e)
+ {
+ timestamp = get4();
+ }
+
+next_tag:;
+#ifdef LOCALTIME
+ if ((type | 0x4000) == 0x580e)
+ timestamp = mktime(gmtime(&timestamp));
+#endif
+ fseek(ifp, save, SEEK_SET);
+ }
+}
diff --git a/libkdcraw/libraw/src/metadata/cr3_parser.cpp b/libkdcraw/libraw/src/metadata/cr3_parser.cpp
new file mode 100644
index 0000000..52061e9
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/cr3_parser.cpp
@@ -0,0 +1,896 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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_defs.h"
+
+
+static libraw_area_t sget_CanonArea(uchar *s) {
+ libraw_area_t la = {};
+ la.l = s[0] << 8 | s[1];
+ la.t = s[2] << 8 | s[3];
+ la.r = s[4] << 8 | s[5];
+ la.b = s[6] << 8 | s[7];
+ return la;
+}
+
+int LibRaw::selectCRXFrame(short trackNum, unsigned frameIndex)
+{
+ uint32_t sample_size;
+ uint32_t stsc_index = 0;
+ uint32_t current_sample = 0;
+ crx_data_header_t *hdr = &libraw_internal_data.unpacker_data.crx_header[trackNum];
+
+ if (frameIndex >= hdr->sample_count)
+ return -1;
+
+ for (int i = 0; i < hdr->chunk_count; i++)
+ {
+ int64_t current_offset = hdr->chunk_offsets[i];
+
+ while((stsc_index < hdr->stsc_count) && (i+1 == hdr->stsc_data[stsc_index+1].first))
+ stsc_index++;
+
+ for (int j = 0; j < hdr->stsc_data[stsc_index].count; j++)
+ {
+ if (current_sample > hdr->sample_count)
+ return -1;
+
+ sample_size = hdr->sample_size > 0 ? hdr->sample_size : hdr->sample_sizes[current_sample];
+ if(current_sample == frameIndex)
+ {
+ hdr->MediaOffset = current_offset;
+ hdr->MediaSize = sample_size;
+ return 0;
+ }
+ current_offset += sample_size;
+ current_sample++;
+ }
+ }
+ return -1;
+}
+
+void LibRaw::selectCRXTrack()
+{
+ short maxTrack = libraw_internal_data.unpacker_data.crx_track_count;
+ if (maxTrack < 0)
+ return;
+
+ INT64 bitcounts[LIBRAW_CRXTRACKS_MAXCOUNT], maxbitcount = 0;
+ int framecounts[LIBRAW_CRXTRACKS_MAXCOUNT], maxframecount = 0;
+ uint32_t maxjpegbytes = 0;
+ int framecnt = 0;
+ int media_tracks = 0;
+ int track_select = 0;
+ int frame_select = 0;
+ int err;
+ memset(bitcounts, 0, sizeof(bitcounts));
+ memset(framecounts, 0, sizeof(framecounts));
+
+ // Calc max frame bitcount for max-sized RAW track(s) selection
+ for (int i = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++)
+ {
+ crx_data_header_t *d = &libraw_internal_data.unpacker_data.crx_header[i];
+ if (d->MediaType == 1) // RAW
+ {
+ bitcounts[i] = INT64(d->nBits) * INT64(d->f_width) * INT64(d->f_height);
+ maxbitcount = MAX(bitcounts[i], maxbitcount);
+ if (d->sample_count > 1)
+ framecounts[i] = d->sample_count;
+ }
+ }
+
+ if (maxbitcount < 8) // no raw tracks
+ return;
+
+ // Calc RAW tracks and frames
+ for (int i = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++)
+ {
+ if (bitcounts[i] == maxbitcount)
+ {
+ media_tracks++;
+ if (framecounts[i] > 1)
+ framecnt = MAX(framecnt, framecounts[i]);
+ }
+ }
+
+ // If the file has only 1 media track shot_select represents frames select.
+ // If the file has multiple media tracks shot_select represents track select.
+ // If the file has multiple media tracks and multiple frames it is currently unsupported.
+
+ if (framecnt && media_tracks > 1)
+ return;
+ else if (framecnt)
+ frame_select = shot_select;
+ else
+ track_select = shot_select;
+
+ int tracki = -1;
+ for (int i = 0, trackcnt = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++)
+ {
+ if (bitcounts[i] == maxbitcount)
+ {
+ if (trackcnt <= (int)track_select)
+ tracki = i;
+ trackcnt++;
+ }
+ }
+
+ if (tracki >= 0 && tracki < LIBRAW_CRXTRACKS_MAXCOUNT /* && frame_select > 0 */)
+ {
+ framecnt = framecounts[tracki]; // Update to selected track
+ frame_select = LIM(frame_select, 0, framecnt);
+ if(frame_select > 0)
+ if (selectCRXFrame(tracki, frame_select))
+ return;
+ }
+ else
+ return; // No RAW track index
+
+ // Frame selected: parse CTMD metadata
+ for (int i = 0, trackcnt = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++)
+ {
+ crx_data_header_t *d = &libraw_internal_data.unpacker_data.crx_header[i];
+ int fsel = LIM(frame_select, 0, d->sample_count);
+ if (d->MediaType == 3) // CTMD metadata
+ {
+ /* ignore errors !*/
+ if (fsel)
+ selectCRXFrame(i, fsel);
+ parseCR3_CTMD(i);
+ }
+ else if (d->MediaType == 2) // JPEG
+ {
+ if (fsel)
+ selectCRXFrame(i, fsel);
+ if (d->MediaSize > maxjpegbytes)
+ {
+ maxjpegbytes = d->MediaSize;
+ thumb_offset = d->MediaOffset;
+ thumb_length = d->MediaSize;
+ if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT)
+ {
+ bool do_add = true;
+ for (int idx = 0; idx < imgdata.thumbs_list.thumbcount; idx++)
+ if (imgdata.thumbs_list.thumblist[idx].toffset == thumb_offset)
+ {
+ do_add = false;
+ break;
+ }
+ if (do_add)
+ {
+ int idx = imgdata.thumbs_list.thumbcount;
+ imgdata.thumbs_list.thumblist[idx].tformat = LIBRAW_INTERNAL_THUMBNAIL_JPEG;
+ imgdata.thumbs_list.thumblist[idx].toffset = thumb_offset;
+ imgdata.thumbs_list.thumblist[idx].tlength = thumb_length;
+ imgdata.thumbs_list.thumblist[idx].tflip = 0xffff;
+ imgdata.thumbs_list.thumblist[idx].tmisc = (3 << 5) | 8; // 3 samples/8 bps
+ imgdata.thumbs_list.thumblist[idx].twidth = 0;
+ imgdata.thumbs_list.thumblist[idx].theight = 0;
+ imgdata.thumbs_list.thumbcount++;
+ }
+ }
+ }
+ }
+ }
+
+ if (framecnt)
+ is_raw = framecnt;
+ else
+ is_raw = media_tracks;
+
+ if (tracki >= 0 && tracki < LIBRAW_CRXTRACKS_MAXCOUNT)
+ {
+ crx_data_header_t *d =
+ &libraw_internal_data.unpacker_data.crx_header[tracki];
+ data_offset = d->MediaOffset;
+ data_size = d->MediaSize;
+ raw_width = d->f_width;
+ raw_height = d->f_height;
+ load_raw = &LibRaw::crxLoadRaw;
+ tiff_bps = d->encType == 3? d->medianBits : d->nBits;
+ switch (d->cfaLayout)
+ {
+ case 0:
+ filters = 0x94949494;
+ break;
+ case 1:
+ filters = 0x61616161;
+ break;
+ case 2:
+ filters = 0x49494949;
+ break;
+ case 3:
+ filters = 0x16161616;
+ break;
+ }
+
+ libraw_internal_data.unpacker_data.crx_track_selected = tracki;
+
+ int tiff_idx = -1;
+ INT64 tpixels = 0;
+ for (unsigned i = 0; i < tiff_nifds && i < LIBRAW_IFD_MAXCOUNT; i++)
+ if (INT64(tiff_ifd[i].t_height) * INT64(tiff_ifd[i].t_height) > tpixels)
+ {
+ tpixels = INT64(tiff_ifd[i].t_height) * INT64(tiff_ifd[i].t_height);
+ tiff_idx = i;
+ }
+ if (tiff_idx >= 0)
+ flip = tiff_ifd[tiff_idx].t_flip;
+ }
+}
+
+#define bad_hdr() \
+ (((order != 0x4d4d) && (order != 0x4949)) || (get2() != 0x002a) || \
+ (get4() != 0x00000008))
+
+int LibRaw::parseCR3_CTMD(short trackNum)
+{
+ int err = 0;
+ short s_order = order;
+ order = 0x4949;
+ uint32_t relpos_inDir = 0;
+ uint32_t relpos_inBox = 0;
+ unsigned szItem, Tag, lTag;
+ ushort tItem;
+
+#define track libraw_internal_data.unpacker_data.crx_header[trackNum]
+
+ if (track.MediaType != 3)
+ {
+ err = -10;
+ goto ctmd_fin;
+ }
+
+ while (relpos_inDir + 6 < track.MediaSize)
+ {
+ if (track.MediaOffset + relpos_inDir > ifp->size() - 6) // need at least 6 bytes
+ {
+ err = -11;
+ goto ctmd_fin;
+ }
+ fseek(ifp, track.MediaOffset + relpos_inDir, SEEK_SET);
+ szItem = get4();
+ tItem = get2();
+ if (szItem < 1 || ( (relpos_inDir + szItem) > track.MediaSize))
+ {
+ err = -11;
+ goto ctmd_fin;
+ }
+ if ((tItem == 7) || (tItem == 8) || (tItem == 9))
+ {
+ relpos_inBox = relpos_inDir + 12L;
+ while (relpos_inBox + 8 < relpos_inDir + szItem)
+ {
+ if (track.MediaOffset + relpos_inBox > ifp->size() - 8) // need at least 8 bytes
+ {
+ err = -11;
+ goto ctmd_fin;
+ }
+ fseek(ifp, track.MediaOffset + relpos_inBox, SEEK_SET);
+ lTag = get4();
+ Tag = get4();
+ if (lTag < 8)
+ {
+ err = -12;
+ goto ctmd_fin;
+ }
+ else if ((relpos_inBox + lTag) > (relpos_inDir + szItem))
+ {
+ err = -11;
+ goto ctmd_fin;
+ }
+ if ((Tag == 0x927c) && ((tItem == 7) || (tItem == 8)))
+ {
+ fseek(ifp, track.MediaOffset + relpos_inBox + 8L,
+ SEEK_SET);
+ short q_order = order;
+ order = get2();
+ if (bad_hdr())
+ {
+ err = -13;
+ goto ctmd_fin;
+ }
+ fseek(ifp, -8L, SEEK_CUR);
+ libraw_internal_data.unpacker_data.CR3_CTMDtag = 1;
+ parse_makernote(track.MediaOffset + relpos_inBox + 8,
+ 0);
+ libraw_internal_data.unpacker_data.CR3_CTMDtag = 0;
+ order = q_order;
+ }
+ relpos_inBox += lTag;
+ }
+ }
+ relpos_inDir += szItem;
+ }
+
+ctmd_fin:
+ order = s_order;
+ return err;
+}
+#undef track
+
+int LibRaw::parseCR3(INT64 oAtomList,
+ INT64 szAtomList, short &nesting,
+ char *AtomNameStack, short &nTrack, short &TrackType)
+{
+ /*
+ Atom starts with 4 bytes for Atom size and 4 bytes containing Atom name
+ Atom size includes the length of the header and the size of all "contained"
+ Atoms if Atom size == 1, Atom has the extended size stored in 8 bytes located
+ after the Atom name if Atom size == 0, it is the last top-level Atom extending
+ to the end of the file Atom name is often a 4 symbol mnemonic, but can be a
+ 4-byte integer
+ */
+ const char UIID_Canon[17] =
+ "\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48";
+ const unsigned char UIID_CanonPreview[17] = "\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16";
+ const unsigned char UUID_XMP[17] = "\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac";
+
+ /*
+ AtomType = 0 - unknown: "unk."
+ AtomType = 1 - container atom: "cont"
+ AtomType = 2 - leaf atom: "leaf"
+ AtomType = 3 - can be container, can be leaf: "both"
+ */
+ short AtomType;
+ static const struct
+ {
+ char AtomName[5];
+ short AtomType;
+ } AtomNamesList[] = {
+ {"dinf", 1},
+ {"edts", 1},
+ {"fiin", 1},
+ {"ipro", 1},
+ {"iprp", 1},
+ {"mdia", 1},
+ {"meco", 1},
+ {"mere", 1},
+ {"mfra", 1},
+ {"minf", 1},
+ {"moof", 1},
+ {"moov", 1},
+ {"mvex", 1},
+ {"paen", 1},
+ {"schi", 1},
+ {"sinf", 1},
+ {"skip", 1},
+ {"stbl", 1},
+ {"stsd", 1},
+ {"strk", 1},
+ {"tapt", 1},
+ {"traf", 1},
+ {"trak", 1},
+
+ {"cdsc", 2},
+ {"colr", 2},
+ {"dimg", 2},
+ // {"dref", 2},
+ {"free", 2},
+ {"frma", 2},
+ {"ftyp", 2},
+ {"hdlr", 2},
+ {"hvcC", 2},
+ {"iinf", 2},
+ {"iloc", 2},
+ {"infe", 2},
+ {"ipco", 2},
+ {"ipma", 2},
+ {"iref", 2},
+ {"irot", 2},
+ {"ispe", 2},
+ {"meta", 2},
+ {"mvhd", 2},
+ {"pitm", 2},
+ {"pixi", 2},
+ {"schm", 2},
+ {"thmb", 2},
+ {"tkhd", 2},
+ {"url ", 2},
+ {"urn ", 2},
+
+ {"CCTP", 1},
+ {"CRAW", 1},
+
+ {"JPEG", 2},
+ {"CDI1", 2},
+ {"CMP1", 2},
+
+ {"CNCV", 2},
+ {"CCDT", 2},
+ {"CTBO", 2},
+ {"CMT1", 2},
+ {"CMT2", 2},
+ {"CMT3", 2},
+ {"CMT4", 2},
+ {"CNOP", 2},
+ {"THMB", 2},
+ {"co64", 2},
+ {"mdat", 2},
+ {"mdhd", 2},
+ {"nmhd", 2},
+ {"stsc", 2},
+ {"stsz", 2},
+ {"stts", 2},
+ {"vmhd", 2},
+
+ {"dref", 3},
+ {"uuid", 3},
+ };
+
+ const char sHandlerType[5][5] = {"unk.", "soun", "vide", "hint", "meta"};
+
+ int c, err=0;
+
+ ushort tL; // Atom length represented in 4 or 8 bytes
+ char nmAtom[5]; // Atom name
+ INT64 oAtom, szAtom; // Atom offset and Atom size
+ INT64 oAtomContent,
+ szAtomContent; // offset and size of Atom content
+ INT64 lHdr;
+
+ char UIID[16];
+ uchar CMP1[85];
+ uchar CDI1[60];
+ char HandlerType[5], MediaFormatID[5];
+ uint32_t relpos_inDir, relpos_inBox;
+ unsigned szItem, Tag, lTag;
+ ushort tItem;
+
+ nmAtom[0] = MediaFormatID[0] = nmAtom[4] = MediaFormatID[4] = '\0';
+ strcpy(HandlerType, sHandlerType[0]);
+ oAtom = oAtomList;
+ nesting++;
+ if (nesting > 31)
+ return -14; // too deep nesting
+ short s_order = order;
+
+ while ((oAtom + 8LL) <= (oAtomList + szAtomList))
+ {
+ lHdr = 0ULL;
+ err = 0;
+ order = 0x4d4d;
+ fseek(ifp, oAtom, SEEK_SET);
+ szAtom = get4();
+ FORC4 nmAtom[c] = AtomNameStack[nesting * 4 + c] = fgetc(ifp);
+ AtomNameStack[(nesting + 1) * 4] = '\0';
+ tL = 4;
+ AtomType = 0;
+
+ for (c = 0; c < int(sizeof AtomNamesList / sizeof *AtomNamesList); c++)
+ if (!strcmp(nmAtom, AtomNamesList[c].AtomName))
+ {
+ AtomType = AtomNamesList[c].AtomType;
+ break;
+ }
+
+ if (!AtomType)
+ {
+ err = 1;
+ }
+
+ if (szAtom == 0ULL)
+ {
+ if (nesting != 0)
+ {
+ err = -2;
+ goto fin;
+ }
+ szAtom = szAtomList - oAtom;
+ oAtomContent = oAtom + 8ULL;
+ szAtomContent = szAtom - 8ULL;
+ }
+ else if (szAtom == 1LL)
+ {
+ if ((oAtom + 16LL) > (oAtomList + szAtomList))
+ {
+ err = -3;
+ goto fin;
+ }
+ tL = 8;
+ szAtom = (((unsigned long long)get4()) << 32) | get4();
+ oAtomContent = oAtom + 16ULL;
+ szAtomContent = szAtom - 16ULL;
+ }
+ else
+ {
+ oAtomContent = oAtom + 8ULL;
+ szAtomContent = szAtom - 8ULL;
+ }
+
+ if (!strcmp(AtomNameStack, "uuid")) // Top level uuid
+ {
+ INT64 tt = ftell(ifp);
+ lHdr = 16ULL;
+ fread(UIID, 1, lHdr, ifp);
+ if (!memcmp(UIID, UUID_XMP, 16) && szAtom > 24LL && szAtom < 1024000LL)
+ {
+ xmpdata = (char *)malloc(xmplen = unsigned(szAtom - 23));
+ fread(xmpdata, szAtom - 24, 1, ifp);
+ xmpdata[szAtom - 24] = 0;
+ }
+ else if (!memcmp(UIID, UIID_CanonPreview, 16) && szAtom > 48LL && szAtom < 100LL * 1024000LL)
+ {
+ // read next 48 bytes, check for 'PRVW'
+ unsigned char xdata[32];
+ fread(xdata, 32, 1, ifp);
+ if (!memcmp(xdata + 12, "PRVW", 4))
+ {
+ thumb_length = unsigned(szAtom - 56);
+ thumb_offset = ftell(ifp);
+ if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT)
+ {
+ bool do_add = true;
+ for(int idx = 0; idx < imgdata.thumbs_list.thumbcount; idx++)
+ if (imgdata.thumbs_list.thumblist[idx].toffset == thumb_offset)
+ {
+ do_add = false;
+ break;
+ }
+ if (do_add)
+ {
+ int idx = imgdata.thumbs_list.thumbcount;
+ imgdata.thumbs_list.thumblist[idx].tformat = LIBRAW_INTERNAL_THUMBNAIL_JPEG;
+ imgdata.thumbs_list.thumblist[idx].toffset = thumb_offset;
+ imgdata.thumbs_list.thumblist[idx].tlength = thumb_length;
+ imgdata.thumbs_list.thumblist[idx].tflip = 0xffff;
+ imgdata.thumbs_list.thumblist[idx].tmisc = (3 << 5) | 8; // 3 samples/8 bps
+ imgdata.thumbs_list.thumblist[idx].twidth = (xdata[22] << 8) + xdata[23];
+ imgdata.thumbs_list.thumblist[idx].theight = (xdata[24] << 8) + xdata[25];
+ imgdata.thumbs_list.thumbcount++;
+ }
+ }
+
+ }
+ }
+ fseek(ifp, tt, SEEK_SET);
+ }
+
+ if (!strcmp(nmAtom, "trak"))
+ {
+ nTrack++;
+ TrackType = 0;
+ if (nTrack >= LIBRAW_CRXTRACKS_MAXCOUNT)
+ break;
+ }
+ if (!strcmp(AtomNameStack, "moovuuid"))
+ {
+ lHdr = 16ULL;
+ fread(UIID, 1, lHdr, ifp);
+ if (!strncmp(UIID, UIID_Canon, lHdr))
+ {
+ AtomType = 1;
+ }
+ else
+ fseek(ifp, -lHdr, SEEK_CUR);
+ }
+ else if (!strcmp(AtomNameStack, "moovuuidCCTP"))
+ {
+ lHdr = 12ULL;
+ }
+ else if (!strcmp(AtomNameStack, "moovuuidCMT1"))
+ {
+ short q_order = order;
+ order = get2();
+ if ((tL != 4) || bad_hdr())
+ {
+ err = -4;
+ goto fin;
+ }
+ if (!libraw_internal_data.unpacker_data.cr3_ifd0_length)
+ libraw_internal_data.unpacker_data.cr3_ifd0_length = unsigned(szAtomContent);
+ parse_tiff_ifd(oAtomContent);
+ order = q_order;
+ }
+ else if (!strcmp(AtomNameStack, "moovuuidTHMB") && szAtom > 24)
+ {
+ unsigned char xdata[16];
+ fread(xdata, 16, 1, ifp);
+ INT64 xoffset = ftell(ifp);
+ if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT)
+ {
+ bool do_add = true;
+ for (int idx = 0; idx < imgdata.thumbs_list.thumbcount; idx++)
+ if (imgdata.thumbs_list.thumblist[idx].toffset == xoffset)
+ {
+ do_add = false;
+ break;
+ }
+ if (do_add)
+ {
+ int idx = imgdata.thumbs_list.thumbcount;
+ imgdata.thumbs_list.thumblist[idx].tformat = LIBRAW_INTERNAL_THUMBNAIL_JPEG;
+ imgdata.thumbs_list.thumblist[idx].toffset = xoffset;
+ imgdata.thumbs_list.thumblist[idx].tlength = szAtom-24;
+ imgdata.thumbs_list.thumblist[idx].tflip = 0xffff;
+ imgdata.thumbs_list.thumblist[idx].tmisc = (3 << 5) | 8; // 3 samples/8 bps
+ imgdata.thumbs_list.thumblist[idx].twidth = (xdata[4] << 8) + xdata[5];
+ imgdata.thumbs_list.thumblist[idx].theight = (xdata[6] << 8) + xdata[7];
+ imgdata.thumbs_list.thumbcount++;
+ }
+ }
+ }
+ else if (!strcmp(AtomNameStack, "moovuuidCMT2"))
+ {
+ short q_order = order;
+ order = get2();
+ if ((tL != 4) || bad_hdr())
+ {
+ err = -5;
+ goto fin;
+ }
+ if (!libraw_internal_data.unpacker_data.cr3_exif_length)
+ libraw_internal_data.unpacker_data.cr3_exif_length = unsigned(szAtomContent);
+ parse_exif(oAtomContent);
+ order = q_order;
+ }
+ else if (!strcmp(AtomNameStack, "moovuuidCMT3"))
+ {
+ short q_order = order;
+ order = get2();
+ if ((tL != 4) || bad_hdr())
+ {
+ err = -6;
+ goto fin;
+ }
+ fseek(ifp, -12L, SEEK_CUR);
+ parse_makernote(oAtomContent, 0);
+ order = q_order;
+ }
+ else if (!strcmp(AtomNameStack, "moovuuidCMT4"))
+ {
+ short q_order = order;
+ order = get2();
+ if ((tL != 4) || bad_hdr())
+ {
+ err = -6;
+ goto fin;
+ }
+ INT64 off = ftell(ifp);
+ parse_gps(oAtomContent);
+ fseek(ifp, off, SEEK_SET);
+ parse_gps_libraw(oAtomContent);
+ order = q_order;
+ }
+ else if (!strcmp(AtomNameStack, "moovtrakmdiahdlr"))
+ {
+ fseek(ifp, 8L, SEEK_CUR);
+ FORC4 HandlerType[c] = fgetc(ifp);
+ for (c = 1; c < int(sizeof sHandlerType / sizeof *sHandlerType); c++)
+ if (!strcmp(HandlerType, sHandlerType[c]))
+ {
+ TrackType = c;
+ break;
+ }
+ }
+ else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsd"))
+ {
+ if (szAtomContent >= 16)
+ {
+ fseek(ifp, 12L, SEEK_CUR);
+ lHdr = 8;
+ }
+ else
+ {
+ err = -7;
+ goto fin;
+ }
+ FORC4 MediaFormatID[c] = fgetc(ifp);
+ if ((TrackType == 2) && (!strcmp(MediaFormatID, "CRAW")))
+ {
+ if (szAtomContent >= 44)
+ fseek(ifp, 24L, SEEK_CUR);
+ else
+ {
+ err = -8;
+ goto fin;
+ }
+ }
+ else
+ {
+ AtomType = 2; // only continue for CRAW
+ lHdr = 0;
+ }
+#define current_track libraw_internal_data.unpacker_data.crx_header[nTrack]
+
+ /*ImageWidth =*/ get2();
+ /*ImageHeight =*/ get2();
+ }
+ else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAW"))
+ {
+ lHdr = 82;
+ }
+ else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWCMP1"))
+ {
+ int read_size = szAtomContent > 85 ? 85 : szAtomContent;
+ if (szAtomContent >= 40)
+ fread(CMP1, 1, read_size, ifp);
+ else
+ {
+ err = -7;
+ goto fin;
+ }
+ if (!crxParseImageHeader(CMP1, nTrack, read_size))
+ current_track.MediaType = 1;
+ }
+
+ else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWCDI1")) {
+ if (szAtomContent >= 60) {
+ fread(CDI1, 1, 60, ifp);
+ if (!strncmp((char *)CDI1+8, "IAD1", 4) && (sgetn(8, CDI1) == 0x38)) {
+ // sensor area at CDI1+12, 4 16-bit values
+ // Bayer pattern? - next 4 16-bit values
+ imCanon.RecommendedImageArea = sget_CanonArea(CDI1+12 + 2*4*2);
+ imCanon.LeftOpticalBlack = sget_CanonArea(CDI1+12 + 3*4*2);
+ imCanon.UpperOpticalBlack = sget_CanonArea(CDI1+12 + 4*4*2);
+ imCanon.ActiveArea = sget_CanonArea(CDI1+12 + 5*4*2);
+ }
+ }
+ }
+
+ else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWJPEG"))
+ {
+ current_track.MediaType = 2;
+ }
+ else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsc"))
+ {
+ if (szAtomContent >= 12) {
+ fseek(ifp, 4L, SEEK_CUR);
+ int entries = get4();
+ if (entries < 1 || entries > 1000000)
+ {
+ err = -9;
+ goto fin;
+ }
+
+ current_track.stsc_data = (crx_sample_to_chunk_t*) malloc(entries * sizeof(crx_sample_to_chunk_t));
+ if(!current_track.stsc_data)
+ {
+ err = -9;
+ goto fin;
+ }
+ current_track.stsc_count = entries;
+ for(int i = 0; i < entries; i++)
+ {
+ current_track.stsc_data[i].first = get4();
+ current_track.stsc_data[i].count = get4();
+ current_track.stsc_data[i].id = get4();
+ }
+ }
+ }
+ else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsz"))
+ {
+ if (szAtomContent >= 12)
+ {
+ fseek(ifp, 4L, SEEK_CUR);
+ int sample_size = get4();
+ int entries = get4();
+ current_track.sample_count = entries;
+
+ // if sample size is zero sample size is fixed
+ if (sample_size)
+ {
+ current_track.MediaSize = sample_size;
+ current_track.sample_size = sample_size;
+ }
+ else
+ {
+ current_track.sample_size = 0;
+ if (entries < 1 || entries > 1000000) {
+ err = -10;
+ goto fin;
+ }
+ current_track.sample_sizes = (int32_t*)malloc(entries * sizeof(int32_t));
+ if (!current_track.sample_sizes)
+ {
+ err = -10;
+ goto fin;
+ }
+ for (int i = 0; i < entries; i++)
+ current_track.sample_sizes[i] = get4();
+
+ current_track.MediaSize = current_track.sample_sizes[0];
+ }
+ }
+ }
+ else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblco64"))
+ {
+ if (szAtomContent >= 16) {
+ fseek(ifp, 4L, SEEK_CUR);
+ uint32_t entries = get4();
+ int i;
+ if (entries < 1 || entries > 1000000)
+ {
+ err = -11;
+ goto fin;
+ }
+ current_track.chunk_offsets = (INT64*)malloc(entries * sizeof(int64_t));
+ if(!current_track.chunk_offsets)
+ {
+ err = -11;
+ goto fin;
+ }
+
+ current_track.chunk_count = entries;
+ for (i = 0; i < entries; i++)
+ current_track.chunk_offsets[i] = (((int64_t)get4()) << 32) | get4();
+
+ current_track.chunk_count = i;
+ current_track.MediaOffset = current_track.chunk_offsets[0];
+ }
+ }
+
+ if (nTrack >= 0 && nTrack < LIBRAW_CRXTRACKS_MAXCOUNT &&
+ current_track.MediaSize && current_track.MediaOffset &&
+ ((oAtom + szAtom) >= (oAtomList + szAtomList)) &&
+ !strncmp(AtomNameStack, "moovtrakmdiaminfstbl", 20))
+ {
+ if ((TrackType == 4) && (!strcmp(MediaFormatID, "CTMD")))
+ {
+ current_track.MediaType = 3;
+ }
+ }
+#undef current_track
+ if (AtomType == 1)
+ {
+ err = parseCR3(oAtomContent + lHdr, szAtomContent - lHdr, nesting,
+ AtomNameStack, nTrack, TrackType);
+ if (err)
+ goto fin;
+ }
+ oAtom += szAtom;
+ }
+
+fin:
+ nesting--;
+ if (nesting >= 0)
+ AtomNameStack[nesting * 4] = '\0';
+ order = s_order;
+ return err;
+}
+#undef bad_hdr
+
+void LibRaw::parseCR3_Free()
+{
+ short maxTrack = libraw_internal_data.unpacker_data.crx_track_count;
+ if (maxTrack < 0)
+ return;
+
+ for (int i = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++)
+ {
+ crx_data_header_t *d = &libraw_internal_data.unpacker_data.crx_header[i];
+ if (d->stsc_data)
+ {
+ free(d->stsc_data);
+ d->stsc_data = NULL;
+ }
+ if (d->chunk_offsets)
+ {
+ free(d->chunk_offsets);
+ d->chunk_offsets = NULL;
+ }
+
+ if (d->sample_sizes)
+ {
+ free(d->sample_sizes);
+ d->sample_sizes = NULL;
+ }
+ d->stsc_count = 0;
+ d->sample_count = 0;
+ d->sample_size = 0;
+ d->chunk_count = 0;
+ }
+ libraw_internal_data.unpacker_data.crx_track_count = -1;
+}
diff --git a/libkdcraw/libraw/src/metadata/epson.cpp b/libkdcraw/libraw/src/metadata/epson.cpp
new file mode 100644
index 0000000..427d98e
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/epson.cpp
@@ -0,0 +1,96 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::parseEpsonMakernote(int base, int uptag, unsigned dng_writer)
+{
+
+#define isRIC imgdata.sizes.raw_inset_crops[0]
+
+ unsigned entries, tag, type, len, save;
+ short morder, sorder = order;
+ ushort c;
+ INT64 fsize = ifp->size();
+
+ fseek(ifp, -2, SEEK_CUR);
+
+ entries = get2();
+ if (entries > 1000)
+ return;
+ morder = order;
+
+ while (entries--)
+ {
+ order = morder;
+ tiff_get(base, &tag, &type, &len, &save);
+ INT64 pos = ifp->tell();
+ if (len > 8 && pos + len > 2 * fsize)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+
+ tag |= uptag << 16;
+ if (len > 100 * 1024 * 1024)
+ goto next; // 100Mb tag? No!
+
+ if (tag == 0x020b)
+ {
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ isRIC.cwidth = get4();
+ else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT))
+ isRIC.cwidth = get2();
+ }
+ else if (tag == 0x020c)
+ {
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ isRIC.cheight = get4();
+ else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT))
+ isRIC.cheight = get2();
+ }
+ else if (tag == 0x0400)
+ { // sensor area
+ ushort sdims[4] = {0, 0, 0, 0}; // left margin, top margin, width, height
+ FORC4 sdims[c] = get2();
+ isRIC.cleft = (sdims[2] - sdims[0] - isRIC.cwidth) / 2;
+ isRIC.ctop = (sdims[3] - sdims[1] - isRIC.cheight) / 2;
+ }
+
+ if (dng_writer == nonDNG)
+ {
+
+ if (tag == 0x0280)
+ {
+ thumb_offset = ftell(ifp);
+ thumb_length = len;
+ }
+ else if (tag == 0x0401)
+ {
+ FORC4 cblack[RGGB_2_RGBG(c)] = get4();
+ }
+ else if (tag == 0x0e80)
+ {
+ fseek(ifp, 48, SEEK_CUR);
+ cam_mul[0] = get2() * 567.0 / 0x10000;
+ cam_mul[2] = get2() * 431.0 / 0x10000;
+ }
+ }
+
+ next:
+ fseek(ifp, save, SEEK_SET);
+ }
+ order = sorder;
+#undef isRIC
+}
diff --git a/libkdcraw/libraw/src/metadata/exif_gps.cpp b/libkdcraw/libraw/src/metadata/exif_gps.cpp
new file mode 100644
index 0000000..7fb3b53
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/exif_gps.cpp
@@ -0,0 +1,430 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+#include "../../internal/libraw_cameraids.h"
+
+void LibRaw::parse_exif_interop(int base)
+{
+ unsigned entries, tag, type, len, save;
+ char value[4] = { 0,0,0,0 };
+ entries = get2();
+ INT64 fsize = ifp->size();
+ while (entries--)
+ {
+ tiff_get(base, &tag, &type, &len, &save);
+
+ INT64 savepos = ftell(ifp);
+ if (len > 8 && savepos + len > fsize * 2)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+ if (callbacks.exif_cb)
+ {
+ callbacks.exif_cb(callbacks.exifparser_data, tag | 0x40000, type, len, order, ifp, base);
+ fseek(ifp, savepos, SEEK_SET);
+ }
+
+ switch (tag)
+ {
+ case 0x0001: // InteropIndex
+ fread(value, 1, MIN(4, len), ifp);
+ if (strncmp(value, "R98", 3) == 0 &&
+ // Canon bug, when [Canon].ColorSpace = AdobeRGB,
+ // but [ExifIFD].ColorSpace = Uncalibrated and
+ // [InteropIFD].InteropIndex = "R98"
+ imgdata.color.ExifColorSpace == LIBRAW_COLORSPACE_Unknown)
+ imgdata.color.ExifColorSpace = LIBRAW_COLORSPACE_sRGB;
+ else if (strncmp(value, "R03", 3) == 0)
+ imgdata.color.ExifColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ }
+ fseek(ifp, save, SEEK_SET);
+ }
+}
+
+void LibRaw::parse_exif(int base)
+{
+ unsigned entries, tag, type, len, save, c;
+ double expo, ape;
+
+ unsigned kodak = !strncmp(make, "EASTMAN", 7) && tiff_nifds < 3;
+
+ if (!libraw_internal_data.unpacker_data.exif_subdir_offset)
+ {
+ libraw_internal_data.unpacker_data.exif_offset = base;
+ libraw_internal_data.unpacker_data.exif_subdir_offset = ftell(ifp);
+ }
+
+ entries = get2();
+ if (!strncmp(make, "Hasselblad", 10) && (tiff_nifds > 3) && (entries > 512))
+ return;
+ INT64 fsize = ifp->size();
+ while (entries--)
+ {
+ tiff_get(base, &tag, &type, &len, &save);
+
+ INT64 savepos = ftell(ifp);
+ if (len > 8 && savepos + len > fsize * 2)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+ if (callbacks.exif_cb)
+ {
+ callbacks.exif_cb(callbacks.exifparser_data, tag, type, len, order, ifp,
+ base);
+ fseek(ifp, savepos, SEEK_SET);
+ }
+
+ switch (tag)
+ {
+ case 0xA005: // Interoperability IFD
+ fseek(ifp, get4() + base, SEEK_SET);
+ parse_exif_interop(base);
+ break;
+ case 0xA001: // ExifIFD.ColorSpace
+ c = get2();
+ if (c == 1 && imgdata.color.ExifColorSpace == LIBRAW_COLORSPACE_Unknown)
+ imgdata.color.ExifColorSpace = LIBRAW_COLORSPACE_sRGB;
+ else if (c == 2)
+ imgdata.color.ExifColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ case 0x9400:
+ imCommon.exifAmbientTemperature = getreal(type);
+ if ((imCommon.CameraTemperature > -273.15f) &&
+ ((OlyID == OlyID_TG_5) ||
+ (OlyID == OlyID_TG_6))
+ )
+ imCommon.CameraTemperature += imCommon.exifAmbientTemperature;
+ break;
+ case 0x9401:
+ imCommon.exifHumidity = getreal(type);
+ break;
+ case 0x9402:
+ imCommon.exifPressure = getreal(type);
+ break;
+ case 0x9403:
+ imCommon.exifWaterDepth = getreal(type);
+ break;
+ case 0x9404:
+ imCommon.exifAcceleration = getreal(type);
+ break;
+ case 0x9405:
+ imCommon.exifCameraElevationAngle = getreal(type);
+ break;
+
+ case 0xa405: // FocalLengthIn35mmFormat
+ imgdata.lens.FocalLengthIn35mmFormat = get2();
+ break;
+ case 0xa431: // BodySerialNumber
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ break;
+ case 0xa432: // LensInfo, 42034dec, Lens Specification per EXIF standard
+ imgdata.lens.MinFocal = getreal(type);
+ imgdata.lens.MaxFocal = getreal(type);
+ imgdata.lens.MaxAp4MinFocal = getreal(type);
+ imgdata.lens.MaxAp4MaxFocal = getreal(type);
+ break;
+ case 0xa435: // LensSerialNumber
+ stmread(imgdata.lens.LensSerial, len, ifp);
+ if (!strncmp(imgdata.lens.LensSerial, "----", 4))
+ imgdata.lens.LensSerial[0] = '\0';
+ break;
+ case 0xa420: /* 42016, ImageUniqueID */
+ stmread(imgdata.color.ImageUniqueID, len, ifp);
+ break;
+ case 0xc65d: /* 50781, RawDataUniqueID */
+ imgdata.color.RawDataUniqueID[16] = 0;
+ fread(imgdata.color.RawDataUniqueID, 1, 16, ifp);
+ break;
+ case 0xc630: // DNG LensInfo, Lens Specification per EXIF standard
+ imgdata.lens.dng.MinFocal = getreal(type);
+ imgdata.lens.dng.MaxFocal = getreal(type);
+ imgdata.lens.dng.MaxAp4MinFocal = getreal(type);
+ imgdata.lens.dng.MaxAp4MaxFocal = getreal(type);
+ break;
+ case 0xc68b: /* 50827, OriginalRawFileName */
+ stmread(imgdata.color.OriginalRawFileName, len, ifp);
+ break;
+ case 0xa433: // LensMake
+ stmread(imgdata.lens.LensMake, len, ifp);
+ break;
+ case 0xa434: // LensModel
+ stmread(imgdata.lens.Lens, len, ifp);
+ if (!strncmp(imgdata.lens.Lens, "----", 4))
+ imgdata.lens.Lens[0] = '\0';
+ break;
+ case 0x9205:
+ imgdata.lens.EXIF_MaxAp = libraw_powf64l(2.0f, (getreal(type) / 2.0f));
+ break;
+ case 0x829a: // 33434
+ shutter = getreal(type);
+ if (tiff_nifds > 0 && tiff_nifds <= LIBRAW_IFD_MAXCOUNT)
+ tiff_ifd[tiff_nifds - 1].t_shutter = shutter;
+ break;
+ case 0x829d: // 33437, FNumber
+ aperture = getreal(type);
+ break;
+ case 0x8827: // 34855
+ iso_speed = get2();
+ break;
+ case 0x8831: // 34865
+ if (iso_speed == 0xffff && !strncasecmp(make, "FUJI", 4))
+ iso_speed = getreal(type);
+ break;
+ case 0x8832: // 34866
+ if (iso_speed == 0xffff &&
+ (!strncasecmp(make, "SONY", 4) || !strncasecmp(make, "CANON", 5)))
+ iso_speed = getreal(type);
+ break;
+ case 0x9003: // 36867
+ case 0x9004: // 36868
+ get_timestamp(0);
+ break;
+ case 0x9201: // 37377
+ if ((expo = -getreal(type)) < 128 && shutter == 0.)
+ {
+ shutter = libraw_powf64l(2.0, expo);
+ if (tiff_nifds > 0 && tiff_nifds <= LIBRAW_IFD_MAXCOUNT)
+ tiff_ifd[tiff_nifds - 1].t_shutter = shutter;
+ }
+ break;
+ case 0x9202: // 37378 ApertureValue
+ if ((fabs(ape = getreal(type)) < 256.0) && (!aperture))
+ aperture = libraw_powf64l(2.0, ape / 2);
+ break;
+ case 0x9209: // 37385
+ flash_used = getreal(type);
+ break;
+ case 0x920a: // 37386
+ focal_len = getreal(type);
+ break;
+ case 0x927c: // 37500
+#ifndef USE_6BY9RPI
+ if (((make[0] == '\0') && !strncmp(model, "ov5647", 6)) ||
+ (!strncmp(make, "RaspberryPi", 11) &&
+ (!strncmp(model, "RP_OV5647", 9) ||
+ !strncmp(model, "RP_imx219", 9))))
+#else
+ if (((make[0] == '\0') && !strncmp(model, "ov5647", 6)) ||
+ (!strncmp(make, "RaspberryPi", 11) &&
+ (!strncmp(model, "RP_", 3) || !strncmp(model,"imx477",6))))
+#endif
+ {
+ char mn_text[512];
+ char *pos;
+ char ccms[512];
+ ushort l;
+ float num;
+
+ fgets(mn_text, MIN(len, 511), ifp);
+ mn_text[511] = 0;
+
+ pos = strstr(mn_text, "ev=");
+ if (pos)
+ imCommon.ExposureCalibrationShift = atof(pos + 3);
+
+ pos = strstr(mn_text, "gain_r=");
+ if (pos)
+ cam_mul[0] = atof(pos + 7);
+ pos = strstr(mn_text, "gain_b=");
+ if (pos)
+ cam_mul[2] = atof(pos + 7);
+ if ((cam_mul[0] > 0.001f) && (cam_mul[2] > 0.001f))
+ cam_mul[1] = cam_mul[3] = 1.0f;
+ else
+ cam_mul[0] = cam_mul[2] = 0.0f;
+
+ pos = strstr(mn_text, "ccm=");
+ if (pos)
+ {
+ pos += 4;
+ char *pos2 = strstr(pos, " ");
+ if (pos2)
+ {
+ l = pos2 - pos;
+ memcpy(ccms, pos, l);
+ ccms[l] = '\0';
+#ifdef LIBRAW_WIN32_CALLS
+ // Win32 strtok is already thread-safe
+ pos = strtok(ccms, ",");
+#else
+ char *last = 0;
+ pos = strtok_r(ccms, ",", &last);
+#endif
+ if (pos)
+ {
+ for (l = 0; l < 3; l++) // skip last row
+ {
+ num = 0.0;
+ for (c = 0; c < 3; c++)
+ {
+ cmatrix[l][c] = (float)atoi(pos);
+ num += cmatrix[c][l];
+#ifdef LIBRAW_WIN32_CALLS
+ pos = strtok(NULL, ",");
+#else
+ pos = strtok_r(NULL, ",", &last);
+#endif
+ if (!pos)
+ goto end; // broken
+ }
+ if (num > 0.01)
+ FORC3 cmatrix[l][c] = cmatrix[l][c] / num;
+ }
+ }
+ }
+ }
+ end:;
+ }
+ else if (!strncmp(make, "SONY", 4) &&
+ (!strncmp(model, "DSC-V3", 6) || !strncmp(model, "DSC-F828", 8)))
+ {
+ parseSonySRF(len);
+ break;
+ }
+ else if ((len == 1) && !strncmp(make, "NIKON", 5))
+ {
+ c = get4();
+ if (c)
+ fseek(ifp, c, SEEK_SET);
+ is_NikonTransfer = 1;
+ }
+ parse_makernote(base, 0);
+ break;
+ case 0xa002: // 40962
+ if (kodak)
+ raw_width = get4();
+ break;
+ case 0xa003: // 40963
+ if (kodak)
+ raw_height = get4();
+ break;
+ case 0xa302: // 41730
+ if (get4() == 0x20002)
+ for (exif_cfa = c = 0; c < 8; c += 2)
+ exif_cfa |= fgetc(ifp) * 0x01010101U << c;
+ }
+ fseek(ifp, save, SEEK_SET);
+ }
+}
+
+void LibRaw::parse_gps_libraw(int base)
+{
+ unsigned entries, tag, type, len, save, c;
+
+ entries = get2();
+ if (entries > 40)
+ return;
+ if (entries > 0)
+ imgdata.other.parsed_gps.gpsparsed = 1;
+ INT64 fsize = ifp->size();
+ while (entries--)
+ {
+ tiff_get(base, &tag, &type, &len, &save);
+ if (len > 1024)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue; // no GPS tags are 1k or larger
+ }
+ INT64 savepos = ftell(ifp);
+ if (len > 8 && savepos + len > fsize * 2)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+
+ if (callbacks.exif_cb)
+ {
+ callbacks.exif_cb(callbacks.exifparser_data, tag | 0x50000, type, len, order, ifp, base);
+ fseek(ifp, savepos, SEEK_SET);
+ }
+
+ switch (tag)
+ {
+ case 0x0001:
+ imgdata.other.parsed_gps.latref = getc(ifp);
+ break;
+ case 0x0003:
+ imgdata.other.parsed_gps.longref = getc(ifp);
+ break;
+ case 0x0005:
+ imgdata.other.parsed_gps.altref = getc(ifp);
+ break;
+ case 0x0002:
+ if (len == 3)
+ FORC(3) imgdata.other.parsed_gps.latitude[c] = getreal(type);
+ break;
+ case 0x0004:
+ if (len == 3)
+ FORC(3) imgdata.other.parsed_gps.longitude[c] = getreal(type);
+ break;
+ case 0x0007:
+ if (len == 3)
+ FORC(3) imgdata.other.parsed_gps.gpstimestamp[c] = getreal(type);
+ break;
+ case 0x0006:
+ imgdata.other.parsed_gps.altitude = getreal(type);
+ break;
+ case 0x0009:
+ imgdata.other.parsed_gps.gpsstatus = getc(ifp);
+ break;
+ }
+ fseek(ifp, save, SEEK_SET);
+ }
+}
+
+void LibRaw::parse_gps(int base)
+{
+ unsigned entries, tag, type, len, save, c;
+
+ entries = get2();
+ if (entries > 40)
+ return;
+ while (entries--)
+ {
+ tiff_get(base, &tag, &type, &len, &save);
+ if (len > 1024)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue; // no GPS tags are 1k or larger
+ }
+ switch (tag)
+ {
+ case 0x0001:
+ case 0x0003:
+ case 0x0005:
+ gpsdata[29 + tag / 2] = getc(ifp);
+ break;
+ case 0x0002:
+ case 0x0004:
+ case 0x0007:
+ FORC(6) gpsdata[tag / 3 * 6 + c] = get4();
+ break;
+ case 0x0006:
+ FORC(2) gpsdata[18 + c] = get4();
+ break;
+ case 0x0012: // 18
+ case 0x001d: // 29
+ fgets((char *)(gpsdata + 14 + tag / 3), MIN(len, 12), ifp);
+ }
+ fseek(ifp, save, SEEK_SET);
+ }
+}
diff --git a/libkdcraw/libraw/src/metadata/fuji.cpp b/libkdcraw/libraw/src/metadata/fuji.cpp
new file mode 100644
index 0000000..4c9fe50
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/fuji.cpp
@@ -0,0 +1,1427 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+int LibRaw::guess_RAFDataGeneration (uchar *RAFData_start) // returns offset to first valid width/height pair
+{
+
+/* RAFDataGeneration codes, values are 4 bytes, little endian
+
+ RAFData gen. 0: no RAFData
+ DBP for GX680 / DX-2000
+ E550, E900, (F500 / F505?) F550, F600 / F605, F700, F770 / F775, F800, F810, F900
+ HS10 HS11, HS20 / HS22, HS30 / HS33 / HS35, HS50
+ S1, SL1000, S100, S200 / S205, S20Pro, S2Pro, S3Pro, S5Pro
+ S5000, S5100 / S5500, S5200 / S5600, S6000 / S6500, S7000, S9000 / S9500, S9100 / S9600
+
+ RAFData gen. 1, offset to WH pair (offsetWH_inRAFData) = 0:
+ - number in bytes 0..1 is less than 10000
+ - contains WH pair, recommended image size WH pair, 16 bytes unknown, 2*13 values (for crops, scales?)
+ X100, X-Pro1, X-S1, X10, XF1
+
+ RAFData gen. 2, offset to WH pair = 4:
+ - bytes 0..1 contain a number greater than 10000; bytes 2..3 contain zero;
+ version is in bytes 0..1, possibly big endian
+ - contains WH pair, recommended image size WH pair, 16 bytes unknown, 2*13 values
+ X-E1
+
+ RAFData gen. 3, offset to WH pair = 4:
+ - bytes 0..1 contain zero; bytes 2..3 contain version;
+ - contains a table of 3+2*13 values; first 3 values look like WHW
+ X-A1, X-A2, X-E2, X-M1
+ X-T1, X-T10
+ X100S, X100T
+ X20, X30, X70, XQ1, XQ2
+
+ RAFData gen. 4, offset to WH pair = 8:
+ - same conditions as for RAFData gen. 3, but also adds WRTS in bytes 4..7
+ - contains a table of 3+2*13 values; first 3 values look like WHW
+ - H in WHW group has a different meaning if the shot is taken in crop 2 mode
+ GFX 100, GFX 100S, GFX 50R, GFX 50S, GFX 50S II
+ X-E2S, X-E3, X-H1, X-S10
+ X-T2, X-T3, X-T4, X-T20, X-T30
+ X-Pro2, X-Pro3
+ X100F, X100V
+
+ RAFData gen. set to 4096:
+ - RAFData length is exactly 4096
+ X-A3, X-A5, X-A7, X-A10, X-A20
+ X-T100, X-T200,
+ XF10
+*/
+
+ int offsetWH_inRAFData=0; /* clang warns about not initialized value */
+ ushort b01 = sget2(RAFData_start); // bytes 0..1
+ ushort b23 = sget2(RAFData_start+2); // bytes 2..3
+ int is_WRTS = (sget4(RAFData_start + 4) == 0x53545257); // STRW
+ if (b01 && !b23 && (b01<10000))
+ {
+ imFuji.RAFDataGeneration = 1;
+ offsetWH_inRAFData = 0;
+ }
+ else if ((b01>10000) && !b23)
+ {
+ imFuji.RAFDataGeneration = 2;
+ imFuji.RAFDataVersion = b01;
+ offsetWH_inRAFData = 4;
+ }
+ else if (!b01)
+ {
+ if (!is_WRTS)
+ {
+ imFuji.RAFDataGeneration = 3;
+ offsetWH_inRAFData = 4;
+ }
+ else
+ {
+ imFuji.RAFDataGeneration = 4;
+ offsetWH_inRAFData = 8;
+ }
+ imFuji.RAFDataVersion = b23;
+ }
+
+// printf ("RAFDataVersion: 0x%04x, RAFDataGeneration: %d\n",
+// imFuji.RAFDataVersion, imFuji.RAFDataGeneration);
+
+ return offsetWH_inRAFData;
+}
+
+void LibRaw::parseAdobeRAFMakernote()
+{
+
+ uchar *PrivateMknBuf;
+ unsigned posPrivateMknBuf=0; /* clang warns about not inited value */
+ unsigned PrivateMknLength;
+ unsigned PrivateOrder;
+ unsigned ifd_start, ifd_len;
+ unsigned PrivateEntries, PrivateTagID;
+ unsigned PrivateTagBytes;
+ int FujiShotSelect;
+ unsigned wb_section_offset = 0;
+ int posWB;
+ int c;
+
+#define CHECKSPACE_ABS3(s1, s2, s3) \
+ if (INT64(s1) + INT64(s2) + INT64(s3) > INT64(PrivateMknLength)) \
+ { \
+ free(PrivateMknBuf); \
+ return; \
+ }
+
+#define CHECKSPACE_ABS2(s1,s2) \
+ if (INT64(s1) + INT64(s2) > INT64(PrivateMknLength)) \
+ { \
+ free(PrivateMknBuf); \
+ return; \
+ }
+
+#define CHECKSPACE(s) \
+ if (posPrivateMknBuf + (s) > PrivateMknLength) \
+ { \
+ free(PrivateMknBuf); \
+ return; \
+ }
+
+#define isWB(posWB) \
+ sget2(posWB) != 0 && sget2(posWB + 2) != 0 && sget2(posWB + 4) != 0 && \
+ sget2(posWB + 6) != 0 && sget2(posWB + 8) != 0 && \
+ sget2(posWB + 10) != 0 && sget2(posWB) != 0xff && \
+ sget2(posWB + 2) != 0xff && sget2(posWB + 4) != 0xff && \
+ sget2(posWB + 6) != 0xff && sget2(posWB + 8) != 0xff && \
+ sget2(posWB + 10) != 0xff && sget2(posWB) == sget2(posWB + 6) && \
+ sget2(posWB) < sget2(posWB + 2) && sget2(posWB) < sget2(posWB + 4) && \
+ sget2(posWB) < sget2(posWB + 8) && sget2(posWB) < sget2(posWB + 10)
+
+#define get_average_WB(wb_index) \
+ CHECKSPACE(8); \
+ FORC4 icWBC[wb_index][GRGB_2_RGBG(c)] = \
+ sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1)); \
+ if ((PrivateTagBytes == 16) && average_WBData) { \
+ CHECKSPACE(16); \
+ FORC4 icWBC[wb_index][GRGB_2_RGBG(c)] = \
+ (icWBC[wb_index][GRGB_2_RGBG(c)] + \
+ sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1)+8)) /2; \
+ } \
+ if (use_WBcorr_coeffs) { \
+ icWBC[wb_index][0] *= wbR_corr; \
+ icWBC[wb_index][2] *= wbB_corr; \
+ }
+
+ ushort use_WBcorr_coeffs = 0;
+ double wbR_corr = 1.0;
+ double wbB_corr = 1.0;
+
+ if (strstr(model, "S2Pro")
+ || strstr(model, "S20Pro")
+ || strstr(model, "F700")
+ || strstr(model, "S5000")
+ || strstr(model, "S7000")
+ ) {
+ use_WBcorr_coeffs = 1;
+ wbR_corr = 10.0 / 17.0 / 0.652941;
+ wbB_corr = 2.0 /3.0 / (3.0 / 4.0 + 1.0 / 300.0);
+ } else if (strstr(model, "DBP") || strstr(model, "DX-2000")) {
+ use_WBcorr_coeffs = 1;
+ wbR_corr = 0.7632653061;
+ wbB_corr = 0.8591549296;
+ }
+
+ FujiShotSelect = LIM(shot_select, 0, 1);
+ int average_WBData = 1;
+
+ order = 0x4d4d;
+ PrivateMknLength = get4();
+
+ // At least 0x36 bytes because of memcpy(imFuji.RAFVersion, PrivateMknBuf + 0x32, 4);
+ if ((PrivateMknLength >= 0x36) && (PrivateMknLength < 10240000) &&
+ (PrivateMknBuf = (uchar *)malloc(PrivateMknLength + 1024))) // 1024b for safety
+ {
+ fread(PrivateMknBuf, PrivateMknLength, 1, ifp);
+ memcpy(imFuji.SerialSignature, PrivateMknBuf + 6, 0x0c);
+ imFuji.SerialSignature[0x0c] = 0;
+ memcpy(imFuji.SensorID, imFuji.SerialSignature + 0x06, 0x04);
+ imFuji.SensorID[0x04] = 0;
+ c = 11;
+ while (isdigit(imFuji.SerialSignature[c]) && (c>0))
+ c--;
+ ilm.CamID = unique_id = (unsigned long long)atoi(imFuji.SerialSignature+c+1);
+ memcpy(model, PrivateMknBuf + 0x12, 0x20);
+ model[0x20] = 0;
+ memcpy(imFuji.RAFVersion, PrivateMknBuf + 0x32, 4);
+ imFuji.RAFVersion[4] = 0;
+
+ PrivateOrder = sget2(PrivateMknBuf);
+ unsigned s, l;
+ s = ifd_start = sget4(PrivateMknBuf +2)+6;
+ CHECKSPACE(ifd_start+4);
+ l = ifd_len = sget4(PrivateMknBuf +ifd_start);
+ CHECKSPACE_ABS3(ifd_start, ifd_len, 4);
+
+ if (!sget4(PrivateMknBuf+ifd_start+ifd_len+4))
+ FujiShotSelect = 0;
+
+ if ((FujiShotSelect == 1) && (PrivateMknLength > ifd_len*2)) {
+ ifd_start += (ifd_len+4);
+ CHECKSPACE_ABS2(ifd_start, 4);
+ ifd_len = sget4(PrivateMknBuf +ifd_start);
+ if ((ifd_start+ifd_len) > PrivateMknLength) {
+ ifd_start = s;
+ ifd_len = l;
+ FujiShotSelect = 0;
+ }
+ } else FujiShotSelect = 0;
+
+ CHECKSPACE_ABS3(ifd_start, 4, 4);
+ PrivateEntries = sget4(PrivateMknBuf + ifd_start + 4);
+ if ((PrivateEntries > 1000) ||
+ ((PrivateOrder != 0x4d4d) && (PrivateOrder != 0x4949)))
+ {
+ free(PrivateMknBuf);
+ return;
+ }
+ posPrivateMknBuf = (ifd_start+8);
+
+ /*
+ * because Adobe DNG converter strips or misplaces 0xfnnn tags,
+ * for now, Auto WB is missing for the following cameras:
+ * - F550EXR / F600EXR / F770EXR / F800EXR / F900EXR
+ * - HS10 / HS11 / HS20EXR / HS30EXR / HS33EXR / HS35EXR / HS50EXR
+ * - S1 / SL1000
+ **/
+ while (PrivateEntries--)
+ {
+ order = 0x4d4d;
+ CHECKSPACE(4);
+ PrivateTagID = sget2(PrivateMknBuf + posPrivateMknBuf);
+ PrivateTagBytes = sget2(PrivateMknBuf + posPrivateMknBuf + 2);
+ posPrivateMknBuf += 4;
+ order = PrivateOrder;
+
+ if (PrivateTagID == 0x2000)
+ {
+ get_average_WB(LIBRAW_WBI_Auto);
+ }
+ else if (PrivateTagID == 0x2100)
+ {
+ get_average_WB(LIBRAW_WBI_FineWeather);
+ }
+ else if (PrivateTagID == 0x2200)
+ {
+ get_average_WB(LIBRAW_WBI_Shade);
+ }
+ else if (PrivateTagID == 0x2300)
+ {
+ get_average_WB(LIBRAW_WBI_FL_D);
+ }
+ else if (PrivateTagID == 0x2301)
+ {
+ get_average_WB(LIBRAW_WBI_FL_N);
+ }
+ else if (PrivateTagID == 0x2302)
+ {
+ get_average_WB(LIBRAW_WBI_FL_W);
+ }
+ else if (PrivateTagID == 0x2310)
+ {
+ get_average_WB(LIBRAW_WBI_FL_WW);
+ }
+ else if (PrivateTagID == 0x2311)
+ {
+ get_average_WB(LIBRAW_WBI_FL_L);
+ }
+ else if (PrivateTagID == 0x2400)
+ {
+ get_average_WB(LIBRAW_WBI_Tungsten);
+ }
+ else if (PrivateTagID == 0x2410)
+ {
+ get_average_WB(LIBRAW_WBI_Flash);
+ }
+ else if (PrivateTagID == 0x2f00)
+ {
+ CHECKSPACE(4);
+ int nWBs = MIN(sget4(PrivateMknBuf + posPrivateMknBuf), 6);
+ posWB = posPrivateMknBuf + 4;
+ for (int wb_ind = LIBRAW_WBI_Custom1; wb_ind < LIBRAW_WBI_Custom1+nWBs; wb_ind++) {
+ CHECKSPACE_ABS2(posWB, 8);
+ FORC4 icWBC[wb_ind][GRGB_2_RGBG(c)] =
+ sget2(PrivateMknBuf + posWB + (c << 1));
+ if ((PrivateTagBytes >= unsigned(4+16*nWBs)) && average_WBData) {
+ posWB += 8;
+ CHECKSPACE_ABS2(posWB, 8);
+ FORC4 icWBC[wb_ind][GRGB_2_RGBG(c)] =
+ (icWBC[wb_ind][GRGB_2_RGBG(c)] +
+ sget2(PrivateMknBuf + posWB + (c << 1))) /2;
+ }
+ if (use_WBcorr_coeffs) {
+ icWBC[wb_ind][0] *= wbR_corr;
+ icWBC[wb_ind][2] *= wbB_corr;
+ }
+ posWB += 8;
+ }
+ }
+ else if (PrivateTagID == 0x2ff0)
+ {
+ get_average_WB(LIBRAW_WBI_AsShot);
+ FORC4 cam_mul[c] = icWBC[LIBRAW_WBI_AsShot][c];
+ }
+ else if ((PrivateTagID == 0x4000) &&
+ ((PrivateTagBytes == 8) || (PrivateTagBytes == 16)))
+ {
+ imFuji.BlackLevel[0] = PrivateTagBytes / 2;
+ CHECKSPACE(10);
+ FORC4 imFuji.BlackLevel[GRGB_2_RGBG(c)+1] =
+ sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
+ if (imFuji.BlackLevel[0] == 8) {
+ CHECKSPACE(18);
+ FORC4 imFuji.BlackLevel[GRGB_2_RGBG(c) + 5] =
+ sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1) + 8);
+ }
+ }
+ else if (PrivateTagID == 0x9650)
+ {
+ CHECKSPACE(4);
+ short a = (short)sget2(PrivateMknBuf + posPrivateMknBuf);
+ float b = fMAX(1.0f, sget2(PrivateMknBuf + posPrivateMknBuf + 2));
+ imFuji.ExpoMidPointShift = a / b;
+ imCommon.ExposureCalibrationShift += imFuji.ExpoMidPointShift;
+ }
+ else if ((PrivateTagID == 0xc000) && (PrivateTagBytes > 3) &&
+ (PrivateTagBytes < 10240000))
+ {
+ order = 0x4949;
+ if (PrivateTagBytes != 4096) // not one of Fuji X-A3, X-A5, X-A7, X-A10, X-A20, X-T100, X-T200, XF10
+ {
+ int is34 = 0;
+ CHECKSPACE(8);
+ guess_RAFDataGeneration (PrivateMknBuf + posPrivateMknBuf);
+// printf ("RAFDataVersion: 0x%04x, RAFDataGeneration: %d\n",
+// imFuji.RAFDataVersion, imFuji.RAFDataGeneration);
+
+ for (posWB = 0; posWB < (int)PrivateTagBytes - 16; posWB++)
+ {
+ CHECKSPACE_ABS2(posWB, 12);
+ if ((!memcmp(PrivateMknBuf + posWB, "TSNERDTS", 8) &&
+ (sget2(PrivateMknBuf + posWB + 10) > 125)))
+ {
+ posWB += 10;
+ icWBC[LIBRAW_WBI_Auto][1] =
+ icWBC[LIBRAW_WBI_Auto][3] =
+ sget2(PrivateMknBuf + posWB);
+ icWBC[LIBRAW_WBI_Auto][0] =
+ sget2(PrivateMknBuf + posWB + 2);
+ icWBC[LIBRAW_WBI_Auto][2] =
+ sget2(PrivateMknBuf + posWB + 4);
+ break;
+ }
+ }
+
+ if ((imFuji.RAFDataVersion == 0x0260) || // X-Pro3, GFX 100S
+ (imFuji.RAFDataVersion == 0x0261) || // X100V, GFX 50S II
+ (imFuji.RAFDataVersion == 0x0262) || // X-T4
+ (imFuji.RAFDataVersion == 0x0264) || // X-S10
+ (imFuji.RAFDataVersion == 0x0265) || // X-E4
+ (imFuji.RAFDataVersion == 0x0266) || // X-T30 II
+ !strcmp(model, "X-Pro3") ||
+ !strcmp(model, "GFX 100S") ||
+ !strcmp(model, "GFX100S") ||
+ !strcmp(model, "GFX 50S II") ||
+ !strcmp(model, "GFX50S II") ||
+ !strcmp(model, "X100V") ||
+ !strcmp(model, "X-T4") ||
+ !strcmp(model, "X-E4") ||
+ !strcmp(model, "X-T30 II") ||
+ !strcmp(model, "X-S10"))
+ is34 = 1;
+
+ if (imFuji.RAFDataVersion == 0x4500) // X-E1, RAFData gen. 3
+ {
+ wb_section_offset = 0x13ac;
+ }
+ else if (imFuji.RAFDataVersion == 0x0146 || // X20
+ imFuji.RAFDataVersion == 0x0149 || // X100S
+ imFuji.RAFDataVersion == 0x0249) // X100S
+ {
+ wb_section_offset = 0x1410;
+ }
+ else if (imFuji.RAFDataVersion == 0x014d || // X-M1
+ imFuji.RAFDataVersion == 0x014e) // X-A1, X-A2
+ {
+ wb_section_offset = 0x1474;
+ }
+ else if (imFuji.RAFDataVersion == 0x014f || // X-E2
+ imFuji.RAFDataVersion == 0x024f || // X-E2
+ imFuji.RAFDataVersion == 0x025d || // X-H1
+ imFuji.RAFDataVersion == 0x035d) // X-H1
+ {
+ wb_section_offset = 0x1480;
+ }
+ else if (imFuji.RAFDataVersion == 0x0150) // XQ1, XQ2
+ {
+ wb_section_offset = 0x1414;
+ }
+ else if (imFuji.RAFDataVersion == 0x0151 || // X-T1 w/diff. fws
+ imFuji.RAFDataVersion == 0x0251 || imFuji.RAFDataVersion == 0x0351 ||
+ imFuji.RAFDataVersion == 0x0451 || imFuji.RAFDataVersion == 0x0551)
+ {
+ wb_section_offset = 0x14b0;
+ }
+ else if (imFuji.RAFDataVersion == 0x0152 || // X30
+ imFuji.RAFDataVersion == 0x0153) // X100T
+ {
+ wb_section_offset = 0x1444;
+ }
+ else if (imFuji.RAFDataVersion == 0x0154) // X-T10
+ {
+ wb_section_offset = 0x1824;
+ }
+ else if (imFuji.RAFDataVersion == 0x0155) // X70
+ {
+ wb_section_offset = 0x17b4;
+ }
+ else if (imFuji.RAFDataVersion == 0x0255 || // X-Pro2
+ imFuji.RAFDataVersion == 0x0455)
+ {
+ wb_section_offset = 0x135c;
+ }
+ else if (imFuji.RAFDataVersion == 0x0258 || // X-T2
+ imFuji.RAFDataVersion == 0x025b) // X-T20
+ {
+ wb_section_offset = 0x13dc;
+ }
+ else if (imFuji.RAFDataVersion == 0x0259) // X100F
+ {
+ wb_section_offset = 0x1370;
+ }
+ else if (imFuji.RAFDataVersion == 0x025a || // GFX 50S
+ imFuji.RAFDataVersion == 0x045a)
+ {
+ wb_section_offset = 0x1424;
+ }
+ else if (imFuji.RAFDataVersion == 0x025c) // X-E3
+ {
+ wb_section_offset = 0x141c;
+ }
+ else if (imFuji.RAFDataVersion == 0x025e) // X-T3
+ {
+ wb_section_offset = 0x2014;
+ }
+ else if (imFuji.RAFDataVersion == 0x025f) // X-T30, GFX 50R, GFX 100 (? RAFDataVersion 0x045f)
+ {
+ if (!strcmp(model, "X-T30")) {
+ CHECKSPACE(0x20b8 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20b8))
+ wb_section_offset = 0x20b8;
+ else
+ {
+ CHECKSPACE(0x20c8 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20c8))
+ wb_section_offset = 0x20c8;
+ }
+ }
+ else if (!strcmp(model, "GFX 50R"))
+ wb_section_offset = 0x1424;
+ else if (!strcmp(model, "GFX 100"))
+ wb_section_offset = 0x20e4;
+ }
+ else if (imFuji.RAFDataVersion == 0x0260) // X-Pro3, GFX 100S
+ {
+ if (!strcmp(model, "X-Pro3"))
+ wb_section_offset = 0x20e8;
+ else if (!strcmp(model, "GFX 100S") || !strcmp(model, "GFX100S"))
+ wb_section_offset = 0x2108;
+ }
+ else if (imFuji.RAFDataVersion == 0x0261) // X100V, GFX 50S II
+ {
+ if (!strcmp(model, "X100V"))
+ wb_section_offset = 0x2078;
+ else if (!strcmp(model, "GFX 50S II") || !strcmp(model, "GFX50S II"))
+ wb_section_offset = 0x214c;
+ }
+ else if (imFuji.RAFDataVersion == 0x0262) // X-T4
+ {
+ wb_section_offset = 0x21c8;
+ }
+ else if (imFuji.RAFDataVersion == 0x0264) // X-S10
+ {
+ wb_section_offset = 0x21de;
+ }
+ else if ((imFuji.RAFDataVersion == 0x0265) || // X-E4
+ (imFuji.RAFDataVersion == 0x0266)) // X-T30 II
+ {
+ wb_section_offset = 0x21cc;
+ }
+ else if (imFuji.RAFDataVersion == 0x0355) // X-E2S
+ {
+ wb_section_offset = 0x1840;
+ }
+
+/* try for unknown RAF Data versions */
+ else if (!strcmp(model, "X-Pro2"))
+ {
+ CHECKSPACE(0x135c + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x135c))
+ wb_section_offset = 0x135c;
+ }
+ else if (!strcmp(model, "X100F"))
+ {
+ CHECKSPACE(0x1370 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1370))
+ wb_section_offset = 0x1370;
+ }
+ else if (!strcmp(model, "X-E1"))
+ {
+ CHECKSPACE(0x13ac + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x13ac))
+ wb_section_offset = 0x13ac;
+ }
+ else if (!strcmp(model, "X-T2") ||
+ !strcmp(model, "X-T20"))
+ {
+ CHECKSPACE(0x13dc + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x13dc))
+ wb_section_offset = 0x13dc;
+ }
+ else if (!strcmp(model, "X20") ||
+ !strcmp(model, "X100S"))
+ {
+ CHECKSPACE(0x1410 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1410))
+ wb_section_offset = 0x1410;
+ }
+ else if (!strcmp(model, "XQ1") ||
+ !strcmp(model, "XQ2"))
+ {
+ CHECKSPACE(0x1414+ 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1414))
+ wb_section_offset = 0x1414;
+ }
+ else if (!strcmp(model, "X-E3"))
+ {
+ CHECKSPACE(0x141c + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x141c))
+ wb_section_offset = 0x141c;
+ }
+ else if (!strcmp(model, "GFX 50S") ||
+ !strcmp(model, "GFX 50R"))
+ {
+ CHECKSPACE(0x1424 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1424))
+ wb_section_offset = 0x1424;
+ }
+ else if (!strcmp(model, "GFX 50S II") || !strcmp(model, "GFX50S II")) {
+ CHECKSPACE(0x214c + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x214c))
+ wb_section_offset = 0x214c;
+ }
+ else if (!strcmp(model, "X30") ||
+ !strcmp(model, "X100T"))
+ {
+ CHECKSPACE(0x1444 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1444))
+ wb_section_offset = 0x1444;
+ }
+ else if (!strcmp(model, "X-M1") ||
+ !strcmp(model, "X-A1") ||
+ !strcmp(model, "X-A2"))
+ {
+ CHECKSPACE(0x1474 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1474))
+ wb_section_offset = 0x1474;
+ }
+ else if (!strcmp(model, "X-E2") ||
+ !strcmp(model, "X-H1"))
+ {
+ CHECKSPACE(0x1480 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1480))
+ wb_section_offset = 0x1480;
+ }
+ else if (!strcmp(model, "X-T1"))
+ {
+ CHECKSPACE(0x14b0 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x14b0))
+ wb_section_offset = 0x14b0;
+ }
+ else if (!strcmp(model, "X70"))
+ {
+ CHECKSPACE(0x17b4 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x17b4))
+ wb_section_offset = 0x17b4;
+ }
+ else if (!strcmp(model, "X-T10"))
+ {
+ CHECKSPACE(0x1824 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1824))
+ wb_section_offset = 0x1824;
+ }
+ else if (!strcmp(model, "X-E2S"))
+ {
+ CHECKSPACE(0x1840 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1840))
+ wb_section_offset = 0x1840;
+ }
+ else if (!strcmp(model, "X-T3"))
+ {
+ CHECKSPACE(0x2014 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x2014))
+ wb_section_offset = 0x2014;
+ }
+ else if (!strcmp(model, "X100V"))
+ {
+ CHECKSPACE(0x2078 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x2078))
+ wb_section_offset = 0x2078;
+ }
+ else if (!strcmp(model, "X-T30"))
+ {
+ CHECKSPACE(0x20b8 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20b8))
+ wb_section_offset = 0x20b8;
+ else
+ {
+ CHECKSPACE(0x20c8 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20c8))
+ wb_section_offset = 0x20c8;
+ }
+ }
+ else if (!strcmp(model, "GFX 100"))
+ {
+ CHECKSPACE(0x20e4 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20e4))
+ wb_section_offset = 0x20e4;
+ }
+ else if (!strcmp(model, "X-Pro3"))
+ {
+ CHECKSPACE(0x20e8 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20e8))
+ wb_section_offset = 0x20e8;
+ }
+ else if (!strcmp(model, "GFX100S") || !strcmp(model, "GFX 100S"))
+ {
+ CHECKSPACE(0x2108 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x2108))
+ wb_section_offset = 0x2108;
+ }
+ else if (!strcmp(model, "X-T4"))
+ {
+ CHECKSPACE(0x21c8 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x21c8))
+ wb_section_offset = 0x21c8;
+ }
+ else if ((!strcmp(model, "X-E4")) ||
+ (!strcmp(model, "X-T30 II")))
+ {
+ CHECKSPACE(0x21cc + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x21cc))
+ wb_section_offset = 0x21cc;
+ }
+ else if (!strcmp(model, "X-S10"))
+ {
+ CHECKSPACE(0x21de + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x21de))
+ wb_section_offset = 0x21de;
+ }
+/* no RAF Data version for the models below */
+ else if (!strcmp(model, "FinePix X100")) // X100 0 0x19f0 0x19e8
+ {
+ if (!strcmp(imFuji.RAFVersion, "0069"))
+ wb_section_offset = 0x19e8;
+ else if (!strcmp(imFuji.RAFVersion, "0100") ||
+ !strcmp(imFuji.RAFVersion, "0110"))
+ wb_section_offset = 0x19f0;
+ else
+ {
+ CHECKSPACE(0x19e8 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x19e8))
+ wb_section_offset = 0x19e8;
+ else
+ {
+ CHECKSPACE(0x19f0 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x19f0))
+ wb_section_offset = 0x19f0;
+ }
+ }
+ }
+ else if (!strcmp(model, "X-Pro1")) // X-Pro1 0 0x13a4
+ {
+ if (!strcmp(imFuji.RAFVersion, "0100") ||
+ !strcmp(imFuji.RAFVersion, "0101") ||
+ !strcmp(imFuji.RAFVersion, "0204"))
+ wb_section_offset = 0x13a4;
+ else
+ {
+ CHECKSPACE(0x13a4 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x13a4))
+ wb_section_offset = 0x13a4;
+ }
+ }
+ else if (!strcmp(model, "XF1")) // XF1 0 0x138c
+ {
+ if (!strcmp(imFuji.RAFVersion, "0100"))
+ wb_section_offset = 0x138c;
+ else
+ {
+ CHECKSPACE(0x138c + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x138c))
+ wb_section_offset = 0x138c;
+ }
+ }
+ else if (!strcmp(model, "X-S1")) // X-S1 0 0x1284
+ {
+ if (!strcmp(imFuji.RAFVersion, "0100"))
+ wb_section_offset = 0x1284;
+ else
+ {
+ CHECKSPACE(0x1284 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1284))
+ wb_section_offset = 0x1284;
+ }
+ }
+ else if (!strcmp(model, "X10")) // X10 0 0x1280 0x12d4
+ {
+ if (!strcmp(imFuji.RAFVersion, "0100") ||
+ !strcmp(imFuji.RAFVersion, "0102"))
+ wb_section_offset = 0x1280;
+ else if (!strcmp(imFuji.RAFVersion, "0103"))
+ wb_section_offset = 0x12d4;
+ else
+ {
+ CHECKSPACE(0x1280 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1280))
+ wb_section_offset = 0x1280;
+ else
+ {
+ CHECKSPACE(0x12d4 + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x12d4))
+ wb_section_offset = 0x12d4;
+ }
+ }
+ }
+ else if (!strcmp(model, "XF1")) // XF1 0 0x138c
+ {
+ if (!strcmp(imFuji.RAFVersion, "0100"))
+ wb_section_offset = 0x138c;
+ else
+ {
+ CHECKSPACE(0x138c + 12);
+ if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x138c))
+ wb_section_offset = 0x138c;
+ }
+ }
+
+ if (wb_section_offset)
+ {
+ CHECKSPACE(wb_section_offset + 12);
+ }
+
+ if (wb_section_offset &&
+ isWB(PrivateMknBuf + posPrivateMknBuf + wb_section_offset))
+ {
+
+ if (!imFuji.RAFDataVersion)
+ {
+ posWB = posPrivateMknBuf + wb_section_offset - 6;
+ CHECKSPACE_ABS2(posWB, 6);
+ icWBC[LIBRAW_WBI_Auto][1] =
+ icWBC[LIBRAW_WBI_Auto][3] =
+ sget2(PrivateMknBuf + posWB);
+ icWBC[LIBRAW_WBI_Auto][0] =
+ sget2(PrivateMknBuf + posWB + 2);
+ icWBC[LIBRAW_WBI_Auto][2] =
+ sget2(PrivateMknBuf + posWB + 4);
+ }
+
+ posWB = posPrivateMknBuf + wb_section_offset;
+ for (int wb_ind = 0; wb_ind < (int)Fuji_wb_list1.size(); posWB += 6, wb_ind++)
+ {
+ CHECKSPACE_ABS2(posWB, 6);
+ icWBC[Fuji_wb_list1[wb_ind]][1] =
+ icWBC[Fuji_wb_list1[wb_ind]][3] =
+ sget2(PrivateMknBuf + posWB);
+ icWBC[Fuji_wb_list1[wb_ind]][0] =
+ sget2(PrivateMknBuf + posWB + 2);
+ icWBC[Fuji_wb_list1[wb_ind]][2] =
+ sget2(PrivateMknBuf + posWB + 4);
+ }
+ int found = 0;
+ if (is34)
+ posWB += 0x30;
+ posWB += 0xc0;
+ CHECKSPACE_ABS2(posWB, 2);
+ ushort Gval = sget2(PrivateMknBuf + posWB);
+ for (int posEndCCTsection = posWB; posEndCCTsection < (posWB + 30);
+ posEndCCTsection += 6)
+ {
+ CHECKSPACE_ABS2(posEndCCTsection, 2);
+ if (sget2(PrivateMknBuf + posEndCCTsection) != Gval)
+ {
+ if (is34)
+ wb_section_offset = posEndCCTsection - 34*3*2; // 34 records, 3 2-byte values in a record
+ else
+ wb_section_offset = posEndCCTsection - 31*3*2; // 31 records, 3 2-byte values in a record
+ found = 1;
+ break;
+ }
+ }
+
+ if (found)
+ {
+ for (int iCCT = 0; iCCT < 31; iCCT++)
+ {
+ CHECKSPACE_ABS2(wb_section_offset, iCCT*6+6);
+ icWBCCTC[iCCT][0] = FujiCCT_K[iCCT];
+ icWBCCTC[iCCT][1] = sget2(PrivateMknBuf + wb_section_offset + iCCT * 6 + 2);
+ icWBCCTC[iCCT][2] = icWBCCTC[iCCT][4] = sget2(PrivateMknBuf + wb_section_offset + iCCT * 6);
+ icWBCCTC[iCCT][3] = sget2(PrivateMknBuf + wb_section_offset + iCCT * 6 + 4);
+ }
+ }
+ }
+ }
+ else // process 4K raf data
+ {
+ int wb[4];
+ int nWB, tWB, pWB;
+ int iCCT = 0;
+ imFuji.RAFDataGeneration = 4096; // X-A3, X-A5, X-A7, X-A10, X-A20, X-T100, X-T200, XF10
+ posWB = posPrivateMknBuf + 0x200;
+ for (int wb_ind = 0; wb_ind < 42; wb_ind++)
+ {
+ CHECKSPACE_ABS2(posWB, 24);
+ nWB = sget4(PrivateMknBuf + posWB);
+ posWB += 4;
+ tWB = sget4(PrivateMknBuf + posWB);
+ posWB += 4;
+ wb[0] = sget4(PrivateMknBuf + posWB) << 1;
+ posWB += 4;
+ wb[1] = sget4(PrivateMknBuf + posWB);
+ posWB += 4;
+ wb[3] = sget4(PrivateMknBuf + posWB);
+ posWB += 4;
+ wb[2] = sget4(PrivateMknBuf + posWB) << 1;
+ posWB += 4;
+
+ if (tWB && (iCCT < 255))
+ {
+ icWBCCTC[iCCT][0] = tWB;
+ FORC4 icWBCCTC[iCCT][c + 1] = wb[c];
+ iCCT++;
+ }
+ if (nWB != 0x46)
+ {
+ for (pWB = 1; pWB < (int)Fuji_wb_list2.size(); pWB += 2)
+ {
+ if (Fuji_wb_list2[pWB] == nWB)
+ {
+ FORC4 icWBC[Fuji_wb_list2[pWB - 1]][c] = wb[c];
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ posPrivateMknBuf += PrivateTagBytes;
+ }
+ free(PrivateMknBuf);
+ }
+#undef get_average_WB
+#undef CHECKSPACE
+#undef CHECKSPACE_ABS2
+#undef CHECKSPACE_ABS3
+}
+
+void LibRaw::parseFujiMakernotes(unsigned tag, unsigned type, unsigned len,
+ unsigned /*dng_writer*/)
+{
+ if (tag == 0x0010)
+ {
+ char FujiSerial[sizeof(imgdata.shootinginfo.InternalBodySerial)];
+ char *words[4] = { 0,0,0,0 };
+ char yy[2], mm[3], dd[3], ystr[16], ynum[16];
+ int year, nwords, ynum_len;
+ unsigned c;
+ memset(FujiSerial, 0, sizeof(imgdata.shootinginfo.InternalBodySerial));
+ ifp->read(FujiSerial, MIN(len,sizeof(FujiSerial)), 1);
+ nwords = getwords(FujiSerial, words, 4,
+ sizeof(imgdata.shootinginfo.InternalBodySerial));
+ for (int i = 0; i < nwords; i++)
+ {
+ if (!words[i]) break; // probably damaged input
+ mm[2] = dd[2] = 0;
+ if (strnlen(words[i],
+ sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) < 18)
+ {
+ if (i == 0)
+ {
+ strncpy(imgdata.shootinginfo.InternalBodySerial, words[0],
+ sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
+ }
+ else
+ {
+ char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
+ snprintf(tbuf, sizeof(tbuf)-1, "%s %s",
+ imgdata.shootinginfo.InternalBodySerial, words[i]);
+ strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf,
+ sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
+ }
+ }
+ else
+ {
+ strncpy(
+ dd,
+ words[i] +
+ strnlen(words[i],
+ sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
+ 14,
+ 2);
+ strncpy(
+ mm,
+ words[i] +
+ strnlen(words[i],
+ sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
+ 16,
+ 2);
+ strncpy(
+ yy,
+ words[i] +
+ strnlen(words[i],
+ sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
+ 18,
+ 2);
+ year = (yy[0] - '0') * 10 + (yy[1] - '0');
+ if (year < 70)
+ year += 2000;
+ else
+ year += 1900;
+
+ ynum_len = MIN(
+ int(sizeof(ynum) - 1),
+ (int)strnlen(words[i],
+ sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
+ 18);
+ strncpy(ynum, words[i], ynum_len);
+ ynum[ynum_len] = 0;
+ for (int j = 0; ynum[j] && ynum[j + 1] && sscanf(ynum + j, "%2x", &c);
+ j += 2)
+ ystr[j / 2] = c;
+ ynum_len /= 2;
+ ystr[ynum_len + 1] = 0;
+ strcpy(model2, ystr);
+
+ if (i == 0)
+ {
+ char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
+
+ if (nwords == 1)
+ {
+ snprintf(
+ tbuf, sizeof(tbuf), "%s %d:%s:%s %s",
+ ystr, year, mm, dd,
+ words[0] +
+ strnlen(words[0], sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-12);
+ }
+ else
+ {
+ snprintf(
+ tbuf, sizeof(tbuf), "%s %d:%s:%s %s", ystr, year, mm, dd,
+ words[0] +
+ strnlen(words[0],
+ sizeof(imgdata.shootinginfo.InternalBodySerial) -
+ 1) -
+ 12);
+ }
+ strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf,
+ sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
+ }
+ else
+ {
+ char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
+ snprintf(
+ tbuf, sizeof(tbuf), "%s %s %d:%s:%s %s",
+ imgdata.shootinginfo.InternalBodySerial, ystr, year, mm, dd,
+ words[i] +
+ strnlen(words[i],
+ sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
+ 12);
+ strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf,
+ sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
+ }
+ }
+ }
+ }
+ else
+ switch (tag)
+ {
+ case 0x1002:
+ imFuji.WB_Preset = get2();
+ break;
+ case 0x1011:
+ imCommon.FlashEC = getreal(type);
+ break;
+ case 0x1020:
+ imFuji.Macro = get2();
+ break;
+ case 0x1021:
+ imFuji.FocusMode = imgdata.shootinginfo.FocusMode = get2();
+ break;
+ case 0x1022:
+ imFuji.AFMode = get2();
+ break;
+ case 0x1023:
+ imFuji.FocusPixel[0] = get2();
+ imFuji.FocusPixel[1] = get2();
+ break;
+ case 0x102b:
+ imFuji.PrioritySettings = get2();
+ break;
+ case 0x102d:
+ imFuji.FocusSettings = get4();
+ break;
+ case 0x102e:
+ imFuji.AF_C_Settings = get4();
+ break;
+ case 0x1034:
+ imFuji.ExrMode = get2();
+ break;
+ case 0x104d:
+ FujiCropMode = get2(); // odd: one of raw dimensions here can be lost
+ break;
+ case 0x1050:
+ imFuji.ShutterType = get2();
+ break;
+ case 0x1100:
+ imFuji.AutoBracketing = get2(); // AutoBracketing = 6 for pixel shift mode
+ break;
+ case 0x1101:
+ imFuji.SequenceNumber = get2();
+ break;
+ case 0x1103:
+ imgdata.shootinginfo.DriveMode = get2();
+ imFuji.DriveMode = imgdata.shootinginfo.DriveMode & 0xff;
+ break;
+ case 0x1105:
+ imFuji.SeriesLength = get2();
+ break;
+ case 0x1106:
+ imFuji.PixelShiftOffset[0] = getreal(type);
+ imFuji.PixelShiftOffset[1] = getreal(type);
+ break;
+ case 0x1301:
+ imFuji.FocusWarning = get2();
+ break;
+ case 0x1400:
+ imFuji.DynamicRange = get2();
+ break;
+ case 0x1401:
+ imFuji.FilmMode = get2();
+ break;
+ case 0x1402:
+ imFuji.DynamicRangeSetting = get2();
+ break;
+ case 0x1403:
+ imFuji.DevelopmentDynamicRange = get2();
+ break;
+ case 0x1404:
+ ilm.MinFocal = getreal(type);
+ break;
+ case 0x1405:
+ ilm.MaxFocal = getreal(type);
+ break;
+ case 0x1406:
+ ilm.MaxAp4MinFocal = getreal(type);
+ break;
+ case 0x1407:
+ ilm.MaxAp4MaxFocal = getreal(type);
+ break;
+ case 0x140b:
+ imFuji.AutoDynamicRange = get2();
+ break;
+ case 0x1422:
+ imFuji.ImageStabilization[0] = get2();
+ imFuji.ImageStabilization[1] = get2();
+ imFuji.ImageStabilization[2] = get2();
+ imgdata.shootinginfo.ImageStabilization =
+ (imFuji.ImageStabilization[0] << 9) + imFuji.ImageStabilization[1];
+ break;
+ case 0x1438:
+ imFuji.ImageCount = get2();
+ break;
+ case 0x1431:
+ imFuji.Rating = get4();
+ break;
+ case 0x1443:
+ imFuji.DRangePriority = get2();
+ break;
+ case 0x1444:
+ imFuji.DRangePriorityAuto = get2();
+ break;
+ case 0x1445:
+ imFuji.DRangePriorityFixed = get2();
+ break;
+ }
+ return;
+}
+
+void LibRaw::parse_fuji_thumbnail(int offset)
+{
+ uchar xmpmarker[] = "http://ns.adobe.com/xap/1.0/";
+ uchar buf[sizeof(xmpmarker)+1];
+ int xmpsz = sizeof(xmpmarker); // we do not
+
+ INT64 pos = ftell(ifp);
+ fseek(ifp, offset, SEEK_SET);
+ ushort s_order = order;
+ order = 0x4a4a; // JPEG is always in MM order
+
+ if (get2() == 0xFFD8)
+ {
+ while (1)
+ {
+ ushort tag = get2();
+ if (tag != 0xFFE1 && tag != 0xFFE2) // allow APP1/APP2 only
+ break;
+ INT64 tpos = ftell(ifp);
+ int len = get2();
+ if (len > xmpsz + 2)
+ {
+ if ((fread(buf, 1, xmpsz, ifp) == xmpsz) && !memcmp(buf, xmpmarker, xmpsz)) // got it
+ {
+ xmplen = len - xmpsz - 2;
+ xmpdata = (char*) malloc(xmplen+1);
+ fread(xmpdata, 1, xmplen, ifp);
+ xmpdata[xmplen] = 0;
+ break;
+ }
+ }
+ fseek(ifp, tpos + len, SEEK_SET);
+ }
+ }
+
+ order = s_order;
+ fseek(ifp, pos, SEEK_SET);
+}
+
+void LibRaw::parse_fuji(int offset)
+{
+ unsigned entries, tag, len, save, c;
+
+#define get_average_WB(wb_index) \
+ FORC4 icWBC[wb_index][GRGB_2_RGBG(c)] = get2(); \
+ if ((len == 16) && average_WBData) { \
+ FORC4 icWBC[wb_index][GRGB_2_RGBG(c)] = \
+ (icWBC[wb_index][GRGB_2_RGBG(c)] + get2())/2; \
+ } \
+ if (use_WBcorr_coeffs) { \
+ icWBC[wb_index][0] *= wbR_corr; \
+ icWBC[wb_index][2] *= wbB_corr; \
+ }
+
+ ushort raw_inset_present = 0;
+ ushort use_WBcorr_coeffs = 0;
+ double wbR_corr = 1.0;
+ double wbB_corr = 1.0;
+ ilm.CamID = unique_id;
+ int average_WBData = 1;
+
+ fseek(ifp, offset, SEEK_SET);
+ entries = get4();
+ if (entries > 255)
+ return;
+ imgdata.process_warnings |= LIBRAW_WARN_PARSEFUJI_PROCESSED;
+
+ if (strstr(model, "S2Pro")
+ || strstr(model, "S20Pro")
+ || strstr(model, "F700")
+ || strstr(model, "S5000")
+ || strstr(model, "S7000")
+ ) {
+ use_WBcorr_coeffs = 1;
+ wbR_corr = 10.0 / 17.0 / 0.652941;
+ wbB_corr = 2.0 /3.0 / (3.0 / 4.0 + 1.0 / 300.0);
+ } else if (strstr(model, "DBP") || strstr(model, "DX-2000")) {
+ use_WBcorr_coeffs = 1;
+ wbR_corr = 0.7632653061;
+ wbB_corr = 0.8591549296;
+ }
+
+ while (entries--)
+ {
+ tag = get2();
+ len = get2();
+ save = ftell(ifp);
+ if (tag == 0x0100) // RawImageFullSize
+ {
+ raw_height = get2();
+ raw_width = get2();
+ raw_inset_present = 1;
+ }
+ else if ((tag == 0x0110) && raw_inset_present) // RawImageCropTopLeft
+ {
+ imgdata.sizes.raw_inset_crops[0].ctop = get2();
+ imgdata.sizes.raw_inset_crops[0].cleft = get2();
+ }
+ else if ((tag == 0x0111) && raw_inset_present) // RawImageCroppedSize
+ {
+ imgdata.sizes.raw_inset_crops[0].cheight = get2();
+ imgdata.sizes.raw_inset_crops[0].cwidth = get2();
+ }
+ else if ((tag == 0x0115) && raw_inset_present) // RawImageAspectRatio
+ {
+ int a = get2();
+ int b = get2();
+ if (a * b == 6)
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
+ else if (a * b == 12)
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_4to3;
+ else if (a * b == 144)
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_16to9;
+ else if (a * b == 1)
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_1to1;
+ }
+ else if (tag == 0x0121) // RawImageSize
+ {
+ height = get2();
+ if ((width = get2()) == 4284)
+ width += 3;
+ }
+ else if (tag == 0x0130) // FujiLayout,
+ {
+ fuji_layout = fgetc(ifp) >> 7;
+ fuji_width = !(fgetc(ifp) & 8);
+ }
+ else if (tag == 0x0131) // XTransLayout
+ {
+ filters = 9;
+ char *xtrans_abs_alias = &xtrans_abs[0][0];
+ FORC(36)
+ {
+ int q = fgetc(ifp);
+ xtrans_abs_alias[35 - c] = MAX(0, MIN(q, 2)); /* & 3;*/
+ }
+ }
+ else if (tag == 0x2ff0) // WB_GRGBLevels
+ {
+ get_average_WB(LIBRAW_WBI_AsShot);
+ FORC4 cam_mul[c] = icWBC[LIBRAW_WBI_AsShot][c];
+ }
+ else if ((tag == 0x4000) &&
+ ((len == 8) || (len == 16)))
+ {
+ imFuji.BlackLevel[0] = len / 2;
+ FORC4 imFuji.BlackLevel[GRGB_2_RGBG(c)+1] = get2();
+ if (imFuji.BlackLevel[0] == 8)
+ FORC4 imFuji.BlackLevel[GRGB_2_RGBG(c)+5] = get2();
+ if (imFuji.BlackLevel[0] == 4)
+ FORC4 cblack[c] = imFuji.BlackLevel[c+1];
+ else if (imFuji.BlackLevel[0] == 8)
+ FORC4 cblack[c] = (imFuji.BlackLevel[c+1]+imFuji.BlackLevel[c+5]) /2;
+ }
+ else if (tag == 0x9200) // RelativeExposure
+ {
+ int s1 = get2();
+ int s2 = get2();
+ if ((s1 == s2) || !s1)
+ imFuji.BrightnessCompensation = 0.0f;
+ else if ((s1*4) == s2)
+ imFuji.BrightnessCompensation = 2.0f;
+ else if ((s1*16) == s2)
+ imFuji.BrightnessCompensation = 4.0f;
+ else
+ imFuji.BrightnessCompensation = log(double(s2)/double(s1))/log(2.0);
+ }
+ else if (tag == 0x9650) // RawExposureBias
+ {
+ short a = (short)get2();
+ float b = fMAX(1.0f, get2());
+ imFuji.ExpoMidPointShift = a / b;
+ imCommon.ExposureCalibrationShift += imFuji.ExpoMidPointShift;
+ }
+ else if (tag == 0x2000) // WB_GRGBLevelsAuto
+ {
+ get_average_WB(LIBRAW_WBI_Auto);
+ }
+ else if (tag == 0x2100) // WB_GRGBLevelsDaylight
+ {
+ get_average_WB(LIBRAW_WBI_FineWeather);
+ }
+ else if (tag == 0x2200) // WB_GRGBLevelsCloudy
+ {
+ get_average_WB(LIBRAW_WBI_Shade);
+ }
+ else if (tag == 0x2300) // WB_GRGBLevelsDaylightFluor
+ {
+ get_average_WB(LIBRAW_WBI_FL_D);
+ }
+ else if (tag == 0x2301) // WB_GRGBLevelsDayWhiteFluor
+ {
+ get_average_WB(LIBRAW_WBI_FL_N);
+ }
+ else if (tag == 0x2302) // WB_GRGBLevelsWhiteFluorescent
+ {
+ get_average_WB(LIBRAW_WBI_FL_W);
+ }
+ else if (tag == 0x2310) // WB_GRGBLevelsWarmWhiteFluor
+ {
+ get_average_WB(LIBRAW_WBI_FL_WW);
+ }
+ else if (tag == 0x2311) // WB_GRGBLevelsLivingRoomWarmWhiteFluor
+ {
+ get_average_WB(LIBRAW_WBI_FL_L);
+ }
+ else if (tag == 0x2400) // WB_GRGBLevelsTungsten
+ {
+ get_average_WB(LIBRAW_WBI_Tungsten);
+ }
+ else if (tag == 0x2410)
+ {
+ get_average_WB(LIBRAW_WBI_Flash);
+ }
+ else if (tag == 0x2f00) // WB_GRGBLevels
+ {
+ int nWBs = get4();
+ nWBs = MIN(nWBs, 6);
+ for (int wb_ind = LIBRAW_WBI_Custom1; wb_ind < LIBRAW_WBI_Custom1+nWBs; wb_ind++) {
+ FORC4 icWBC[wb_ind][GRGB_2_RGBG(c)] = get2();
+ if ((len >= unsigned(4+16*nWBs)) && average_WBData) {
+ FORC4 icWBC[wb_ind][GRGB_2_RGBG(c)] =
+ (icWBC[wb_ind][GRGB_2_RGBG(c)] +get2()) /2;
+ }
+ if (use_WBcorr_coeffs) {
+ icWBC[LIBRAW_WBI_Custom1 + wb_ind][0] *= wbR_corr;
+ icWBC[LIBRAW_WBI_Custom1 + wb_ind][2] *= wbB_corr;
+ }
+ }
+ }
+
+ else if (tag == 0xc000) // RAFData
+ {
+ int offsetWH_inRAFData;
+ unsigned save_order = order;
+ order = 0x4949;
+ if (len > 20000)
+ {
+ uchar RAFDataHeader[16];
+ libraw_internal_data.unpacker_data.posRAFData = save;
+ libraw_internal_data.unpacker_data.lenRAFData = (len >> 1);
+ fread(RAFDataHeader, sizeof RAFDataHeader, 1, ifp);
+ offsetWH_inRAFData = guess_RAFDataGeneration(RAFDataHeader);
+ fseek(ifp, offsetWH_inRAFData-int(sizeof RAFDataHeader), SEEK_CUR);
+ for (int i=0;
+ i< (int)((sizeof imFuji.RAFData_ImageSizeTable) / (sizeof imFuji.RAFData_ImageSizeTable[0]));
+ i++) {
+ imFuji.RAFData_ImageSizeTable[i] = get4();
+ }
+
+// if ((width > raw_width)
+// || (raw_inset_present && (width < imgdata.sizes.raw_inset_crops[0].cwidth))
+// )
+// width = raw_width;
+// if ((height > raw_height)
+// || (raw_inset_present && (height < imgdata.sizes.raw_inset_crops[0].cheight))
+// )
+// height = raw_height;
+//
+
+ }
+ else if (len == 4096) // X-A3, X-A5, X-A7, X-A10, X-A20, X-T100, X-T200, XF10
+ { // Ill.A aligned to CCT 2850
+ int wb[4];
+ int nWB, tWB;
+ int iCCT = 0;
+ imFuji.RAFDataGeneration = 4096;
+ fseek(ifp, save + 0x200, SEEK_SET);
+ for (int wb_ind = 0; wb_ind < 42; wb_ind++)
+ {
+ nWB = get4();
+ tWB = get4();
+ wb[0] = get4() << 1;
+ wb[1] = get4();
+ wb[3] = get4();
+ wb[2] = get4() << 1;
+ if (tWB && (iCCT < 255))
+ {
+ icWBCCTC[iCCT][0] = tWB;
+ FORC4 icWBCCTC[iCCT][c + 1] = wb[c];
+ iCCT++;
+ }
+ if (nWB != 70)
+ {
+ for (int pWB = 1; pWB < (int)Fuji_wb_list2.size(); pWB += 2)
+ {
+ if (Fuji_wb_list2[pWB] == nWB)
+ {
+ FORC4 icWBC[Fuji_wb_list2[pWB - 1]][c] = wb[c];
+ break;
+ }
+ }
+ }
+ }
+ }
+ order = save_order;
+ }
+ fseek(ifp, save + len, SEEK_SET);
+ }
+
+ if (!imFuji.RAFDataGeneration) {
+ height <<= fuji_layout;
+ width >>= fuji_layout;
+ }
+#undef get_average_WB
+}
+
diff --git a/libkdcraw/libraw/src/metadata/hasselblad_model.cpp b/libkdcraw/libraw/src/metadata/hasselblad_model.cpp
new file mode 100644
index 0000000..b20da5e
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/hasselblad_model.cpp
@@ -0,0 +1,538 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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_defs.h"
+#include "../../internal/libraw_cameraids.h"
+
+ static const struct {
+ const int idx;
+ const char *FormatName;
+ } HassyRawFormat[] = {
+ { LIBRAW_HF_Unknown, "Unknown"},
+ { LIBRAW_HF_3FR, "-3FR"},
+ { LIBRAW_HF_FFF, "-FFF"},
+ { LIBRAW_HF_Imacon, "Imacon"},
+ { LIBRAW_HF_HasselbladDNG, "hDNG"},
+ { LIBRAW_HF_AdobeDNG, "aDNG"},
+ { LIBRAW_HF_AdobeDNG_fromPhocusDNG, "a(hDNG)"},
+ };
+
+const char* LibRaw::HassyRawFormat_idx2HR(unsigned idx) // HR means "human-readable"
+{
+ for (int i = 0; i < int(sizeof HassyRawFormat / sizeof *HassyRawFormat); i++)
+ if((unsigned)HassyRawFormat[i].idx == idx)
+ return HassyRawFormat[i].FormatName;
+ return 0;
+}
+
+void LibRaw::process_Hassy_Lens (int LensMount) {
+// long long unsigned id =
+// mount*100000000ULL + series*10000000ULL +
+// focal1*10000ULL + focal2*10 + version;
+ char *ps;
+ int c;
+ char *q = strchr(imgdata.lens.Lens, ' ');
+ if(!q) return ;
+ c = atoi(q+1);
+ if (!c)
+ return;
+
+ if (LensMount == LIBRAW_MOUNT_Hasselblad_H) {
+ if (imgdata.lens.Lens[2] == ' ') // HC lens
+ ilm.LensID = LensMount*100000000ULL + 10000000ULL;
+ else // HCD lens
+ ilm.LensID = LensMount*100000000ULL + 20000000ULL;
+ ilm.LensFormat = LIBRAW_FORMAT_645;
+ } else if (LensMount == LIBRAW_MOUNT_Hasselblad_XCD) {
+ ilm.LensFormat = LIBRAW_FORMAT_CROP645;
+ ilm.LensID = LensMount*100000000ULL;
+ } else
+ return;
+
+ ilm.LensMount = LensMount;
+ ilm.LensID += c*10000ULL;
+ if ((ps=strchr(imgdata.lens.Lens, '-'))) {
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ ilm.LensID += atoi(ps+1)*10ULL;
+ } else {
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ ilm.LensID += c*10ULL;
+ }
+ if (strstr(imgdata.lens.Lens, "III"))
+ ilm.LensID += 3ULL;
+ else if (strstr(imgdata.lens.Lens, "II"))
+ ilm.LensID += 2ULL;
+}
+
+void LibRaw::parseHassyModel() {
+
+static const char *Hasselblad_Ctrl[] = { // manually selectable options only
+ "ELD", "ELX", "Winder CW", "CW", "Pinhole", "Flash Sync",
+ "SWC", "200 (Mod)", "200", "500 Mech.", "500", "H Series",
+ "H-Series", "H1", "H2", "Black Box", "LENSCONTROL S", "LENSCTRL S", "Generic",
+};
+
+static const char *Hasselblad_SensorEnclosures[] = {
+ "CFH", "CFV", "CFV", "CFII", "CF", "Ixpress",
+};
+
+ char tmp_model[64];
+ const char *ps;
+ char *eos;
+ int c;
+ int nPix = raw_width*raw_height;
+ int add_MP_toName = 1;
+ int norm_model_isSet = 0;
+
+ if (model[0] == ' ')
+ memmove(model, model+1, MIN(sizeof(model)-1,strlen(model)));
+
+ imHassy.HostBody[0] = 0;
+ if ((ps = strrchr(model, '/')))
+ strcpy(imHassy.HostBody, ps+1);
+ else if ((ps = strrchr(imgdata.color.LocalizedCameraModel, '/')))
+ strcpy(imHassy.HostBody, ps+1);
+ else if ((ps = strrchr(imgdata.color.UniqueCameraModel, '/')))
+ strcpy(imHassy.HostBody, ps+1);
+ else if ((ps = strrchr(imHassy.SensorUnitConnector, '/')))
+ strcpy(imHassy.HostBody, ps+1);
+ if (imHassy.HostBody[0]) {
+ if ((eos = strrchr(imHassy.HostBody, '-')))
+ *eos = 0;
+ }
+
+ if (!imHassy.format) {
+ if (dng_version) {
+ if (!strncmp(software, "Adobe", 5)) {
+ if (!imgdata.color.OriginalRawFileName[0] ||
+ !imgdata.color.LocalizedCameraModel[0] ||
+ !strcasestr(imgdata.color.UniqueCameraModel, "coated"))
+ imHassy.format = LIBRAW_HF_AdobeDNG_fromPhocusDNG;
+ else
+ imHassy.format = LIBRAW_HF_AdobeDNG;
+ } else imHassy.format = LIBRAW_HF_HasselbladDNG;
+ } else if ((imHassy.nIFD_CM[0] != -1) &&
+ (imHassy.nIFD_CM[1] == -1) &&
+ !imHassy.mnColorMatrix[0][0]) {
+ imHassy.format = LIBRAW_HF_3FR;
+ } else imHassy.format = LIBRAW_HF_FFF;
+ }
+
+ if (imHassy.SensorUnitConnector[0]) {
+ char buf[64];
+ if (!strncmp(imHassy.SensorUnitConnector, "Hasselblad ", 11))
+ memmove(imHassy.SensorUnitConnector, imHassy.SensorUnitConnector+11, 64-11);
+ strcpy(buf, imHassy.SensorUnitConnector);
+ if ((eos = strrchr(buf, '/'))) {
+ *eos = 0;
+ if ((eos = strrchr(buf, ' '))) {
+ *eos = 0;
+ strcpy (imHassy.SensorUnitConnector, buf);
+ }
+ }
+ }
+
+ if (imHassy.format == LIBRAW_HF_AdobeDNG) { // Adobe DNG, use LocalizedCameraModel
+ imgdata.color.LocalizedCameraModel[63] = 0; // make sure it's 0-terminated
+ if ((ps = strrchr(imgdata.color.LocalizedCameraModel, '-')))
+ c = ps-imgdata.color.LocalizedCameraModel;
+ else c = int(strlen(imgdata.color.LocalizedCameraModel));
+ int cc = MIN(c, (int)sizeof(tmp_model)-1);
+ memcpy(tmp_model, imgdata.color.LocalizedCameraModel,cc);
+ tmp_model[cc] = 0;
+ if (strcasestr(imgdata.color.UniqueCameraModel, "coated")) {
+ strncpy(normalized_model, imgdata.color.UniqueCameraModel,sizeof(imgdata.color.UniqueCameraModel)-1);
+ normalized_model[sizeof(imgdata.color.UniqueCameraModel) - 1] = 0;
+ norm_model_isSet = 1;
+ }
+ if (!strncmp(normalized_model, "Hasselblad ", 11))
+ memmove(normalized_model, normalized_model+11, 64-11);
+ } else {
+ if ((ps = strrchr(imgdata.color.UniqueCameraModel, '/'))) {
+ c = ps-imgdata.color.UniqueCameraModel;
+ }
+ else c = int(strlen(imgdata.color.UniqueCameraModel));
+ int cc = MIN(c, (int)sizeof(tmp_model)-1);
+ memcpy(tmp_model, imgdata.color.UniqueCameraModel,cc);
+ tmp_model[cc] = 0;
+ }
+ if (!strncasecmp(tmp_model, "Hasselblad ", 11))
+ memmove(tmp_model, tmp_model+11, 64-11);
+
+ strncpy(imHassy.CaptureSequenceInitiator, model,31);
+ imHassy.CaptureSequenceInitiator[31] = 0;
+ if ((eos = strrchr(imHassy.CaptureSequenceInitiator, '/'))) {
+ *eos = 0;
+ }
+// check if model tag contains manual CaptureSequenceInitiator info:
+ FORC(int(sizeof Hasselblad_Ctrl / sizeof *Hasselblad_Ctrl)) {
+ if (strcasestr(model, Hasselblad_Ctrl[c])) {
+// yes, fill 'model' with sensor unit data
+ strncpy(model, tmp_model,63);
+ model[63] = 0;
+ break;
+ }
+ }
+
+ if (!imHassy.HostBody[0]) {
+ ps = strchr(model, '-');
+ if (ps) { // check if model contains both host body and sensor version, resolution, MS info
+ strncpy(imHassy.SensorUnit, model,63);
+ memcpy(imHassy.HostBody, model, ps-model);
+ imHassy.HostBody[ps-model] = 0;
+ if (!strncmp(ps-2, "II-", 3))
+ ps -=2;
+ strncpy(imHassy.Sensor, ps,7);
+ imHassy.Sensor[7] = 0;
+ add_MP_toName = 0;
+ } else { // model contains host body only
+ strncpy(imHassy.HostBody, model,63);
+ imHassy.HostBody[63] = 0;
+ // fill 'model' with sensor unit data
+ strncpy(model, tmp_model,63);
+ model[63] = 0;
+ }
+ }
+
+ if (strstr(model, "503CWD")) {
+ strncpy(imHassy.HostBody, model,63);
+ imHassy.HostBody[63] = 0;
+ ilm.CameraFormat = LIBRAW_FORMAT_66;
+ ilm.CameraMount = LIBRAW_MOUNT_Hasselblad_V;
+ if (model[6] == 'I' && model[7] == 'I')
+ strcpy(model, "CFVII");
+ else strcpy(model, "CFV");
+ } else if (strstr(model, "Hasselblad") &&
+ (model[10] != ' ')) {
+ strcpy(model, "CFV");
+ ilm.CameraMount = LIBRAW_MOUNT_DigitalBack;
+ } else {
+ FORC(int(sizeof Hasselblad_SensorEnclosures / sizeof *Hasselblad_SensorEnclosures)) {
+ if (strcasestr(model, Hasselblad_SensorEnclosures[c])) {
+ if (add_MP_toName) strcpy(model, Hasselblad_SensorEnclosures[c]);
+ ilm.CameraMount = LIBRAW_MOUNT_DigitalBack;
+ break;
+ }
+ }
+ }
+
+#define cpynorm(str) \
+ if (!norm_model_isSet) { \
+ strcpy(normalized_model, str); \
+ norm_model_isSet = 1; \
+ }
+
+ if ((imHassy.SensorCode == 4) &&
+ (imHassy.CoatingCode < 2)) {
+ strcpy(imHassy.Sensor, "-16");
+ cpynorm("16-Uncoated");
+
+ } else if ((imHassy.SensorCode == 6) &&
+ (imHassy.CoatingCode < 2)) {
+ strcpy(imHassy.Sensor, "-22");
+ cpynorm("22-Uncoated");
+
+ } else if ((imHassy.SensorCode == 8) &&
+ (imHassy.CoatingCode == 1)) {
+ strcpy(imHassy.Sensor, "-31");
+ cpynorm("31-Uncoated");
+
+ } else if ((imHassy.SensorCode == 9) &&
+ (imHassy.CoatingCode < 2)) {
+ strcpy(imHassy.Sensor, "-39");
+ cpynorm("39-Uncoated");
+
+ } else if ((imHassy.SensorCode == 9) &&
+ (imHassy.CoatingCode == 4)) {
+ strcpy(imHassy.Sensor, "-39");
+ strcpy(model, "H3DII");
+ add_MP_toName = 1;
+ cpynorm("39-Coated");
+
+ } else if ((imHassy.SensorCode == 13) &&
+ (imHassy.CoatingCode == 4)) {
+ strcpy(imHassy.Sensor, "-40");
+ cpynorm("40-Coated");
+
+ } else if ((imHassy.SensorCode == 13) &&
+ (imHassy.CoatingCode == 5)) {
+ strcpy(imHassy.Sensor, "-40");
+ cpynorm("40-Coated5");
+
+ } else if ((imHassy.SensorCode == 11) &&
+ (imHassy.CoatingCode == 4)) {
+ if (!strncmp(model, "H3D", 3))
+ strcpy(model, "H3DII-50");
+ else strcpy(imHassy.Sensor, "-50");
+ cpynorm("50-Coated");
+
+ } else if ((imHassy.SensorCode == 11) &&
+ (imHassy.CoatingCode == 5)) {
+ strcpy(imHassy.Sensor, "-50");
+ cpynorm("50-Coated5");
+
+ } else if ((imHassy.SensorCode == 15) &&
+ (imHassy.CoatingCode == 5)) {
+ strcpy(imHassy.Sensor, "-50c");
+ cpynorm("50-15-Coated5");
+ if (!strncmp(imHassy.CaptureSequenceInitiator, "CFV II 50C", 10)) {
+ imHassy.SensorSubCode = 2;
+ add_MP_toName = 0;
+ strcat(imHassy.Sensor, " II");
+ strcpy(model, "CFV II 50C");
+ strcat(normalized_model, "-II");
+ } else if (!strncmp(imHassy.CaptureSequenceInitiator, "X1D", 3)) {
+ imHassy.SensorSubCode = 2;
+ add_MP_toName = 0;
+ strcat(imHassy.Sensor, " II");
+ if (!strncasecmp(imHassy.CaptureSequenceInitiator, "X1D II 50C", 10)) {
+ strcpy(model, "X1D II 50C");
+ strcat(normalized_model, "-II");
+ } else {
+ strcpy(model, "X1D-50c");
+ }
+ }
+
+ } else if ((imHassy.SensorCode == 12) &&
+ (imHassy.CoatingCode == 4)) {
+ strcpy(imHassy.Sensor, "-60");
+ cpynorm("60-Coated");
+
+ } else if ((imHassy.SensorCode == 17) &&
+ (imHassy.CoatingCode == 5)) {
+ strcpy(imHassy.Sensor, "-100c");
+ cpynorm("100-17-Coated5");
+
+ } else if ((raw_width == 4090) || // V96C
+ ((raw_width == 4096) && (raw_height == 4096)) ||
+ ((raw_width == 4088) && (raw_height == 4088)) || // Adobe crop
+ ((raw_width == 4080) && (raw_height == 4080))) { // Phocus crop
+ strcpy(imHassy.Sensor, "-16");
+ cpynorm("16-Uncoated");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 4;
+
+ } else if ((raw_width == 5568) && (raw_height == 3648)) {
+ strcpy(imHassy.Sensor, "-20c");
+
+ } else if (((raw_width == 4096) && (raw_height == 5456)) ||
+ ((raw_width == 4088) && (raw_height == 5448)) || // Adobe crop
+ ((raw_width == 4080) && (raw_height == 5440))) { // Phocus crop
+ strcpy(imHassy.Sensor, "-22");
+ cpynorm("22-Uncoated");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 6;
+
+ } else if (((raw_width == 6542) && (raw_height == 4916)) ||
+ ((raw_width == 6504) && (raw_height == 4880)) || // Adobe crop
+ ((raw_width == 6496) && (raw_height == 4872))) { // Phocus crop
+ strcpy(imHassy.Sensor, "-31");
+ cpynorm("31-Uncoated");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 8;
+
+ } else if (((raw_width == 7262) && (raw_height == 5456)) || //
+ ((raw_width == 7224) && (raw_height == 5420)) || // Adobe crop
+ ((raw_width == 7216) && (raw_height == 5412)) || // Phocus crop
+ ((raw_width == 7212) && (raw_height == 5412)) || // CF-39, CFV-39, possibly v.II; Phocus crop
+// uncropped, when the exact size is unknown, should be:
+// - greater or equal to the smallest Phocus crop for the current size
+// - smaller than the smallest Phocus crop for the next size
+ ((nPix >= 7212*5412) && (nPix < 7304*5478))) {
+ strcpy(imHassy.Sensor, "-39");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 9;
+ if (!strncmp(model, "H3D", 3)) {
+ if (((imHassy.format == LIBRAW_HF_Imacon) ||
+ strstr(imgdata.color.UniqueCameraModel, "H3D-39") ||
+ strstr(imgdata.color.LocalizedCameraModel, "H3D-39") ||
+ strstr(model, "H3D-39")) &&
+ !strstr(imgdata.color.UniqueCameraModel, "II") &&
+ !strstr(imgdata.color.LocalizedCameraModel, "II") &&
+ !strstr(model, "II")) {
+ strcpy(model, "H3D-39");
+ add_MP_toName = 0;
+ cpynorm("39-Uncoated");
+
+ } else {
+ strcpy(model, "H3DII-39");
+ add_MP_toName = 0;
+ cpynorm("39-Coated");
+ if (!imHassy.CoatingCode) imHassy.CoatingCode = 4;
+ }
+
+ } else
+ cpynorm("39-Uncoated");
+
+ } else if (((raw_width == 7410) && (raw_height == 5586)) || // (H4D-40, H5D-40)
+ ((raw_width == 7312) && (raw_height == 5486)) || // Adobe crop
+ ((raw_width == 7304) && (raw_height == 5478))) { // Phocus crop
+ strcpy(imHassy.Sensor, "-40");
+ if (!strncmp(model, "H4D", 3)) {
+ cpynorm("40-Coated");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 13;
+ if (!imHassy.CoatingCode) imHassy.CoatingCode = 4;
+ } else {
+ cpynorm("40-Coated5");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 13;
+ if (!imHassy.CoatingCode) imHassy.CoatingCode = 5;
+ }
+
+ } else if (((raw_width == 8282) && (raw_height == 6240)) || // (CFV-50, H3DII-50, H5D-50)
+ ((raw_width == 8184) && (raw_height == 6140)) || // Adobe crop
+ ((raw_width == 8176) && (raw_height == 6132))) { // Phocus crop
+ strcpy(imHassy.Sensor, "-50");
+ if (!strncmp(model, "H5D", 3)) {
+ cpynorm("50-Coated5");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 11;
+ if (!imHassy.CoatingCode) imHassy.CoatingCode = 5;
+ } else {
+ cpynorm("50-Coated"); // CFV-50, H3DII-50,
+ if (!strncmp(model, "H3D", 3)) {
+ strcpy(model, "H3DII-50");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 11;
+ if (!imHassy.CoatingCode) imHassy.CoatingCode = 4;
+ add_MP_toName = 0;
+ }
+ }
+
+ } else if (((raw_width == 8374) && (raw_height == 6304)) || // (H5D-50c)
+ ((raw_width == 8384) && (raw_height == 6304)) || // (X1D-50c, "X1D II 50C", "CFV II 50C")
+ ((raw_width == 8280) && (raw_height == 6208)) || // Adobe crop
+ ((raw_width == 8272) && (raw_height == 6200))) { // Phocus crop
+ cpynorm("50-15-Coated5");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 15;
+ if (!imHassy.CoatingCode) imHassy.CoatingCode = 5;
+ strcpy(imHassy.Sensor, "-50c");
+ if ((raw_width == 8384) ||
+ !strncmp(imHassy.CaptureSequenceInitiator, "X1D", 3) ||
+ !strncmp(imHassy.CaptureSequenceInitiator, "CFV II", 6)) {
+ imHassy.SensorSubCode = 2;
+ add_MP_toName = 0;
+ strcat(imHassy.Sensor, " II");
+ if (strstr(imHassy.CaptureSequenceInitiator, " II ")) {
+ strcat(normalized_model, "-II");
+ if (!strncasecmp(imHassy.CaptureSequenceInitiator, "X1D II 50C", 10)) {
+ strcpy(model, "X1D II 50C");
+ } else if (!strncasecmp(imHassy.CaptureSequenceInitiator, "CFV II 50C", 10)) {
+ strcpy(model, "CFV II 50C");
+ }
+ } else {
+ strcpy(model, "X1D-50c");
+ }
+ }
+
+ } else if (((raw_width == 9044) && (raw_height == 6732)) ||
+ ((raw_width == 8964) && (raw_height == 6716)) || // Adobe crop
+ ((raw_width == 8956) && (raw_height == 6708))) { // Phocus crop
+ strcpy(imHassy.Sensor, "-60");
+ cpynorm("60-Coated");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 12;
+ if (!imHassy.CoatingCode) imHassy.CoatingCode = 4;
+
+
+ } else if (((raw_width == 10320) && (raw_height == 7752)) || // Phocus crop, A5D-80
+ ((nPix >= 10320*7752) && (nPix < 10520*8000))) {
+ strcpy(imHassy.Sensor, "-80");
+ cpynorm("80-Coated");
+
+ } else if (((raw_width == 12000) && (raw_height == 8816)) ||
+ ((raw_width == 11608) && (raw_height == 8708)) || // Adobe crop
+ ((raw_width == 11600) && (raw_height == 8700))) { // Phocus crop
+ strcpy(imHassy.Sensor, "-100c");
+ cpynorm("100-17-Coated5");
+ if (!imHassy.SensorCode) imHassy.SensorCode = 17;
+ if (!imHassy.CoatingCode) imHassy.CoatingCode = 5;
+
+ }
+
+ if (raw_width == 4090)
+ strcpy(model, "V96C");
+
+ if (
+ (raw_width == 4090) ||
+ ((raw_width == 4096) && (raw_height == 4096)) ||
+ ((raw_width == 5568) && (raw_height == 3648)) ||
+ ((raw_width == 4096) && (raw_height == 5456)) ||
+ ((raw_width == 6542) && (raw_height == 4916)) ||
+ ((raw_width == 7262) && (raw_height == 5456)) ||
+ ((raw_width == 7410) && (raw_height == 5586)) ||
+ ((raw_width == 8282) && (raw_height == 6240)) ||
+ ((raw_width == 8374) && (raw_height == 6304)) ||
+ ((raw_width == 8384) && (raw_height == 6304)) ||
+ ((raw_width == 9044) && (raw_height == 6732)) ||
+ ((raw_width == 10320) && (raw_height == 7752)) ||
+ ((raw_width == 12000) && (raw_height == 8816))
+ )
+ imHassy.uncropped = 1;
+
+
+ if (model[0] && add_MP_toName)
+ strcat(model, imHassy.Sensor);
+ if (imHassy.Sensor[0] == '-')
+ memmove(imHassy.Sensor, imHassy.Sensor+1, strlen(imHassy.Sensor));
+
+ if (dng_version &&
+ (imHassy.SensorCode == 13) &&
+ (imHassy.CoatingCode == 4)) {
+ c = LIBRAW_HF_AdobeDNG;
+ } else if ((imHassy.format == LIBRAW_HF_HasselbladDNG) ||
+ (imHassy.format == LIBRAW_HF_AdobeDNG_fromPhocusDNG)) {
+ c = LIBRAW_HF_FFF;
+ } else if (imHassy.format == LIBRAW_HF_Imacon) {
+ c = LIBRAW_HF_3FR;
+ } else {
+ c = imHassy.format;
+ }
+ ps = HassyRawFormat_idx2HR(c);
+ if ((c == LIBRAW_HF_3FR) ||
+ (c == LIBRAW_HF_FFF))
+ strcat(normalized_model, ps);
+
+ if (((imHassy.CaptureSequenceInitiator[0] == 'H') &&
+ (imHassy.CaptureSequenceInitiator[1] != 'a')) ||
+ ((imHassy.CaptureSequenceInitiator[0] == 'A') &&
+ isdigit(imHassy.CaptureSequenceInitiator[1]))) {
+ ilm.CameraFormat = LIBRAW_FORMAT_645;
+ ilm.CameraMount = LIBRAW_MOUNT_Hasselblad_H;
+ if (imgdata.lens.Lens[0] == 'H')
+ process_Hassy_Lens(LIBRAW_MOUNT_Hasselblad_H);
+ } else if (((imHassy.CaptureSequenceInitiator[0] == 'X') &&
+ isdigit(imHassy.CaptureSequenceInitiator[1])) ||
+ !strncmp(imHassy.HostBody, "907", 3)) {
+ ilm.CameraFormat = LIBRAW_FORMAT_CROP645;
+ ilm.CameraMount = LIBRAW_MOUNT_Hasselblad_XCD;
+ if (imgdata.lens.Lens[0] == 'H') {
+ process_Hassy_Lens(LIBRAW_MOUNT_Hasselblad_H);
+ strcpy(ilm.Adapter, "XH");
+ } else {
+ if (imgdata.lens.Lens[0] == 'X') {
+ process_Hassy_Lens(LIBRAW_MOUNT_Hasselblad_XCD);
+ } else if (!imgdata.lens.Lens[0] &&
+ (aperture > 1.0f) &&
+ (focal_len > 10.0f)) {
+ ilm.LensID = focal_len;
+ if (ilm.LensID == 35) {
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ ilm.LensID = LIBRAW_MOUNT_Hasselblad_XCD*100000000ULL +
+ 35*10000ULL + 75*10;
+ }
+ else {
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ ilm.LensID = LIBRAW_MOUNT_Hasselblad_XCD*100000000ULL +
+ ilm.LensID*10000ULL + ilm.LensID*10;
+ }
+ }
+ }
+ }
+ if (normalized_model[0] && !CM_found)
+ CM_found = adobe_coeff(maker_index, normalized_model);
+}
diff --git a/libkdcraw/libraw/src/metadata/identify.cpp b/libkdcraw/libraw/src/metadata/identify.cpp
new file mode 100644
index 0000000..aabbf85
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/identify.cpp
@@ -0,0 +1,3167 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+#include "../../internal/libraw_cameraids.h"
+
+// clang-format on
+static const struct
+{
+ const int CorpId;
+ const char *CorpName;
+} CorpTable[] = {
+ {LIBRAW_CAMERAMAKER_Agfa, "AgfaPhoto"},
+ {LIBRAW_CAMERAMAKER_Apple, "Apple"},
+ {LIBRAW_CAMERAMAKER_Broadcom, "Broadcom"},
+ {LIBRAW_CAMERAMAKER_Canon, "Canon"},
+ {LIBRAW_CAMERAMAKER_Casio, "Casio"},
+ {LIBRAW_CAMERAMAKER_CINE, "CINE"},
+ {LIBRAW_CAMERAMAKER_Epson, "Epson"},
+ {LIBRAW_CAMERAMAKER_Fujifilm, "Fujifilm"},
+ {LIBRAW_CAMERAMAKER_Mamiya, "Mamiya"},
+ {LIBRAW_CAMERAMAKER_Motorola, "Motorola"},
+ {LIBRAW_CAMERAMAKER_Kodak, "Kodak"},
+ {LIBRAW_CAMERAMAKER_Konica, "Konica"},
+ {LIBRAW_CAMERAMAKER_Minolta, "Minolta"},
+ {LIBRAW_CAMERAMAKER_Leica, "Leica"},
+ {LIBRAW_CAMERAMAKER_Nikon, "Nikon"},
+ {LIBRAW_CAMERAMAKER_Nokia, "Nokia"},
+ {LIBRAW_CAMERAMAKER_Olympus, "Olympus"},
+ {LIBRAW_CAMERAMAKER_OmDigital, "OM Digital"},
+ {LIBRAW_CAMERAMAKER_Ricoh, "Ricoh"},
+ {LIBRAW_CAMERAMAKER_Pentax, "Pentax"},
+ {LIBRAW_CAMERAMAKER_PhaseOne, "Phase One"},
+ {LIBRAW_CAMERAMAKER_PhaseOne, "PhaseOne"},
+ {LIBRAW_CAMERAMAKER_Samsung, "Samsung"},
+ {LIBRAW_CAMERAMAKER_Sigma, "Sigma"},
+ {LIBRAW_CAMERAMAKER_Sinar, "Sinar"},
+ {LIBRAW_CAMERAMAKER_Sony, "Sony"},
+ {LIBRAW_CAMERAMAKER_YI, "YI"},
+ // add corp. names below
+ {LIBRAW_CAMERAMAKER_Alcatel, "Alcatel"},
+ {LIBRAW_CAMERAMAKER_Aptina, "Aptina"},
+ {LIBRAW_CAMERAMAKER_AVT, "AVT"},
+ {LIBRAW_CAMERAMAKER_Baumer, "Baumer"},
+ {LIBRAW_CAMERAMAKER_Clauss, "Clauss"},
+ {LIBRAW_CAMERAMAKER_Contax, "Contax"},
+ {LIBRAW_CAMERAMAKER_Creative, "Creative"},
+ {LIBRAW_CAMERAMAKER_DJI, "DJI"},
+ {LIBRAW_CAMERAMAKER_Foculus, "Foculus"},
+ {LIBRAW_CAMERAMAKER_Generic, "Generic"},
+ {LIBRAW_CAMERAMAKER_Gione, "Gione"},
+ {LIBRAW_CAMERAMAKER_GITUP, "GITUP"},
+ {LIBRAW_CAMERAMAKER_Hasselblad, "Hasselblad"},
+ {LIBRAW_CAMERAMAKER_HTC, "HTC"},
+ {LIBRAW_CAMERAMAKER_I_Mobile, "I_Mobile"},
+ {LIBRAW_CAMERAMAKER_Imacon, "Imacon"},
+ {LIBRAW_CAMERAMAKER_ISG, "ISG"},
+ {LIBRAW_CAMERAMAKER_JK_Imaging, "JK Imaging"}, // Kodak
+ {LIBRAW_CAMERAMAKER_Leaf, "Leaf"},
+ {LIBRAW_CAMERAMAKER_Lenovo, "Lenovo"},
+ {LIBRAW_CAMERAMAKER_LG, "LG"},
+ {LIBRAW_CAMERAMAKER_Logitech, "Logitech"},
+ {LIBRAW_CAMERAMAKER_Matrix, "Matrix"},
+ {LIBRAW_CAMERAMAKER_Meizu, "Meizu"},
+ {LIBRAW_CAMERAMAKER_Micron, "Micron"},
+ {LIBRAW_CAMERAMAKER_NGM, "NGM"},
+ {LIBRAW_CAMERAMAKER_OmniVison, "OmniVison"},
+ {LIBRAW_CAMERAMAKER_Panasonic, "Panasonic"},
+ {LIBRAW_CAMERAMAKER_Photron, "Photron"},
+ {LIBRAW_CAMERAMAKER_Pixelink, "Pixelink"},
+ {LIBRAW_CAMERAMAKER_Polaroid, "Polaroid"},
+ {LIBRAW_CAMERAMAKER_Rollei, "Rollei"},
+ {LIBRAW_CAMERAMAKER_RoverShot, "RoverShot"},
+ {LIBRAW_CAMERAMAKER_SMaL, "SMaL"},
+ {LIBRAW_CAMERAMAKER_ST_Micro, "ST Micro"},
+ {LIBRAW_CAMERAMAKER_THL, "THL"},
+ {LIBRAW_CAMERAMAKER_Xiaomi, "Xiaomi"},
+ {LIBRAW_CAMERAMAKER_XIAOYI, "Xiayi"},
+ {LIBRAW_CAMERAMAKER_Yuneec, "Yuneec"},
+ {LIBRAW_CAMERAMAKER_DXO, "DxO"},
+ {LIBRAW_CAMERAMAKER_RED, "Red"},
+ {LIBRAW_CAMERAMAKER_PhotoControl, "Photo Control"},
+ {LIBRAW_CAMERAMAKER_Google, "Google"},
+ {LIBRAW_CAMERAMAKER_GoPro, "GoPro"},
+ {LIBRAW_CAMERAMAKER_Parrot, "Parrot"},
+ {LIBRAW_CAMERAMAKER_Zeiss, "Zeiss"},
+ {LIBRAW_CAMERAMAKER_OnePlus, "OnePlus"},
+ {LIBRAW_CAMERAMAKER_VIVO, "Vivo"},
+ {LIBRAW_CAMERAMAKER_HMD_Global, "HMD Global"},
+ {LIBRAW_CAMERAMAKER_HUAWEI, "Huawei"},
+ {LIBRAW_CAMERAMAKER_RaspberryPi, "RaspberryPi"},
+};
+// clang-format on
+
+int LibRaw::setMakeFromIndex(unsigned makei)
+{
+ if (makei <= LIBRAW_CAMERAMAKER_Unknown || makei >= LIBRAW_CAMERAMAKER_TheLastOne) return 0;
+
+ for (int i = 0; i < int(sizeof CorpTable / sizeof *CorpTable); i++)
+ if ((unsigned)CorpTable[i].CorpId == makei)
+ {
+ strcpy(normalized_make, CorpTable[i].CorpName);
+ maker_index = makei;
+ return 1;
+ }
+ return 0;
+}
+
+const char *LibRaw::cameramakeridx2maker(unsigned maker)
+{
+ for (int i = 0; i < int(sizeof CorpTable / sizeof *CorpTable); i++)
+ if((unsigned)CorpTable[i].CorpId == maker)
+ return CorpTable[i].CorpName;
+ return 0;
+}
+
+
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+void LibRaw::fixupArri()
+{
+ struct alist_t
+ {
+ const char *a_model;
+ const char *a_software;
+ ushort a_width,a_height;
+ int a_black;
+ unsigned a_filters;
+ float a_aspect;
+ }
+ alist[] =
+ {
+ {"ALEXA65", "Alexa65 XT", 6560 ,3100, 256,0x49494949,1.f},
+
+ {"ALEXALF", "Alexa LF Plus W", 3840 ,2160, 256,0x49494949,1.0f },
+ {"ALEXALF", "Alexa LF Plus W", 4448 ,1856, 256,0x49494949,0.75f },
+ {"ALEXALF", "Alexa LF Plus W", 4448 ,3096, 256,0x49494949,1.f },
+
+ {"ALEXA", "Alexa Plus 4:3 SXT", 2880 ,1620, 256,0x61616161,.75f},
+ {"ALEXA", "Alexa Plus 4:3 SXT", 3168 ,1782, 256,0x61616161,0.75f},
+ {"ALEXA", "Alexa Plus 4:3 SXT", 3424 ,2202, 256,0x61616161,1.f},
+ {"ALEXA", "Alexa Plus 4:3 SXT", 2592 ,2160, 256,0x61616161,1.12f},
+
+ {"ALEXA", "Alexa Plus 4:3 XT", 2592 ,2160, 256,0x61616161,1.12f},
+ {"ALEXA", "Alexa Plus 4:3 XT", 2880 ,2160, 256,0x61616161,1.f},
+ {"ALEXA", "Alexa Plus 4:3 XT", 2880 ,1620, 256,0x61616161,0.75f},
+ {"ALEXA", "Alexa Plus 4:3 XT", 3424 ,2202, 256,0x61616161,1.f},
+ };
+ for(int i = 0; i < int(sizeof(alist)/sizeof(alist[0])); i++)
+ if(!strncasecmp(model,alist[i].a_model,strlen(alist[i].a_model)) && software
+ && !strncasecmp(software,alist[i].a_software,strlen(alist[i].a_software))
+ && width == alist[i].a_width && height == alist[i].a_height)
+ {
+ filters = alist[i].a_filters;
+ black = alist[i].a_black;
+ pixel_aspect = alist[i].a_aspect;
+ strcpy(model,software);
+ software[0]=0;
+ return;
+ }
+}
+#endif
+/*
+ Identify which camera created this file, and set global variables
+ accordingly.
+ */
+void LibRaw::identify()
+{
+ // clang-format off
+ static const ushort canon[][11] = {
+ // raw_width, raw_height, left_margin, top_margin,
+ // width_decrement, height_decrement,
+ // mask01, mask03, mask11, mask13,
+ // CFA_filters.
+ { 1944, 1416, 0, 0, 48, 0 }, // 00 "PowerShot Pro90 IS"
+ { 2144, 1560, 4, 8, 52, 2, 0, 0, 0, 25 }, // 01 "PowerShot S30", "PowerShot G1"
+ { 2224, 1456, 48, 6, 0, 2 }, // 02 "EOS D30"
+ { 2376, 1728, 12, 6, 52, 2 }, // 03 "PowerShot G2", "PowerShot S40", "PowerShot G3", "PowerShot S45"
+ { 2672, 1968, 12, 6, 44, 2 }, // 04 "PowerShot G5", "PowerShot S50", "PowerShot S60"
+ { 3152, 2068, 64, 12, 0, 0, 16 }, // 05 "EOS D60", "EOS 10D", "EOS 300D"
+ { 3160, 2344, 44, 12, 4, 4 }, // 06 "PowerShot G6", "PowerShot S70"
+ { 3344, 2484, 4, 6, 52, 6 }, // 07 "PowerShot Pro1"
+ { 3516, 2328, 42, 14, 0, 0 }, // 08 "EOS 350D"
+ { 3596, 2360, 74, 12, 0, 0 }, // 09 "EOS-1D Mark II", "EOS 20D", "EOS-1D Mark II N", "EOS 30D"
+ { 3744, 2784, 52, 12, 8, 12 }, // 10 "PowerShot G11", "PowerShot S90", "PowerShot G12", "PowerShot S95"
+ { 3944, 2622, 30, 18, 6, 2 }, // 11 "EOS 40D"
+ { 3948, 2622, 42, 18, 0, 2 }, // 12 "EOS 400D", "EOS 1000D"
+ { 3984, 2622, 76, 20, 0, 2, 14 }, // 13 "EOS-1D Mark III"
+ { 4032, 2656, 112, 44, 10, 0 }, // 14 APS-C crop mode: "EOS 6D Mark II"??, "EOS RP"
+ { 4104, 3048, 48, 12, 24, 12 }, // 15 "PowerShot G9"
+ { 4116, 2178, 4, 2, 0, 0 }, // 16 ??
+ { 4152, 2772, 192, 12, 0, 0 }, // 17 "PowerShot SX1 IS"
+ { 4160, 3124, 104, 11, 8, 65 }, // 18 "PowerShot S100 (new)", "PowerShot S100V", "PowerShot G15", "PowerShot S110 (new)"
+ { 4176, 3062, 96, 17, 8, 0, 0, 16, 0, 7, 0x49 }, // 19 "PowerShot SX50 HS"
+ { 4192, 3062, 96, 17, 24, 0, 0, 16, 0, 0, 0x49 }, // 20 "PowerShot G16", "PowerShot S120"
+ { 4312, 2876, 22, 18, 0, 2 }, // 21 "EOS 450D"
+ { 4352, 2850, 144, 46, 0, 0 }, // 22 APS-C crop mode: "EOS R"
+ { 4352, 2874, 62, 18, 0, 0 }, // 23 "EOS 1100D"
+ { 4476, 2954, 90, 34, 0, 0 }, // 24 "EOS 5D"
+ { 4480, 3348, 12, 10, 36, 12, 0, 0, 0, 18, 0x49 }, // 25 "PowerShot G10"
+ { 4480, 3366, 80, 50, 0, 0 }, // 26 "PowerShot G1 X Mark II"
+ { 4496, 3366, 80, 50, 12, 0 }, // 27 "PowerShot G1 X"
+ { 4768, 3516, 96, 16, 0, 0, 0, 16 }, // 28 "PowerShot SX60 HS"
+ { 4832, 3204, 62, 26, 0, 0 }, // 29 "EOS 500D"
+ { 4832, 3228, 62, 51, 0, 0 }, // 30 "EOS 50D"
+ { 5108, 3349, 98, 13, 0, 0 }, // 31 "EOS-1Ds Mark II"
+ { 5120, 3318, 142, 45, 62, 0 }, // 32 "EOS-1D Mark IV"
+ { 5280, 3528, 72, 52, 0, 0 }, // 33 "EOS M10", "EOS 650D", "EOS 700D", "EOS M", "EOS 100D", "EOS M2"
+ { 5344, 3516, 142, 51, 0, 0 }, // 34 "EOS 550D", "EOS 600D", "EOS 60D", "EOS 1200D", "EOS 1300D", "EOS 3000D"
+ { 5344, 3584, 126, 100, 0, 2 }, // 35 "EOS-1D X", "EOS-1D C"
+ { 5344, 3950, 98, 18, 0, 0, 0, 24, 0, 0 }, // 36 "PowerShot SX70 HS"
+ { 5360, 3516, 158, 51, 0, 0 }, // 37 "EOS 7D"
+ { 5568, 3708, 72, 38, 0, 0 }, // 38; "EOS 7D Mark II", "EOS 6D", "EOS 70D", "EOS-1D X MARK II"
+ { 5632, 3710, 96, 17, 0, 0, 0, 16, 0, 0, 0x49 }, // 39 "PowerShot G7 X", "PowerShot G3 X", "PowerShot G9 X", "PowerShot G5 X", "PowerShot G7 X Mark II", "PowerShot G9 X Mark II"
+ { 5712, 3774, 62, 20, 10, 2 }, // 40 "EOS-1Ds Mark III"
+ { 5792, 3804, 158, 51, 0, 0 }, // 41 "EOS 5D Mark II"
+ { 5920, 3950, 122, 80, 2, 0 }, // 42 "EOS 5D Mark III"
+ { 6096, 4051, 76, 35, 0, 0 }, // 43 "EOS 1500D"
+ { 6096, 4056, 72, 34, 0, 0 }, // 44 "EOS M3", "EOS 760D", "EOS 750D"
+ { 6288, 4056, 264, 36, 0, 0 }, // 45 "EOS M5", "EOS M100", "EOS M6", "PowerShot G1 X Mark III", "EOS 80D", "EOS 800D", "EOS 77D", "EOS 200D", "EOS 250D", "EOS M50"
+ { 6384, 4224, 120, 44, 0, 0 }, // 46 "EOS 6D Mark II", "EOS RP"
+ { 6880, 4544, 136, 42, 0, 0 }, // 47 "EOS 5D Mark IV"
+ { 6888, 4546, 146, 48, 0, 0 }, // 48 "EOS R"
+ { 7128, 4732, 144, 72, 0, 0 }, // 49 "EOS M6 II", "EOS 90D"
+ { 8896, 5920, 160, 64, 0, 0 }, // 50 "EOS 5DS", "EOS 5DS R"
+ { 6192, 4152, 160, 120, 0, 0}, // EOS R3
+ { 6192, 4060, 168, 52, 24, 8, 16,48,32,0,} // EOS R10
+ };
+
+ static const libraw_custom_camera_t const_table[] = {
+ { 786432, 1024, 768, 0, 0, 0, 0, 0, 0x94, 0, 0, "AVT", "F-080C" },
+ { 1447680, 1392, 1040, 0, 0, 0, 0, 0, 0x94, 0, 0, "AVT", "F-145C" },
+ { 1920000, 1600, 1200, 0, 0, 0, 0, 0, 0x94, 0, 0, "AVT", "F-201C" },
+ { 5067304, 2588, 1958, 0, 0, 0, 0, 0, 0x94, 0, 0, "AVT", "F-510C" },
+ { 5067316, 2588, 1958, 0, 0, 0, 0, 0, 0x94, 0, 0, "AVT", "F-510C", 12 },
+ { 10134608, 2588, 1958, 0, 0, 0, 0, 9, 0x94, 0, 0, "AVT", "F-510C" },
+ { 10134620, 2588, 1958, 0, 0, 0, 0, 9, 0x94, 0, 0, "AVT", "F-510C", 12 },
+ { 16157136, 3272, 2469, 0, 0, 0, 0, 9, 0x94, 0, 0, "AVT", "F-810C" },
+ { 3995136, 1632, 1224, 0, 0, 0, 0, 8, 0x61, 0, 1, "AgfaPhoto", "DC-833m" },
+ { 15980544, 3264, 2448, 0, 0, 0, 0, 8, 0x61, 0, 1, "AgfaPhoto", "DC-833m" },
+ { 9631728, 2532, 1902, 0, 0, 0, 0, 96, 0x61, 0, 0, "Alcatel", "5035D" },
+ { 31850496, 4608, 3456, 0, 0, 0, 0, 0, 0x94, 0, 0, "GITUP", "GIT2 4:3" },
+ { 23887872, 4608, 2592, 0, 0, 0, 0, 0, 0x94, 0, 0, "GITUP", "GIT2 16:9" },
+ { 32257024, 4624, 3488, 8, 2, 16, 2, 0, 0x94, 0, 0, "GITUP", "GIT2P 4:3" },
+ { 24192768, 4624, 2616, 8, 2, 16, 2, 0, 0x94, 0, 0, "GITUP", "GIT2P 16:9" },
+ { 18016000, 4000, 2252, 0, 0, 0, 0, 0, 0x94, 0, 0, "GITUP", "G3DUO 16:9" },
+ // {24000000, 4000, 3000, 0, 0, 0, 0, 0, 0x94, 0, 0, "GITUP",
+ // "G3DUO 4:3"}, // Conflict w/ Samsung WB550
+
+ // Android Raw dumps id start
+ // File Size in bytes Horizontal Res Vertical Flag then bayer order eg
+ // 0x16 bbgr 0x94 rggb
+ { 1540857, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "Samsung", "S3" },
+ { 2658304, 1212, 1096, 0, 0, 0, 0, 1, 0x16, 0, 0, "LG", "G3FrontMipi" },
+ { 2842624, 1296, 1096, 0, 0, 0, 0, 1, 0x16, 0, 0, "LG", "G3FrontQCOM" },
+ { 2969600, 1976, 1200, 0, 0, 0, 0, 1, 0x16, 0, 0, "Xiaomi", "MI3wMipi" },
+ { 3170304, 1976, 1200, 0, 0, 0, 0, 1, 0x16, 0, 0, "Xiaomi", "MI3wQCOM" },
+ { 3763584, 1584, 1184, 0, 0, 0, 0, 96, 0x61, 0, 0, "I_Mobile", "I_StyleQ6" },
+ { 5107712, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "OmniVisi", "UltraPixel1" },
+ { 5382640, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "OmniVisi", "UltraPixel2" },
+ { 5664912, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "OmniVisi", "4688" },
+ { 5664912, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "OmniVisi", "4688" },
+ { 5364240, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "OmniVisi", "4688" },
+ { 6299648, 2592, 1944, 0, 0, 0, 0, 1, 0x16, 0, 0, "OmniVisi", "OV5648" },
+ { 6721536, 2592, 1944, 0, 0, 0, 0, 0, 0x16, 0, 0, "OmniVisi", "OV56482" },
+ { 6746112, 2592, 1944, 0, 0, 0, 0, 0, 0x16, 0, 0, "HTC", "OneSV" },
+ { 9631728, 2532, 1902, 0, 0, 0, 0, 96, 0x61, 0, 0, "Sony", "5mp" },
+ { 9830400, 2560, 1920, 0, 0, 0, 0, 96, 0x61, 0, 0, "NGM", "ForwardArt" },
+ { 10186752, 3264, 2448, 0, 0, 0, 0, 1, 0x94, 0, 0, "Sony", "IMX219-mipi 8mp" },
+ { 10223360, 2608, 1944, 0, 0, 0, 0, 96, 0x16, 0, 0, "Sony", "IMX" },
+ { 10782464, 3282, 2448, 0, 0, 0, 0, 0, 0x16, 0, 0, "HTC", "MyTouch4GSlide" },
+ { 10788864, 3282, 2448, 0, 0, 0, 0, 0, 0x16, 0, 0, "Xperia", "L" },
+ { 15967488, 3264, 2446, 0, 0, 0, 0, 96, 0x16, 0, 0, "OmniVison", "OV8850" },
+ { 16224256, 4208, 3082, 0, 0, 0, 0, 1, 0x16, 0, 0, "LG", "G3MipiL" },
+ { 16424960, 4208, 3120, 0, 0, 0, 0, 1, 0x16, 0, 0, "IMX135", "MipiL" },
+ { 17326080, 4164, 3120, 0, 0, 0, 0, 1, 0x16, 0, 0, "LG", "G3LQCom" },
+ { 17522688, 4212, 3120, 0, 0, 0, 0, 0, 0x16, 0, 0, "Sony", "IMX135-QCOM" },
+ { 19906560, 4608, 3456, 0, 0, 0, 0, 1, 0x16, 0, 0, "Gione", "E7mipi" },
+ { 19976192, 5312, 2988, 0, 0, 0, 0, 1, 0x16, 0, 0, "LG", "G4" },
+ { 20389888, 4632, 3480, 0, 0, 0, 0, 1, 0x16, 0, 0, "Xiaomi", "RedmiNote3Pro" },
+ { 20500480, 4656, 3496, 0, 0, 0, 0, 1, 0x94, 0, 0, "Sony", "IMX298-mipi 16mp" },
+ { 21233664, 4608, 3456, 0, 0, 0, 0, 1, 0x16, 0, 0, "Gione", "E7qcom" },
+ { 26023936, 4192, 3104, 0, 0, 0, 0, 96, 0x94, 0, 0, "THL", "5000" },
+ { 26257920, 4208, 3120, 0, 0, 0, 0, 96, 0x94, 0, 0, "Sony", "IMX214" },
+ { 26357760, 4224, 3120, 0, 0, 0, 0, 96, 0x61, 0, 0, "OV", "13860" },
+ { 41312256, 5248, 3936, 0, 0, 0, 0, 96, 0x61, 0, 0, "Meizu", "MX4" },
+ { 42923008, 5344, 4016, 0, 0, 0, 0, 96, 0x61, 0, 0, "Sony", "IMX230" },
+ // Android Raw dumps id end
+ { 20137344, 3664, 2748, 0, 0, 0, 0, 0x40, 0x49, 0, 0, "Aptina", "MT9J003", 0xffff },
+ { 2868726, 1384, 1036, 0, 0, 0, 0, 64, 0x49, 0, 8, "Baumer", "TXG14", 1078 },
+ { 6553440, 2664, 1968, 4, 4, 44, 4, 40, 0x94, 0, 2, "Canon", "PowerShot A460" }, // chdk hack
+ { 9243240, 3152, 2346, 12, 7, 44, 13, 40, 0x49, 0, 2, "Canon", "PowerShot A470" }, // chdk hack
+ { 6653280, 2672, 1992, 10, 6, 42, 2, 40, 0x94, 0, 2, "Canon", "PowerShot A530" }, // chdk hack
+ { 6573120, 2672, 1968, 12, 8, 44, 0, 40, 0x94, 0, 2, "Canon", "PowerShot A610" }, // chdk hack
+ { 9219600, 3152, 2340, 36, 12, 4, 0, 40, 0x94, 0, 2, "Canon", "PowerShot A620" }, // chdk hack
+ { 10383120, 3344, 2484, 12, 6, 44, 6, 40, 0x94, 0, 2, "Canon", "PowerShot A630" }, // chdk hack
+ { 12945240, 3736, 2772, 12, 6, 52, 6, 40, 0x94, 0, 2, "Canon", "PowerShot A640" }, // chdk hack
+ { 15636240, 4104, 3048, 48, 12, 24, 12, 40, 0x94, 0, 2, "Canon", "PowerShot A650 IS" }, // chdk hack
+ { 10341600, 3336, 2480, 6, 5, 32, 3, 40, 0x94, 0, 2, "Canon", "PowerShot A720 IS" }, // chdk hack
+ { 24724224, 4704, 3504, 8, 16, 56, 8, 40, 0x49, 0, 2, "Canon", "PowerShot A3300 IS" }, // chdk hack
+ { 18763488, 4104, 3048, 10, 22, 82, 22, 8, 0x49, 0, 0, "Canon", "PowerShot D10" }, // ? chdk hack ?
+ { 19493760, 4160, 3124, 104, 12, 8, 66, 40, 0x49, 0, 2, "Canon", "PowerShot S100" }, // chdk hack CRW
+ { 7710960, 2888, 2136, 44, 8, 4, 0, 40, 0x94, 0, 2, "Canon", "PowerShot S3 IS" }, // chdk hack
+ { 5298000, 2400, 1766, 12, 12, 44, 2, 40, 0x94, 0, 2, "Canon", "PowerShot SD300" }, // chdk hack
+ { 18653760, 4080, 3048, 24, 12, 24, 12, 40, 0x94, 0, 2, "Canon", "PowerShot SX20 IS" }, // chdk hack
+ { 21936096, 4464, 3276, 25, 10, 73, 12, 40, 0x16, 0, 2, "Canon", "PowerShot SX30 IS" }, // chdk hack
+ { 19167840, 4176, 3060, 96, 16, 8, 0, 40, 0x94, 0, 2, "Canon", "PowerShot SX40 HS" }, // chdk hack CR2
+ { 15467760, 3720, 2772, 6, 12, 30, 0, 40, 0x94, 0, 2, "Canon", "PowerShot SX110 IS" }, // chdk hack
+ { 15534576, 3728, 2778, 12, 9, 44, 9, 40, 0x94, 0, 2, "Canon", "PowerShot SX120 IS" }, // chdk hack
+ { 19131120, 4168, 3060, 92, 16, 4, 1, 40, 0x94, 0, 2, "Canon", "PowerShot SX220 HS" }, // chdk hack
+ { 31663200, 5344, 3950, 96, 18, 0, 0, 40, 0x94, 0, 2, "Canon", "PowerShot SX710 HS" }, // chdk hack
+ { 30858240, 5248, 3920, 8, 16, 56, 16, 40, 0x94, 0, 2, "Canon", "IXUS 160" }, // chdk hack
+ { 1976352, 1632, 1211, 0, 2, 0, 1, 0, 0x94, 0, 1, "Casio", "QV-2000UX" },
+ { 3217760, 2080, 1547, 0, 0, 10, 1, 0, 0x94, 0, 1, "Casio", "QV-3*00EX" },
+ { 6218368, 2585, 1924, 0, 0, 9, 0, 0, 0x94, 0, 1, "Casio", "QV-5700" },
+ { 7816704, 2867, 2181, 0, 0, 34, 36, 0, 0x16, 0, 1, "Casio", "EX-Z60" },
+ { 2937856, 1621, 1208, 0, 0, 1, 0, 0, 0x94, 7, 13, "Casio", "EX-S20" },
+ { 4948608, 2090, 1578, 0, 0, 32, 34, 0, 0x94, 7, 1, "Casio", "EX-S100" },
+ { 6054400, 2346, 1720, 2, 0, 32, 0, 0, 0x94, 7, 1, "Casio", "QV-R41" },
+ { 7426656, 2568, 1928, 0, 0, 0, 0, 0, 0x94, 0, 1, "Casio", "EX-P505" },
+ { 7530816, 2602, 1929, 0, 0, 22, 0, 0, 0x94, 7, 1, "Casio", "QV-R51" },
+ { 7542528, 2602, 1932, 0, 0, 32, 0, 0, 0x94, 7, 1, "Casio", "EX-Z50" },
+ { 7562048, 2602, 1937, 0, 0, 25, 0, 0, 0x16, 7, 1, "Casio", "EX-Z500" },
+ { 7753344, 2602, 1986, 0, 0, 32, 26, 0, 0x94, 7, 1, "Casio", "EX-Z55" },
+ { 9313536, 2858, 2172, 0, 0, 14, 30, 0, 0x94, 7, 1, "Casio", "EX-P600" },
+ { 10834368, 3114, 2319, 0, 0, 27, 0, 0, 0x94, 0, 1, "Casio", "EX-Z750" },
+ { 10843712, 3114, 2321, 0, 0, 25, 0, 0, 0x94, 0, 1, "Casio", "EX-Z75" },
+ { 10979200, 3114, 2350, 0, 0, 32, 32, 0, 0x94, 7, 1, "Casio", "EX-P700" },
+ { 12310144, 3285, 2498, 0, 0, 6, 30, 0, 0x94, 0, 1, "Casio", "EX-Z850" },
+ { 12489984, 3328, 2502, 0, 0, 47, 35, 0, 0x94, 0, 1, "Casio", "EX-Z8" },
+ { 15499264, 3754, 2752, 0, 0, 82, 0, 0, 0x94, 0, 1, "Casio", "EX-Z1050" },
+ { 18702336, 4096, 3044, 0, 0, 24, 0, 80, 0x94, 7, 1, "Casio", "EX-ZR100" },
+ { 7684000, 2260, 1700, 0, 0, 0, 0, 13, 0x94, 0, 1, "Casio", "QV-4000" },
+ { 787456, 1024, 769, 0, 1, 0, 0, 0, 0x49, 0, 0, "Creative", "PC-CAM 600" },
+ { 28829184, 4384, 3288, 0, 0, 0, 0, 36, 0x61, 0, 0, "DJI" },
+ { 15151104, 4608, 3288, 0, 0, 0, 0, 0, 0x94, 0, 0, "Matrix" },
+ { 3840000, 1600, 1200, 0, 0, 0, 0, 65, 0x49, 0, 0, "Foculus", "531C" },
+ { 307200, 640, 480, 0, 0, 0, 0, 0, 0x94, 0, 0, "Generic" },
+ { 62464, 256, 244, 1, 1, 6, 1, 0, 0x8d, 0, 0, "Kodak", "DC20" },
+ { 124928, 512, 244, 1, 1, 10, 1, 0, 0x8d, 0, 0, "Kodak", "DC20" },
+ { 1652736, 1536, 1076, 0, 52, 0, 0, 0, 0x61, 0, 0, "Kodak", "DCS200" },
+ { 4159302, 2338, 1779, 1, 33, 1, 2, 0, 0x94, 0, 0, "Kodak", "C330" },
+ { 4162462, 2338, 1779, 1, 33, 1, 2, 0, 0x94, 0, 0, "Kodak", "C330", 3160 },
+ { 2247168, 1232, 912, 0, 0, 16, 0, 0, 0x00, 0, 0, "Kodak", "C330" },
+ { 3370752, 1232, 912, 0, 0, 16, 0, 0, 0x00, 0, 0, "Kodak", "C330" },
+ { 6163328, 2864, 2152, 0, 0, 0, 0, 0, 0x94, 0, 0, "Kodak", "C603" },
+ { 6166488, 2864, 2152, 0, 0, 0, 0, 0, 0x94, 0, 0, "Kodak", "C603", 3160 },
+ { 460800, 640, 480, 0, 0, 0, 0, 0, 0x00, 0, 0, "Kodak", "C603" },
+ { 9116448, 2848, 2134, 0, 0, 0, 0, 0, 0x00, 0, 0, "Kodak", "C603" },
+ { 12241200, 4040, 3030, 2, 0, 0, 13, 0, 0x49, 0, 0, "Kodak", "12MP" },
+ { 12272756, 4040, 3030, 2, 0, 0, 13, 0, 0x49, 0, 0, "Kodak", "12MP", 31556 },
+ { 18000000, 4000, 3000, 0, 0, 0, 0, 0, 0x00, 0, 0, "Kodak", "12MP" },
+ { 614400, 640, 480, 0, 3, 0, 0, 64, 0x94, 0, 0, "Kodak", "KAI-0340" },
+ { 15360000, 3200, 2400, 0, 0, 0, 0, 96, 0x16, 0, 0, "Lenovo", "A820" },
+ { 3884928, 1608, 1207, 0, 0, 0, 0, 96, 0x16, 0, 0, "Micron", "2010", 3212 },
+ { 1138688, 1534, 986, 0, 0, 0, 0, 0, 0x61, 0, 0, "Minolta", "RD175", 513 },
+ { 1581060, 1305, 969, 0, 0, 18, 6, 6, 0x1e, 4, 1, "Nikon", "E900" }, // "diag raw" hack
+ { 2465792, 1638, 1204, 0, 0, 22, 1, 6, 0x4b, 5, 1, "Nikon", "E950" }, // "diag raw" hack; possibly also Nikon E700, E800, E775;
+ // Olympus C-2020Z
+ { 2940928, 1616, 1213, 0, 0, 0, 7, 30, 0x94, 0, 1, "Nikon", "E2100" }, // "diag raw" hack; also Nikon E2500
+ { 4771840, 2064, 1541, 0, 0, 0, 1, 6, 0xe1, 0, 1, "Nikon", "E990" }, // "diag raw" hack; possibly also Nikon E880, E885, E995;
+ // Olympus C-3030Z
+ { 4775936, 2064, 1542, 0, 0, 0, 0, 30, 0x94, 0, 1, "Nikon", "E3700" }, // "diag raw" hack; Nikon E3100, E3200, E3500;
+ // Pentax "Optio 33WR"; possibly also Olympus C-740UZ
+ { 5865472, 2288, 1709, 0, 0, 0, 1, 6, 0xb4, 0, 1, "Nikon", "E4500" }, // "diag raw" hack; possibly also Olympus C-4040Z
+ { 5869568, 2288, 1710, 0, 0, 0, 0, 6, 0x16, 0, 1, "Nikon", "E4300" }, // "diag raw" hack; also Minolta "DiMAGE Z2"
+ { 7438336, 2576, 1925, 0, 0, 0, 1, 6, 0xb4, 0, 1, "Nikon", "E5000" }, // also Nikon E5700
+ { 8998912, 2832, 2118, 0, 0, 0, 0, 30, 0x94, 7, 1, "Nikon", "COOLPIX S6" }, // "diag raw" hack
+ { 5939200, 2304, 1718, 0, 0, 0, 0, 30, 0x16, 0, 0, "Olympus", "C-770UZ" }, // possibly also Olympus C-4100Z, C-765UZ
+ { 3178560, 2064, 1540, 0, 0, 0, 0, 0, 0x94, 0, 1, "Pentax", "Optio S V1.01" },
+ { 4841984, 2090, 1544, 0, 0, 22, 0, 0, 0x94, 7, 1, "Pentax", "Optio S" },
+ { 6114240, 2346, 1737, 0, 0, 22, 0, 0, 0x94, 7, 1, "Pentax", "Optio S4" },
+ { 10702848, 3072, 2322, 0, 0, 0, 21, 30, 0x94, 0, 1, "Pentax", "Optio 750Z" },
+ { 4147200, 1920, 1080, 0, 0, 0, 0, 0, 0x49, 0, 0, "Photron", "BC2-HD" },
+ { 4151666, 1920, 1080, 0, 0, 0, 0, 0, 0x49, 0, 0, "Photron", "BC2-HD", 8 },
+ { 13248000, 2208, 3000, 0, 0, 0, 0, 13, 0x61, 0, 0, "Pixelink", "A782" },
+ { 6291456, 2048, 1536, 0, 0, 0, 0, 96, 0x61, 0, 0, "RoverShot", "3320AF" },
+ { 311696, 644, 484, 0, 0, 0, 0, 0, 0x16, 0, 8, "ST Micro", "STV680 VGA" },
+ { 16098048, 3288, 2448, 0, 0, 24, 0, 9, 0x94, 0, 1, "Samsung", "S85" }, // hack
+ { 16215552, 3312, 2448, 0, 0, 48, 0, 9, 0x94, 0, 1, "Samsung", "S85" }, // hack
+ { 20487168, 3648, 2808, 0, 0, 0, 0, 13, 0x94, 5, 1, "Samsung", "WB550" },
+ { 24000000, 4000, 3000, 0, 0, 0, 0, 13, 0x94, 5, 1, "Samsung", "WB550" },
+ { 12582980, 3072, 2048, 0, 0, 0, 0, 33, 0x61, 0, 0, "Sinar", "", 68 }, // Sinarback 23; same res. as Leaf Volare & Cantare
+ { 33292868, 4080, 4080, 0, 0, 0, 0, 33, 0x61, 0, 0, "Sinar", "", 68 }, // Sinarback 44
+ { 44390468, 4080, 5440, 0, 0, 0, 0, 33, 0x61, 0, 0, "Sinar", "", 68 }, // Sinarback 54
+ { 1409024, 1376, 1024, 0, 0, 1, 0, 0, 0x49, 0, 0, "Sony", "XCD-SX910CR" },
+ { 2818048, 1376, 1024, 0, 0, 1, 0, 97, 0x49, 0, 0, "Sony", "XCD-SX910CR" },
+ };
+
+ libraw_custom_camera_t
+ table[64 + sizeof(const_table) / sizeof(const_table[0])];
+
+
+ // clang-format on
+
+ char head[64] = {0}, *cp;
+ int hlen, fsize, flen, zero_fsize = 1, i, c;
+ INT64 fsize64;
+ struct jhead jh;
+
+ unsigned camera_count =
+ parse_custom_cameras(64, table, imgdata.rawparams.custom_camera_strings);
+ for (int q = 0; q < int(sizeof(const_table) / sizeof(const_table[0])); q++)
+ memmove(&table[q + camera_count], &const_table[q], sizeof(const_table[0]));
+ camera_count += sizeof(const_table) / sizeof(const_table[0]);
+
+ tiff_flip = flip = filters = UINT_MAX; /* unknown */
+ raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
+ maximum = height = width = top_margin = left_margin = 0;
+ cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
+ iso_speed = shutter = aperture = focal_len = 0;
+ unique_id = 0ULL;
+ tiff_nifds = 0;
+ is_NikonTransfer = 0;
+ is_Olympus = 0;
+ OlympusDNG_SubDirOffsetValid = 0;
+ is_Sony = 0;
+ is_pana_raw = 0;
+ maker_index = LIBRAW_CAMERAMAKER_Unknown;
+ FujiCropMode = 0;
+ is_PentaxRicohMakernotes = 0;
+ normalized_model[0] = 0;
+ normalized_make[0] = 0;
+ CM_found = 0;
+ memset(tiff_ifd, 0, sizeof tiff_ifd);
+ libraw_internal_data.unpacker_data.crx_track_selected = -1;
+ libraw_internal_data.unpacker_data.crx_track_count = -1;
+ libraw_internal_data.unpacker_data.CR3_CTMDtag = 0;
+ imHassy.nIFD_CM[0] = imHassy.nIFD_CM[1] = -1;
+ imKodak.ISOCalibrationGain = 1.0f;
+ imCommon.CameraTemperature = imCommon.SensorTemperature =
+ imCommon.SensorTemperature2 = imCommon.LensTemperature =
+ imCommon.AmbientTemperature = imCommon.BatteryTemperature =
+ imCommon.exifAmbientTemperature = -1000.0f;
+
+ libraw_internal_data.unpacker_data.ifd0_offset = -1LL;
+
+ imgdata.color.ExifColorSpace = LIBRAW_COLORSPACE_Unknown;
+ for (i = 0; i < LIBRAW_IFD_MAXCOUNT; i++)
+ {
+ tiff_ifd[i].dng_color[0].illuminant = tiff_ifd[i].dng_color[1].illuminant =
+ 0xffff;
+ for (int q = 0; q < 4; q++)
+ tiff_ifd[i].dng_levels.analogbalance[q] = 1.0f;
+ }
+
+ memset(gpsdata, 0, sizeof gpsdata);
+ memset(cblack, 0, sizeof cblack);
+ memset(white, 0, sizeof white);
+ memset(mask, 0, sizeof mask);
+ thumb_offset = thumb_length = thumb_width = thumb_height = 0;
+ load_raw = 0;
+ thumb_format = LIBRAW_INTERNAL_THUMBNAIL_JPEG; // default to JPEG
+ data_offset = meta_offset = meta_length = tiff_bps = tiff_compress = 0;
+ kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
+ timestamp = shot_order = tiff_samples = black = is_foveon = 0;
+ mix_green = profile_length = data_error = zero_is_bad = 0;
+ pixel_aspect = is_raw = raw_color = 1;
+ tile_width = tile_length = 0;
+ metadata_blocks = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ cam_mul[i] = i == 1;
+ pre_mul[i] = i < 3;
+ FORC3 cmatrix[c][i] = 0;
+ FORC3 rgb_cam[c][i] = c == i;
+ }
+ colors = 3;
+ for (i = 0; i < 0x10000; i++)
+ curve[i] = i;
+
+ order = get2();
+ hlen = get4();
+ fseek(ifp, 0, SEEK_SET);
+
+ if (fread(head, 1, 64, ifp) < 64)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ libraw_internal_data.unpacker_data.lenRAFData =
+ libraw_internal_data.unpacker_data.posRAFData = 0;
+
+ fseek(ifp, 0, SEEK_END);
+ fsize64 = ftell(ifp);
+ if(fsize64 > LIBRAW_MAX_NONDNG_RAW_FILE_SIZE && fsize64 > LIBRAW_MAX_DNG_RAW_FILE_SIZE)
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ flen = fsize = ftell(ifp);
+ if ((cp = (char *)memmem(head, 32, (char *)"MMMM", 4)) ||
+ (cp = (char *)memmem(head, 32, (char *)"IIII", 4)))
+ {
+ parse_phase_one(cp - head);
+ if (cp - head && parse_tiff(0))
+ apply_tiff();
+ }
+ else if (order == 0x4949 || order == 0x4d4d)
+ {
+ if (!memcmp(head + 6, "HEAPCCDR", 8))
+ {
+ data_offset = hlen;
+ parse_ciff(hlen, flen - hlen, 0);
+ load_raw = &LibRaw::canon_load_raw;
+ }
+ else if (parse_tiff(0))
+ apply_tiff();
+ }
+ else if (!memcmp(head, "\xff\xd8\xff\xe1", 4) && !memcmp(head + 6, "Exif", 4))
+ {
+ fseek(ifp, 4, SEEK_SET);
+ data_offset = 4 + get2();
+ fseek(ifp, data_offset, SEEK_SET);
+ if (fgetc(ifp) != 0xff)
+ parse_tiff(12);
+ thumb_offset = 0;
+ }
+ else if (!memcmp(head + 25, "ARECOYK", 7)) // 'KYOCERA' right-to-left
+ {
+ strcpy(make, "Contax");
+ strcpy(model, "N Digital");
+ parse_kyocera();
+ }
+ else if (!strcmp(head, "PXN"))
+ {
+ strcpy(make, "Logitech");
+ strcpy(model, "Fotoman Pixtura");
+ }
+ else if (!strcmp(head, "qktk"))
+ {
+ strcpy(make, "Apple");
+ strcpy(model, "QuickTake 100");
+ load_raw = &LibRaw::quicktake_100_load_raw;
+ }
+ else if (!strcmp(head, "qktn"))
+ {
+ strcpy(make, "Apple");
+ strcpy(model, "QuickTake 150");
+ load_raw = &LibRaw::kodak_radc_load_raw;
+ }
+ else if (!memcmp(head, "FUJIFILM", 8))
+ {
+ memcpy(imFuji.SerialSignature, head + 0x10, 0x0c);
+ imFuji.SerialSignature[0x0c] = 0;
+ memcpy(imFuji.SensorID, imFuji.SerialSignature + 0x06, 0x04);
+ imFuji.SensorID[0x04] = 0;
+ strncpy(model, head + 0x1c, 0x20);
+ model[0x20] = 0;
+ c = 11;
+ while (imFuji.SerialSignature[c] > 0 && isdigit(imFuji.SerialSignature[c]) && (c>0))
+ c--;
+ if(c < 11)
+ unique_id = (unsigned long long)atoi(imFuji.SerialSignature+c+1);
+ memcpy(imFuji.RAFVersion, head + 0x3c, 4);
+ imFuji.RAFVersion[4] = 0;
+ fseek(ifp, 84, SEEK_SET);
+ thumb_offset = get4();
+ thumb_length = get4();
+ fseek(ifp, 92, SEEK_SET);
+ parse_fuji(get4());
+ if (thumb_offset > 120)
+ {
+ fseek(ifp, 120, SEEK_SET);
+ is_raw += (i = get4()) ? 1 : 0;
+ if (is_raw == 2 && shot_select)
+ parse_fuji(i);
+ }
+ load_raw = &LibRaw::unpacked_load_raw;
+ fseek(ifp, 100 + 28 * (shot_select > 0), SEEK_SET);
+ parse_tiff(data_offset = get4());
+ parse_tiff(thumb_offset + 12);
+ parse_fuji_thumbnail(thumb_offset);
+ apply_tiff();
+ }
+ else if (!memcmp(head, "RIFF", 4))
+ {
+ fseek(ifp, 0, SEEK_SET);
+ parse_riff(100);
+ }
+ else if (!memcmp(head + 4, "ftypqt ", 9))
+ {
+ fseek(ifp, 0, SEEK_SET);
+ parse_qt(fsize);
+ is_raw = 0;
+ }
+ else if (!memcmp(head, "\0\001\0\001\0@", 6))
+ {
+ fseek(ifp, 6, SEEK_SET);
+ fread(make, 1, 8, ifp);
+ fread(model, 1, 8, ifp);
+ fread(model2, 1, 16, ifp);
+ data_offset = get2();
+ get2();
+ raw_width = get2();
+ raw_height = get2();
+ load_raw = &LibRaw::nokia_load_raw;
+ filters = 0x61616161;
+ }
+ else if (!memcmp(head, "NOKIARAW", 8))
+ {
+ strcpy(make, "NOKIA");
+ order = 0x4949;
+ fseek(ifp, 300, SEEK_SET);
+ data_offset = get4();
+ i = get4(); // bytes count
+ width = get2();
+ height = get2();
+
+ // Data integrity check
+ if (width < 1 || width > 16000 || height < 1 || height > 16000 ||
+ i < (width * height) || i > (2 * width * height))
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ switch (tiff_bps = i * 8 / (width * height))
+ {
+ case 8:
+ load_raw = &LibRaw::eight_bit_load_raw;
+ break;
+ case 10:
+ load_raw = &LibRaw::nokia_load_raw;
+ break;
+ case 0:
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ break;
+ }
+ raw_height = height + (top_margin = i / (width * tiff_bps / 8) - height);
+ mask[0][3] = 1;
+ filters = 0x61616161;
+ }
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ else if (!memcmp(head, "ARRI", 4))
+ {
+ order = 0x4949;
+ fseek(ifp, 20, SEEK_SET);
+ width = get4();
+ height = get4();
+ strcpy(make, "ARRI");
+ fseek(ifp, 668, SEEK_SET);
+ fread(model, 1, 64, ifp);
+ model[63] = 0;
+ fseek(ifp, 760, SEEK_SET);
+ fread(software, 1, 64, ifp);
+ if((unsigned char)software[0] == 0xff) software[0] = 0;
+ software[63] = 0;
+ data_offset = 4096;
+ load_raw = &LibRaw::packed_load_raw;
+ load_flags = 88;
+ filters = 0x61616161;
+ fixupArri();
+ }
+ else if (!memcmp(head, "XPDS", 4))
+ {
+ order = 0x4949;
+ fseek(ifp, 0x800, SEEK_SET);
+ fread(make, 1, 41, ifp);
+ raw_height = get2();
+ raw_width = get2();
+ fseek(ifp, 56, SEEK_CUR);
+ fread(model, 1, 30, ifp);
+ data_offset = 0x10000;
+ load_raw = &LibRaw::canon_rmf_load_raw;
+ gamma_curve(0, 12.25, 1, 1023);
+ }
+ else if (!memcmp(head + 4, "RED1", 4))
+ {
+ strcpy(make, "Red");
+ strcpy(model, "One");
+ parse_redcine();
+ load_raw = &LibRaw::redcine_load_raw;
+ gamma_curve(1 / 2.4, 12.92, 1, 4095);
+ filters = 0x49494949;
+ }
+#endif
+ else if (!memcmp(head, "DSC-Image", 9))
+ parse_rollei();
+ else if (!memcmp(head, "PWAD", 4))
+ parse_sinar_ia();
+ else if (!memcmp(head, "\0MRM", 4))
+ parse_minolta(0);
+ else if (!memcmp(head, "FOVb", 4))
+ {
+ parse_x3f(); /* Does nothing if USE_X3FTOOLS is not defined */
+ }
+ else if (!memcmp(head, "CI", 2))
+ parse_cine();
+#ifdef USE_6BY9RPI
+ else if (!memcmp(head, "BRCM", 4)) {
+ fseek(ifp, 0, SEEK_SET);
+ strcpy(make, "RaspberryPi");
+ strcpy(model, "Pi");
+ parse_raspberrypi();
+ }
+#endif
+ else if (!memcmp(head + 4, "ftypcrx ", 8))
+ {
+ int err;
+ unsigned long long szAtomList;
+ short nesting = -1;
+ short nTrack = -1;
+ short TrackType;
+ char AtomNameStack[129];
+ strcpy(make, "Canon");
+
+ szAtomList = ifp->size();
+ err = parseCR3(0ULL, szAtomList, nesting, AtomNameStack, nTrack, TrackType);
+ libraw_internal_data.unpacker_data.crx_track_count = nTrack;
+ if ((err == 0 || err == -14) &&
+ nTrack >= 0) // no error, or too deep nesting
+ selectCRXTrack();
+ }
+
+ if (dng_version)
+ {
+ if (fsize64 > LIBRAW_MAX_DNG_RAW_FILE_SIZE)
+ throw LIBRAW_EXCEPTION_TOOBIG;
+ }
+ else
+ {
+ if (fsize64 > LIBRAW_MAX_NONDNG_RAW_FILE_SIZE)
+ throw LIBRAW_EXCEPTION_TOOBIG;
+ }
+
+ if (make[0] == 0)
+ for (zero_fsize = i = 0; i < (int)camera_count; i++)
+ if (fsize == (int)table[i].fsize)
+ {
+ strcpy(make, table[i].t_make);
+ strcpy(model, table[i].t_model);
+ flip = table[i].flags >> 2;
+ zero_is_bad = table[i].flags & 2;
+ data_offset = table[i].offset == 0xffff ? 0 : table[i].offset;
+ raw_width = table[i].rw;
+ raw_height = table[i].rh;
+ left_margin = table[i].lm;
+ top_margin = table[i].tm;
+ width = raw_width - left_margin - table[i].rm;
+ height = raw_height - top_margin - table[i].bm;
+ filters = 0x1010101U * table[i].cf;
+ colors = 4 - !((filters & filters >> 1) & 0x5555);
+ load_flags = table[i].lf & 0xff;
+ if (table[i].lf & 0x100) /* Monochrome sensor dump */
+ {
+ colors = 1;
+ filters = 0;
+ }
+ switch (tiff_bps = (fsize - data_offset) * 8 / (raw_width * raw_height))
+ {
+ case 6:
+ load_raw = &LibRaw::minolta_rd175_load_raw;
+ ilm.CameraMount = LIBRAW_MOUNT_Minolta_A;
+ break;
+ case 8:
+ load_raw = &LibRaw::eight_bit_load_raw;
+ break;
+ case 10:
+ if ((fsize - data_offset) / raw_height * 3 >= raw_width * 4)
+ {
+ load_raw = &LibRaw::android_loose_load_raw;
+ break;
+ }
+ else if (load_flags & 1)
+ {
+ load_raw = &LibRaw::android_tight_load_raw;
+ break;
+ }
+ case 12:
+ load_flags |= 128;
+ load_raw = &LibRaw::packed_load_raw;
+ break;
+ case 16:
+ order = 0x4949 | 0x404 * (load_flags & 1);
+ tiff_bps -= load_flags >> 4;
+ tiff_bps -= load_flags = load_flags >> 1 & 7;
+ load_raw = table[i].offset == 0xffff
+ ? &LibRaw::unpacked_load_raw_reversed
+ : &LibRaw::unpacked_load_raw;
+ }
+ maximum = (1 << tiff_bps) - (1 << table[i].max);
+ break;
+ }
+ if (zero_fsize)
+ fsize = 0;
+ if (make[0] == 0 && fsize64 < 25000000LL)
+ parse_smal(0, flen);
+ if (make[0] == 0)
+ {
+ parse_jpeg(0);
+#ifdef USE_6BY9RPI
+ if (!(strncmp(model, "ov", 2) && strncmp(model, "RP_", 3) && strncmp(model, "imx477", 6))) {
+ //Assume that this isn't a raw unless the header can be found
+ is_raw = 0;
+
+ if (!strncasecmp(model, "RP_testc",8)
+ || !strncasecmp(model, "imx477", 6) // from PyDNG
+ || !strncasecmp(model, "RP_imx477",9)) {
+ const long offsets[] = {
+ //IMX477 offsets
+ 3375104, //2028x1080 12bit
+ 4751360, //2028x1520 12bit
+ 18711040, //4056x3040 12bit
+ 1015808, //1012x760 10bit
+ -1 //Marker for end of table
+ };
+ int offset_idx;
+ for (offset_idx=0; offsets[offset_idx]!=-1; offset_idx++) {
+ if(!fseek (ifp, -offsets[offset_idx], SEEK_END) &&
+ fread (head, 1, 32, ifp) && !strncmp(head,"BRCM", 4)) {
+ fseek(ifp, -32, SEEK_CUR);
+ strcpy (make, "RaspberryPi");
+ strcpy(model, "RP_imx477"); // Force single model
+ black = (offset_idx == 3) ? 64 : 256;
+ parse_raspberrypi();
+ break;
+ }
+ }
+ }
+ else if (!strncasecmp(model, "RP_imx", 6)) {
+ const long offsets[] = {
+ //IMX219 offsets
+ 10270208, //8MPix 3280x2464
+ 2678784, //1920x1080
+ 2628608, //1640x1232
+ 1963008, //1640x922
+ 1233920, //1280x720
+ 445440, //640x480
+ -1 //Marker for end of table
+ };
+ int offset_idx;
+ for (offset_idx = 0; offsets[offset_idx] != -1; offset_idx++) {
+ if (!fseek(ifp, -offsets[offset_idx], SEEK_END) &&
+ fread(head, 1, 32, ifp) && !strncmp(head, "BRCM", 4)) {
+
+ fseek(ifp, -32, SEEK_CUR);
+ strcpy(make, "RaspberryPi");
+ black = 66;
+ parse_raspberrypi();
+ break;
+ }
+ }
+ }
+ else if (!strncasecmp(model, "RP_OV", 5) || !strncasecmp(model, "ov5647", 6)) {
+ const long offsets[] = {
+ 6404096, //5MPix 2592x1944
+ 2717696, //1920x1080
+ 1625600, //1296x972
+ 1233920, //1296x730
+ 445440, //640x480
+ -1 //Marker for end of table
+ };
+ int offset_idx;
+ for (offset_idx = 0; offsets[offset_idx] != -1; offset_idx++) {
+ if (!fseek(ifp, -offsets[offset_idx], SEEK_END) &&
+ fread(head, 1, 32, ifp) && !strncmp(head, "BRCM", 4)) {
+ fseek(ifp, -32, SEEK_CUR);
+ strcpy(make, "RaspberryPi");
+ strcpy(model, "ov5647"); // Force single model
+ width = raw_width;
+ //Defaults
+ raw_width = 2611;
+ filters = 0x16161616;
+ black = 16;
+ parse_raspberrypi();
+ break;
+ }
+ }
+ }
+ }// else is_raw = 0;
+#else
+ fseek(ifp, 0, SEEK_END);
+ int sz = ftell(ifp);
+ if (!strncmp(model, "RP_imx219", 9) && sz >= 0x9cb600 &&
+ !fseek(ifp, -0x9cb600, SEEK_END) && fread(head, 1, 0x20, ifp) &&
+ !strncmp(head, "BRCM", 4))
+ {
+ strcpy(make, "Broadcom");
+ strcpy(model, "RPi IMX219");
+ if (raw_height > raw_width)
+ flip = 5;
+ data_offset = ftell(ifp) + 0x8000 - 0x20;
+ parse_broadcom();
+ black = 66;
+ maximum = 0x3ff;
+ load_raw = &LibRaw::broadcom_load_raw;
+ thumb_offset = 0;
+ thumb_length = sz - 0x9cb600 - 1;
+ }
+ else if (!(strncmp(model, "ov5647", 6) && strncmp(model, "RP_OV5647", 9)) &&
+ sz >= 0x61b800 && !fseek(ifp, -0x61b800, SEEK_END) &&
+ fread(head, 1, 0x20, ifp) && !strncmp(head, "BRCM", 4))
+ {
+ strcpy(make, "Broadcom");
+ if (!strncmp(model, "ov5647", 6))
+ strcpy(model, "RPi OV5647 v.1");
+ else
+ strcpy(model, "RPi OV5647 v.2");
+ if (raw_height > raw_width)
+ flip = 5;
+ data_offset = ftell(ifp) + 0x8000 - 0x20;
+ parse_broadcom();
+ black = 16;
+ maximum = 0x3ff;
+ load_raw = &LibRaw::broadcom_load_raw;
+ thumb_offset = 0;
+ thumb_length = sz - 0x61b800 - 1;
+ }
+ else
+ is_raw = 0;
+#endif
+ }
+
+ // make sure strings are terminated
+ desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0;
+
+ for (i = 0; i < int(sizeof CorpTable / sizeof *CorpTable); i++)
+ {
+ if (strcasestr(make, CorpTable[i].CorpName))
+ { /* Simplify company names */
+ maker_index = CorpTable[i].CorpId;
+ break;
+ }
+ }
+
+ if (makeIs(LIBRAW_CAMERAMAKER_HMD_Global) && !strncasecmp(model, "Nokia", 5)) {
+ maker_index = LIBRAW_CAMERAMAKER_Nokia;
+ } else if (makeIs(LIBRAW_CAMERAMAKER_JK_Imaging) && !strncasecmp(model, "Kodak", 5)) {
+ maker_index = LIBRAW_CAMERAMAKER_Kodak;
+ } else if (makeIs(LIBRAW_CAMERAMAKER_Ricoh) && !strncasecmp(model, "PENTAX", 6)) {
+ maker_index = LIBRAW_CAMERAMAKER_Pentax;
+ }
+
+ for (i = 0; i < int(sizeof CorpTable / sizeof *CorpTable); i++) {
+ if (maker_index == (unsigned)CorpTable[i].CorpId) {
+ strcpy(make, CorpTable[i].CorpName);
+ break;
+ }
+ }
+
+ if ((makeIs(LIBRAW_CAMERAMAKER_Kodak) || makeIs(LIBRAW_CAMERAMAKER_Leica)) &&
+ ((cp = strcasestr(model, " DIGITAL CAMERA")) ||
+ (cp = strstr(model, "FILE VERSION")))) {
+ *cp = 0;
+ }
+
+ remove_trailing_spaces(make, sizeof(make));
+ remove_trailing_spaces(model, sizeof(model));
+
+ i = int(strbuflen(make)); /* Remove make from model */
+ if (!strncasecmp(model, make, i) && model[i++] == ' ')
+ memmove(model, model + i, 64 - i);
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Fujifilm) && !strncmp(model, "FinePix", 7)) {
+ memmove(model, model + 7, strlen(model) - 6);
+ if (model[0] == ' ') {
+ memmove(model, model + 1, strlen(model));
+ }
+ } else if ((makeIs(LIBRAW_CAMERAMAKER_Kodak) || makeIs(LIBRAW_CAMERAMAKER_Konica)) &&
+ !strncmp(model, "Digital Camera ", 15)) {
+ memmove(model, model + 15, strlen(model) - 14);
+ }
+
+ desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0;
+ if (!is_raw)
+ goto notraw;
+
+ if (!height)
+ height = raw_height;
+ if (!width)
+ width = raw_width;
+
+ identify_finetune_pentax();
+
+
+ if (dng_version)
+ {
+ if (filters == UINT_MAX)
+ filters = 0;
+ if (!filters)
+ colors = tiff_samples;
+ switch (tiff_compress)
+ {
+ case 0: // Compression not set, assuming uncompressed
+ case 1:
+ // Uncompressed float: decoder set in apply_tiff for valid files; not set for non-valid with sampleformat==3
+ if ((load_raw != &LibRaw::uncompressed_fp_dng_load_raw) && (tiff_sampleformat != 3))
+ load_raw = &LibRaw::packed_dng_load_raw;
+ break;
+ case 7:
+ load_raw = &LibRaw::lossless_dng_load_raw;
+ break;
+ case 8:
+ if (tiff_sampleformat == 3 && tiff_bps > 8 && (tiff_bps % 8 == 0) && tiff_bps <= 32)
+ load_raw = &LibRaw::deflate_dng_load_raw;
+ else if((tiff_sampleformat == 0 || tiff_sampleformat == 1) && tiff_bps>=8 && tiff_bps <=16)
+ load_raw = &LibRaw::deflate_dng_load_raw;
+ break;
+#ifdef USE_GPRSDK
+ case 9:
+ load_raw = &LibRaw::vc5_dng_load_raw_placeholder;
+ break;
+#endif
+ case 34892:
+ load_raw = &LibRaw::lossy_dng_load_raw;
+ break;
+ default:
+ load_raw = 0;
+ }
+ GetNormalizedModel();
+ if (makeIs(LIBRAW_CAMERAMAKER_Leica)) {
+ if (!strcmp(model, "SL2"))
+ height -= 3;
+ if (!strncasecmp(model, "Q2 MONO",7))
+ height -= 18;
+ }
+
+ else if (makeIs(LIBRAW_CAMERAMAKER_Olympus) &&
+ (OlyID == OlyID_STYLUS_1) && // don't use normalized_model below, it is 'Stylus 1'
+ (strchr(model+6, 's') ||
+ strchr(model+6, 'S')))
+ {
+ width -= 16;
+ }
+ goto dng_skip;
+ }
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Canon) && !fsize && tiff_bps != 15)
+ {
+ bool fromtable = false;
+ if (!load_raw)
+ load_raw = &LibRaw::lossless_jpeg_load_raw;
+ for (i = 0; i < int(sizeof canon / sizeof *canon); i++)
+ if (raw_width == canon[i][0] && raw_height == canon[i][1])
+ {
+ width = raw_width - (left_margin = canon[i][2]);
+ height = raw_height - (top_margin = canon[i][3]);
+ width -= canon[i][4];
+ height -= canon[i][5];
+ mask[0][1] = canon[i][6];
+ mask[0][3] = -canon[i][7];
+ mask[1][1] = canon[i][8];
+ mask[1][3] = -canon[i][9];
+ if (canon[i][10])
+ filters = canon[i][10] * 0x01010101U;
+ fromtable = true;
+ }
+ if ((unique_id | 0x20000ULL) ==
+ 0x2720000ULL) // "PowerShot G11", "PowerShot S90": 0x2700000, 0x2720000
+ // possibly "PowerShot SX120 IS" (if not chdk hack?): 0x2710000
+ {
+ left_margin = 8;
+ top_margin = 16;
+ }
+ if(!fromtable && imCanon.AverageBlackLevel) // not known, but metadata known
+ {
+ FORC4 cblack[c] = imCanon.ChannelBlackLevel[c];
+ black = cblack[4] = cblack[5] = 0;
+ // Prevent automatic BL calculation
+ mask[0][3] = 1;
+ mask[0][1] = 2;
+
+ if ((imCanon.SensorWidth == raw_width) &&
+ (imCanon.SensorHeight == raw_height))
+ {
+ left_margin = (imCanon.DefaultCropAbsolute.l+1) & 0xfffe; // round to 2
+ width = imCanon.DefaultCropAbsolute.r - left_margin;
+ top_margin = (imCanon.DefaultCropAbsolute.t +1) & 0xfffe;
+ height = imCanon.DefaultCropAbsolute.b - top_margin;
+ }
+ }
+ }
+
+ identify_finetune_by_filesize(fsize);
+
+ if (!strcmp(model, "KAI-0340") && find_green(16, 16, 3840, 5120) < 25)
+ {
+ height = 480;
+ top_margin = filters = 0;
+ strcpy(model, "C603");
+ }
+
+ GetNormalizedModel();
+
+ identify_finetune_dcr(head, fsize, flen);
+
+ /* Early reject for damaged images */
+ if (!load_raw || height < 22 || width < 22 ||
+ (tiff_bps > 16 &&
+ (load_raw != &LibRaw::deflate_dng_load_raw &&
+ load_raw != &LibRaw::uncompressed_fp_dng_load_raw)) ||
+ tiff_samples > 4 || colors > 4 ||
+ colors < 1
+ /* alloc in unpack() may be fooled by size adjust */
+ || ((int)width + (int)left_margin > 65535) ||
+ ((int)height + (int)top_margin > 65535))
+ {
+ is_raw = 0;
+ RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY, 1, 2);
+ return;
+ }
+ if (!model[0])
+ {
+ sprintf(model, "%dx%d", width, height);
+ strcpy(normalized_model, model);
+ }
+
+ if (!(imgdata.rawparams.options & LIBRAW_RAWOPTIONS_ZEROFILTERS_FOR_MONOCHROMETIFFS) &&
+ (filters == UINT_MAX)) // Default dcraw behaviour
+ filters = 0x94949494;
+ else if (filters == UINT_MAX)
+ {
+ if (tiff_nifds > 0 && tiff_samples == 1)
+ {
+ colors = 1;
+ filters = 0;
+ }
+ else
+ filters = 0x94949494;
+ }
+
+ if (thumb_offset && !thumb_height)
+ {
+ fseek(ifp, thumb_offset, SEEK_SET);
+ if (ljpeg_start(&jh, 1))
+ {
+ thumb_width = jh.wide;
+ thumb_height = jh.high;
+ }
+ }
+
+dng_skip:
+ if (dng_version)
+ identify_process_dng_fields();
+
+ /* Early reject for damaged images again (after dng fields processing) */
+ if (!load_raw || height < 22 || width < 22 ||
+ (tiff_bps > 16 &&
+ (load_raw != &LibRaw::deflate_dng_load_raw &&
+ load_raw != &LibRaw::uncompressed_fp_dng_load_raw )) ||
+ ((load_raw == &LibRaw::deflate_dng_load_raw || load_raw == &LibRaw::uncompressed_fp_dng_load_raw)
+ && (tiff_bps < 16 || tiff_bps > 32 || (tiff_bps % 8)) )
+ ||tiff_samples > 4 || colors > 4 || colors < 1)
+ {
+ is_raw = 0;
+ RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY, 1, 2);
+ return;
+ }
+ {
+ // Check cam_mul range
+ int cmul_ok = 1;
+ FORCC if (cam_mul[c] <= 0.001f) cmul_ok = 0;
+ ;
+
+ if (cmul_ok)
+ {
+ double cmin = cam_mul[0], cmax;
+ double cnorm[4];
+ FORCC cmin = MIN(cmin, cam_mul[c]);
+ FORCC cnorm[c] = cam_mul[c] / cmin;
+ cmax = cmin = cnorm[0];
+ FORCC
+ {
+ cmin = MIN(cmin, cnorm[c]);
+ cmax = MIN(cmax, cnorm[c]);
+ }
+ if (cmin <= 0.01f || cmax > 100.f)
+ cmul_ok = false;
+ }
+ if (!cmul_ok)
+ {
+ if (cam_mul[0] > 0)
+ cam_mul[0] = 0;
+ cam_mul[3] = 0;
+ }
+ }
+ if ((use_camera_matrix & (((use_camera_wb || dng_version)?1:0) | 0x2)) &&
+ cmatrix[0][0] > 0.125)
+ {
+ memcpy(rgb_cam, cmatrix, sizeof cmatrix);
+ raw_color = 0;
+ }
+ if (raw_color && !CM_found)
+ CM_found = adobe_coeff(maker_index, normalized_model);
+ else if ((imgdata.color.cam_xyz[0][0] < 0.01) && !CM_found)
+ CM_found = adobe_coeff(maker_index, normalized_model, 1);
+
+ if (load_raw == &LibRaw::kodak_radc_load_raw)
+ if ((raw_color) && !CM_found)
+ CM_found = adobe_coeff(LIBRAW_CAMERAMAKER_Apple, "Quicktake");
+
+ if ((maker_index != LIBRAW_CAMERAMAKER_Unknown) && normalized_model[0])
+ SetStandardIlluminants (maker_index, normalized_model);
+
+ // Clear erroneous fuji_width if not set through parse_fuji or for DNG
+ if (fuji_width && !dng_version &&
+ !(imgdata.process_warnings & LIBRAW_WARN_PARSEFUJI_PROCESSED))
+ fuji_width = 0;
+
+ if (fuji_width)
+ {
+ fuji_width = width >> int(!fuji_layout);
+ filters = fuji_width & 1 ? 0x94949494 : 0x49494949;
+ width = (height >> fuji_layout) + fuji_width;
+ height = width - 1;
+ pixel_aspect = 1;
+ // Prevent incorrect-sized fuji-rotated files
+ if (INT64(width)*INT64(height) > INT64(raw_width) * INT64(raw_height) * 8LL)
+ is_raw = 0;
+ }
+ else
+ {
+ if (raw_height < height)
+ raw_height = height;
+ if (raw_width < width)
+ raw_width = width;
+ }
+ if (!tiff_bps)
+ tiff_bps = 12;
+ if (!maximum)
+ {
+ maximum = (1 << tiff_bps) - 1;
+ if (maximum < 0x10000 && curve[maximum] > 0 &&
+ load_raw == &LibRaw::sony_arw2_load_raw)
+ maximum = curve[maximum];
+ }
+ if (maximum > 0xffff)
+ maximum = 0xffff;
+ if (!load_raw || height < 22 || width < 22 ||
+ (tiff_bps > 16 &&
+ (load_raw != &LibRaw::deflate_dng_load_raw &&
+ load_raw != &LibRaw::uncompressed_fp_dng_load_raw)) ||
+ tiff_samples > 6 || colors > 4)
+ is_raw = 0;
+
+ if (raw_width < 22 || raw_width > 64000 || raw_height < 22 ||
+ pixel_aspect < 0.1 || pixel_aspect > 10. ||
+ raw_height > 64000)
+ is_raw = 0;
+ if(raw_width <= left_margin || raw_height <= top_margin)
+ is_raw = 0;
+ if (dng_version && (tiff_samples < 1 || tiff_samples > 4))
+ is_raw = 0; // we do not handle DNGs with more than 4 values per pixel
+
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+#ifdef NO_JASPER
+ if (load_raw == &LibRaw::redcine_load_raw)
+ {
+ is_raw = 0;
+ imgdata.process_warnings |= LIBRAW_WARN_NO_JASPER;
+ }
+#endif
+#endif
+#ifdef NO_JPEG
+ if (load_raw == &LibRaw::kodak_jpeg_load_raw ||
+ load_raw == &LibRaw::lossy_dng_load_raw)
+ {
+ is_raw = 0;
+ imgdata.process_warnings |= LIBRAW_WARN_NO_JPEGLIB;
+ }
+#endif
+ if (!cdesc[0])
+ strcpy(cdesc, colors == 3 ? "RGBG" : "GMCY");
+ if (!raw_height)
+ raw_height = height;
+ if (!raw_width)
+ raw_width = width;
+ if (filters > 999 && colors == 3)
+ filters |= ((filters >> 2 & 0x22222222) | (filters << 2 & 0x88888888)) &
+ filters << 1;
+notraw:
+ if (flip == (int)UINT_MAX)
+ flip = tiff_flip;
+ if (flip == (int)UINT_MAX)
+ flip = 0;
+
+ // Convert from degrees to bit-field if needed
+ if (flip > 89 || flip < -89)
+ {
+ switch ((flip + 3600) % 360)
+ {
+ case 270:
+ flip = 5;
+ break;
+ case 180:
+ flip = 3;
+ break;
+ case 90:
+ flip = 6;
+ break;
+ }
+ }
+
+ if (pana_bpp)
+ imgdata.color.raw_bps = pana_bpp;
+ else if ((load_raw == &LibRaw::phase_one_load_raw) ||
+ (load_raw == &LibRaw::phase_one_load_raw_s) ||
+ (load_raw == &LibRaw::phase_one_load_raw_c))
+ imgdata.color.raw_bps = ph1.format;
+ else
+ imgdata.color.raw_bps = tiff_bps;
+
+ RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY, 1, 2);
+}
+
+void LibRaw::identify_process_dng_fields()
+{
+ if (!dng_version) return;
+
+ // Cleanup inset_crops if set by makernotes parser
+ imgdata.sizes.raw_inset_crops[0].cleft = imgdata.sizes.raw_inset_crops[0].ctop =
+ imgdata.sizes.raw_inset_crops[1].cleft = imgdata.sizes.raw_inset_crops[1].ctop = 0xffff;
+ imgdata.sizes.raw_inset_crops[0].cwidth = imgdata.sizes.raw_inset_crops[0].cheight =
+ imgdata.sizes.raw_inset_crops[1].cwidth = imgdata.sizes.raw_inset_crops[1].cheight = 0;
+
+
+ int c;
+ {
+ /* copy DNG data from per-IFD field to color.dng */
+ int iifd = find_ifd_by_offset(data_offset);
+ int pifd = find_ifd_by_offset(thumb_offset);
+
+
+#define IFDCOLORINDEX(ifd, subset, bit) \
+ (tiff_ifd[ifd].dng_color[subset].parsedfields & bit) \
+ ? ifd \
+ : ((tiff_ifd[0].dng_color[subset].parsedfields & bit) ? 0 : -1)
+
+#define IFDLEVELINDEX(ifd, bit) \
+ (tiff_ifd[ifd].dng_levels.parsedfields & bit) \
+ ? ifd \
+ : ((tiff_ifd[0].dng_levels.parsedfields & bit) ? 0 : -1)
+
+#define COPYARR(to, from) memmove(&to, &from, sizeof(from))
+
+ if (iifd < (int)tiff_nifds && iifd >= 0)
+ {
+ int sidx;
+ // Per field, not per structure
+ if (!(imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DONT_CHECK_DNG_ILLUMINANT))
+ {
+ int illidx[2], cmidx[2], calidx[2], abidx;
+ for (int i = 0; i < 2; i++)
+ {
+ illidx[i] = IFDCOLORINDEX(iifd, i, LIBRAW_DNGFM_ILLUMINANT);
+ cmidx[i] = IFDCOLORINDEX(iifd, i, LIBRAW_DNGFM_COLORMATRIX);
+ calidx[i] = IFDCOLORINDEX(iifd, i, LIBRAW_DNGFM_CALIBRATION);
+ }
+ abidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_ANALOGBALANCE);
+ // Data found, all in same ifd, illuminants are inited
+ if (illidx[0] >= 0 && illidx[0] < (int)tiff_nifds &&
+ illidx[0] == illidx[1] && illidx[0] == cmidx[0] &&
+ illidx[0] == cmidx[1] &&
+ tiff_ifd[illidx[0]].dng_color[0].illuminant > 0 &&
+ tiff_ifd[illidx[0]].dng_color[1].illuminant > 0)
+ {
+ sidx = illidx[0]; // => selected IFD
+ double cc[4][4], cm[4][3], cam_xyz[4][3];
+ // CM -> Color Matrix
+ // CC -> Camera calibration
+ for (int j = 0; j < 4; j++)
+ for (int i = 0; i < 4; i++)
+ cc[j][i] = i == j;
+ int colidx = -1;
+
+ // IS D65 here?
+ for (int i = 0; i < 2; i++)
+ {
+ if (tiff_ifd[sidx].dng_color[i].illuminant == LIBRAW_WBI_D65)
+ {
+ colidx = i;
+ break;
+ }
+ }
+
+ // Other daylight-type ill
+ if (colidx < 0)
+ for (int i = 0; i < 2; i++)
+ {
+ int ill = tiff_ifd[sidx].dng_color[i].illuminant;
+ if (ill == LIBRAW_WBI_Daylight || ill == LIBRAW_WBI_D55 ||
+ ill == LIBRAW_WBI_D75 || ill == LIBRAW_WBI_D50 ||
+ ill == LIBRAW_WBI_Flash)
+ {
+ colidx = i;
+ break;
+ }
+ }
+ if (colidx >= 0) // Selected
+ {
+ // Init camera matrix from DNG
+ FORCC for (int j = 0; j < 3; j++) cm[c][j] =
+ tiff_ifd[sidx].dng_color[colidx].colormatrix[c][j];
+
+ if (calidx[colidx] == sidx)
+ {
+ for (int i = 0; i < colors && i < 4; i++)
+ FORCC
+ cc[i][c] = tiff_ifd[sidx].dng_color[colidx].calibration[i][c];
+ }
+
+ if (abidx == sidx)
+ for (int i = 0; i < colors && i < 4; i++)
+ FORCC cc[i][c] *= tiff_ifd[sidx].dng_levels.analogbalance[i];
+ int j;
+ FORCC for (int i = 0; i < 3; i++)
+ for (cam_xyz[c][i] = j = 0; j < colors && j < 4; j++)
+ cam_xyz[c][i] +=
+ cc[c][j] * cm[j][i]; // add AsShotXY later * xyz[i];
+ cam_xyz_coeff(cmatrix, cam_xyz);
+ }
+ }
+ }
+
+ bool noFujiDNGCrop = makeIs(LIBRAW_CAMERAMAKER_Fujifilm)
+ && (!strcmp(normalized_model, "S3Pro")
+ || !strcmp(normalized_model, "S5Pro")
+ || !strcmp(normalized_model, "S2Pro"));
+
+ if (!noFujiDNGCrop) // Promote DNG Crops to raw_inset_crops
+ {
+ sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_CROPORIGIN);
+ int sidx2 = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_CROPSIZE);
+ if (sidx >= 0 && sidx == sidx2 &&
+ tiff_ifd[sidx].dng_levels.default_crop[2] > 0 &&
+ tiff_ifd[sidx].dng_levels.default_crop[3] > 0)
+ {
+ int lm = tiff_ifd[sidx].dng_levels.default_crop[0];
+ int tm = tiff_ifd[sidx].dng_levels.default_crop[1];
+ int ww = tiff_ifd[sidx].dng_levels.default_crop[2];
+ int hh = tiff_ifd[sidx].dng_levels.default_crop[3];
+ if ((lm + ww < int(raw_width) + int(left_margin))
+ && (tm + hh < int(raw_height) + int(top_margin))) // Crop data is correct
+ {
+ imgdata.sizes.raw_inset_crops[0].cleft = left_margin + lm;
+ imgdata.sizes.raw_inset_crops[0].cwidth = ww;
+ imgdata.sizes.raw_inset_crops[0].ctop = top_margin + tm;
+ imgdata.sizes.raw_inset_crops[0].cheight = hh;
+
+ int sidx3 = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_USERCROP);
+ if (sidx3 >= 0 && sidx3 == sidx) // No need to check values range, it is checked at parse
+ {
+ int dt = int(imgdata.sizes.raw_inset_crops[0].cheight * tiff_ifd[sidx].dng_levels.user_crop[0]);
+ int dl = int(imgdata.sizes.raw_inset_crops[0].cwidth * tiff_ifd[sidx].dng_levels.user_crop[1]);
+ int db = int(imgdata.sizes.raw_inset_crops[0].cheight * tiff_ifd[sidx].dng_levels.user_crop[2]);
+ int dr = int(imgdata.sizes.raw_inset_crops[0].cwidth * tiff_ifd[sidx].dng_levels.user_crop[3]);
+
+ int dh = db - dt;
+ int dw = dr - dl;
+
+ if (dh > 0 && dw > 0
+ && dh < imgdata.sizes.raw_inset_crops[0].cheight // No need to repeat crop for 0,0,1,1
+ && dw < imgdata.sizes.raw_inset_crops[0].cwidth)
+ {
+ imgdata.sizes.raw_inset_crops[1].cleft = imgdata.sizes.raw_inset_crops[0].cleft + dl;
+ imgdata.sizes.raw_inset_crops[1].cwidth = dw;
+ imgdata.sizes.raw_inset_crops[1].ctop = imgdata.sizes.raw_inset_crops[0].ctop + dt;
+ imgdata.sizes.raw_inset_crops[1].cheight = dh;
+ }
+ }
+
+ }
+ }
+ }
+ if (!(imgdata.color.dng_color[0].parsedfields &
+ LIBRAW_DNGFM_FORWARDMATRIX)) // Not set already (Leica makernotes)
+ {
+ sidx = IFDCOLORINDEX(iifd, 0, LIBRAW_DNGFM_FORWARDMATRIX);
+ if (sidx >= 0)
+ COPYARR(imgdata.color.dng_color[0].forwardmatrix,
+ tiff_ifd[sidx].dng_color[0].forwardmatrix);
+ }
+ if (!(imgdata.color.dng_color[1].parsedfields &
+ LIBRAW_DNGFM_FORWARDMATRIX)) // Not set already (Leica makernotes)
+ {
+ sidx = IFDCOLORINDEX(iifd, 1, LIBRAW_DNGFM_FORWARDMATRIX);
+ if (sidx >= 0)
+ COPYARR(imgdata.color.dng_color[1].forwardmatrix,
+ tiff_ifd[sidx].dng_color[1].forwardmatrix);
+ }
+ for (int ss = 0; ss < 2; ss++)
+ {
+ sidx = IFDCOLORINDEX(iifd, ss, LIBRAW_DNGFM_COLORMATRIX);
+ if (sidx >= 0)
+ COPYARR(imgdata.color.dng_color[ss].colormatrix,
+ tiff_ifd[sidx].dng_color[ss].colormatrix);
+
+ sidx = IFDCOLORINDEX(iifd, ss, LIBRAW_DNGFM_CALIBRATION);
+ if (sidx >= 0)
+ COPYARR(imgdata.color.dng_color[ss].calibration,
+ tiff_ifd[sidx].dng_color[ss].calibration);
+
+ sidx = IFDCOLORINDEX(iifd, ss, LIBRAW_DNGFM_ILLUMINANT);
+ if (sidx >= 0)
+ imgdata.color.dng_color[ss].illuminant =
+ tiff_ifd[sidx].dng_color[ss].illuminant;
+ }
+ // Levels
+ sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_ANALOGBALANCE);
+ if (sidx >= 0)
+ COPYARR(imgdata.color.dng_levels.analogbalance,
+ tiff_ifd[sidx].dng_levels.analogbalance);
+
+ sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_BASELINEEXPOSURE);
+ if (sidx >= 0)
+ imgdata.color.dng_levels.baseline_exposure =
+ tiff_ifd[sidx].dng_levels.baseline_exposure;
+
+ sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_WHITE);
+ if (sidx >= 0 && tiff_ifd[sidx].dng_levels.dng_whitelevel[0])
+ COPYARR(imgdata.color.dng_levels.dng_whitelevel,
+ tiff_ifd[sidx].dng_levels.dng_whitelevel);
+ else if (tiff_ifd[iifd].sample_format <= 2 && tiff_ifd[iifd].bps > 0 && tiff_ifd[iifd].bps < 32)
+ FORC4
+ imgdata.color.dng_levels.dng_whitelevel[c] = (1 << tiff_ifd[iifd].bps) - 1;
+
+
+
+ sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_ASSHOTNEUTRAL);
+ if (sidx >= 0)
+ {
+ COPYARR(imgdata.color.dng_levels.asshotneutral,
+ tiff_ifd[sidx].dng_levels.asshotneutral);
+ if (imgdata.color.dng_levels.asshotneutral[0])
+ {
+ cam_mul[3] = 0;
+ FORCC
+ if (fabs(imgdata.color.dng_levels.asshotneutral[c]) > 0.0001)
+ cam_mul[c] = 1 / imgdata.color.dng_levels.asshotneutral[c];
+ }
+ }
+ sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_BLACK);
+ if (sidx >= 0)
+ {
+ imgdata.color.dng_levels.dng_fblack =
+ tiff_ifd[sidx].dng_levels.dng_fblack;
+ imgdata.color.dng_levels.dng_black =
+ tiff_ifd[sidx].dng_levels.dng_black;
+ COPYARR(imgdata.color.dng_levels.dng_cblack,
+ tiff_ifd[sidx].dng_levels.dng_cblack);
+ COPYARR(imgdata.color.dng_levels.dng_fcblack,
+ tiff_ifd[sidx].dng_levels.dng_fcblack);
+ }
+
+
+ if (pifd >= 0)
+ {
+ sidx = IFDLEVELINDEX(pifd, LIBRAW_DNGFM_PREVIEWCS);
+ if (sidx >= 0)
+ imgdata.color.dng_levels.preview_colorspace =
+ tiff_ifd[sidx].dng_levels.preview_colorspace;
+ }
+ sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_OPCODE2);
+ if (sidx >= 0)
+ meta_offset = tiff_ifd[sidx].opcode2_offset;
+
+ sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_LINTABLE);
+ INT64 linoff = -1;
+ int linlen = 0;
+ if (sidx >= 0)
+ {
+ linoff = tiff_ifd[sidx].lineartable_offset;
+ linlen = tiff_ifd[sidx].lineartable_len;
+ }
+
+ if (linoff >= 0 && linlen > 0)
+ {
+ INT64 pos = ftell(ifp);
+ fseek(ifp, linoff, SEEK_SET);
+ linear_table(linlen);
+ fseek(ifp, pos, SEEK_SET);
+ }
+ // Need to add curve too
+ }
+ /* Copy DNG black level to LibRaw's */
+ if (load_raw == &LibRaw::lossy_dng_load_raw)
+ {
+ maximum = 0xffff;
+ FORC4 imgdata.color.linear_max[c] = imgdata.color.dng_levels.dng_whitelevel[c] = 0xffff;
+ }
+ else
+ {
+ maximum = imgdata.color.dng_levels.dng_whitelevel[0];
+ }
+ black = imgdata.color.dng_levels.dng_black;
+ if (tiff_samples == 2 &&
+ !imgdata.color.dng_levels.dng_cblack[2] &&
+ !imgdata.color.dng_levels.dng_cblack[3] &&
+ (imgdata.color.dng_levels.dng_cblack[4] == 1) &&
+ (imgdata.color.dng_levels.dng_cblack[5] == 1)
+ && (imgdata.color.dng_levels.dng_cblack[LIBRAW_CBLACK_SIZE - 1] == tiff_samples)
+ ) {
+ black = imgdata.color.dng_levels.dng_cblack[shot_select];
+ imgdata.color.dng_levels.dng_cblack[0] = imgdata.color.dng_levels.dng_cblack[1] = 0;
+ imgdata.color.dng_levels.dng_cblack[4] = imgdata.color.dng_levels.dng_cblack[5] = 0;
+ imgdata.color.dng_levels.dng_fcblack[0] = imgdata.color.dng_levels.dng_fcblack[1] = 0.0f;
+ imgdata.color.dng_levels.dng_fcblack[4] = imgdata.color.dng_levels.dng_fcblack[5] = 0.0f;
+ }
+ else if (tiff_samples == 2 && imgdata.color.dng_levels.dng_cblack[4] * imgdata.color.dng_levels.dng_cblack[5] * tiff_samples
+ == imgdata.color.dng_levels.dng_cblack[LIBRAW_CBLACK_SIZE - 1])
+ {
+ unsigned ff = filters;
+ if (filters > 999 && colors == 3)
+ filters |= ((filters >> 2 & 0x22222222) | (filters << 2 & 0x88888888)) &
+ filters << 1;
+
+ /* Special case, Fuji SuperCCD dng */
+ int csum[4] = { 0,0,0,0 }, ccount[4] = { 0,0,0,0 };
+ int i = 6 + shot_select;
+ for (unsigned row = 0; row < imgdata.color.dng_levels.dng_cblack[4]; row++)
+ for (unsigned col = 0; col < imgdata.color.dng_levels.dng_cblack[5]; col++)
+ {
+ csum[FC(row, col)] += imgdata.color.dng_levels.dng_cblack[i];
+ ccount[FC(row, col)]++;
+ i += tiff_samples;
+ }
+ for (int q = 0; q < 4; q++)
+ if (ccount[q])
+ imgdata.color.dng_levels.dng_cblack[q] += csum[q] / ccount[q];
+ imgdata.color.dng_levels.dng_cblack[4] = imgdata.color.dng_levels.dng_cblack[5] = 0;
+ filters = ff;
+ }
+ else if (tiff_samples > 2 && tiff_samples <= 4 && imgdata.color.dng_levels.dng_cblack[4] * imgdata.color.dng_levels.dng_cblack[5] * tiff_samples
+ == imgdata.color.dng_levels.dng_cblack[LIBRAW_CBLACK_SIZE - 1])
+ {
+ /* Special case, per_channel blacks in RepeatDim, average for per-channel */
+ int csum[4] = { 0,0,0,0 }, ccount[4] = { 0,0,0,0 };
+ int i = 6;
+ for (unsigned row = 0; row < imgdata.color.dng_levels.dng_cblack[4]; row++)
+ for (unsigned col = 0; col < imgdata.color.dng_levels.dng_cblack[5]; col++)
+ for (unsigned q = 0; q < tiff_samples && q < 4; q++)
+ {
+ csum[q] += imgdata.color.dng_levels.dng_cblack[i];
+ ccount[q]++;
+ i++;
+ }
+ for (int q = 0; q < 4; q++)
+ if (ccount[q])
+ imgdata.color.dng_levels.dng_cblack[q] += csum[q] / ccount[q];
+ imgdata.color.dng_levels.dng_cblack[4] = imgdata.color.dng_levels.dng_cblack[5] = 0;
+ }
+
+ memmove(cblack, imgdata.color.dng_levels.dng_cblack, sizeof(cblack));
+
+ if (iifd < (int)tiff_nifds && iifd >= 0)
+ {
+ int sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_LINEARRESPONSELIMIT);
+ if (sidx >= 0)
+ {
+ imgdata.color.dng_levels.LinearResponseLimit =
+ tiff_ifd[sidx].dng_levels.LinearResponseLimit;
+ if (imgdata.color.dng_levels.LinearResponseLimit > 0.1 &&
+ imgdata.color.dng_levels.LinearResponseLimit <= 1.0)
+ {
+ // And approx promote it to linear_max:
+ int bl4 = 0, bl64 = 0;
+ for (int chan = 0; chan < colors && chan < 4; chan++)
+ bl4 += cblack[chan];
+ bl4 /= LIM(colors, 1, 4);
+
+ if (cblack[4] * cblack[5] > 0)
+ {
+ unsigned cnt = 0;
+ for (unsigned q = 0; q < 4096 && q < cblack[4] * cblack[5]; q++)
+ {
+ bl64 += cblack[q + 6];
+ cnt++;
+ }
+ bl64 /= LIM(cnt, 1, 4096);
+ }
+ int rblack = black + bl4 + bl64;
+ for (int chan = 0; chan < colors && chan < 4; chan++)
+ imgdata.color.linear_max[chan] =
+ (maximum - rblack) *
+ imgdata.color.dng_levels.LinearResponseLimit +
+ rblack;
+ if (imgdata.color.linear_max[1] && !imgdata.color.linear_max[3])
+ imgdata.color.linear_max[3] = imgdata.color.linear_max[1];
+ }
+ }
+ }
+ }
+}
+
+void LibRaw::identify_finetune_pentax()
+{
+ if (dng_version && data_offset)
+ {
+ for(int i = 0; i < (int)tiff_nifds; i++)
+ if (tiff_ifd[i].offset == data_offset)
+ {
+ if (tiff_ifd[i].phint == 34892) return; // Linear DNG made from Pentax source
+ break;
+ }
+ }
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Pentax) ||
+ makeIs(LIBRAW_CAMERAMAKER_Samsung)) {
+ if (height == 2624 &&
+ width == 3936) // Pentax K10D, Samsung GX10;
+ {
+ height = 2616;
+ width = 3896;
+ }
+ if (height == 3136 &&
+ width == 4864) // Pentax K20D, Samsung GX20;
+ {
+ height = 3124;
+ width = 4688;
+ filters = 0x16161616;
+ }
+ }
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Pentax)) {
+ if ((width == 4352) &&
+ ((unique_id == PentaxID_K_r) ||
+ (unique_id == PentaxID_K_x)))
+ {
+ width = 4309;
+ filters = 0x16161616;
+ }
+ if ((width >= 4960) &&
+ ((unique_id == PentaxID_K_5) ||
+ (unique_id == PentaxID_K_5_II) ||
+ (unique_id == PentaxID_K_5_II_s)))
+ {
+ left_margin = 10;
+ width = 4950;
+ filters = 0x16161616;
+ }
+ if ((width == 6080) && (unique_id == PentaxID_K_70))
+ {
+ height = 4016;
+ top_margin = 32;
+ width = 6020;
+ left_margin = 60;
+ }
+ if ((width == 4736) && (unique_id == PentaxID_K_7))
+ {
+ height = 3122;
+ width = 4684;
+ filters = 0x16161616;
+ top_margin = 2;
+ }
+ if ((width == 6080) && (unique_id == PentaxID_K_3_II))
+ {
+ left_margin = 4;
+ width = 6040;
+ }
+ if ((width == 6304) && (unique_id == PentaxID_K_3_III)) // From DNG ActiveArea
+ {
+ left_margin = 26;
+ width = 6224;
+ top_margin = 34;
+ height = 4160;
+ }
+ if ((width == 6112) && (unique_id == PentaxID_KP))
+ {
+ // From DNG, maybe too strict
+ left_margin = 54;
+ top_margin = 28;
+ width = 6028;
+ height = raw_height - top_margin;
+ }
+ if ((width == 6080) && (unique_id == PentaxID_K_3))
+ {
+ left_margin = 4;
+ width = 6040;
+ }
+ if ((width == 7424) && (unique_id == PentaxID_645D))
+ {
+ height = 5502;
+ width = 7328;
+ filters = 0x61616161;
+ top_margin = 29;
+ left_margin = 48;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Ricoh) &&
+ (height == 3014) && (width == 4096)) // Ricoh GX200
+ width = 4014;
+}
+
+void LibRaw::identify_finetune_by_filesize(int fsize)
+{
+
+ if (fsize == 4771840)
+ { // hack Nikon 3mpix: E880, E885, E990, E995;
+ // Olympus C-3030Z
+ if (!timestamp && nikon_e995())
+ strcpy(model, "E995");
+ }
+ else if (fsize == 2940928)
+ { // hack Nikon 2mpix: E2100, E2500
+ if (!timestamp && !nikon_e2100())
+ strcpy(model, "E2500");
+ }
+ else if (fsize == 4775936)
+ { // hack Nikon 3mpix: E3100, E3200, E3500, E3700;
+ // Pentax "Optio 33WR";
+ // Olympus C-740UZ
+ if (!timestamp)
+ nikon_3700();
+ }
+ else if (fsize == 5869568)
+ { // hack Nikon 4mpix: E4300;
+ // hack Minolta "DiMAGE Z2"
+ if (!timestamp && minolta_z2())
+ {
+ maker_index = LIBRAW_CAMERAMAKER_Minolta;
+ strcpy(make, "Minolta");
+ strcpy(model, "DiMAGE Z2");
+ }
+ }
+}
+
+void LibRaw::identify_finetune_dcr(char head[64], int fsize, int flen)
+{
+ static const short pana[][6] = {
+ // raw_width, raw_height, left_margin, top_margin, width_increment,
+ // height_increment
+ {3130, 1743, 4, 0, -6, 0}, /* 00 */
+ {3130, 2055, 4, 0, -6, 0}, /* 01 */
+ {3130, 2319, 4, 0, -6, 0}, /* 02 DMC-FZ8 */
+ {3170, 2103, 18, 0, -42, 20}, /* 03 */
+ {3170, 2367, 18, 13, -42, -21}, /* 04 */
+ {3177, 2367, 0, 0, -1, 0}, /* 05 DMC-L1 */
+ {3304, 2458, 0, 0, -1, 0}, /* 06 DMC-FZ30 */
+ {3330, 2463, 9, 0, -5, 0}, /* 07 DMC-FZ18 */
+ {3330, 2479, 9, 0, -17, 4}, /* 08 */
+ {3370, 1899, 15, 0, -44, 20}, /* 09 */
+ {3370, 2235, 15, 0, -44, 20}, /* 10 */
+ {3370, 2511, 15, 10, -44, -21}, /* 11 */
+ {3690, 2751, 3, 0, -8, -3}, /* 12 DMC-FZ50 */
+ {3710, 2751, 0, 0, -3, 0}, /* 13 DMC-L10 */
+ {3724, 2450, 0, 0, 0, -2}, /* 14 */
+ {3770, 2487, 17, 0, -44, 19}, /* 15 */
+ {3770, 2799, 17, 15, -44, -19}, /* 16 */
+ {3880, 2170, 6, 0, -6, 0}, /* 17 DMC-LX1 */
+ {4060, 3018, 0, 0, 0, -2}, /* 18 DMC-FZ35, DMC-FZ38 */
+ {4290, 2391, 3, 0, -8, -1}, /* 19 DMC-LX2 */
+ {4330, 2439, 17, 15, -44, -19}, /* 20 "D-LUX 3" */
+ {4508, 2962, 0, 0, -3, -4}, /* 21 */
+ {4508, 3330, 0, 0, -3, -6}, /* 22 */
+ {10480, 7794, 0, 0, -2, 0}, /* 23: G9 in high-res */
+ };
+ int i,c;
+ struct jhead jh;
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Canon)
+ && ( !tiff_flip || unique_id == CanonID_EOS_40D)
+ && !(imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CANON_IGNORE_MAKERNOTES_ROTATION)
+ && imCanon.MakernotesFlip)
+ {
+ tiff_flip = imCanon.MakernotesFlip;
+ }
+
+ else if (makeIs(LIBRAW_CAMERAMAKER_Nikon))
+ {
+ if (!load_raw)
+ load_raw = &LibRaw::packed_load_raw;
+ if (model[0] == 'E') // Nikon E8800, E8700, E8400, E5700, E5400, E5000,
+ // others are diag hacks?
+ load_flags |= !data_offset << 2 | 2;
+ }
+ /* Set parameters based on camera name (for non-DNG files). */
+
+ /* Always 512 for arw2_load_raw */
+ else if (makeIs(LIBRAW_CAMERAMAKER_Sony) &&
+ (raw_width > 3888) && !black && !cblack[0])
+ {
+ black = (load_raw == &LibRaw::sony_arw2_load_raw)
+ ? 512
+ : (128 << (tiff_bps - 12));
+ }
+
+ if (is_foveon) {
+ if (height * 2 < width)
+ pixel_aspect = 0.5;
+ if (height > width)
+ pixel_aspect = 2;
+ filters = 0;
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Pentax)) {
+ if ((unique_id == PentaxID_K_1) ||
+ (unique_id == PentaxID_K_1_Mark_II)) {
+ top_margin = 18;
+ height = raw_height - top_margin;
+ if (raw_width == 7392) {
+ left_margin = 6;
+ width = 7376;
+ }
+
+ }
+ else if (unique_id == PentaxID_Optio_S_V101) { // (fsize == 3178560)
+ cam_mul[0] *= 4;
+ cam_mul[2] *= 4;
+
+ }
+ else if (unique_id == PentaxID_Optio_33WR) { // (fsize == 4775936)
+ flip = 1;
+ filters = 0x16161616;
+
+ }
+ else if (unique_id == PentaxID_staristD) {
+ load_raw = &LibRaw::unpacked_load_raw;
+ /* data_error = -1; */ /* No way to know why data_error was raised in dcraw.c, looks not needed esp. for unpacked_load_raw */
+ }
+ else if (unique_id == PentaxID_staristDS) {
+ height -= 2;
+ }
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Canon)) {
+ if (tiff_bps == 15) { // Canon sRAW
+ if (width == 3344)
+ width = 3272;
+ else if (width == 3872)
+ width = 3866;
+
+ if (height > width) {
+ SWAP(height, width);
+ SWAP(raw_height, raw_width);
+ }
+ if (width == 7200 &&
+ height == 3888) { // Canon EOS 5DS (R);
+ raw_width = width = 6480;
+ raw_height = height = 4320;
+ }
+ filters = 0;
+ tiff_samples = colors = 3;
+ load_raw = &LibRaw::canon_sraw_load_raw;
+ }
+
+ if (!strcmp(normalized_model, "PowerShot 600")) {
+ height = 613;
+ width = 854;
+ raw_width = 896;
+ colors = 4;
+ filters = 0xe1e4e1e4;
+ load_raw = &LibRaw::canon_600_load_raw;
+
+ }
+ else if (!strcmp(normalized_model, "PowerShot A5") ||
+ !strcmp(normalized_model, "PowerShot A5 Zoom")) {
+ height = 773;
+ width = 960;
+ raw_width = 992;
+ pixel_aspect = 256 / 235.0;
+ filters = 0x1e4e1e4e;
+ goto canon_a5;
+
+ }
+ else if (!strcmp(normalized_model, "PowerShot A50")) {
+ height = 968;
+ width = 1290;
+ raw_width = 1320;
+ filters = 0x1b4e4b1e;
+ goto canon_a5;
+
+ }
+ else if (!strcmp(normalized_model, "PowerShot Pro70")) {
+ height = 1024;
+ width = 1552;
+ filters = 0x1e4b4e1b;
+ canon_a5:
+ colors = 4;
+ tiff_bps = 10;
+ load_raw = &LibRaw::packed_load_raw;
+ load_flags = 40;
+
+ }
+ else if (!strcmp(normalized_model, "PowerShot Pro90 IS") ||
+ !strcmp(normalized_model, "PowerShot G1")) {
+ colors = 4;
+ filters = 0xb4b4b4b4;
+
+ }
+ else if (!strcmp(normalized_model, "PowerShot A610")) { // chdk hack
+ if (canon_s2is()) {
+ strcpy(model + 10, "S2 IS");
+ strcpy(normalized_model + 10, "S2 IS");
+ }
+
+ }
+ else if (!strcmp(normalized_model, "PowerShot SX220 HS")) { // chdk hack
+ mask[1][3] = -4;
+ top_margin = 16;
+ left_margin = 92;
+
+ }
+ else if (!strcmp(normalized_model, "PowerShot S120")) { // chdk hack
+ raw_width = 4192;
+ raw_height = 3062;
+ width = 4022;
+ height = 3016;
+ mask[0][0] = top_margin = 31;
+ mask[0][2] = top_margin + height;
+ left_margin = 120;
+ mask[0][1] = 23;
+ mask[0][3] = 72;
+
+ }
+ else if (!strcmp(normalized_model, "PowerShot G16")) {
+ mask[0][0] = 0;
+ mask[0][2] = 80;
+ mask[0][1] = 0;
+ mask[0][3] = 16;
+ top_margin = 29;
+ left_margin = 120;
+ width = raw_width - left_margin - 48;
+ height = raw_height - top_margin - 14;
+
+ }
+ else if (!strcmp(normalized_model, "PowerShot SX50 HS")) {
+ top_margin = 17;
+ }
+
+ }
+
+ else if (makeIs(LIBRAW_CAMERAMAKER_Nikon)) {
+ if (!strcmp(model, "D1"))
+ {
+ imgdata.other.analogbalance[0] = cam_mul[0];
+ imgdata.other.analogbalance[2] = cam_mul[2];
+ imgdata.other.analogbalance[1] = imgdata.other.analogbalance[3] =
+ cam_mul[1];
+ cam_mul[0] = cam_mul[1] = cam_mul[2] = 1.0f;
+ }
+
+ else if (!strcmp(model, "D1X"))
+ {
+ width -= 4;
+ pixel_aspect = 0.5;
+ }
+ else if (!strcmp(model, "D40X") ||
+ !strcmp(model, "D60") ||
+ !strcmp(model, "D80") ||
+ !strcmp(model, "D3000"))
+ {
+ height -= 3;
+ width -= 4;
+ }
+ else if (!strcmp(model, "D3") ||
+ !strcmp(model, "D3S") ||
+ !strcmp(model, "D700"))
+ {
+ width -= 4;
+ left_margin = 2;
+ }
+ else if (!strcmp(model, "D3100"))
+ {
+ width -= 28;
+ left_margin = 6;
+ }
+ else if (!strcmp(model, "D5000") ||
+ !strcmp(model, "D90"))
+ {
+ width -= 42;
+ }
+ else if (!strcmp(model, "D5100") ||
+ !strcmp(model, "D7000") ||
+ !strcmp(model, "COOLPIX A"))
+ {
+ width -= 44;
+ }
+ else if (!strcmp(model, "D3200") ||
+ !strcmp(model, "D600") ||
+ !strcmp(model, "D610") ||
+ !strncmp(model, "D800", 4)) // Nikons: D800, D800E
+ {
+ width -= 46;
+ }
+ else if (!strcmp(model, "D4") ||
+ !strcmp(model, "Df"))
+ {
+ width -= 52;
+ left_margin = 2;
+ }
+ else if (!strcmp(model, "D500"))
+ {
+ // Empty - to avoid width-1 below
+ }
+ else if (!strncmp(model, "D40", 3) ||
+ !strncmp(model, "D50", 3) ||
+ !strncmp(model, "D70", 3))
+ {
+ width--;
+ }
+ else if (!strcmp(model, "D100"))
+ {
+ if (load_flags) // compressed NEF
+ raw_width = (width += 3) + 3;
+ }
+ else if (!strcmp(model, "D200"))
+ {
+ left_margin = 1;
+ width -= 4;
+ filters = 0x94949494;
+ }
+ else if (!strncmp(model, "D2H", 3)) // Nikons: D2H, D2Hs
+ {
+ left_margin = 6;
+ width -= 14;
+ }
+ else if (!strncmp(model, "D2X", 3)) // Nikons: D2X, D2Xs
+ {
+ if (width == 3264) // in-camera Hi-speed crop: On
+ width -= 32;
+ else
+ width -= 8;
+ }
+ else if (!strncmp(model, "D300", 4)) // Nikons: D300, D300s
+ {
+ width -= 32;
+ }
+ else if (raw_width == 4032) // Nikon "COOLPIX P7700", "COOLPIX P7800",
+ // "COOLPIX P330", "COOLPIX P340"
+ {
+ if (!strcmp(normalized_model, "COOLPIX P7700"))
+ {
+ maximum = 65504;
+ load_flags = 0;
+ }
+ else if (!strcmp(normalized_model, "COOLPIX P7800"))
+ {
+ maximum = 65504;
+ load_flags = 0;
+ }
+ else if (!strcmp(model, "COOLPIX P340"))
+ {
+ load_flags = 0;
+ }
+ }
+ else if (!strncmp(model, "COOLPIX P", 9) &&
+ raw_width != 4032) // Nikon "COOLPIX P1000", "COOLPIX P6000",
+ // "COOLPIX P7000", "COOLPIX P7100"
+ {
+ load_flags = 24;
+ filters = 0x94949494;
+ /* the following 'if' is most probably obsolete, because we now read black
+ * level from metadata */
+ if ((model[9] == '7') && /* P7000, P7100 */
+ ((iso_speed >= 400) || (iso_speed == 0)) &&
+ !strstr(software, "V1.2")) /* v. 1.2 seen for P7000 only */
+ black = 255;
+ }
+ else if (!strncmp(model, "COOLPIX B700", 12))
+ {
+ load_flags = 24;
+ }
+ else if (!strncmp(model, "1 ",
+ 2)) // Nikons: "1 AW1", "1 J1", "1 J2", "1 J3", "1 J4",
+ // "1 J5", "1 S1", "1 S2", "1 V1", "1 V2", "1 V3"
+ {
+ height -= 2;
+ }
+ else if (fsize == 1581060) // hack Nikon 1mpix: E900
+ {
+ simple_coeff(3);
+ pre_mul[0] = 1.2085f;
+ pre_mul[1] = 1.0943f;
+ pre_mul[3] = 1.1103f;
+ }
+ else if ((fsize == 4771840) && // hack Nikon 3mpix: E880, E885, E990
+ strcmp(model, "E995")) // but not E995
+ {
+ filters = 0xb4b4b4b4;
+ simple_coeff(3);
+ pre_mul[0] = 1.196f;
+ pre_mul[1] = 1.246f;
+ pre_mul[2] = 1.018f;
+ }
+ else if ((fsize == 4775936) && // hack Nikon 3mpix: E3100, E3200, E3500
+ (atoi(model + 1) < 3700)) // but not E3700;
+ {
+ filters = 0x49494949;
+ }
+ else if (fsize == 5869568) // hack Nikon 4mpix: E4300;
+ {
+ load_flags = 6;
+ }
+ else if (!strcmp(model, "E2500"))
+ {
+ height -= 2;
+ load_flags = 6;
+ colors = 4;
+ filters = 0x4b4b4b4b;
+ }
+ }
+
+ else if (makeIs(LIBRAW_CAMERAMAKER_Olympus)) {
+ if (OlyID == OlyID_C_740UZ) { // (fsize == 4775936)
+ i = find_green(12, 32, 1188864, 3576832);
+ c = find_green(12, 32, 2383920, 2387016);
+ if (abs(i) < abs(c)) {
+ SWAP(i, c);
+ load_flags = 24;
+ }
+ if (i < 0)
+ filters = 0x61616161;
+ }
+ else if (OlyID == OlyID_C_770UZ) {
+ height = 1718;
+ width = 2304;
+ filters = 0x16161616;
+ load_raw = &LibRaw::packed_load_raw;
+ load_flags = 30;
+ }
+ else {
+ height += height & 1;
+ if (exif_cfa)
+ filters = exif_cfa;
+
+ if (width == 4100) // Olympus E-PL2, E-PL1, E-P2, E-P1, E-620, E-600, E-5, E-30;
+ width -= 4;
+
+ if (width == 4080) // Olympus E-PM1, E-PL3, E-P3;
+ width -= 24;
+
+ if (width == 10400) // Olympus PEN-F, E-M1-II, E-M1-III, E-M1X, OM-1
+ width -= 12;
+
+ if (width == 8200) // E-M1-III in 50Mp mode, E-M1X
+ width -= 30;
+
+ if (width == 8180) // OM-1 in 50Mp
+ width -= 10;
+
+ if (width == 9280) { // Olympus E-M5 Mark II;
+ width -= 6;
+ height -= 6;
+ }
+
+ if (load_raw == &LibRaw::unpacked_load_raw) {
+ load_flags = 4;
+ if (imOly.ValidBits == 10) load_flags += 2;
+ }
+ tiff_bps = imOly.ValidBits;
+
+ if ((OlyID == OlyID_E_300) ||
+ (OlyID == OlyID_E_500)) {
+ width -= 20;
+ if (load_raw == &LibRaw::unpacked_load_raw) {
+ maximum = 0xfc3;
+ memset(cblack, 0, sizeof cblack);
+ }
+ }
+ else if (OlyID == OlyID_STYLUS_1) {
+ width -= 16;
+ maximum = 0xfff;
+
+ }
+ else if (OlyID == OlyID_E_330) {
+ width -= 30;
+ if (load_raw == &LibRaw::unpacked_load_raw)
+ maximum = 0xf79;
+
+ }
+ else if (OlyID == OlyID_SP_550UZ) {
+ thumb_length = flen - (thumb_offset = 0xa39800);
+ thumb_height = 480;
+ thumb_width = 640;
+
+ }
+ else if (OlyID == OlyID_TG_4) {
+ width -= 16;
+
+ }
+ else if ((OlyID == OlyID_TG_5) ||
+ (OlyID == OlyID_TG_6)) {
+ width -= 26;
+ }
+ }
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_RoverShot) &&
+ (fsize == 6291456)) { // RoverShot 3320AF
+ fseek(ifp, 0x300000, SEEK_SET);
+ if ((order = guess_byte_order(0x10000)) == 0x4d4d)
+ {
+ height -= (top_margin = 16);
+ width -= (left_margin = 28);
+ maximum = 0xf5c0;
+ strcpy(make, "ISG");
+ maker_index = LIBRAW_CAMERAMAKER_ISG;
+ model[0] = 0;
+ }
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Fujifilm)) {
+ if (!imFuji.RAFDataGeneration && (raw_width == 2944)) // S2Pro
+ {
+ height = 2144;
+ width = 2880;
+ flip = 6;
+ }
+ else if (load_raw != &LibRaw::packed_load_raw &&
+ strncmp(model, "X-", 2) &&
+ filters >= 1000) // Bayer and not an X-model
+ maximum = (is_raw == 2 && shot_select) ? 0x2f00 : 0x3e00;
+
+ if (!FujiCropMode && imFuji.RAFDataGeneration && (imFuji.RAFDataGeneration != 4096))
+ {
+ width = imFuji.RAFData_ImageSizeTable[0];
+ height = imFuji.RAFData_ImageSizeTable[1];
+ }
+ else if (FujiCropMode == 1) // FF crop on GFX
+ {
+ width = raw_width;
+ height = raw_height;
+ }
+ // Do we need set height = raw_height for CropMode == 2 for all cameras??
+ else if (FujiCropMode == 4) // electronic shutter, high speed mode (1.25x crop)
+ {
+ height = raw_height;
+ }
+
+ top_margin = (raw_height >= height) ? (raw_height - height) >> 2 << 1 : 0;
+ left_margin = (raw_width >= width) ? (raw_width - width) >> 2 << 1 : 0;
+
+ if (imFuji.RAFDataGeneration && (imFuji.RAFDataGeneration != 4096)) {
+ switch (raw_width) {
+ case 2944: // X-S1, X10, XF1
+ filters = 0x16161616;
+ break;
+ case 4096: // X20, X30, XQ1, XQ2
+ case 5120: // X-Pro1, X-E1, X-A1, X-A2, X-M1
+ case 6048: // lossless compressed X100F, X-T2, X-T20, X-Pro2, X-H1, X-E3
+ case 6160: // uncompressed (unpacked) X100F, X-T2, X-T20, X-Pro2, X-H1, X-E3
+ left_margin = 0;
+ break;
+ case 4992: // X-E2S, X-E2, X-T10, X-T1, X100S, X100T, X70
+ left_margin = 4;
+ break;
+ case 6336: // X-H2S
+ top_margin = 6;
+ left_margin = 0;
+ width = 6264;
+ height = 4176;
+ break;
+ case 6384: // X-T3, X-T4, X100V, X-S10, X-T30, X-Pro3
+ top_margin = 0;
+ switch (FujiCropMode) {
+ case 0: // no crop
+ left_margin = 0;
+ top_margin = 6;
+ width = 6246;
+ height = 4170;
+ break;
+ case 2: // sports finder mode
+ left_margin = 624;
+ width = 5004;
+ height = raw_height;
+ break;
+ case 4: // electronic shutter, high speed mode (1.25x crop)
+ left_margin = 624;
+ width = 5004;
+ break;
+ }
+ break;
+ case 6912: // GFX 50S, GFX 50R; FF crop
+ case 9216: // GFX 50S, GFX 50R; no crop
+ left_margin = 0;
+ top_margin = 0;
+ break;
+ case 8472: // GFX 50S II
+ left_margin = 0;
+ top_margin = 0;
+ width = raw_width - 192;
+ break;
+ case 9696: // GFX 100; FF crop
+ case 11808: // GFX 100; no crop
+ left_margin = 0;
+ width = raw_width - 146;
+ height = raw_height - (top_margin = 2);
+ if (tiff_bps == 16)
+ maximum = 0xffff;
+ default:
+ /* insert model name-based width/height/margins/etc. assignments */
+ break;
+ }
+
+ } else if (!imFuji.RAFDataGeneration) {
+ switch (raw_width) {
+ case 2304: // S5100
+ height -= (top_margin = 6);
+ break;
+ case 3328: // F550EXR, F600EXR, F770EXR, F800EXR, F900EXR,
+ // HS20EXR, HS30EXR, HS33EXR, HS50EXR
+ if ((width = raw_width - 66))
+ left_margin = 34;
+ if (imgdata.sizes.raw_inset_crops[0].cleft == 8) // HS50EXR, F900EXR
+ {
+ left_margin = 0;
+ width += 2;
+ filters = 0x16161616;
+ }
+ break;
+ case 3664: // "HS10 HS11"
+ filters = 0x16161616;
+ break;
+ case 5504: // DBP for GX680 aka DX-2000
+
+// 7712 2752 -> 5504 3856
+// width = 688;
+// height = 30848;
+// raw_width = 688;
+// raw_height = 30848;
+
+ left_margin = 32; // imgdata.sizes.raw_inset_crops[0].cleft
+ top_margin = 8;
+ width = raw_width - 2*left_margin;
+ height = raw_height - 2*top_margin;
+
+ load_raw = &LibRaw::unpacked_load_raw_FujiDBP;
+ // maximum = 0x0fff;
+ filters = 0x16161616;
+ load_flags = 0;
+ flip = 6;
+ break;
+ default:
+ /* insert model name-based width/height/margins/etc. assignments */
+ break;
+ }
+ }
+ if (fuji_layout)
+ raw_width *= is_raw;
+ if (filters == 9)
+ FORC(36)
+ ((char *)xtrans)[c] =
+ xtrans_abs[(c / 6 + top_margin) % 6][(c + left_margin) % 6];
+ }
+
+ else if (makeIs(LIBRAW_CAMERAMAKER_Konica)) {
+ if (!strcmp(model, "KD-400Z")) {
+ height = 1711; // 1712
+ width = 2312;
+ raw_width = 2336;
+ goto konica_400z;
+ }
+ else if (!strcmp(model, "KD-510Z")) {
+ goto konica_510z;
+ }
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Minolta)) {
+ if (fsize == 5869568) { // hack "DiMAGE Z2"
+ load_flags = 30;
+ }
+
+ if (imSony.prd_StorageMethod == LIBRAW_MINOLTA_UNPACKED) {
+ load_raw = &LibRaw::unpacked_load_raw;
+ } else if (imSony.prd_StorageMethod == LIBRAW_MINOLTA_PACKED) {
+ load_raw = &LibRaw::packed_load_raw;
+ } else if (!load_raw && (maximum = 0xfff)) {
+ load_raw = &LibRaw::unpacked_load_raw;
+ }
+
+ if (imSony.prd_BayerPattern == LIBRAW_MINOLTA_G2BRG1) {
+ filters = 0x49494949;
+ } else if (imSony.prd_BayerPattern == LIBRAW_MINOLTA_RGGB) {
+ filters = 0x94949494;
+ }
+
+ if (imSony.prd_Active_bps && imSony.prd_Total_bps) {
+ tiff_bps = imSony.prd_Active_bps;
+ }
+
+ if (!strncmp(model, "DiMAGE G", 8)) // hack "DiMAGE G400", "DiMAGE G500",
+ // "DiMAGE G530", "DiMAGE G600"
+ {
+ if (model[8] == '4') // DiMAGE G400
+ {
+ height = 1716;
+ width = 2304;
+ }
+ else if (model[8] == '5') // DiMAGE G500 / G530
+ {
+ konica_510z:
+ height = 1956;
+ width = 2607;
+ raw_width = 2624;
+ }
+ else if (model[8] == '6') // DiMAGE G600
+ {
+ height = 2136;
+ width = 2848;
+ }
+ data_offset += 14;
+ filters = 0x61616161;
+ konica_400z:
+ load_raw = &LibRaw::unpacked_load_raw;
+ maximum = 0x3df;
+ order = 0x4d4d;
+ }
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Samsung)) {
+ if (raw_width == 4704) // Samsung NX100, NX10, NX11,
+ {
+ height -= top_margin = 8;
+ width -= 2 * (left_margin = 8);
+ load_flags = 32;
+ }
+ else if (!strcmp(model, "NX3000")) // Samsung NX3000; raw_width: 5600
+ {
+ top_margin = 38;
+ left_margin = 92;
+ width = 5456;
+ height = 3634;
+ filters = 0x61616161;
+ colors = 3;
+ }
+ else if (raw_height == 3714) // Samsung NX2000, NX300M, NX300, NX30,
+ // "NX U" (aka:
+ // "EK-GN100", "EK-GN110", "EK-GN120",
+ // "EK-KN120", "Galaxy NX")
+ {
+ height -= top_margin = 18;
+ left_margin = raw_width - (width = 5536);
+ if (raw_width != 5600)
+ left_margin = top_margin = 0;
+ filters = 0x61616161;
+ colors = 3;
+ }
+ else if (raw_width == 5632) // Samsung NX1000, NX200, NX20, NX210
+ {
+ order = 0x4949;
+ height = 3694;
+ top_margin = 2;
+ width = 5574 - (left_margin = 32 + tiff_bps);
+ if (tiff_bps == 12)
+ load_flags = 80;
+ }
+ else if (raw_width == 5664) // Samsung "NX mini"
+ {
+ height -= top_margin = 17;
+ left_margin = 96;
+ width = 5544;
+ filters = 0x49494949;
+ }
+ else if (raw_width == 6496) // Samsung NX1, NX500
+ {
+ filters = 0x61616161;
+ if (!black && !cblack[0] && !cblack[1] && !cblack[2] && !cblack[3])
+ black = 1 << (tiff_bps - 7);
+ }
+ else if (!strcmp(normalized_model, "EX1")) // Samsung EX1; raw_width: 3688
+ {
+ order = 0x4949;
+ height -= 20;
+ top_margin = 2;
+ if ((width -= 6) > 3682)
+ {
+ height -= 10;
+ width -= 46;
+ top_margin = 8;
+ }
+ }
+ else if (!strcmp(normalized_model, "WB2000")) // Samsung WB2000; raw_width: 3728
+ {
+ order = 0x4949;
+ height -= 3;
+ top_margin = 2;
+ if ((width -= 10) > 3718)
+ {
+ height -= 28;
+ width -= 56;
+ top_margin = 8;
+ }
+ }
+ else if (!strcmp(model, "WB550")) // Samsung WB550; raw_width: 4000
+ {
+ order = 0x4949;
+ }
+ else if (!strcmp(model, "EX2F")) // Samsung EX2F; raw_width: 4176
+ {
+ height = 3030;
+ width = 4040;
+ top_margin = 15;
+ left_margin = 24;
+ order = 0x4949;
+ filters = 0x49494949;
+ load_raw = &LibRaw::unpacked_load_raw;
+ }
+ }
+
+ else if (makeIs(LIBRAW_CAMERAMAKER_ST_Micro) && !strcmp(model, "STV680 VGA"))
+ {
+ black = 16;
+ }
+ else if (!strcmp(model, "N95"))
+ {
+ height = raw_height - (top_margin = 2);
+ }
+ else if (!strcmp(model, "640x480"))
+ {
+ gamma_curve(0.45, 4.5, 1, 255);
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Hasselblad))
+ {
+ if (load_raw == &LibRaw::lossless_jpeg_load_raw)
+ load_raw = &LibRaw::hasselblad_load_raw;
+
+ if ((imHassy.SensorCode == 4) && !strncmp(model, "V96C", 4)) { // Hasselblad V96C
+ strcpy(model, "V96C");
+ strcpy(normalized_model, model);
+ height -= (top_margin = 6);
+ width -= (left_margin = 3) + 7;
+ filters = 0x61616161;
+
+ }
+ else if ((imHassy.SensorCode == 9) && imHassy.uncropped) { // various Hasselblad '-39'
+ height = 5444;
+ width = 7248;
+ top_margin = 4;
+ left_margin = 7;
+ filters = 0x61616161;
+
+ }
+ else if ((imHassy.SensorCode == 13) && imHassy.uncropped) { // Hasselblad H4D-40, H5D-40
+ height -= 84;
+ width -= 82;
+ top_margin = 4;
+ left_margin = 41;
+ filters = 0x61616161;
+
+ }
+ else if ((imHassy.SensorCode == 11) && imHassy.uncropped) { // Hasselblad H5D-50
+ height -= 84;
+ width -= 82;
+ top_margin = 4;
+ left_margin = 41;
+ filters = 0x61616161;
+
+ }
+ else if ((imHassy.SensorCode == 15) &&
+ !imHassy.SensorSubCode && // Hasselblad H5D-50c
+ imHassy.uncropped) {
+ left_margin = 52;
+ top_margin = 100;
+ width = 8272;
+ height = 6200;
+ black = 256;
+
+ }
+ else if ((imHassy.SensorCode == 15) &&
+ (imHassy.SensorSubCode == 2) && // various Hasselblad X1D cameras
+ imHassy.uncropped) {
+ top_margin = 96;
+ height -= 96;
+ left_margin = 48;
+ width -= 106;
+ maximum = 0xffff;
+ tiff_bps = 16;
+
+ }
+ else if ((imHassy.SensorCode == 12) && imHassy.uncropped) { // Hasselblad H4D-60
+ if (black > 500) { // (imHassy.format == LIBRAW_HF_FFF)
+ top_margin = 12;
+ left_margin = 44;
+ width = 8956;
+ height = 6708;
+ memset(cblack, 0, sizeof(cblack));
+ black = 512;
+ }
+ else { // (imHassy.format == LIBRAW_HF_3FR)
+ top_margin = 8;
+ left_margin = 40;
+ width = 8964;
+ height = 6716;
+ black += load_flags = 256;
+ maximum = 0x8101;
+ }
+
+ }
+ else if ((imHassy.SensorCode == 17) && imHassy.uncropped) { // Hasselblad H6D-100c, A6D-100c
+ left_margin = 64;
+ width = 11608;
+ top_margin = 108;
+ height = raw_height - top_margin;
+ }
+
+ if (tiff_samples > 1)
+ {
+ is_raw = tiff_samples + 1;
+ if (!shot_select && !half_size)
+ filters = 0;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Sinar))
+ {
+ if (!load_raw)
+ load_raw = &LibRaw::unpacked_load_raw;
+ if (is_raw > 1 && !shot_select)
+ filters = 0;
+ maximum = 0x3fff;
+ }
+
+ if (load_raw == &LibRaw::sinar_4shot_load_raw)
+ {
+ if (is_raw > 1 && !shot_select)
+ filters = 0;
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Leaf))
+ {
+ maximum = 0x3fff;
+ fseek(ifp, data_offset, SEEK_SET);
+ if (ljpeg_start(&jh, 1) && jh.bits == 15)
+ maximum = 0x1fff;
+ if (tiff_samples > 1)
+ filters = 0;
+ if (tiff_samples > 1 || tile_length < raw_height)
+ {
+ load_raw = &LibRaw::leaf_hdr_load_raw;
+ raw_width = tile_width;
+ }
+ if ((width | height) == 2048)
+ {
+ if (tiff_samples == 1)
+ {
+ filters = 1;
+ strcpy(cdesc, "RBTG");
+ strcpy(model, "CatchLight");
+ strcpy(normalized_model, model);
+ top_margin = 8;
+ left_margin = 18;
+ height = 2032;
+ width = 2016;
+ }
+ else
+ {
+ strcpy(model, "DCB2");
+ strcpy(normalized_model, model);
+ top_margin = 10;
+ left_margin = 16;
+ height = 2028;
+ width = 2022;
+ }
+ }
+ else if (width + height == 3144 + 2060)
+ {
+ if (!model[0])
+ {
+ strcpy(model, "Cantare");
+ strcpy(normalized_model, model);
+ }
+ if (width > height)
+ {
+ top_margin = 6;
+ left_margin = 32;
+ height = 2048;
+ width = 3072;
+ filters = 0x61616161;
+ }
+ else
+ {
+ left_margin = 6;
+ top_margin = 32;
+ width = 2048;
+ height = 3072;
+ filters = 0x16161616;
+ }
+ if (!cam_mul[0] || model[0] == 'V')
+ filters = 0;
+ else
+ is_raw = tiff_samples;
+ }
+ else if (width == 2116) // Leaf "Valeo 6"
+ {
+ strcpy(model, "Valeo 6");
+ strcpy(normalized_model, model);
+ height -= 2 * (top_margin = 30);
+ width -= 2 * (left_margin = 55);
+ filters = 0x49494949;
+ }
+ else if (width == 3171) // Leaf "Valeo 6"
+ {
+ strcpy(model, "Valeo 6");
+ strcpy(normalized_model, model);
+ height -= 2 * (top_margin = 24);
+ width -= 2 * (left_margin = 24);
+ filters = 0x16161616;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Panasonic))
+ {
+ if (raw_width > 0 &&
+ ((flen - data_offset) / (raw_width * 8 / 7) == raw_height))
+ load_raw = &LibRaw::panasonic_load_raw;
+ if (!load_raw)
+ {
+ load_raw = &LibRaw::unpacked_load_raw;
+ load_flags = 4;
+ }
+ zero_is_bad = 1;
+ if ((height += 12) > raw_height)
+ height = raw_height;
+ for (i = 0; i < int(sizeof pana / sizeof *pana); i++)
+ if (raw_width == pana[i][0] && raw_height == pana[i][1])
+ {
+ left_margin = pana[i][2];
+ top_margin = pana[i][3];
+ width += pana[i][4];
+ height += pana[i][5];
+ }
+ if (!tiff_bps && pana_bpp >= 12 && pana_bpp <= 14)
+ tiff_bps = pana_bpp;
+
+ if (!strcmp(model, "DC-LX100M2") && raw_height == 3568 && raw_width == 4816 && filters == 3)
+ filters = 4;
+
+ filters = 0x01010101U *
+ (uchar) "\x94\x61\x49\x16"[((filters - 1) ^ (left_margin & 1) ^
+ (top_margin << 1)) &
+ 3];
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Contax) &&
+ !strcmp(model, "N Digital")) {
+ height = 2047;
+ width = 3072;
+ filters = 0x61616161;
+ data_offset = 0x1a00;
+ load_raw = &LibRaw::packed_load_raw;
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Sony)) {
+ if (!strcmp(model, "DSC-F828")) { // Sony DSC-F828
+ width = 3288;
+ left_margin = 5;
+ mask[1][3] = -17;
+ data_offset = 862144;
+ load_raw = &LibRaw::sony_load_raw;
+ filters = 0x9c9c9c9c;
+ colors = 4;
+ strcpy(cdesc, "RGBE");
+
+ }
+ else if (!strcmp(model, "DSC-V3")) { // Sony DSC-V3
+ width = 3109;
+ left_margin = 59;
+ mask[0][1] = 9;
+ data_offset = 787392;
+ load_raw = &LibRaw::sony_load_raw;
+
+ }
+ else if (raw_width == 3984) { // Sony DSC-R1;
+ width = 3925;
+ order = 0x4d4d;
+
+ }
+ else if (raw_width == 4288) { // Sony ILCE-7S, ILCE-7SM2, ILCE-7SM3, DSLR-A700, DSLR-A500;
+ width -= 32;
+ }
+ else if (raw_width == 4600) { // Sony DSLR-A290, DSLR-A350, DSLR-A380;
+ if (!strcmp(model, "DSLR-A350"))
+ height -= 4;
+ black = 0;
+
+ }
+ else if (raw_width == 4928) {
+ // Sony DSLR-A580, NEX-C3, SLT-A35, DSC-HX99, SLT-A55,
+ // NEX-5N, SLT-A37, SLT-A57, NEX-F3, NEX-6, NEX-5R, NEX-3N, NEX-5T;
+ if (height < 3280)
+ width -= 8;
+
+ }
+ else if (raw_width == 5504) {
+ // Sony ILCE-3000, SLT-A58, DSC-RX100M3, ILCE-QX1,
+ // DSC-RX10M4, DSC-RX100M6, DSC-RX100, DSC-RX100M2, DSC-RX10,
+ // ILCE-5000, DSC-RX100M4, DSC-RX10M2, DSC-RX10M3,
+ // DSC-RX100M5, DSC-RX100M5A;
+ width -= height > 3664 ? 8 : 32;
+
+ }
+ else if (raw_width == 6048) {
+ // Sony SLT-A65, DSC-RX1, SLT-A77, DSC-RX1, ILCA-77M2,
+ // ILCE-7M3, NEX-7, SLT-A99, ILCE-7, DSC-RX1R, ILCE-6000,
+ // ILCE-5100, ILCE-7M2, ILCA-68, ILCE-6300, ILCE-9,
+ // ILCE-6500, ILCE-6400;
+ width -= 24;
+ if (strstr(normalized_model, "RX1") ||
+ strstr(normalized_model, "A99"))
+ width -= 6;
+
+ }
+ else if (raw_width == 7392) { // Sony ILCE-7R;
+ width -= 30;
+
+ }
+ else if (raw_width == 8000) {
+ // Sony ILCE-7RM2, ILCE-7RM2, ILCE-7RM3, DSC-RX1RM2, ILCA-99M2;
+ width -= 32;
+
+ }
+ else if (raw_width == 9600) { // Sony ILCE-7RM4
+ width -= 32;
+
+ }
+ else if(unique_id == SonyID_ILCE_1)
+ {
+ if (raw_width == 8704 && raw_height == 6144) // ILCE-1 FF@Compressed
+ {
+ width = 8660;
+ height = 5784;
+ }
+ else if (raw_width == 8672) // FF uncompressed/lossy
+ {
+ width -= 12;
+ }
+ else if (raw_width == 6144 && raw_height == 4096) // APSC/Lossless
+ {
+ width = 5636;
+ height = 3768;
+ }
+ else if (raw_width == 5664) // APS-C/Uncompressed or lossy
+ {
+ width -= 28;
+ }
+ }
+ else if (unique_id == SonyID_ILCE_7M4)
+ {
+ if (raw_width == 7168 && raw_height == 5120) // ILCE-1 FF@Compressed
+ {
+ width = 7028;
+ height = 4688;
+ }
+ else if (raw_width == 7040) // FF uncompressed/lossy
+ {
+ width -= 12;
+ }
+ /* FIXME: need APS-C samples, both losslesscompressed and uncompressed or lossy */
+ }
+
+ else if (!strcmp(model, "DSLR-A100")) {
+ if (width == 3880) {
+ height--;
+ width = ++raw_width;
+ }
+ else {
+ height -= 4;
+ width -= 4;
+ order = 0x4d4d;
+ load_flags = 2;
+ }
+ filters = 0x61616161;
+ }
+ }
+
+ else if (!strcmp(model, "PIXL")) {
+ height -= top_margin = 4;
+ width -= left_margin = 32;
+ gamma_curve(0, 7, 1, 255);
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Kodak)) {
+
+ if (!strncasecmp(model, "EasyShare", 9)) {
+ data_offset = data_offset < 0x15000 ? 0x15000 : 0x17000;
+ load_raw = &LibRaw::packed_load_raw;
+
+ }
+ else if (!strcmp(model, "C603") ||
+ !strcmp(model, "C330") ||
+ !strcmp(model, "12MP")) {
+ order = 0x4949;
+ if (filters && data_offset) {
+ fseek(ifp, data_offset < 4096 ? 168 : 5252, SEEK_SET);
+ read_shorts(curve, 256);
+ }
+ else
+ gamma_curve(0, 3.875, 1, 255);
+
+ load_raw = filters ? &LibRaw::eight_bit_load_raw
+ : strcmp(model, "C330") ? &LibRaw::kodak_c603_load_raw
+ : &LibRaw::kodak_c330_load_raw;
+ load_flags = tiff_bps > 16;
+ tiff_bps = 8;
+
+ }
+ else {
+ if (!strncmp(model, "NC2000", 6) ||
+ !strncmp(model, "EOSDCS", 6) ||
+ !strncmp(model, "DCS4", 4)) {
+ width -= 4;
+ left_margin = 2;
+
+ }
+ else if (!strcmp(model, "DCS660M")) {
+ black = 214;
+
+ }
+ else if (!strcmp(model, "EOS D2000C")) {
+ filters = 0x61616161;
+ if (!black) black = curve[200];
+ }
+
+ if (filters == UINT_MAX) filters = 0x61616161;
+
+ if (!strcmp(model + 4, "20X"))
+ strcpy(cdesc, "MYCY");
+ if (!strcmp(model, "DC25")) {
+ data_offset = 15424;
+ }
+
+ if (!strncmp(model, "DC2", 3)) {
+ raw_height = 2 + (height = 242);
+ if (!strncmp(model, "DC290", 5))
+ iso_speed = 100;
+ if (!strncmp(model, "DC280", 5))
+ iso_speed = 70;
+ if (flen < 100000) {
+ raw_width = 256;
+ width = 249;
+ pixel_aspect = (4.0 * height) / (3.0 * width);
+ }
+ else {
+ raw_width = 512;
+ width = 501;
+ pixel_aspect = (493.0 * height) / (373.0 * width);
+ }
+ top_margin = left_margin = 1;
+ colors = 4;
+ filters = 0x8d8d8d8d;
+ simple_coeff(1);
+ pre_mul[1] = 1.179f;
+ pre_mul[2] = 1.209f;
+ pre_mul[3] = 1.036f;
+ load_raw = &LibRaw::eight_bit_load_raw;
+ }
+ else if (!strcmp(model, "DC40")) {
+ height = 512;
+ width = 768;
+ data_offset = 1152;
+ load_raw = &LibRaw::kodak_radc_load_raw;
+ tiff_bps = 12;
+ FORC4 cam_mul[c] = 1.0f;
+
+ }
+ else if (!strcmp(model, "DC50")) {
+ height = 512;
+ width = 768;
+ iso_speed = 84;
+ data_offset = 19712;
+ load_raw = &LibRaw::kodak_radc_load_raw;
+ FORC4 cam_mul[c] = 1.0f;
+
+ }
+ else if (!strcmp(model, "DC120")) {
+ raw_height = height = 976;
+ raw_width = width = 848;
+ iso_speed = 160;
+ pixel_aspect = height / 0.75 / width;
+ load_raw = tiff_compress == 7 ? &LibRaw::kodak_jpeg_load_raw
+ : &LibRaw::kodak_dc120_load_raw;
+
+ }
+ else if (!strcmp(model, "DCS200")) {
+ thumb_height = 128;
+ thumb_width = 192;
+ thumb_offset = 6144;
+ thumb_misc = 360;
+ iso_speed = 140;
+ thumb_format = LIBRAW_INTERNAL_THUMBNAIL_LAYER;
+ black = 17;
+ }
+ }
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Logitech) &&
+ !strcmp(model, "Fotoman Pixtura")) {
+ height = 512;
+ width = 768;
+ data_offset = 3632;
+ load_raw = &LibRaw::kodak_radc_load_raw;
+ filters = 0x61616161;
+ simple_coeff(2);
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Apple) &&
+ !strncmp(model, "QuickTake", 9)) {
+ if (head[5]) {
+ strcpy(model + 10, "200");
+ strcpy(normalized_model, model);
+ }
+ fseek(ifp, 544, SEEK_SET);
+ height = get2();
+ width = get2();
+ data_offset = (get4(), get2()) == 30 ? 738 : 736;
+ if (height > width) {
+ SWAP(height, width);
+ fseek(ifp, data_offset - 6, SEEK_SET);
+ flip = ~get2() & 3 ? 5 : 6;
+ }
+ filters = 0x61616161;
+
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Rollei) &&
+ !load_raw) {
+ switch (raw_width) {
+ case 1316: // Rollei d530flex
+ height = 1030;
+ width = 1300;
+ top_margin = 1;
+ left_margin = 6;
+ break;
+ case 2568:
+ height = 1960;
+ width = 2560;
+ top_margin = 2;
+ left_margin = 8;
+ }
+ filters = 0x16161616;
+ load_raw = &LibRaw::rollei_load_raw;
+
+ }
+ else if (!strcmp(model, "GRAS-50S5C")) {
+ height = 2048;
+ width = 2440;
+ load_raw = &LibRaw::unpacked_load_raw;
+ data_offset = 0;
+ filters = 0x49494949;
+ order = 0x4949;
+ maximum = 0xfffC;
+
+ }
+ else if (!strcmp(model, "BB-500CL")) {
+ height = 2058;
+ width = 2448;
+ load_raw = &LibRaw::unpacked_load_raw;
+ data_offset = 0;
+ filters = 0x94949494;
+ order = 0x4949;
+ maximum = 0x3fff;
+
+ }
+ else if (!strcmp(model, "BB-500GE")) {
+ height = 2058;
+ width = 2456;
+ load_raw = &LibRaw::unpacked_load_raw;
+ data_offset = 0;
+ filters = 0x94949494;
+ order = 0x4949;
+ maximum = 0x3fff;
+
+ }
+ else if (!strcmp(model, "SVS625CL")) {
+ height = 2050;
+ width = 2448;
+ load_raw = &LibRaw::unpacked_load_raw;
+ data_offset = 0;
+ filters = 0x94949494;
+ order = 0x4949;
+ maximum = 0x0fff;
+ }
+}
diff --git a/libkdcraw/libraw/src/metadata/identify_tools.cpp b/libkdcraw/libraw/src/metadata/identify_tools.cpp
new file mode 100644
index 0000000..28a1d69
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/identify_tools.cpp
@@ -0,0 +1,140 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+short LibRaw::guess_byte_order(int words)
+{
+ uchar test[4][2];
+ int t = 2, msb;
+ double diff, sum[2] = {0, 0};
+
+ fread(test[0], 2, 2, ifp);
+ for (words -= 2; words--;)
+ {
+ fread(test[t], 2, 1, ifp);
+ for (msb = 0; msb < 2; msb++)
+ {
+ diff = (test[t ^ 2][msb] << 8 | test[t ^ 2][!msb]) -
+ (test[t][msb] << 8 | test[t][!msb]);
+ sum[msb] += diff * diff;
+ }
+ t = (t + 1) & 3;
+ }
+ return sum[0] < sum[1] ? 0x4d4d : 0x4949;
+}
+
+float LibRaw::find_green(int bps, int bite, int off0, int off1)
+{
+ UINT64 bitbuf = 0;
+ int vbits, col, i, c;
+ ushort img[2][2064];
+ double sum[] = {0, 0};
+ if (width > 2064)
+ return 0.f; // too wide
+
+ FORC(2)
+ {
+ fseek(ifp, c ? off1 : off0, SEEK_SET);
+ for (vbits = col = 0; col < width; col++)
+ {
+ for (vbits -= bps; vbits < 0; vbits += bite)
+ {
+ bitbuf <<= bite;
+ for (i = 0; i < bite; i += 8)
+ bitbuf |= (unsigned)(fgetc(ifp) << i);
+ }
+ img[c][col] = bitbuf << (64 - bps - vbits) >> (64 - bps);
+ }
+ }
+ FORC(width - 1)
+ {
+ sum[c & 1] += ABS(img[0][c] - img[1][c + 1]);
+ sum[~c & 1] += ABS(img[1][c] - img[0][c + 1]);
+ }
+ if (sum[0] >= 1.0 && sum[1] >= 1.0)
+ return 100 * log(sum[0] / sum[1]);
+ else
+ return 0.f;
+}
+
+void LibRaw::trimSpaces(char *s)
+{
+ char *p = s;
+ int l = int(strlen(p));
+ if (!l)
+ return;
+ while (isspace(p[l - 1]))
+ p[--l] = 0; /* trim trailing spaces */
+ while (*p && isspace(*p))
+ ++p, --l; /* trim leading spaces */
+ memmove(s, p, l + 1);
+}
+
+void LibRaw::remove_trailing_spaces(char *string, size_t len)
+{
+ if (len < 1)
+ return; // not needed, b/c sizeof of make/model is 64
+ string[len - 1] = 0;
+ if (len < 3)
+ return; // also not needed
+ len = strnlen(string, len - 1);
+ for (size_t i = len - 1; i >= 0; i--)
+ {
+ if (isspace((unsigned char)string[i]))
+ string[i] = 0;
+ else
+ break;
+ }
+}
+
+void LibRaw::remove_caseSubstr(char *string, char *subStr) // replace a substring with an equal length of spaces
+{
+ char *found;
+ while ((found = strcasestr(string,subStr))) {
+ if (!found) return;
+ int fill_len = int(strlen(subStr));
+ int p = found - string;
+ for (int i=p; i<p+fill_len; i++) {
+ string[i] = 32;
+ }
+ }
+ trimSpaces (string);
+}
+
+void LibRaw::removeExcessiveSpaces(char *string) // replace repeating spaces with one space
+{
+ int orig_len = int(strlen(string));
+ int i = 0; // counter for resulting string
+ int j = -1;
+ bool prev_char_is_space = false;
+ while (++j < orig_len && string[j] == ' ');
+ while (j < orig_len) {
+ if (string[j] != ' ') {
+ string[i++] = string[j++];
+ prev_char_is_space = false;
+ } else if (string[j++] == ' ') {
+ if (!prev_char_is_space) {
+ string[i++] = ' ';
+ prev_char_is_space = true;
+ }
+ }
+ }
+ if (string[i-1] == ' ')
+ string[i-1] = 0;
+}
diff --git a/libkdcraw/libraw/src/metadata/kodak.cpp b/libkdcraw/libraw/src/metadata/kodak.cpp
new file mode 100644
index 0000000..1193eac
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/kodak.cpp
@@ -0,0 +1,363 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::Kodak_KDC_WBtags(int wb, int wbi)
+{
+ int c;
+ FORC3 icWBC[wb][c] = get4();
+ icWBC[wb][3] = icWBC[wb][1];
+ if (wbi == wb)
+ FORC4 cam_mul[c] = icWBC[wb][c];
+ return;
+}
+
+void LibRaw::Kodak_DCR_WBtags(int wb, unsigned type, int wbi)
+{
+ float mul[3] = {1.0f, 1.0f, 1.0f}, num, mul2;
+ int c;
+ FORC3 mul[c] = (num = getreal(type)) <= 0.001f ? 1.0f : num;
+ icWBC[wb][1] = icWBC[wb][3] = mul[1];
+ mul2 = mul[1] * mul[1];
+ icWBC[wb][0] = mul2 / mul[0];
+ icWBC[wb][2] = mul2 / mul[2];
+ if (wbi == wb)
+ FORC4 cam_mul[c] = icWBC[wb][c];
+ return;
+}
+
+short LibRaw::KodakIllumMatrix(unsigned type, float *romm_camIllum)
+{
+ int c, j, romm_camTemp[9], romm_camScale[3];
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SRATIONAL))
+ {
+ for (j = 0; j < 9; j++)
+ ((float *)romm_camIllum)[j] = getreal(type);
+ return 1;
+ }
+ else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SLONG))
+ {
+ FORC3
+ {
+ romm_camScale[c] = 0;
+ for (j = 0; j < 3; j++)
+ {
+ romm_camTemp[c * 3 + j] = get4();
+ romm_camScale[c] += romm_camTemp[c * 3 + j];
+ }
+ }
+ if ((romm_camScale[0] > 0x1fff) && (romm_camScale[1] > 0x1fff) &&
+ (romm_camScale[2] > 0x1fff))
+ {
+ FORC3 for (j = 0; j < 3; j++)((float *)romm_camIllum)[c * 3 + j] =
+ ((float)romm_camTemp[c * 3 + j]) / ((float)romm_camScale[c]);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Thanks to Alexey Danilchenko for wb as-shot parsing code */
+void LibRaw::parse_kodak_ifd(int base)
+{
+ unsigned entries, tag, type, len, save;
+ int c, wbi = -1;
+
+ static const int wbtag_kdc[] = {
+ LIBRAW_WBI_Auto, // 64037 / 0xfa25
+ LIBRAW_WBI_Fluorescent, // 64040 / 0xfa28
+ LIBRAW_WBI_Tungsten, // 64039 / 0xfa27
+ LIBRAW_WBI_Daylight, // 64041 / 0xfa29
+ -1,
+ -1,
+ LIBRAW_WBI_Shade // 64042 / 0xfa2a
+ };
+
+ static const int wbtag_dcr[] = {
+ LIBRAW_WBI_Daylight, // 2120 / 0x0848
+ LIBRAW_WBI_Tungsten, // 2121 / 0x0849
+ LIBRAW_WBI_Fluorescent, // 2122 / 0x084a
+ LIBRAW_WBI_Flash, // 2123 / 0x084b
+ LIBRAW_WBI_Custom, // 2124 / 0x084c
+ LIBRAW_WBI_Auto // 2125 / 0x084d
+ };
+
+ // int a_blck = 0;
+
+ entries = get2();
+ if (entries > 1024)
+ return;
+ INT64 fsize = ifp->size();
+ while (entries--)
+ {
+ tiff_get(base, &tag, &type, &len, &save);
+ INT64 savepos = ftell(ifp);
+ if (len > 8 && len + savepos > 2 * fsize)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+ if (callbacks.exif_cb)
+ {
+ callbacks.exif_cb(callbacks.exifparser_data, tag | 0x20000, type, len,
+ order, ifp, base);
+ fseek(ifp, savepos, SEEK_SET);
+ }
+ if (tag == 0x03eb) // 1003
+ imgdata.sizes.raw_inset_crops[0].cleft = get2();
+ else if (tag == 0x03ec) // 1004
+ imgdata.sizes.raw_inset_crops[0].ctop = get2();
+ else if (tag == 0x03ed) // 1005
+ imgdata.sizes.raw_inset_crops[0].cwidth = get2();
+ else if (tag == 0x03ee) // 1006
+ imgdata.sizes.raw_inset_crops[0].cheight = get2();
+ else if (tag == 0x03ef) // 1007
+ {
+ if (!strcmp(model, "EOS D2000C"))
+ black = get2();
+ else
+ imKodak.BlackLevelTop = get2();
+ }
+ else if (tag == 0x03f0) // 1008
+ {
+ if (!strcmp(model, "EOS D2000C"))
+ {
+ if (black) // already set by tag 1007 (0x03ef)
+ black = (black + get2()) / 2;
+ else
+ black = get2();
+ }
+ else
+ imKodak.BlackLevelBottom = get2();
+ }
+
+ else if (tag == 0x03f1)
+ { // 1009 Kodak TextualInfo
+ if (len > 0)
+ {
+ char kti[1024];
+ char *pkti;
+ int nsym = MIN(len, 1023);
+ fread(kti, 1, nsym, ifp);
+ kti[nsym] = 0;
+#ifdef LIBRAW_WIN32_CALLS
+ pkti = strtok(kti, "\x0a");
+#else
+ char *last = 0;
+ pkti = strtok_r(kti, "\x0a", &last);
+#endif
+ while (pkti != NULL)
+ {
+ c = 12;
+ if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Camera body:", c)))
+ {
+ while ((pkti[c] == ' ') && (c < (int)strlen(pkti)))
+ {
+ c++;
+ }
+ strcpy(ilm.body, pkti + c);
+ }
+ c = 5;
+ if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Lens:", c)))
+ {
+ ilm.CurFocal = atoi(pkti + c);
+ }
+ c = 9;
+ if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Aperture:", c)))
+ {
+ while (((pkti[c] == ' ') || (pkti[c] == 'f')) && (c < (int)strlen(pkti)))
+ {
+ c++;
+ }
+ ilm.CurAp = atof(pkti + c);
+ }
+ c = 10;
+ if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "ISO Speed:", c)))
+ {
+ iso_speed = atoi(pkti + c);
+ }
+ c = 13;
+ if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Focal Length:", c)))
+ {
+ ilm.CurFocal = atoi(pkti + c);
+ }
+ c = 13;
+ if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Max Aperture:", c)))
+ {
+ while (((pkti[c] == ' ') || (pkti[c] == 'f')) && (c < (int)strlen(pkti)))
+ {
+ c++;
+ }
+ ilm.MaxAp4CurFocal = atof(pkti + c);
+ }
+ c = 13;
+ if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Min Aperture:", c)))
+ {
+ while (((pkti[c] == ' ') || (pkti[c] == 'f')) && (c < (int)strlen(pkti)))
+ {
+ c++;
+ }
+ ilm.MinAp4CurFocal = atof(pkti + c);
+ }
+#ifdef LIBRAW_WIN32_CALLS
+ pkti = strtok(NULL, "\x0a");
+#else
+ pkti = strtok_r(NULL, "\x0a", &last);
+#endif
+ }
+ }
+ }
+
+ else if (tag == 0x03f3) // 1011
+ imCommon.FlashEC = getreal(type);
+
+ else if (tag == 0x03fc) // 1020
+ {
+ wbi = getint(type);
+ if ((wbi >= 0) && (wbi < 6) && (wbi != -2))
+ wbi = wbtag_dcr[wbi];
+ }
+ else if (tag == 0x03fd && len == 72) // 1021
+ { /* WB set in software */
+ fseek(ifp, 40, SEEK_CUR);
+ FORC3 cam_mul[c] = 2048.0 / fMAX(1.0f, get2());
+ wbi = -2;
+ }
+
+ else if ((tag == 0x0406) && (len == 1)) // 1030
+ imCommon.CameraTemperature = getreal(type);
+ else if ((tag == 0x0413) && (len == 1)) // 1043
+ imCommon.SensorTemperature = getreal(type);
+ else if (tag == 0x0848) // 2120
+ Kodak_DCR_WBtags(LIBRAW_WBI_Daylight, type, wbi);
+ else if (tag == 0x0849) // 2121
+ Kodak_DCR_WBtags(LIBRAW_WBI_Tungsten, type, wbi);
+ else if (tag == 0x084a) // 2122
+ Kodak_DCR_WBtags(LIBRAW_WBI_Fluorescent, type, wbi);
+ else if (tag == 0x084b) // 2123
+ Kodak_DCR_WBtags(LIBRAW_WBI_Flash, type, wbi);
+ else if (tag == 0x084c) // 2124
+ Kodak_DCR_WBtags(LIBRAW_WBI_Custom, type, wbi);
+ else if (tag == 0x084d) // 2125
+ {
+ if (wbi == -1)
+ wbi = LIBRAW_WBI_Auto;
+ Kodak_DCR_WBtags(LIBRAW_WBI_Auto, type, wbi);
+ }
+ else if (tag == 0x089f) // 2207
+ imKodak.ISOCalibrationGain = getreal(type);
+ else if (tag == 0x0903) // 2307
+ imKodak.AnalogISO = iso_speed = getreal(type);
+ else if (tag == 0x090d) // 2317
+ linear_table(len);
+ else if (tag == 0x09ce) // 2510
+ stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp);
+ else if (tag == 0x0e92) // 3730
+ {
+ imKodak.val018percent = get2();
+ imgdata.color.linear_max[0] = imgdata.color.linear_max[1] =
+ imgdata.color.linear_max[2] = imgdata.color.linear_max[3] =
+ (int)(((float)imKodak.val018percent) / 18.0f * 170.0f);
+ }
+ else if (tag == 0x0e93) // 3731
+ imgdata.color.linear_max[0] = imgdata.color.linear_max[1] =
+ imgdata.color.linear_max[2] = imgdata.color.linear_max[3] =
+ imKodak.val170percent = get2();
+ else if (tag == 0x0e94) // 3732
+ imKodak.val100percent = get2();
+ /*
+ else if (tag == 0x1784) // 6020
+ iso_speed = getint(type);
+ */
+ else if (tag == 0xfa00) // 64000
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ else if (tag == 0xfa0d) // 64013
+ {
+ wbi = fgetc(ifp);
+ if ((wbi >= 0) && (wbi < 7))
+ wbi = wbtag_kdc[wbi];
+ }
+ else if (tag == 0xfa13) // 64019
+ width = getint(type);
+ else if (tag == 0xfa14) // 64020
+ height = (getint(type) + 1) & -2;
+ /*
+ height = getint(type);
+
+ else if (tag == 0xfa16) // 64022
+ raw_width = get2();
+ else if (tag == 0xfa17) // 64023
+ raw_height = get2();
+ */
+ else if (tag == 0xfa18) // 64024
+ {
+ imKodak.offset_left = getint(LIBRAW_EXIFTAG_TYPE_SSHORT);
+ if (type != LIBRAW_EXIFTAG_TYPE_SSHORT)
+ imKodak.offset_left += 1;
+ }
+ else if (tag == 0xfa19) // 64025
+ {
+ imKodak.offset_top = getint(LIBRAW_EXIFTAG_TYPE_SSHORT);
+ if (type != LIBRAW_EXIFTAG_TYPE_SSHORT)
+ imKodak.offset_top += 1;
+ }
+
+ else if (tag == 0xfa25) // 64037
+ Kodak_KDC_WBtags(LIBRAW_WBI_Auto, wbi);
+ else if (tag == 0xfa27) // 64039
+ Kodak_KDC_WBtags(LIBRAW_WBI_Tungsten, wbi);
+ else if (tag == 0xfa28) // 64040
+ Kodak_KDC_WBtags(LIBRAW_WBI_Fluorescent, wbi);
+ else if (tag == 0xfa29) // 64041
+ Kodak_KDC_WBtags(LIBRAW_WBI_Daylight, wbi);
+ else if (tag == 0xfa2a) // 64042
+ Kodak_KDC_WBtags(LIBRAW_WBI_Shade, wbi);
+
+ else if (tag == 0xfa31) // 64049
+ imgdata.sizes.raw_inset_crops[0].cwidth = get2();
+ else if (tag == 0xfa32) // 64050
+ imgdata.sizes.raw_inset_crops[0].cheight = get2();
+ else if (tag == 0xfa3e) // 64062
+ imgdata.sizes.raw_inset_crops[0].cleft = get2();
+ else if (tag == 0xfa3f) // 64063
+ imgdata.sizes.raw_inset_crops[0].ctop = get2();
+
+ else if (((tag == 0x07e4) || (tag == 0xfb01)) &&
+ (len == 9)) // 2020 or 64257
+ {
+ if (KodakIllumMatrix(type, (float *)imKodak.romm_camDaylight))
+ {
+ romm_coeff(imKodak.romm_camDaylight);
+ }
+ }
+ else if (((tag == 0x07e5) || (tag == 0xfb02)) &&
+ (len == 9)) // 2021 or 64258
+ KodakIllumMatrix(type, (float *)imKodak.romm_camTungsten);
+ else if (((tag == 0x07e6) || (tag == 0xfb03)) &&
+ (len == 9)) // 2022 or 64259
+ KodakIllumMatrix(type, (float *)imKodak.romm_camFluorescent);
+ else if (((tag == 0x07e7) || (tag == 0xfb04)) &&
+ (len == 9)) // 2023 or 64260
+ KodakIllumMatrix(type, (float *)imKodak.romm_camFlash);
+ else if (((tag == 0x07e8) || (tag == 0xfb05)) &&
+ (len == 9)) // 2024 or 64261
+ KodakIllumMatrix(type, (float *)imKodak.romm_camCustom);
+ else if (((tag == 0x07e9) || (tag == 0xfb06)) &&
+ (len == 9)) // 2025 or 64262
+ KodakIllumMatrix(type, (float *)imKodak.romm_camAuto);
+
+ fseek(ifp, save, SEEK_SET);
+ }
+}
diff --git a/libkdcraw/libraw/src/metadata/leica.cpp b/libkdcraw/libraw/src/metadata/leica.cpp
new file mode 100644
index 0000000..cda4b0c
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/leica.cpp
@@ -0,0 +1,375 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::setLeicaBodyFeatures(int LeicaMakernoteSignature)
+{
+ if (LeicaMakernoteSignature == -3) // M8
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_APSH;
+ ilm.CameraMount = LIBRAW_MOUNT_Leica_M;
+ }
+ else if (LeicaMakernoteSignature == -2) // DMR
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_Leica_DMR;
+ if ((model[0] == 'R') || (model[6] == 'R'))
+ ilm.CameraMount = LIBRAW_MOUNT_Leica_R;
+ }
+ else if (LeicaMakernoteSignature == 0) // "DIGILUX 2"
+ {
+ ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ }
+ else if ((LeicaMakernoteSignature == 0x0100) || // X1
+ (LeicaMakernoteSignature == 0x0500) || // X2, "X-E (Typ 102)"
+ (LeicaMakernoteSignature == 0x0700) || // "X (Typ 113)"
+ (LeicaMakernoteSignature == 0x1000)) // "X-U (Typ 113)"
+ {
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ }
+ else if (LeicaMakernoteSignature == 0x0400) // "X VARIO (Typ 107)"
+ {
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ }
+ else if ((LeicaMakernoteSignature ==
+ 0x0200) || // M10, M10-D, M10-R, "S (Typ 007)", M11
+ (LeicaMakernoteSignature ==
+ 0x02ff) || // "M (Typ 240)", "M (Typ 262)", "M-D (Typ 262)",
+ // "M Monochrom (Typ 246)", "S (Typ 006)", "S-E (Typ 006)", S2, S3
+ (LeicaMakernoteSignature ==
+ 0x0300)) // M9, "M9 Monochrom", "M Monochrom", M-E
+ {
+ if ((model[0] == 'M') || (model[6] == 'M'))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ ilm.CameraMount = LIBRAW_MOUNT_Leica_M;
+ }
+ else if ((model[0] == 'S') || (model[6] == 'S'))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_LeicaS;
+ ilm.CameraMount = LIBRAW_MOUNT_Leica_S;
+ }
+ }
+ else if ((LeicaMakernoteSignature == 0x0600) || // "T (Typ 701)", TL
+ (LeicaMakernoteSignature == 0x0900) || // SL2, "SL2-S", "SL (Typ 601)", CL, Q2, "Q2 MONO"
+ (LeicaMakernoteSignature == 0x1a00)) // TL2
+ {
+ if ((model[0] == 'S') || (model[6] == 'S'))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ ilm.CameraMount = LIBRAW_MOUNT_LPS_L;
+ }
+ else if ((model[0] == 'T') || (model[6] == 'T') ||
+ (model[0] == 'C') || (model[6] == 'C'))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_LPS_L;
+ }
+ else if (((model[0] == 'Q') || (model[6] == 'Q')) &&
+ ((model[1] == '2') || (model[7] == '2')))
+ {
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_FF;
+ ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ }
+ }
+ else if (LeicaMakernoteSignature == 0x0800) // "Q (Typ 116)"
+ {
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_FF;
+ ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ }
+}
+
+void LibRaw::parseLeicaLensID()
+{
+ ilm.LensID = get4();
+ if (ilm.LensID)
+ {
+ ilm.LensID = ((ilm.LensID >> 2) << 8) | (ilm.LensID & 0x3);
+ if ((ilm.LensID > 0x00ff) && (ilm.LensID < 0x3b00))
+ {
+ ilm.LensMount = ilm.CameraMount;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ }
+ }
+}
+
+int LibRaw::parseLeicaLensName(unsigned len)
+{
+#define plln ilm.Lens
+ if (!len)
+ {
+ strcpy(plln, "N/A");
+ return 0;
+ }
+ stmread(plln, len, ifp);
+ if ((plln[0] == ' ') || !strncasecmp(plln, "not ", 4) ||
+ !strncmp(plln, "---", 3) || !strncmp(plln, "***", 3))
+ {
+ strcpy(plln, "N/A");
+ return 0;
+ }
+ else
+ return 1;
+#undef plln
+}
+
+int LibRaw::parseLeicaInternalBodySerial(unsigned len)
+{
+#define plibs imgdata.shootinginfo.InternalBodySerial
+ if (!len)
+ {
+ strcpy(plibs, "N/A");
+ return 0;
+ }
+ stmread(plibs, len, ifp);
+ if (!strncmp(plibs, "000000000000", 12))
+ {
+ plibs[0] = '0';
+ plibs[1] = '\0';
+ return 1;
+ }
+
+ if (strnlen(plibs, len) == 13)
+ {
+ for (int i = 3; i < 13; i++)
+ {
+ if (!isdigit(plibs[i]))
+ goto non_std;
+ }
+ memcpy(plibs + 15, plibs + 9, 4);
+ memcpy(plibs + 12, plibs + 7, 2);
+ memcpy(plibs + 9, plibs + 5, 2);
+ memcpy(plibs + 6, plibs + 3, 2);
+ plibs[3] = plibs[14] = ' ';
+ plibs[8] = plibs[11] = '/';
+ if (((short)(plibs[3] - '0') * 10 + (short)(plibs[4] - '0')) < 70)
+ {
+ memcpy(plibs + 4, "20", 2);
+ }
+ else
+ {
+ memcpy(plibs + 4, "19", 2);
+ }
+ return 2;
+ }
+non_std:
+#undef plibs
+ return 1;
+}
+
+void LibRaw::parseLeicaMakernote(int base, int uptag, unsigned MakernoteTagType)
+{
+ int c;
+ uchar ci, cj;
+ unsigned entries, tag, type, len, save;
+ short morder, sorder = order;
+ char buf[10];
+ int LeicaMakernoteSignature = -1;
+ INT64 fsize = ifp->size();
+
+ fread(buf, 1, 10, ifp);
+ if (strncmp(buf, "LEICA", 5))
+ {
+ fseek(ifp, -10, SEEK_CUR);
+ if (uptag == 0x3400)
+ LeicaMakernoteSignature = 0x3400;
+ else
+ LeicaMakernoteSignature = -2; // DMR
+ }
+ else
+ {
+ fseek(ifp, -2, SEEK_CUR);
+ LeicaMakernoteSignature = ((uchar)buf[6] << 8) | (uchar)buf[7];
+ // printf ("LeicaMakernoteSignature 0x%04x\n", LeicaMakernoteSignature);
+ if (!LeicaMakernoteSignature &&
+ (!strncmp(model, "M8", 2) || !strncmp(model + 6, "M8", 2)))
+ LeicaMakernoteSignature = -3;
+ if ((LeicaMakernoteSignature != 0x0000) &&
+ (LeicaMakernoteSignature != 0x0200) &&
+ (LeicaMakernoteSignature != 0x0800) &&
+ (LeicaMakernoteSignature != 0x0900) &&
+ (LeicaMakernoteSignature != 0x02ff))
+ base = ftell(ifp) - 8;
+ }
+ setLeicaBodyFeatures(LeicaMakernoteSignature);
+
+ entries = get2();
+ if (entries > 1000)
+ return;
+ morder = order;
+
+ while (entries--)
+ {
+ order = morder;
+ tiff_get(base, &tag, &type, &len, &save);
+
+ INT64 pos = ifp->tell();
+ if (len > 8 && pos + len > 2 * fsize)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+ tag |= uptag << 16;
+ if (len > 100 * 1024 * 1024)
+ goto next; // 100Mb tag? No!
+
+ if (LeicaMakernoteSignature == -3) // M8
+ {
+ if (tag == 0x0310)
+ {
+ parseLeicaLensID();
+ }
+ else if ((tag == 0x0313) && (fabs(ilm.CurAp) < 0.17f))
+ {
+ ilm.CurAp = getreal(type);
+ if (ilm.CurAp > 126.3)
+ {
+ ilm.CurAp = 0.0f;
+ } else if (fabs(aperture) < 0.17f)
+ aperture = ilm.CurAp;
+ }
+ else if (tag == 0x0320)
+ {
+ imCommon.CameraTemperature = getreal(type);
+ }
+ }
+ else if (LeicaMakernoteSignature == -2) // DMR
+ {
+ if (tag == 0x000d)
+ {
+ FORC3 cam_mul[c] = get2();
+ cam_mul[3] = cam_mul[1];
+ }
+ }
+ else if (LeicaMakernoteSignature == 0) // "DIGILUX 2"
+ {
+ if (tag == 0x0007)
+ {
+ imgdata.shootinginfo.FocusMode = get2();
+ }
+ else if (tag == 0x001a)
+ {
+ imgdata.shootinginfo.ImageStabilization = get2();
+ }
+ }
+ else if ((LeicaMakernoteSignature == 0x0100) || // X1
+ (LeicaMakernoteSignature == 0x0400) || // "X VARIO"
+ (LeicaMakernoteSignature == 0x0500) || // X2, "X-E (Typ 102)"
+ (LeicaMakernoteSignature == 0x0700) || // "X (Typ 113)"
+ (LeicaMakernoteSignature == 0x1000)) // "X-U (Typ 113)"
+ {
+ if (tag == 0x040d)
+ {
+ ci = fgetc(ifp);
+ cj = fgetc(ifp);
+ imgdata.shootinginfo.ExposureMode = ((ushort)ci << 8) | cj;
+ }
+ }
+ else if ((LeicaMakernoteSignature == 0x0600) || // TL, "T (Typ 701)"
+ (LeicaMakernoteSignature == 0x1a00)) // TL2
+ {
+ if (tag == 0x040d)
+ {
+ ci = fgetc(ifp);
+ cj = fgetc(ifp);
+ imgdata.shootinginfo.ExposureMode = ((ushort)ci << 8) | cj;
+ }
+ else if (tag == 0x0303)
+ {
+ parseLeicaLensName(len);
+ }
+ }
+ else if (LeicaMakernoteSignature == 0x0200) // M10, M10-D, M10-R, "S (Typ 007)", M11
+ {
+ if ((tag == 0x035a) && (fabs(ilm.CurAp) < 0.17f))
+ {
+ ilm.CurAp = get4() / 1000.0f;
+ if (ilm.CurAp > 126.3)
+ {
+ ilm.CurAp = 0.0f;
+ } else if (fabs(aperture) < 0.17f)
+ aperture = ilm.CurAp;
+ }
+ }
+ else if (LeicaMakernoteSignature == 0x02ff)
+ // "M (Typ 240)", "M (Typ 262)", "M-D (Typ 262)"
+ // "M Monochrom (Typ 246)"
+ // "S (Typ 006)", "S-E (Typ 006)", S2, S3
+ {
+ if (tag == 0x0303)
+ {
+ if (parseLeicaLensName(len))
+ {
+ ilm.LensMount = ilm.CameraMount;
+ ilm.LensFormat = ilm.CameraFormat;
+ }
+ }
+ }
+ else if (LeicaMakernoteSignature == 0x0300) // M9, "M9 Monochrom", "M Monochrom", M-E
+ {
+ if (tag == 0x3400)
+ {
+ parseLeicaMakernote(base, 0x3400, MakernoteTagType);
+ }
+ }
+ else if ((LeicaMakernoteSignature == 0x0800) || // "Q (Typ 116)"
+ (LeicaMakernoteSignature == 0x0900)) // SL2, "SL2-S", "SL (Typ 601)",
+ // CL, Q2, "Q2 MONO"
+ {
+ if ((tag == 0x0304) && (len == 1) && ((c = fgetc(ifp)) != 0) &&
+ (ilm.CameraMount == LIBRAW_MOUNT_LPS_L))
+ {
+ strcpy(ilm.Adapter, "M-Adapter L");
+ ilm.LensMount = LIBRAW_MOUNT_Leica_M;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ if (c != 0xff) ilm.LensID = c * 256;
+ }
+ else if (tag == 0x0500)
+ {
+ parseLeicaInternalBodySerial(len);
+ }
+ }
+ else if (LeicaMakernoteSignature == 0x3400) // tag 0x3400 in M9, "M9 Monochrom", "M Monochrom"
+ {
+ if (tag == 0x34003402)
+ {
+ imCommon.CameraTemperature = getreal(type);
+ }
+ else if (tag == 0x34003405)
+ {
+ parseLeicaLensID();
+ }
+ else if ((tag == 0x34003406) && (fabs(ilm.CurAp) < 0.17f))
+ {
+ ilm.CurAp = getreal(type);
+ if (ilm.CurAp > 126.3)
+ {
+ ilm.CurAp = 0.0f;
+ } else if (fabs(aperture) < 0.17f)
+ aperture = ilm.CurAp;
+ }
+ }
+
+ next:
+ fseek(ifp, save, SEEK_SET);
+ }
+ order = sorder;
+}
diff --git a/libkdcraw/libraw/src/metadata/makernotes.cpp b/libkdcraw/libraw/src/metadata/makernotes.cpp
new file mode 100644
index 0000000..b8ed4d3
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/makernotes.cpp
@@ -0,0 +1,786 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::parseSigmaMakernote (int base, int /*uptag*/, unsigned /*dng_writer*/) {
+unsigned wb_table1 [] = {
+ LIBRAW_WBI_Auto, LIBRAW_WBI_Daylight, LIBRAW_WBI_Shade, LIBRAW_WBI_Cloudy,
+ LIBRAW_WBI_Tungsten, LIBRAW_WBI_Fluorescent, LIBRAW_WBI_Flash,
+ LIBRAW_WBI_Custom, LIBRAW_WBI_Custom1, LIBRAW_WBI_Custom2
+};
+
+ unsigned entries, tag, type, len, save;
+ unsigned i;
+
+ entries = get2();
+ if (entries > 1000)
+ return;
+ while (entries--) {
+ tiff_get(base, &tag, &type, &len, &save);
+ if (tag == 0x0027) {
+ ilm.LensID = get2();
+ } else if (tag == 0x002a) {
+ ilm.MinFocal = getreal(type);
+ ilm.MaxFocal = getreal(type);
+ } else if (tag == 0x002b) {
+ ilm.MaxAp4MinFocal = getreal(type);
+ ilm.MaxAp4MaxFocal = getreal(type);
+ } else if (tag == 0x0120) {
+ const unsigned tblsz = (sizeof wb_table1 / sizeof wb_table1[0]);
+ if ((len >= tblsz) && (len%3 == 0) && len/3 <= tblsz) {
+ for (i=0; i<(len/3); i++) {
+ icWBC[wb_table1[i]][0] = (int)(getreal(type)*10000.0);
+ icWBC[wb_table1[i]][1] = icWBC[wb_table1[i]][3] = (int)(getreal(type)*10000.0);
+ icWBC[wb_table1[i]][2] = (int)(getreal(type)*10000.0);
+ }
+ }
+ }
+ fseek(ifp, save, SEEK_SET);
+ }
+
+ return;
+}
+
+void LibRaw::parse_makernote_0xc634(int base, int uptag, unsigned dng_writer)
+{
+
+ if (metadata_blocks++ > LIBRAW_MAX_METADATA_BLOCKS)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ if (!strncmp(make, "NIKON", 5))
+ {
+ parseNikonMakernote(base, uptag, AdobeDNG);
+ return;
+ }
+ else if (!strncasecmp(make, "LEICA", 5))
+ {
+ parseLeicaMakernote(base, uptag, is_0xc634);
+ return;
+ }
+
+ short morder, sorder = order;
+ char buf[10];
+ INT64 fsize = ifp->size();
+
+ fread(buf, 1, 10, ifp);
+
+ if (!strcmp(buf, "EPSON"))
+ {
+ parseEpsonMakernote(base, uptag, AdobeDNG);
+ return;
+ }
+ else if (!strcmp(buf, "SIGMA"))
+ {
+ parseSigmaMakernote(base, uptag, AdobeDNG);
+ return;
+ }
+
+ unsigned entries, tag, type, len, save, c;
+
+ uchar *CanonCameraInfo = NULL;
+ unsigned lenCanonCameraInfo = 0;
+ unsigned typeCanonCameraInfo = 0;
+
+ uchar *table_buf_0x0116;
+ ushort table_buf_0x0116_len = 0;
+ uchar *table_buf_0x2010;
+ ushort table_buf_0x2010_len = 0;
+ uchar *table_buf_0x9050;
+ ushort table_buf_0x9050_len = 0;
+ uchar *table_buf_0x9400;
+ ushort table_buf_0x9400_len = 0;
+ uchar *table_buf_0x9402;
+ ushort table_buf_0x9402_len = 0;
+ uchar *table_buf_0x9403;
+ ushort table_buf_0x9403_len = 0;
+ uchar *table_buf_0x9406;
+ ushort table_buf_0x9406_len = 0;
+ uchar *table_buf_0x940c;
+ ushort table_buf_0x940c_len = 0;
+ uchar *table_buf_0x940e;
+ ushort table_buf_0x940e_len = 0;
+
+ if (!strcmp(buf, "OLYMPUS") || !strcmp(buf, "PENTAX ") || !strncmp(buf,"OM SYS",6)||
+ (!strncmp(make, "SAMSUNG", 7) && (dng_writer == CameraDNG)))
+ {
+ base = ftell(ifp) - 10;
+ fseek(ifp, -2, SEEK_CUR);
+ order = get2();
+ if (buf[0] == 'O')
+ get2();
+ else if (buf[0] == 'P')
+ is_PentaxRicohMakernotes = 1;
+ }
+ else if (is_PentaxRicohMakernotes && (dng_writer == CameraDNG))
+ {
+ base = ftell(ifp) - 10;
+ fseek(ifp, -4, SEEK_CUR);
+ order = get2();
+ }
+ else if (!strncmp(buf, "SONY", 4) ||
+ !strcmp(buf, "Panasonic"))
+ {
+ order = 0x4949;
+ fseek(ifp, 2, SEEK_CUR);
+ }
+ else if (!strncmp(buf, "FUJIFILM", 8))
+ {
+ base = ftell(ifp) - 10;
+ order = 0x4949;
+ fseek(ifp, 2, SEEK_CUR);
+ }
+ else if (!strcmp(buf, "OLYMP") ||
+ !strcmp(buf, "Ricoh"))
+ {
+ fseek(ifp, -2, SEEK_CUR);
+ }
+ else if (!strcmp(buf, "AOC") || !strcmp(buf, "QVC"))
+ {
+ fseek(ifp, -4, SEEK_CUR);
+ }
+ else
+ {
+ fseek(ifp, -10, SEEK_CUR);
+ if ((!strncmp(make, "SAMSUNG", 7) && (dng_writer == AdobeDNG)))
+ base = ftell(ifp);
+ }
+
+ entries = get2();
+ if (entries > 1000)
+ return;
+
+ if (!strncasecmp(make, "SONY", 4) ||
+ !strncasecmp(make, "Konica", 6) ||
+ !strncasecmp(make, "Minolta", 7) ||
+ (!strncasecmp(make, "Hasselblad", 10) &&
+ (!strncasecmp(model, "Stellar", 7) ||
+ !strncasecmp(model, "Lunar", 5) ||
+ !strncasecmp(model, "Lusso", 5) ||
+ !strncasecmp(model, "HV", 2))))
+ is_Sony = 1;
+
+ if (!is_Olympus &&
+ (!strncmp(make, "OLYMPUS", 7) || !strncmp(make, "OM Digi", 7) ||
+ (!strncasecmp(make, "CLAUSS", 6) && !strncasecmp(model, "piX 5oo", 7)))) {
+ is_Olympus = 1;
+ OlympusDNG_SubDirOffsetValid =
+ strncmp(model, "E-300", 5) && strncmp(model, "E-330", 5) &&
+ strncmp(model, "E-400", 5) && strncmp(model, "E-500", 5) &&
+ strncmp(model, "E-1", 3);
+ }
+
+ morder = order;
+ while (entries--)
+ {
+ order = morder;
+
+ tiff_get(base, &tag, &type, &len, &save);
+
+ INT64 pos = ifp->tell();
+ if (len > 8 && pos + len > 2 * fsize)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+ tag |= uptag << 16;
+ if (len > 100 * 1024 * 1024)
+ goto next; // 100Mb tag? No!
+
+ if (!strncmp(make, "Canon", 5))
+ {
+ if (tag == 0x000d && len < 256000)
+ { // camera info
+ if (!tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ {
+ CanonCameraInfo = (uchar *)malloc(MAX(16, len));
+ fread(CanonCameraInfo, len, 1, ifp);
+ }
+ else
+ {
+ CanonCameraInfo = (uchar *)malloc(MAX(16, len * 4));
+ fread(CanonCameraInfo, len, 4, ifp);
+ }
+ lenCanonCameraInfo = len;
+ typeCanonCameraInfo = type;
+ }
+
+ else if (tag == 0x0010) // Canon ModelID
+ {
+ unique_id = get4();
+ setCanonBodyFeatures(unique_id);
+ if (lenCanonCameraInfo)
+ {
+ processCanonCameraInfo(unique_id, CanonCameraInfo, lenCanonCameraInfo,
+ typeCanonCameraInfo, AdobeDNG);
+ free(CanonCameraInfo);
+ CanonCameraInfo = 0;
+ lenCanonCameraInfo = 0;
+ }
+ }
+
+ else
+ parseCanonMakernotes(tag, type, len, AdobeDNG);
+ }
+
+ else if (!strncmp(make, "FUJI", 4)) {
+ parseFujiMakernotes(tag, type, len, AdobeDNG);
+
+ } else if (!strncasecmp(make, "Hasselblad", 10) && !is_Sony) {
+ if (tag == 0x0011) {
+ imHassy.SensorCode = getint(type);
+ } else if ((tag == 0x0015) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII)) {
+ stmread (imHassy.SensorUnitConnector, len, ifp);
+ for (int i=0; i<(int)len; i++) {
+ if(!isalnum(imHassy.SensorUnitConnector[i]) &&
+ (imHassy.SensorUnitConnector[i]!=' ') &&
+ (imHassy.SensorUnitConnector[i]!='/') &&
+ (imHassy.SensorUnitConnector[i]!='-')) {
+ imHassy.SensorUnitConnector[0] = 0;
+ break;
+ }
+ }
+ } else if (tag == 0x0016) {
+ imHassy.CoatingCode = getint(type);
+ } else if ((tag == 0x002a) &&
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_SRATIONAL) &&
+ (len == 12) &&
+ imHassy.SensorUnitConnector[0]) {
+ FORC4 for (int i = 0; i < 3; i++)
+ imHassy.mnColorMatrix[c][i] = getreal(type);
+
+ } else if ((tag == 0x0031) &&
+ imHassy.SensorUnitConnector[0]) {
+ imHassy.RecommendedCrop[0] = getint(type);
+ imHassy.RecommendedCrop[1] = getint(type);
+ }
+
+ } else if (is_Olympus) {
+
+ if ((tag == 0x2010) || (tag == 0x2020) || (tag == 0x2030) ||
+ (tag == 0x2031) || (tag == 0x2040) || (tag == 0x2050) ||
+ (tag == 0x3000))
+ {
+ fseek(ifp, save - 4, SEEK_SET);
+ fseek(ifp, base + get4(), SEEK_SET);
+ parse_makernote_0xc634(base, tag, dng_writer);
+ }
+
+ if (!OlympusDNG_SubDirOffsetValid &&
+ ((len > 4) ||
+ ((tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) ||
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_SSHORT)) && (len > 2)) ||
+ ((tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG) ||
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_SLONG)) && (len > 1)) ||
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_RATIONAL) ||
+ (type > LIBRAW_EXIFTAG_TYPE_SLONG))) {
+ goto skip_Oly_broken_tags;
+ }
+ else {
+ parseOlympusMakernotes(base, tag, type, len, AdobeDNG);
+ }
+ skip_Oly_broken_tags:;
+ }
+
+ else if (!strncmp(make, "PENTAX", 6) ||
+ !strncmp(model, "PENTAX", 6) ||
+ is_PentaxRicohMakernotes)
+ {
+ parsePentaxMakernotes(base, tag, type, len, dng_writer);
+ }
+ else if (!strncmp(make, "SAMSUNG", 7))
+ {
+ if (dng_writer == AdobeDNG)
+ parseSamsungMakernotes(base, tag, type, len, dng_writer);
+ else
+ parsePentaxMakernotes(base, tag, type, len, dng_writer);
+ }
+ else if (is_Sony)
+ {
+ parseSonyMakernotes(
+ base, tag, type, len, AdobeDNG,
+ table_buf_0x0116, table_buf_0x0116_len,
+ table_buf_0x2010, table_buf_0x2010_len,
+ table_buf_0x9050, table_buf_0x9050_len,
+ table_buf_0x9400, table_buf_0x9400_len,
+ table_buf_0x9402, table_buf_0x9402_len,
+ table_buf_0x9403, table_buf_0x9403_len,
+ table_buf_0x9406, table_buf_0x9406_len,
+ table_buf_0x940c, table_buf_0x940c_len,
+ table_buf_0x940e, table_buf_0x940e_len);
+ }
+ next:
+ fseek(ifp, save, SEEK_SET);
+ }
+
+ order = sorder;
+}
+
+void LibRaw::parse_makernote(int base, int uptag)
+{
+
+ if (metadata_blocks++ > LIBRAW_MAX_METADATA_BLOCKS)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ if (!strncmp(make, "NIKON", 5))
+ {
+ parseNikonMakernote(base, uptag, nonDNG);
+ return;
+ }
+ else if (!strncasecmp(make, "LEICA", 5))
+ {
+ parseLeicaMakernote(base, uptag, is_0x927c);
+ return;
+ }
+
+ if (!strncmp(make, "Nokia", 5))
+ return;
+
+ char buf[10];
+ char another_buf[128];
+
+ fseek(ifp, -12, SEEK_CUR);
+ fread (another_buf, 1, 12, ifp);
+ if (!strncmp(another_buf, "SONY", 4) ||
+ !strncmp(another_buf, "VHAB", 4)) { // Sony branded as Hasselblad
+ is_Sony = 1;
+ }
+
+ fread(buf, 1, 10, ifp);
+
+ if (!strncmp(buf, "KDK", 3) || /* these aren't TIFF tables */
+ !strncmp(buf, "VER", 3) ||
+ !strncmp(buf, "IIII", 4) ||
+ !strncmp(buf, "MMMM", 4))
+ return;
+
+ if (!strcmp(buf, "EPSON"))
+ {
+ parseEpsonMakernote(base, uptag, nonDNG);
+ return;
+ }
+ else if (!strcmp(buf, "SIGMA"))
+ {
+ parseSigmaMakernote(base, uptag, CameraDNG);
+ return;
+ }
+
+
+ unsigned entries, tag, type, len, save, c;
+ unsigned i, wb[4] = {0, 0, 0, 0};
+ short morder, sorder = order;
+
+ uchar *CanonCameraInfo = 0;;
+ unsigned lenCanonCameraInfo = 0;
+ unsigned typeCanonCameraInfo = 0;
+ imCanon.wbi = 0;
+
+ uchar *table_buf_0x0116;
+ ushort table_buf_0x0116_len = 0;
+ uchar *table_buf_0x2010;
+ ushort table_buf_0x2010_len = 0;
+ uchar *table_buf_0x9050;
+ ushort table_buf_0x9050_len = 0;
+ uchar *table_buf_0x9400;
+ ushort table_buf_0x9400_len = 0;
+ uchar *table_buf_0x9402;
+ ushort table_buf_0x9402_len = 0;
+ uchar *table_buf_0x9403;
+ ushort table_buf_0x9403_len = 0;
+ uchar *table_buf_0x9406;
+ ushort table_buf_0x9406_len = 0;
+ uchar *table_buf_0x940c;
+ ushort table_buf_0x940c_len = 0;
+ uchar *table_buf_0x940e;
+ ushort table_buf_0x940e_len = 0;
+
+ INT64 fsize = ifp->size();
+
+ /*
+ The MakerNote might have its own TIFF header (possibly with
+ its own byte-order!), or it might just be a table.
+ */
+
+ if (!strncmp(buf, "KC", 2) || /* Konica KD-400Z, KD-510Z */
+ !strncmp(buf, "MLY", 3)) /* Minolta DiMAGE G series */
+ {
+ order = 0x4d4d;
+ while ((i = ftell(ifp)) < data_offset && i < 16384)
+ {
+ wb[0] = wb[2];
+ wb[2] = wb[1];
+ wb[1] = wb[3];
+ if (feof(ifp))
+ break;
+ wb[3] = get2();
+ if (wb[1] == 256 && wb[3] == 256 && wb[0] > 256 && wb[0] < 640 &&
+ wb[2] > 256 && wb[2] < 640)
+ FORC4 cam_mul[c] = wb[c];
+ }
+ goto quit;
+ }
+
+ if (!strcmp(buf, "OLYMPUS") || !strncmp(buf, "OM SYS",6) ||
+ !strcmp(buf, "PENTAX "))
+ {
+ base = ftell(ifp) - 10;
+ fseek(ifp, -2, SEEK_CUR);
+ if (buf[1] == 'M')
+ get4();
+ order = get2();
+ if (buf[0] == 'O')
+ get2();
+ }
+ else if (!strncmp(buf, "SONY", 4) || // DSLR-A100
+ !strcmp(buf, "Panasonic")) {
+ if (buf[0] == 'S')
+ is_Sony = 1;
+ goto nf;
+ }
+ else if (!strncmp(buf, "FUJIFILM", 8))
+ {
+ base = ftell(ifp) - 10;
+ nf:
+ order = 0x4949;
+ fseek(ifp, 2, SEEK_CUR);
+ }
+ else if (!strcmp (buf, "OLYMP") ||
+ !strncmp(buf, "LEICA", 5) ||
+ !strcmp (buf, "Ricoh"))
+ {
+ fseek(ifp, -2, SEEK_CUR);
+ }
+ else if (!strcmp(buf, "AOC") || // Pentax, tribute to Asahi Optical Co.
+ !strcmp(buf, "QVC")) // Casio, from "QV-Camera"
+ {
+ fseek(ifp, -4, SEEK_CUR);
+ }
+ else if (!strncmp(buf, "CMT3", 4))
+ {
+ order = sget2((uchar *)(buf + 4));
+ fseek(ifp, 2L, SEEK_CUR);
+ }
+ else if (libraw_internal_data.unpacker_data.CR3_CTMDtag)
+ {
+ order = sget2((uchar *)buf);
+ fseek(ifp, -2L, SEEK_CUR);
+ }
+ else
+ {
+ fseek(ifp, -10, SEEK_CUR);
+ if (!strncmp(make, "SAMSUNG", 7))
+ base = ftell(ifp);
+ }
+
+ if (!is_Olympus &&
+ (!strncasecmp(make, "Olympus", 7) || !strncmp(make, "OM Digi", 7) ||
+ (!strncasecmp(make, "CLAUSS", 6) && !strncasecmp(model, "piX 5oo", 7)))) {
+ is_Olympus = 1;
+ }
+
+ if (!is_Sony &&
+ (!strncasecmp(make, "SONY", 4) ||
+ !strncasecmp(make, "Konica", 6) ||
+ !strncasecmp(make, "Minolta", 7) ||
+ (!strncasecmp(make, "Hasselblad", 10) &&
+ (!strncasecmp(model, "Stellar", 7) ||
+ !strncasecmp(model, "Lunar", 5) ||
+ !strncasecmp(model, "Lusso", 5) ||
+ !strncasecmp(model, "HV", 2))))) {
+ is_Sony = 1;
+ }
+
+ if (strcasestr(make, "Kodak") &&
+ (sget2((uchar *)buf) > 1) && // check number of entries
+ (sget2((uchar *)buf) < 128) &&
+ (sget2((uchar *)(buf + 4)) > 0) && // check type
+ (sget2((uchar *)(buf + 4)) < 13) &&
+ (sget4((uchar *)(buf + 6)) < 256) // check count
+ )
+ imKodak.MakerNoteKodak8a = 1; // Kodak P712 / P850 / P880
+
+ entries = get2();
+ if (entries > 1000)
+ return;
+
+ morder = order;
+ while (entries--)
+ {
+ order = morder;
+ tiff_get(base, &tag, &type, &len, &save);
+ tag |= uptag << 16;
+
+ INT64 _pos = ftell(ifp);
+ if (len > 100 * 1024 * 1024)
+ goto next; // 100Mb tag? No!
+ if (len > 8 && _pos + len > 2 * fsize)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+ if (imKodak.MakerNoteKodak8a)
+ {
+ if ((tag == 0xff00) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG) && (len == 1))
+ {
+ INT64 _pos1 = get4();
+ if ((_pos1 < fsize) && (_pos1 > 0))
+ {
+ fseek(ifp, _pos1, SEEK_SET);
+ parse_makernote(base, tag);
+ }
+ }
+ else if (tag == 0xff00f90b)
+ {
+ imKodak.clipBlack = get2();
+ }
+ else if (tag == 0xff00f90c)
+ {
+ imKodak.clipWhite = imgdata.color.linear_max[0] =
+ imgdata.color.linear_max[1] = imgdata.color.linear_max[2] =
+ imgdata.color.linear_max[3] = get2();
+ }
+ }
+ else if (!strncmp(make, "Canon", 5))
+ {
+ if (tag == 0x000d && len < 256000) // camera info
+ {
+ if (!tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ {
+ CanonCameraInfo = (uchar *)malloc(MAX(16, len));
+ fread(CanonCameraInfo, len, 1, ifp);
+ }
+ else
+ {
+ CanonCameraInfo = (uchar *)malloc(MAX(16, len * 4));
+ fread(CanonCameraInfo, len, 4, ifp);
+ }
+ lenCanonCameraInfo = len;
+ typeCanonCameraInfo = type;
+ }
+
+ else if (tag == 0x0010) // Canon ModelID
+ {
+ unique_id = get4();
+ setCanonBodyFeatures(unique_id);
+ if (lenCanonCameraInfo)
+ {
+ processCanonCameraInfo(unique_id, CanonCameraInfo, lenCanonCameraInfo,
+ typeCanonCameraInfo, nonDNG);
+ if(CanonCameraInfo)
+ free(CanonCameraInfo);
+ CanonCameraInfo = 0;
+ lenCanonCameraInfo = 0;
+ }
+ }
+
+ else
+ parseCanonMakernotes(tag, type, len, nonDNG);
+ }
+
+ else if (!strncmp(make, "FUJI", 4))
+ parseFujiMakernotes(tag, type, len, nonDNG);
+
+ else if (!strncasecmp(model, "Hasselblad X1D", 14) ||
+ !strncasecmp(model, "Hasselblad H6D", 14) ||
+ !strncasecmp(model, "Hasselblad A6D", 14))
+ {
+ if (tag == 0x0045)
+ {
+ imHassy.BaseISO = get4();
+ }
+ else if (tag == 0x0046)
+ {
+ imHassy.Gain = getreal(type);
+ }
+ }
+
+ else if (!strncmp(make, "PENTAX", 6) ||
+ !strncmp(make, "RICOH", 5) ||
+ !strncmp(model, "PENTAX", 6))
+ {
+ if (!strncmp(model, "GR", 2) ||
+ !strncmp(model, "GXR", 3))
+ {
+ parseRicohMakernotes(base, tag, type, len, CameraDNG);
+ }
+ else
+ {
+ parsePentaxMakernotes(base, tag, type, len, nonDNG);
+ }
+ }
+
+ else if (!strncmp(make, "SAMSUNG", 7))
+ {
+ if (!dng_version)
+ parseSamsungMakernotes(base, tag, type, len, nonDNG);
+ else
+ parsePentaxMakernotes(base, tag, type, len, CameraDNG);
+ }
+
+ else if (is_Sony)
+ {
+ if ((tag == 0xb028) && (len == 1) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG)) // DSLR-A100
+ {
+ if ((c = get4()))
+ {
+ fseek(ifp, c, SEEK_SET);
+ parse_makernote(base, tag);
+ }
+ }
+ else
+ {
+ parseSonyMakernotes(
+ base, tag, type, len, nonDNG,
+ table_buf_0x0116, table_buf_0x0116_len,
+ table_buf_0x2010, table_buf_0x2010_len,
+ table_buf_0x9050, table_buf_0x9050_len,
+ table_buf_0x9400, table_buf_0x9400_len,
+ table_buf_0x9402, table_buf_0x9402_len,
+ table_buf_0x9403, table_buf_0x9403_len,
+ table_buf_0x9406, table_buf_0x9406_len,
+ table_buf_0x940c, table_buf_0x940c_len,
+ table_buf_0x940e, table_buf_0x940e_len);
+ }
+ }
+ fseek(ifp, _pos, SEEK_SET);
+
+ if (!strncasecmp(make, "Hasselblad", 10) && !is_Sony) {
+ if (tag == 0x0011)
+ imHassy.SensorCode = getint(type);
+ else if (tag == 0x0016)
+ imHassy.CoatingCode = getint(type);
+ else if ((tag == 0x002a) &&
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_SRATIONAL) &&
+ (len == 12)) {
+ FORC4 for (int ii = 0; ii < 3; ii++)
+ imHassy.mnColorMatrix[c][ii] = getreal(type);
+
+ } else if (tag == 0x0031) {
+ imHassy.RecommendedCrop[0] = getint(type);
+ imHassy.RecommendedCrop[1] = getint(type);
+ }
+ }
+
+ if ((tag == 0x0004 || tag == 0x0114) && !strncmp(make, "KONICA", 6))
+ {
+ fseek(ifp, tag == 0x0004 ? 140 : 160, SEEK_CUR);
+ switch (get2())
+ {
+ case 72:
+ flip = 0;
+ break;
+ case 76:
+ flip = 6;
+ break;
+ case 82:
+ flip = 5;
+ break;
+ }
+ }
+
+ if (is_Olympus) {
+ INT64 _pos2 = ftell(ifp);
+ if ((tag == 0x2010) || (tag == 0x2020) || (tag == 0x2030) ||
+ (tag == 0x2031) || (tag == 0x2040) || (tag == 0x2050) ||
+ (tag == 0x3000))
+ {
+ if (tagtypeIs(LIBRAW_EXIFTOOLTAGTYPE_binary)) {
+ parse_makernote(base, tag);
+
+ } else if (tagtypeIs(LIBRAW_EXIFTOOLTAGTYPE_ifd) ||
+ tagtypeIs(LIBRAW_EXIFTOOLTAGTYPE_int32u)) {
+ fseek(ifp, base + get4(), SEEK_SET);
+ parse_makernote(base, tag);
+ }
+
+ } else {
+ parseOlympusMakernotes(base, tag, type, len, nonDNG);
+ }
+ fseek(ifp, _pos2, SEEK_SET);
+ }
+
+ if ((tag == 0x0015) &&
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII) &&
+ is_raw)
+ { // Hasselblad
+ stmread (imHassy.SensorUnitConnector, len, ifp);
+ }
+
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_UNDEFINED) &&
+ ((tag == 0x0081) || // Minolta
+ (tag == 0x0100))) // Olympus
+ {
+ thumb_offset = ftell(ifp);
+ thumb_length = len;
+ }
+ if ((tag == 0x0088) && // Minolta, possibly Olympus too
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG) &&
+ (thumb_offset = get4()))
+ thumb_offset += base;
+
+ if ((tag == 0x0089) && // Minolta, possibly Olympus too
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ thumb_length = get4();
+
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_UNDEFINED) && // Nikon
+ ((tag == 0x008c) ||
+ (tag == 0x0096))) {
+ meta_offset = ftell(ifp);
+ }
+
+ if ((tag == 0x00a1) &&
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_UNDEFINED) &&
+ strncasecmp(make, "Samsung", 7))
+ {
+ order = 0x4949;
+ fseek(ifp, 140, SEEK_CUR);
+ FORC3 cam_mul[c] = get4();
+ }
+
+ if (tag == 0xb001 && tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT)) // Sony ModelID
+ {
+ unique_id = get2();
+ }
+ if (tag == 0x0200 && len == 3) // Olympus
+ shot_order = (get4(), get4());
+
+ if (tag == 0x0f00 && tagtypeIs(LIBRAW_EXIFTAG_TYPE_UNDEFINED))
+ {
+ if (len == 614)
+ fseek(ifp, 176, SEEK_CUR);
+ else if (len == 734 || len == 1502) // Kodak, Minolta, Olympus
+ fseek(ifp, 148, SEEK_CUR);
+ else
+ goto next;
+ goto get2_256;
+ }
+
+ if (tag == 0x2011 && len == 2) // Casio
+ {
+ get2_256:
+ order = 0x4d4d;
+ cam_mul[0] = get2() / 256.0;
+ cam_mul[2] = get2() / 256.0;
+ }
+
+ next:
+ fseek(ifp, save, SEEK_SET);
+ }
+quit:
+ order = sorder;
+}
diff --git a/libkdcraw/libraw/src/metadata/mediumformat.cpp b/libkdcraw/libraw/src/metadata/mediumformat.cpp
new file mode 100644
index 0000000..6bb8705
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/mediumformat.cpp
@@ -0,0 +1,521 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::parse_phase_one(int base)
+{
+ unsigned entries, tag, type, len, data, i, c;
+ INT64 save;
+ float romm_cam[3][3];
+ char *cp;
+
+ memset(&ph1, 0, sizeof ph1);
+ fseek(ifp, base, SEEK_SET);
+ order = get4() & 0xffff;
+ if (get4() >> 8 != 0x526177)
+ return; /* "Raw" */
+ unsigned offset = get4();
+ if (offset == 0xbad0bad)
+ return;
+ fseek(ifp, offset + base, SEEK_SET);
+ entries = get4();
+ if (entries > 8192)
+ return; // too much??
+ get4();
+ while (entries--)
+ {
+ tag = get4();
+ type = get4();
+ len = get4();
+ if (feof(ifp))
+ break;
+ data = get4();
+ save = ftell(ifp);
+ bool do_seek = (tag < 0x0108 || tag > 0x0110); // to make it single rule, not copy-paste
+ if(do_seek)
+ fseek(ifp, base + data, SEEK_SET);
+ switch (tag)
+ {
+
+ case 0x0100:
+ flip = "0653"[data & 3] - '0';
+ break;
+ case 0x0102:
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ if ((imgdata.shootinginfo.BodySerial[0] == 0x4c) && (imgdata.shootinginfo.BodySerial[1] == 0x49))
+ {
+ unique_id =
+ (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[2] & 0x3f)) - 0x41;
+ }
+ else
+ {
+ unique_id =
+ (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[1] & 0x3f)) - 0x41;
+ }
+ setPhaseOneFeatures(unique_id);
+ break;
+ case 0x0106:
+ for (i = 0; i < 9; i++)
+ imgdata.color.P1_color[0].romm_cam[i] = ((float *)romm_cam)[i] =
+ (float)getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ romm_coeff(romm_cam);
+ break;
+ case 0x0107:
+ FORC3 cam_mul[c] = (float)getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ break;
+ case 0x0108:
+ raw_width = data;
+ break;
+ case 0x0109:
+ raw_height = data;
+ break;
+ case 0x010a:
+ left_margin = data;
+ break;
+ case 0x010b:
+ top_margin = data;
+ break;
+ case 0x010c:
+ width = data;
+ break;
+ case 0x010d:
+ height = data;
+ break;
+ case 0x010e:
+ ph1.format = data;
+ break;
+ case 0x010f:
+ data_offset = data + base;
+ data_size = len;
+ break;
+ case 0x0110:
+ meta_offset = data + base;
+ meta_length = len;
+ break;
+ case 0x0112:
+ ph1.key_off = int(save - 4);
+ break;
+ case 0x0203:
+ stmread(imPhaseOne.Software, len, ifp);
+ case 0x0204:
+ stmread(imPhaseOne.SystemType, len, ifp);
+ case 0x0210:
+ ph1.tag_210 = int_to_float(data);
+ imCommon.SensorTemperature = ph1.tag_210;
+ break;
+ case 0x0211:
+ imCommon.SensorTemperature2 = int_to_float(data);
+ break;
+ case 0x021a:
+ ph1.tag_21a = data;
+ break;
+ case 0x021c:
+ strip_offset = data + base;
+ break;
+ case 0x021d:
+ ph1.t_black = data;
+ break;
+ case 0x0222:
+ ph1.split_col = data;
+ break;
+ case 0x0223:
+ ph1.black_col = data + base;
+ break;
+ case 0x0224:
+ ph1.split_row = data;
+ break;
+ case 0x0225:
+ ph1.black_row = data + base;
+ break;
+ case 0x0226:
+ for (i = 0; i < 9; i++)
+ imgdata.color.P1_color[1].romm_cam[i] = (float)getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ break;
+ case 0x0301:
+ model[63] = 0;
+ fread(imPhaseOne.FirmwareString, 1, 255, ifp);
+ imPhaseOne.FirmwareString[255] = 0;
+ memcpy(model, imPhaseOne.FirmwareString, 63);
+ model[63] = 0;
+ if ((cp = strstr(model, " camera")))
+ *cp = 0;
+ else if ((cp = strchr(model, ',')))
+ *cp = 0;
+ /* minus and the letter after it are not always present
+ if present, last letter means:
+ C : Contax 645AF
+ H : Hasselblad H1 / H2
+ M : Mamiya
+ V : Hasselblad 555ELD / 553ELX / 503CW / 501CM; not included below
+ because of adapter conflicts (Mamiya RZ body) if not present, Phase One
+ 645 AF, Mamiya 645AFD Series, or anything
+ */
+ strcpy(imPhaseOne.SystemModel, model);
+ if ((cp = strchr(model, '-')))
+ {
+ if (cp[1] == 'C')
+ {
+ strcpy(ilm.body, "Contax 645AF");
+ ilm.CameraMount = LIBRAW_MOUNT_Contax645;
+ ilm.CameraFormat = LIBRAW_FORMAT_645;
+ }
+ else if (cp[1] == 'M')
+ {
+ strcpy(ilm.body, "Mamiya 645");
+ ilm.CameraMount = LIBRAW_MOUNT_Mamiya645;
+ ilm.CameraFormat = LIBRAW_FORMAT_645;
+ }
+ else if (cp[1] == 'H')
+ {
+ strcpy(ilm.body, "Hasselblad H1/H2");
+ ilm.CameraMount = LIBRAW_MOUNT_Hasselblad_H;
+ ilm.CameraFormat = LIBRAW_FORMAT_645;
+ }
+ *cp = 0;
+ }
+ case 0x0401:
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ ilm.CurAp = libraw_powf64l(2.0f, (int_to_float(data) / 2.0f));
+ else
+ ilm.CurAp = libraw_powf64l(2.0f, float(getreal(type) / 2.0f));
+ break;
+ case 0x0403:
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ ilm.CurFocal = int_to_float(data);
+ else
+ ilm.CurFocal = (float)getreal(type);
+ break;
+ case 0x0410:
+ stmread(ilm.body, len, ifp);
+ if (((unsigned char)ilm.body[0]) == 0xff)
+ ilm.body[0] = 0;
+ break;
+ case 0x0412:
+ stmread(ilm.Lens, len, ifp);
+ if (((unsigned char)ilm.Lens[0]) == 0xff)
+ ilm.Lens[0] = 0;
+ break;
+ case 0x0414:
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ {
+ ilm.MaxAp4CurFocal = libraw_powf64l(2.0f, (int_to_float(data) / 2.0f));
+ }
+ else
+ {
+ ilm.MaxAp4CurFocal = libraw_powf64l(2.0f, float(getreal(type) / 2.0f));
+ }
+ break;
+ case 0x0415:
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ {
+ ilm.MinAp4CurFocal = libraw_powf64l(2.0f, (int_to_float(data) / 2.0f));
+ }
+ else
+ {
+ ilm.MinAp4CurFocal = libraw_powf64l(2.0f, float(getreal(type) / 2.0f));
+ }
+ break;
+ case 0x0416:
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ {
+ ilm.MinFocal = int_to_float(data);
+ }
+ else
+ {
+ ilm.MinFocal = (float)getreal(type);
+ }
+ if (ilm.MinFocal > 1000.0f)
+ {
+ ilm.MinFocal = 0.0f;
+ }
+ break;
+ case 0x0417:
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ {
+ ilm.MaxFocal = int_to_float(data);
+ }
+ else
+ {
+ ilm.MaxFocal = (float)getreal(type);
+ }
+ break;
+ }
+ if (do_seek)
+ fseek(ifp, save, SEEK_SET);
+ }
+
+ if (!ilm.body[0] && !imgdata.shootinginfo.BodySerial[0])
+ {
+ fseek(ifp, meta_offset, SEEK_SET);
+ order = get2();
+ fseek(ifp, 6, SEEK_CUR);
+ fseek(ifp, meta_offset + get4(), SEEK_SET);
+ entries = get4();
+ if (entries > 8192)
+ return; // too much??
+ get4();
+ while (entries--)
+ {
+ tag = get4();
+ len = get4();
+ if (feof(ifp))
+ break;
+ data = get4();
+ save = ftell(ifp);
+ fseek(ifp, meta_offset + data, SEEK_SET);
+ if (tag == 0x0407)
+ {
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ if ((imgdata.shootinginfo.BodySerial[0] == 0x4c) &&
+ (imgdata.shootinginfo.BodySerial[1] == 0x49))
+ {
+ unique_id = (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) |
+ (imgdata.shootinginfo.BodySerial[2] & 0x3f)) -
+ 0x41;
+ }
+ else
+ {
+ unique_id = (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) |
+ (imgdata.shootinginfo.BodySerial[1] & 0x3f)) -
+ 0x41;
+ }
+ setPhaseOneFeatures(unique_id);
+ }
+ fseek(ifp, save, SEEK_SET);
+ }
+ }
+
+ if ((ilm.MaxAp4CurFocal > 0.7f) &&
+ (ilm.MinAp4CurFocal > 0.7f)) {
+ float MinAp4CurFocal = MAX(ilm.MaxAp4CurFocal,ilm.MinAp4CurFocal);
+ ilm.MaxAp4CurFocal = MIN(ilm.MaxAp4CurFocal,ilm.MinAp4CurFocal);
+ ilm.MinAp4CurFocal = MinAp4CurFocal;
+ }
+
+ if (ph1.format == 6)
+ load_raw = &LibRaw::phase_one_load_raw_s;
+ else
+ load_raw = ph1.format < 3 ? &LibRaw::phase_one_load_raw : &LibRaw::phase_one_load_raw_c;
+ maximum = 0xffff; // Always scaled to 16bit?
+ strcpy(make, "Phase One");
+ if (model[0])
+ return;
+ switch (raw_height)
+ {
+ case 2060:
+ strcpy(model, "LightPhase");
+ break;
+ case 2682:
+ strcpy(model, "H 10");
+ break;
+ case 4128:
+ strcpy(model, "H 20");
+ break;
+ case 5488:
+ strcpy(model, "H 25");
+ break;
+ }
+}
+
+void LibRaw::parse_mos(INT64 offset)
+{
+ char data[40];
+ int i, c, neut[4], planes = 0, frot = 0;
+ INT64 from;
+ unsigned skip;
+ static const char *mod[] = {
+ /* DM22, DM28, DM40, DM56 are somewhere here too */
+ "", // 0
+ "DCB2", // 1
+ "Volare", // 2
+ "Cantare", // 3
+ "CMost", // 4
+ "Valeo 6", // 5
+ "Valeo 11", // 6
+ "Valeo 22", // 7
+ "Valeo 11p", // 8
+ "Valeo 17", // 9
+ "", // 10
+ "Aptus 17", // 11
+ "Aptus 22", // 12
+ "Aptus 75", // 13
+ "Aptus 65", // 14
+ "Aptus 54S", // 15
+ "Aptus 65S", // 16
+ "Aptus 75S", // 17
+ "AFi 5", // 18
+ "AFi 6", // 19
+ "AFi 7", // 20
+ "AFi-II 7", // 21
+ "Aptus-II 7", // 22 (same CMs as Mamiya DM33)
+ "", // 23
+ "Aptus-II 6", // 24 (same CMs as Mamiya DM28)
+ "AFi-II 10", // 25
+ "", // 26
+ "Aptus-II 10", // 27 (same CMs as Mamiya DM56)
+ "Aptus-II 5", // 28 (same CMs as Mamiya DM22)
+ "", // 29
+ "DM33", // 30, make is Mamiya
+ "", // 31
+ "", // 32
+ "Aptus-II 10R", // 33
+ "Aptus-II 8", // 34 (same CMs as Mamiya DM40)
+ "", // 35
+ "Aptus-II 12", // 36
+ "", // 37
+ "AFi-II 12" // 38
+ };
+ float romm_cam[3][3];
+
+ fseek(ifp, offset, SEEK_SET);
+ while (!feof(ifp))
+ {
+ if (get4() != 0x504b5453)
+ break;
+ get4();
+ fread(data, 1, 40, ifp);
+ skip = get4();
+ from = ftell(ifp);
+
+ if (!strcmp(data, "CameraObj_camera_type"))
+ {
+ stmread(ilm.body, (unsigned)skip, ifp);
+ if (ilm.body[0])
+ {
+ if (!strncmp(ilm.body, "Mamiya R", 8))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Mamiya67;
+ ilm.CameraFormat = LIBRAW_FORMAT_67;
+ }
+ else if (!strncmp(ilm.body, "Hasselblad 5", 12))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_66;
+ ilm.CameraMount = LIBRAW_MOUNT_Hasselblad_V;
+ }
+ else if (!strncmp(ilm.body, "Hasselblad H", 12))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Hasselblad_H;
+ ilm.CameraFormat = LIBRAW_FORMAT_645;
+ }
+ else if (!strncmp(ilm.body, "Mamiya 6", 8) ||
+ !strncmp(ilm.body, "Phase One 6", 11))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Mamiya645;
+ ilm.CameraFormat = LIBRAW_FORMAT_645;
+ }
+ else if (!strncmp(ilm.body, "Large F", 7))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_LF;
+ ilm.CameraFormat = LIBRAW_FORMAT_LF;
+ }
+ else if (!strncmp(model, "Leaf AFi", 8))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Rollei_bayonet;
+ ilm.CameraFormat = LIBRAW_FORMAT_66;
+ }
+ }
+ }
+ if (!strcmp(data, "back_serial_number"))
+ {
+ char buffer[sizeof(imgdata.shootinginfo.BodySerial)];
+ char *words[4] = {0, 0, 0, 0};
+ stmread(buffer, (unsigned)skip, ifp);
+ /*nwords = */
+ getwords(buffer, words, 4, sizeof(imgdata.shootinginfo.BodySerial));
+ if(words[0])
+ strcpy(imgdata.shootinginfo.BodySerial, words[0]);
+ }
+ if (!strcmp(data, "CaptProf_serial_number"))
+ {
+ char buffer[sizeof(imgdata.shootinginfo.InternalBodySerial)];
+ char *words[4] = {0, 0, 0, 0};
+ stmread(buffer, (unsigned)skip, ifp);
+ getwords(buffer, words, 4, sizeof(imgdata.shootinginfo.InternalBodySerial));
+ if(words[0])
+ strcpy(imgdata.shootinginfo.InternalBodySerial, words[0]);
+ }
+
+ if (!strcmp(data, "JPEG_preview_data"))
+ {
+ thumb_offset = from;
+ thumb_length = skip;
+ }
+ if (!strcmp(data, "icc_camera_profile"))
+ {
+ profile_offset = from;
+ profile_length = skip;
+ }
+ if (!strcmp(data, "ShootObj_back_type"))
+ {
+ fscanf(ifp, "%d", &i);
+ if ((unsigned)i < sizeof mod / sizeof(*mod))
+ {
+ strcpy(model, mod[i]);
+ if (!strncmp(model, "AFi", 3))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Rollei_bayonet;
+ ilm.CameraFormat = LIBRAW_FORMAT_66;
+ }
+ ilm.CamID = i;
+ }
+ }
+ if (!strcmp(data, "icc_camera_to_tone_matrix"))
+ {
+ for (i = 0; i < 9; i++)
+ ((float *)romm_cam)[i] = int_to_float(get4());
+ romm_coeff(romm_cam);
+ }
+ if (!strcmp(data, "CaptProf_color_matrix"))
+ {
+ for (i = 0; i < 9; i++)
+ fscanf(ifp, "%f", (float *)romm_cam + i);
+ romm_coeff(romm_cam);
+ }
+ if (!strcmp(data, "CaptProf_number_of_planes"))
+ fscanf(ifp, "%d", &planes);
+ if (!strcmp(data, "CaptProf_raw_data_rotation"))
+ fscanf(ifp, "%d", &flip);
+ if (!strcmp(data, "CaptProf_mosaic_pattern"))
+ FORC4
+ {
+ fscanf(ifp, "%d", &i);
+ if (i == 1)
+ frot = c ^ (c >> 1); // 0123 -> 0132
+ }
+ if (!strcmp(data, "ImgProf_rotation_angle"))
+ {
+ fscanf(ifp, "%d", &i);
+ flip = i - flip;
+ }
+ if (!strcmp(data, "NeutObj_neutrals") && !cam_mul[0])
+ {
+ FORC4 fscanf(ifp, "%d", neut + c);
+ FORC3
+ if (neut[c + 1])
+ cam_mul[c] = (float)neut[0] / neut[c + 1];
+ }
+ if (!strcmp(data, "Rows_data"))
+ load_flags = get4();
+ parse_mos(from);
+ fseek(ifp, skip + from, SEEK_SET);
+ }
+ if (planes)
+ filters = (planes == 1) * 0x01010101U *
+ (uchar) "\x94\x61\x16\x49"[(flip / 90 + frot) & 3];
+}
diff --git a/libkdcraw/libraw/src/metadata/minolta.cpp b/libkdcraw/libraw/src/metadata/minolta.cpp
new file mode 100644
index 0000000..c822433
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/minolta.cpp
@@ -0,0 +1,110 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::parse_minolta(int base)
+{
+ int tag, len, offset, high = 0, wide = 0, i, c;
+ short sorder = order;
+ INT64 save;
+
+ fseek(ifp, base, SEEK_SET);
+ if (fgetc(ifp) || fgetc(ifp) - 'M' || fgetc(ifp) - 'R')
+ return;
+ order = fgetc(ifp) * 0x101;
+ offset = base + get4() + 8;
+ INT64 fsize = ifp->size();
+ if (offset > fsize - 8) // At least 8 bytes for tag/len
+ offset = fsize - 8;
+
+ while ((save = ftell(ifp)) < offset)
+ {
+ for (tag = i = 0; i < 4; i++)
+ tag = tag << 8 | fgetc(ifp);
+ len = get4();
+ if (len < 0)
+ return; // just ignore wrong len?? or raise bad file exception?
+ if ((INT64)len + save + 8LL > fsize)
+ return; // just ignore out of file metadata, stop parse
+ switch (tag)
+ {
+ case 0x505244: /* PRD */
+ fseek(ifp, 8, SEEK_CUR);
+ high = get2();
+ wide = get2();
+ imSony.prd_ImageHeight = get2();
+ imSony.prd_ImageWidth = get2();
+ imSony.prd_Total_bps = (ushort)fgetc(ifp);
+ imSony.prd_Active_bps = (ushort)fgetc(ifp);
+ imSony.prd_StorageMethod = (ushort)fgetc(ifp);
+ fseek(ifp, 4L, SEEK_CUR);
+ imSony.prd_BayerPattern = (ushort)fgetc(ifp);
+ break;
+ case 0x524946: /* RIF */
+ fseek(ifp, 8, SEEK_CUR);
+ icWBC[LIBRAW_WBI_Tungsten][0] = get2();
+ icWBC[LIBRAW_WBI_Tungsten][2] = get2();
+ icWBC[LIBRAW_WBI_Daylight][0] = get2();
+ icWBC[LIBRAW_WBI_Daylight][2] = get2();
+ icWBC[LIBRAW_WBI_Cloudy][0] = get2();
+ icWBC[LIBRAW_WBI_Cloudy][2] = get2();
+ icWBC[LIBRAW_WBI_FL_W][0] = get2();
+ icWBC[LIBRAW_WBI_FL_W][2] = get2();
+ icWBC[LIBRAW_WBI_Flash][0] = get2();
+ icWBC[LIBRAW_WBI_Flash][2] = get2();
+ icWBC[LIBRAW_WBI_Custom][0] = get2();
+ icWBC[LIBRAW_WBI_Custom][2] = get2();
+ icWBC[LIBRAW_WBI_Tungsten][1] = icWBC[LIBRAW_WBI_Tungsten][3] =
+ icWBC[LIBRAW_WBI_Daylight][1] = icWBC[LIBRAW_WBI_Daylight][3] =
+ icWBC[LIBRAW_WBI_Cloudy][1] = icWBC[LIBRAW_WBI_Cloudy][3] =
+ icWBC[LIBRAW_WBI_FL_W][1] = icWBC[LIBRAW_WBI_FL_W][3] =
+ icWBC[LIBRAW_WBI_Flash][1] = icWBC[LIBRAW_WBI_Flash][3] =
+ icWBC[LIBRAW_WBI_Custom][1] = icWBC[LIBRAW_WBI_Custom][3] = 0x100;
+ if (!strncasecmp(model, "DSLR-A100", 9)) {
+ icWBC[LIBRAW_WBI_Shade][0] = get2();
+ icWBC[LIBRAW_WBI_Shade][2] = get2();
+ icWBC[LIBRAW_WBI_FL_D][0] = get2();
+ icWBC[LIBRAW_WBI_FL_D][2] = get2();
+ icWBC[LIBRAW_WBI_FL_N][0] = get2();
+ icWBC[LIBRAW_WBI_FL_N][2] = get2();
+ icWBC[LIBRAW_WBI_FL_WW][0] = get2();
+ icWBC[LIBRAW_WBI_FL_WW][2] = get2();
+ icWBC[LIBRAW_WBI_Shade][1] = icWBC[LIBRAW_WBI_Shade][3] =
+ icWBC[LIBRAW_WBI_FL_D][1] = icWBC[LIBRAW_WBI_FL_D][3] =
+ icWBC[LIBRAW_WBI_FL_N][1] = icWBC[LIBRAW_WBI_FL_N][3] =
+ icWBC[LIBRAW_WBI_FL_WW][1] = icWBC[LIBRAW_WBI_FL_WW][3] = 0x0100;
+ }
+ break;
+ case 0x574247: /* WBG */
+ get4();
+ if (imSony.prd_BayerPattern == LIBRAW_MINOLTA_G2BRG1)
+ FORC4 cam_mul[G2BRG1_2_RGBG(c)] = get2();
+ else
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = get2();
+ break;
+ case 0x545457: /* TTW */
+ parse_tiff(ftell(ifp));
+ data_offset = offset;
+ }
+ fseek(ifp, save + len + 8, SEEK_SET);
+ }
+ raw_height = high;
+ raw_width = wide;
+ order = sorder;
+}
diff --git a/libkdcraw/libraw/src/metadata/misc_parsers.cpp b/libkdcraw/libraw/src/metadata/misc_parsers.cpp
new file mode 100644
index 0000000..7d6e2f4
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/misc_parsers.cpp
@@ -0,0 +1,694 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+/*
+ Returns 1 for a Coolpix 2100, 0 for anything else.
+ */
+int LibRaw::nikon_e2100()
+{
+ uchar t[12];
+ int i;
+
+ fseek(ifp, 0, SEEK_SET);
+ for (i = 0; i < 1024; i++)
+ {
+ fread(t, 1, 12, ifp);
+ if (((t[2] & t[4] & t[7] & t[9]) >> 4 & t[1] & t[6] & t[8] & t[11] & 3) !=
+ 3)
+ return 0;
+ }
+ return 1;
+}
+
+void LibRaw::nikon_3700()
+{
+ int bits, i;
+ uchar dp[24];
+ static const struct
+ {
+ int bits;
+ char t_make[12], t_model[15];
+ int t_maker_idx;
+ } table[] = {{0x00, "Pentax", "Optio 33WR", LIBRAW_CAMERAMAKER_Pentax},
+ {0x03, "Nikon", "E3200", LIBRAW_CAMERAMAKER_Nikon},
+ {0x32, "Nikon", "E3700", LIBRAW_CAMERAMAKER_Nikon},
+ {0x33, "Olympus", "C-740UZ", LIBRAW_CAMERAMAKER_Olympus}};
+
+ fseek(ifp, 3072, SEEK_SET);
+ fread(dp, 1, 24, ifp);
+ bits = (dp[8] & 3) << 4 | (dp[20] & 3);
+ for (i = 0; i < int(sizeof table / sizeof *table); i++)
+ if (bits == table[i].bits)
+ {
+ strcpy(make, table[i].t_make);
+ maker_index = table[i].t_maker_idx;
+ strcpy(model, table[i].t_model);
+ }
+}
+
+/*
+ Separates a Minolta DiMAGE Z2 from a Nikon E4300.
+ */
+int LibRaw::minolta_z2()
+{
+ int i, nz;
+ char tail[424];
+
+ fseek(ifp, -int(sizeof tail), SEEK_END);
+ fread(tail, 1, sizeof tail, ifp);
+ for (nz = i = 0; i < int(sizeof tail); i++)
+ if (tail[i])
+ nz++;
+ return nz > 20;
+}
+
+int LibRaw::canon_s2is()
+{
+ unsigned row;
+
+ for (row = 0; row < 100; row++)
+ {
+ fseek(ifp, row * 3340 + 3284, SEEK_SET);
+ if (getc(ifp) > 15)
+ return 1;
+ }
+ return 0;
+}
+
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+void LibRaw::parse_redcine()
+{
+ unsigned i, len, rdvo;
+
+ order = 0x4d4d;
+ is_raw = 0;
+ fseek(ifp, 52, SEEK_SET);
+ width = get4();
+ height = get4();
+ fseek(ifp, 0, SEEK_END);
+ fseek(ifp, -(i = ftello(ifp) & 511), SEEK_CUR);
+ if (get4() != i || get4() != 0x52454f42)
+ {
+ fseek(ifp, 0, SEEK_SET);
+ while ((len = get4()) != (unsigned)EOF)
+ {
+ if (get4() == 0x52454456)
+ if (is_raw++ == shot_select)
+ data_offset = ftello(ifp) - 8;
+ fseek(ifp, len - 8, SEEK_CUR);
+ }
+ }
+ else
+ {
+ rdvo = get4();
+ fseek(ifp, 12, SEEK_CUR);
+ is_raw = get4();
+ fseeko(ifp, rdvo + 8 + shot_select * 4, SEEK_SET);
+ data_offset = get4();
+ }
+}
+#endif
+
+void LibRaw::parse_cine()
+{
+ unsigned off_head, off_setup, off_image, i, temp;
+
+ order = 0x4949;
+ fseek(ifp, 4, SEEK_SET);
+ is_raw = get2() == 2;
+ fseek(ifp, 14, SEEK_CUR);
+ is_raw *= get4();
+ off_head = get4();
+ off_setup = get4();
+ off_image = get4();
+ timestamp = get4();
+ if ((i = get4()))
+ timestamp = i;
+ fseek(ifp, off_head + 4, SEEK_SET);
+ raw_width = get4();
+ raw_height = get4();
+ switch (get2(), get2())
+ {
+ case 8:
+ load_raw = &LibRaw::eight_bit_load_raw;
+ break;
+ case 16:
+ load_raw = &LibRaw::unpacked_load_raw;
+ }
+ fseek(ifp, off_setup + 792, SEEK_SET);
+ strcpy(make, "CINE");
+ sprintf(model, "%d", get4());
+ fseek(ifp, 12, SEEK_CUR);
+ switch ((i = get4()) & 0xffffff)
+ {
+ case 3:
+ filters = 0x94949494;
+ break;
+ case 4:
+ filters = 0x49494949;
+ break;
+ default:
+ is_raw = 0;
+ }
+ fseek(ifp, 72, SEEK_CUR);
+ switch ((get4() + 3600) % 360)
+ {
+ case 270:
+ flip = 4;
+ break;
+ case 180:
+ flip = 1;
+ break;
+ case 90:
+ flip = 7;
+ break;
+ case 0:
+ flip = 2;
+ }
+ cam_mul[0] = getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ cam_mul[2] = getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ temp = get4();
+ maximum = ~((~0u) << LIM(temp, 1, 31));
+ fseek(ifp, 668, SEEK_CUR);
+ shutter = get4() / 1000000000.0;
+ fseek(ifp, off_image, SEEK_SET);
+ if (shot_select < is_raw)
+ fseek(ifp, shot_select * 8, SEEK_CUR);
+ data_offset = (INT64)get4() + 8;
+ data_offset += (INT64)get4() << 32;
+}
+
+void LibRaw::parse_qt(int end)
+{
+ unsigned save, size;
+ char tag[4];
+
+ order = 0x4d4d;
+ while (ftell(ifp) + 7 < end)
+ {
+ save = ftell(ifp);
+ if ((size = get4()) < 8)
+ return;
+ if ((int)size < 0)
+ return; // 2+GB is too much
+ if (save + size < save)
+ return; // 32bit overflow
+ fread(tag, 4, 1, ifp);
+ if (!memcmp(tag, "moov", 4) || !memcmp(tag, "udta", 4) ||
+ !memcmp(tag, "CNTH", 4))
+ parse_qt(save + size);
+ if (!memcmp(tag, "CNDA", 4))
+ parse_jpeg(ftell(ifp));
+ fseek(ifp, save + size, SEEK_SET);
+ }
+}
+
+void LibRaw::parse_smal(int offset, int fsize)
+{
+ int ver;
+
+ fseek(ifp, offset + 2, SEEK_SET);
+ order = 0x4949;
+ ver = fgetc(ifp);
+ if (ver == 6)
+ fseek(ifp, 5, SEEK_CUR);
+ if (get4() != (unsigned)fsize)
+ return;
+ if (ver > 6)
+ data_offset = get4();
+ raw_height = height = get2();
+ raw_width = width = get2();
+ strcpy(make, "SMaL");
+ sprintf(model, "v%d %dx%d", ver, width, height);
+ if (ver == 6)
+ load_raw = &LibRaw::smal_v6_load_raw;
+ if (ver == 9)
+ load_raw = &LibRaw::smal_v9_load_raw;
+}
+
+void LibRaw::parse_riff(int maxdepth)
+{
+ unsigned i, size, end;
+ char tag[4], date[64], month[64];
+ static const char mon[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ struct tm t;
+ if (maxdepth < 1)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ order = 0x4949;
+ fread(tag, 4, 1, ifp);
+ size = get4();
+ end = ftell(ifp) + size;
+ if (!memcmp(tag, "RIFF", 4) || !memcmp(tag, "LIST", 4))
+ {
+ int maxloop = 1000;
+ get4();
+ while (ftell(ifp) + 7 < end && !feof(ifp) && maxloop--)
+ parse_riff(maxdepth-1);
+ }
+ else if (!memcmp(tag, "nctg", 4))
+ {
+ while (ftell(ifp) + 7 < end)
+ {
+ if (feof(ifp))
+ break;
+ i = get2();
+ size = get2();
+ if ((i + 1) >> 1 == 10 && size == 20)
+ get_timestamp(0);
+ else
+ fseek(ifp, size, SEEK_CUR);
+ }
+ }
+ else if (!memcmp(tag, "IDIT", 4) && size < 64)
+ {
+ fread(date, 64, 1, ifp);
+ date[size] = 0;
+ memset(&t, 0, sizeof t);
+ if (sscanf(date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday, &t.tm_hour,
+ &t.tm_min, &t.tm_sec, &t.tm_year) == 6)
+ {
+ for (i = 0; i < 12 && strcasecmp(mon[i], month); i++)
+ ;
+ t.tm_mon = i;
+ t.tm_year -= 1900;
+ if (mktime(&t) > 0)
+ timestamp = mktime(&t);
+ }
+ }
+ else
+ fseek(ifp, size, SEEK_CUR);
+}
+
+void LibRaw::parse_rollei()
+{
+ char line[128], *val;
+ struct tm t;
+
+ fseek(ifp, 0, SEEK_SET);
+ memset(&t, 0, sizeof t);
+ do
+ {
+ line[0] = 0;
+ if (!fgets(line, 128, ifp))
+ break;
+ line[127] = 0;
+ if(!line[0]) break; // zero-length
+ if ((val = strchr(line, '=')))
+ *val++ = 0;
+ else
+ val = line + strbuflen(line);
+ if (!strcmp(line, "DAT"))
+ sscanf(val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
+ if (!strcmp(line, "TIM"))
+ sscanf(val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
+ if (!strcmp(line, "HDR"))
+ thumb_offset = atoi(val);
+ if (!strcmp(line, "X "))
+ raw_width = atoi(val);
+ if (!strcmp(line, "Y "))
+ raw_height = atoi(val);
+ if (!strcmp(line, "TX "))
+ thumb_width = atoi(val);
+ if (!strcmp(line, "TY "))
+ thumb_height = atoi(val);
+ if (!strcmp(line, "APT"))
+ aperture = atof(val);
+ if (!strcmp(line, "SPE"))
+ shutter = atof(val);
+ if (!strcmp(line, "FOCLEN"))
+ focal_len = atof(val);
+ if (!strcmp(line, "BLKOFS"))
+ black = atoi(val) +1;
+ if (!strcmp(line, "ORI"))
+ switch (atoi(val)) {
+ case 1:
+ flip = 6;
+ break;
+ case 2:
+ flip = 3;
+ break;
+ case 3:
+ flip = 5;
+ break;
+ }
+ if (!strcmp(line, "CUTRECT")) {
+ sscanf(val, "%hu %hu %hu %hu",
+ &imgdata.sizes.raw_inset_crops[0].cleft,
+ &imgdata.sizes.raw_inset_crops[0].ctop,
+ &imgdata.sizes.raw_inset_crops[0].cwidth,
+ &imgdata.sizes.raw_inset_crops[0].cheight);
+ }
+ } while (strncmp(line, "EOHD", 4));
+ data_offset = thumb_offset + thumb_width * thumb_height * 2;
+ t.tm_year -= 1900;
+ t.tm_mon -= 1;
+ if (mktime(&t) > 0)
+ timestamp = mktime(&t);
+ strcpy(make, "Rollei");
+ strcpy(model, "d530flex");
+ thumb_format = LIBRAW_INTERNAL_THUMBNAIL_ROLLEI;
+}
+
+void LibRaw::parse_sinar_ia()
+{
+ int entries, off;
+ char str[8], *cp;
+
+ order = 0x4949;
+ fseek(ifp, 4, SEEK_SET);
+ entries = get4();
+ if (entries < 1 || entries > 8192)
+ return;
+ fseek(ifp, get4(), SEEK_SET);
+ while (entries--)
+ {
+ off = get4();
+ get4();
+ fread(str, 8, 1, ifp);
+ str[7] = 0; // Ensure end of string
+ if (!strcmp(str, "META"))
+ meta_offset = off;
+ if (!strcmp(str, "THUMB"))
+ thumb_offset = off;
+ if (!strcmp(str, "RAW0"))
+ data_offset = off;
+ }
+ fseek(ifp, meta_offset + 20, SEEK_SET);
+ fread(make, 64, 1, ifp);
+ make[63] = 0;
+ if ((cp = strchr(make, ' ')))
+ {
+ strcpy(model, cp + 1);
+ *cp = 0;
+ }
+ raw_width = get2();
+ raw_height = get2();
+ load_raw = &LibRaw::unpacked_load_raw;
+ thumb_width = (get4(), get2());
+ thumb_height = get2();
+ thumb_format = LIBRAW_INTERNAL_THUMBNAIL_PPM;
+ maximum = 0x3fff;
+}
+
+void LibRaw::parse_kyocera()
+{
+
+ int c;
+ static const ushort table[13] = {25, 32, 40, 50, 64, 80, 100,
+ 125, 160, 200, 250, 320, 400};
+
+ fseek(ifp, 33, SEEK_SET);
+ get_timestamp(1);
+ fseek(ifp, 52, SEEK_SET);
+ c = get4();
+ if ((c > 6) && (c < 20))
+ iso_speed = table[c - 7];
+ shutter = libraw_powf64l(2.0f, (((float)get4()) / 8.0f)) / 16000.0f;
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = get4();
+ fseek(ifp, 88, SEEK_SET);
+ aperture = libraw_powf64l(2.0f, ((float)get4()) / 16.0f);
+ fseek(ifp, 112, SEEK_SET);
+ focal_len = get4();
+
+ fseek(ifp, 104, SEEK_SET);
+ ilm.MaxAp4CurFocal = libraw_powf64l(2.0f, ((float)get4()) / 16.0f);
+ fseek(ifp, 124, SEEK_SET);
+ stmread(ilm.Lens, 32, ifp);
+ ilm.CameraMount = LIBRAW_MOUNT_Contax_N;
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ if (ilm.Lens[0])
+ {
+ ilm.LensMount = LIBRAW_MOUNT_Contax_N;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ }
+}
+
+int LibRaw::parse_jpeg(int offset)
+{
+ int len, save, hlen, mark;
+ fseek(ifp, offset, SEEK_SET);
+ if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8)
+ return 0;
+
+ while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda)
+ {
+ order = 0x4d4d;
+ len = get2() - 2;
+ save = ftell(ifp);
+ if (mark == 0xc0 || mark == 0xc3 || mark == 0xc9)
+ {
+ fgetc(ifp);
+ raw_height = get2();
+ raw_width = get2();
+ }
+ order = get2();
+ hlen = get4();
+ if (get4() == 0x48454150 && (save + hlen) >= 0 &&
+ (save + hlen) <= ifp->size()) /* "HEAP" */
+ {
+ parse_ciff(save + hlen, len - hlen, 0);
+ }
+ if (parse_tiff(save + 6))
+ apply_tiff();
+ fseek(ifp, save + len, SEEK_SET);
+ }
+ return 1;
+}
+
+void LibRaw::parse_thumb_note(int base, unsigned toff, unsigned tlen)
+{
+ unsigned entries, tag, type, len, save;
+
+ entries = get2();
+ while (entries--)
+ {
+ tiff_get(base, &tag, &type, &len, &save);
+ if (tag == toff)
+ thumb_offset = get4() + base;
+ if (tag == tlen)
+ thumb_length = get4();
+ fseek(ifp, save, SEEK_SET);
+ }
+}
+
+void LibRaw::parse_broadcom()
+{
+
+ /* This structure is at offset 0xb0 from the 'BRCM' ident. */
+ struct
+ {
+ uint8_t umode[32];
+ uint16_t uwidth;
+ uint16_t uheight;
+ uint16_t padding_right;
+ uint16_t padding_down;
+ uint32_t unknown_block[6];
+ uint16_t transform;
+ uint16_t format;
+ uint8_t bayer_order;
+ uint8_t bayer_format;
+ } header;
+
+ header.bayer_order = 0;
+ fseek(ifp, 0xb0 - 0x20, SEEK_CUR);
+ fread(&header, 1, sizeof(header), ifp);
+ raw_stride =
+ ((((((header.uwidth + header.padding_right) * 5) + 3) >> 2) + 0x1f) &
+ (~0x1f));
+ raw_width = width = header.uwidth;
+ raw_height = height = header.uheight;
+ filters = 0x16161616; /* default Bayer order is 2, BGGR */
+
+ switch (header.bayer_order)
+ {
+ case 0: /* RGGB */
+ filters = 0x94949494;
+ break;
+ case 1: /* GBRG */
+ filters = 0x49494949;
+ break;
+ case 3: /* GRBG */
+ filters = 0x61616161;
+ break;
+ }
+}
+
+/*
+ Returns 1 for a Coolpix 995, 0 for anything else.
+ */
+int LibRaw::nikon_e995()
+{
+ int i, histo[256];
+ const uchar often[] = {0x00, 0x55, 0xaa, 0xff};
+
+ memset(histo, 0, sizeof histo);
+ fseek(ifp, -2000, SEEK_END);
+ for (i = 0; i < 2000; i++)
+ histo[fgetc(ifp)]++;
+ for (i = 0; i < 4; i++)
+ if (histo[often[i]] < 200)
+ return 0;
+ return 1;
+}
+
+/*
+ Since the TIFF DateTime string has no timezone information,
+ assume that the camera's clock was set to Universal Time.
+ */
+void LibRaw::get_timestamp(int reversed)
+{
+ struct tm t;
+ char str[20];
+ int i;
+
+ str[19] = 0;
+ if (reversed)
+ for (i = 19; i--;)
+ str[i] = fgetc(ifp);
+ else
+ fread(str, 19, 1, ifp);
+ memset(&t, 0, sizeof t);
+ if (sscanf(str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon, &t.tm_mday,
+ &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
+ return;
+ t.tm_year -= 1900;
+ t.tm_mon -= 1;
+ t.tm_isdst = -1;
+ if (mktime(&t) > 0)
+ timestamp = mktime(&t);
+}
+
+#ifdef USE_6BY9RPI
+void LibRaw::parse_raspberrypi()
+{
+ //This structure is at offset 0xB0 from the 'BRCM' ident.
+ struct brcm_raw_header {
+ uint8_t name[32];
+ uint16_t h_width;
+ uint16_t h_height;
+ uint16_t padding_right;
+ uint16_t padding_down;
+ uint32_t dummy[6];
+ uint16_t transform;
+ uint16_t format;
+ uint8_t bayer_order;
+ uint8_t bayer_format;
+ };
+ //Values taken from https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
+#define BRCM_FORMAT_BAYER 33
+#define BRCM_BAYER_RAW8 2
+#define BRCM_BAYER_RAW10 3
+#define BRCM_BAYER_RAW12 4
+#define BRCM_BAYER_RAW14 5
+#define BRCM_BAYER_RAW16 6
+
+ struct brcm_raw_header header;
+ uint8_t brcm_tag[4];
+
+ if (ftell(ifp) > 22LL) // 22 bytes is minimum jpeg size
+ {
+ thumb_length = ftell(ifp);
+ thumb_offset = 0;
+ thumb_width = thumb_height = 0;
+ load_flags |= 0x4000; // flag: we have JPEG from beginning to meta_offset
+ }
+
+ // Sanity check that the caller has found a BRCM header
+ if (!fread(brcm_tag, 1, sizeof(brcm_tag), ifp) ||
+ memcmp(brcm_tag, "BRCM", sizeof(brcm_tag)))
+ return;
+
+ width = raw_width;
+ data_offset = ftell(ifp) + 0x8000 - sizeof(brcm_tag);
+
+ if (!fseek(ifp, 0xB0 - int(sizeof(brcm_tag)), SEEK_CUR) &&
+ fread(&header, 1, sizeof(header), ifp)) {
+ switch (header.bayer_order) {
+ case 0: //RGGB
+ filters = 0x94949494;
+ break;
+ case 1: //GBRG
+ filters = 0x49494949;
+ break;
+ default:
+ case 2: //BGGR
+ filters = 0x16161616;
+ break;
+ case 3: //GRBG
+ filters = 0x61616161;
+ break;
+ }
+
+ if (header.format == BRCM_FORMAT_BAYER) {
+ switch (header.bayer_format) {
+ case BRCM_BAYER_RAW8:
+ load_raw = &LibRaw::rpi_load_raw8;
+ //1 pixel per byte
+ raw_stride = ((header.h_width + header.padding_right) + 31)&(~31);
+ width = header.h_width;
+ raw_height = height = header.h_height;
+ is_raw = 1;
+ order = 0x4d4d;
+ break;
+ case BRCM_BAYER_RAW10:
+ load_raw = &LibRaw::nokia_load_raw;
+ //4 pixels per 5 bytes
+ raw_stride = (((((header.h_width + header.padding_right) * 5) + 3) >> 2) + 31)&(~31);
+ width = header.h_width;
+ raw_height = height = header.h_height;
+ is_raw = 1;
+ order = 0x4d4d;
+ break;
+ case BRCM_BAYER_RAW12:
+ load_raw = &LibRaw::rpi_load_raw12;
+ //2 pixels per 3 bytes
+ raw_stride = (((((header.h_width + header.padding_right) * 3) + 1) >> 1) + 31)&(~31);
+ width = header.h_width;
+ raw_height = height = header.h_height;
+ is_raw = 1;
+ order = 0x4d4d;
+ break;
+ case BRCM_BAYER_RAW14:
+ load_raw = &LibRaw::rpi_load_raw14;
+ //4 pixels per 7 bytes
+ raw_stride = (((((header.h_width + header.padding_right) * 7) + 3) >> 2) + 31)&(~31);
+ width = header.h_width;
+ raw_height = height = header.h_height;
+ is_raw = 1;
+ order = 0x4d4d;
+ break;
+ case BRCM_BAYER_RAW16:
+ load_raw = &LibRaw::rpi_load_raw16;
+ //1 pixel per 2 bytes
+ raw_stride = (((header.h_width + header.padding_right) << 1) + 31)&(~31);
+ width = header.h_width;
+ raw_height = height = header.h_height;
+ is_raw = 1;
+ order = 0x4d4d;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+#endif
diff --git a/libkdcraw/libraw/src/metadata/nikon.cpp b/libkdcraw/libraw/src/metadata/nikon.cpp
new file mode 100644
index 0000000..c0c90f8
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/nikon.cpp
@@ -0,0 +1,1051 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+// void hexDump(char *title, void *addr, int len);
+
+unsigned sget4_order (short _order, uchar *s);
+double sget_fixed32u (short _order, uchar *s);
+double AngleConversion_a (short _order, uchar *s);
+double AngleConversion (short _order, uchar *s);
+
+static const uchar xlat[2][256] = {
+ {0xc1, 0xbf, 0x6d, 0x0d, 0x59, 0xc5, 0x13, 0x9d, 0x83, 0x61, 0x6b, 0x4f,
+ 0xc7, 0x7f, 0x3d, 0x3d, 0x53, 0x59, 0xe3, 0xc7, 0xe9, 0x2f, 0x95, 0xa7,
+ 0x95, 0x1f, 0xdf, 0x7f, 0x2b, 0x29, 0xc7, 0x0d, 0xdf, 0x07, 0xef, 0x71,
+ 0x89, 0x3d, 0x13, 0x3d, 0x3b, 0x13, 0xfb, 0x0d, 0x89, 0xc1, 0x65, 0x1f,
+ 0xb3, 0x0d, 0x6b, 0x29, 0xe3, 0xfb, 0xef, 0xa3, 0x6b, 0x47, 0x7f, 0x95,
+ 0x35, 0xa7, 0x47, 0x4f, 0xc7, 0xf1, 0x59, 0x95, 0x35, 0x11, 0x29, 0x61,
+ 0xf1, 0x3d, 0xb3, 0x2b, 0x0d, 0x43, 0x89, 0xc1, 0x9d, 0x9d, 0x89, 0x65,
+ 0xf1, 0xe9, 0xdf, 0xbf, 0x3d, 0x7f, 0x53, 0x97, 0xe5, 0xe9, 0x95, 0x17,
+ 0x1d, 0x3d, 0x8b, 0xfb, 0xc7, 0xe3, 0x67, 0xa7, 0x07, 0xf1, 0x71, 0xa7,
+ 0x53, 0xb5, 0x29, 0x89, 0xe5, 0x2b, 0xa7, 0x17, 0x29, 0xe9, 0x4f, 0xc5,
+ 0x65, 0x6d, 0x6b, 0xef, 0x0d, 0x89, 0x49, 0x2f, 0xb3, 0x43, 0x53, 0x65,
+ 0x1d, 0x49, 0xa3, 0x13, 0x89, 0x59, 0xef, 0x6b, 0xef, 0x65, 0x1d, 0x0b,
+ 0x59, 0x13, 0xe3, 0x4f, 0x9d, 0xb3, 0x29, 0x43, 0x2b, 0x07, 0x1d, 0x95,
+ 0x59, 0x59, 0x47, 0xfb, 0xe5, 0xe9, 0x61, 0x47, 0x2f, 0x35, 0x7f, 0x17,
+ 0x7f, 0xef, 0x7f, 0x95, 0x95, 0x71, 0xd3, 0xa3, 0x0b, 0x71, 0xa3, 0xad,
+ 0x0b, 0x3b, 0xb5, 0xfb, 0xa3, 0xbf, 0x4f, 0x83, 0x1d, 0xad, 0xe9, 0x2f,
+ 0x71, 0x65, 0xa3, 0xe5, 0x07, 0x35, 0x3d, 0x0d, 0xb5, 0xe9, 0xe5, 0x47,
+ 0x3b, 0x9d, 0xef, 0x35, 0xa3, 0xbf, 0xb3, 0xdf, 0x53, 0xd3, 0x97, 0x53,
+ 0x49, 0x71, 0x07, 0x35, 0x61, 0x71, 0x2f, 0x43, 0x2f, 0x11, 0xdf, 0x17,
+ 0x97, 0xfb, 0x95, 0x3b, 0x7f, 0x6b, 0xd3, 0x25, 0xbf, 0xad, 0xc7, 0xc5,
+ 0xc5, 0xb5, 0x8b, 0xef, 0x2f, 0xd3, 0x07, 0x6b, 0x25, 0x49, 0x95, 0x25,
+ 0x49, 0x6d, 0x71, 0xc7},
+ {0xa7, 0xbc, 0xc9, 0xad, 0x91, 0xdf, 0x85, 0xe5, 0xd4, 0x78, 0xd5, 0x17,
+ 0x46, 0x7c, 0x29, 0x4c, 0x4d, 0x03, 0xe9, 0x25, 0x68, 0x11, 0x86, 0xb3,
+ 0xbd, 0xf7, 0x6f, 0x61, 0x22, 0xa2, 0x26, 0x34, 0x2a, 0xbe, 0x1e, 0x46,
+ 0x14, 0x68, 0x9d, 0x44, 0x18, 0xc2, 0x40, 0xf4, 0x7e, 0x5f, 0x1b, 0xad,
+ 0x0b, 0x94, 0xb6, 0x67, 0xb4, 0x0b, 0xe1, 0xea, 0x95, 0x9c, 0x66, 0xdc,
+ 0xe7, 0x5d, 0x6c, 0x05, 0xda, 0xd5, 0xdf, 0x7a, 0xef, 0xf6, 0xdb, 0x1f,
+ 0x82, 0x4c, 0xc0, 0x68, 0x47, 0xa1, 0xbd, 0xee, 0x39, 0x50, 0x56, 0x4a,
+ 0xdd, 0xdf, 0xa5, 0xf8, 0xc6, 0xda, 0xca, 0x90, 0xca, 0x01, 0x42, 0x9d,
+ 0x8b, 0x0c, 0x73, 0x43, 0x75, 0x05, 0x94, 0xde, 0x24, 0xb3, 0x80, 0x34,
+ 0xe5, 0x2c, 0xdc, 0x9b, 0x3f, 0xca, 0x33, 0x45, 0xd0, 0xdb, 0x5f, 0xf5,
+ 0x52, 0xc3, 0x21, 0xda, 0xe2, 0x22, 0x72, 0x6b, 0x3e, 0xd0, 0x5b, 0xa8,
+ 0x87, 0x8c, 0x06, 0x5d, 0x0f, 0xdd, 0x09, 0x19, 0x93, 0xd0, 0xb9, 0xfc,
+ 0x8b, 0x0f, 0x84, 0x60, 0x33, 0x1c, 0x9b, 0x45, 0xf1, 0xf0, 0xa3, 0x94,
+ 0x3a, 0x12, 0x77, 0x33, 0x4d, 0x44, 0x78, 0x28, 0x3c, 0x9e, 0xfd, 0x65,
+ 0x57, 0x16, 0x94, 0x6b, 0xfb, 0x59, 0xd0, 0xc8, 0x22, 0x36, 0xdb, 0xd2,
+ 0x63, 0x98, 0x43, 0xa1, 0x04, 0x87, 0x86, 0xf7, 0xa6, 0x26, 0xbb, 0xd6,
+ 0x59, 0x4d, 0xbf, 0x6a, 0x2e, 0xaa, 0x2b, 0xef, 0xe6, 0x78, 0xb6, 0x4e,
+ 0xe0, 0x2f, 0xdc, 0x7c, 0xbe, 0x57, 0x19, 0x32, 0x7e, 0x2a, 0xd0, 0xb8,
+ 0xba, 0x29, 0x00, 0x3c, 0x52, 0x7d, 0xa8, 0x49, 0x3b, 0x2d, 0xeb, 0x25,
+ 0x49, 0xfa, 0xa3, 0xaa, 0x39, 0xa7, 0xc5, 0xa7, 0x50, 0x11, 0x36, 0xfb,
+ 0xc6, 0x67, 0x4a, 0xf5, 0xa5, 0x12, 0x65, 0x7e, 0xb0, 0xdf, 0xaf, 0x4e,
+ 0xb3, 0x61, 0x7f, 0x2f} };
+
+void LibRaw::processNikonLensData(uchar *LensData, unsigned len)
+{
+
+ ushort i=0;
+ if (imgdata.lens.nikon.LensType & 0x80) {
+ strcpy (ilm.LensFeatures_pre, "AF-P");
+ } else if (!(imgdata.lens.nikon.LensType & 0x01)) {
+ ilm.LensFeatures_pre[0] = 'A';
+ ilm.LensFeatures_pre[1] = 'F';
+ } else {
+ ilm.LensFeatures_pre[0] = 'M';
+ ilm.LensFeatures_pre[1] = 'F';
+ }
+
+ if (imgdata.lens.nikon.LensType & 0x40) {
+ ilm.LensFeatures_suf[0] = 'E';
+ } else if (imgdata.lens.nikon.LensType & 0x04) {
+ ilm.LensFeatures_suf[0] = 'G';
+ } else if (imgdata.lens.nikon.LensType & 0x02) {
+ ilm.LensFeatures_suf[0] = 'D';
+ }
+
+ if (imgdata.lens.nikon.LensType & 0x08)
+ {
+ ilm.LensFeatures_suf[1] = ' ';
+ ilm.LensFeatures_suf[2] = 'V';
+ ilm.LensFeatures_suf[3] = 'R';
+ }
+
+ if (imgdata.lens.nikon.LensType & 0x10)
+ {
+ ilm.LensMount = ilm.CameraMount = LIBRAW_MOUNT_Nikon_CX;
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_1INCH;
+ }
+ else
+ ilm.LensMount = ilm.CameraMount = LIBRAW_MOUNT_Nikon_F;
+
+ if (imgdata.lens.nikon.LensType & 0x20)
+ {
+ strcpy(ilm.Adapter, "FT-1");
+ ilm.LensMount = LIBRAW_MOUNT_Nikon_F;
+ ilm.CameraMount = LIBRAW_MOUNT_Nikon_CX;
+ ilm.CameraFormat = LIBRAW_FORMAT_1INCH;
+ }
+
+ imgdata.lens.nikon.LensType = imgdata.lens.nikon.LensType & 0xdf;
+
+ if ((len < 20) || (len == 58) || (len == 108))
+ {
+ switch (len)
+ {
+ case 9:
+ i = 2;
+ break;
+ case 15:
+ i = 7;
+ break;
+ case 16:
+ i = 8;
+ break;
+ case 58: // "Z 6", "Z 6 II", "Z 7", "Z 7 II", "Z 50", D780, "Z 5", "Z fc"
+ case 108: // "Z 9"
+ if (model[6] == 'Z')
+ ilm.CameraMount = LIBRAW_MOUNT_Nikon_Z;
+ if (imNikon.HighSpeedCropFormat != 12)
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ i = 1;
+ while ((LensData[i] == LensData[0]) && (i < 17))
+ i++;
+ if (i == 17)
+ {
+ ilm.LensMount = LIBRAW_MOUNT_Nikon_Z;
+ ilm.LensID = sget2(LensData + 0x2c);
+ if (
+ (ilm.LensID == 11)
+ || (ilm.LensID == 12)
+ || (ilm.LensID == 26)
+ ) ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ else ilm.LensFormat = LIBRAW_FORMAT_FF;
+ if (ilm.MaxAp4CurFocal < 0.7f)
+ ilm.MaxAp4CurFocal = libraw_powf64l(
+ 2.0f, (float)sget2(LensData + 0x32) / 384.0f - 1.0f);
+ if (ilm.CurAp < 0.7f)
+ ilm.CurAp = libraw_powf64l(
+ 2.0f, (float)sget2(LensData + 0x34) / 384.0f - 1.0f);
+ if (fabsf(ilm.CurFocal) < 1.1f)
+ ilm.CurFocal = sget2(LensData + 0x38);
+ return;
+ }
+ i = 9;
+ ilm.LensMount = LIBRAW_MOUNT_Nikon_F;
+ if (ilm.CameraMount == LIBRAW_MOUNT_Nikon_Z)
+ strcpy(ilm.Adapter, "FTZ");
+ break;
+ }
+ imgdata.lens.nikon.LensIDNumber = LensData[i];
+ imgdata.lens.nikon.LensFStops = LensData[i + 1];
+ ilm.LensFStops = (float)imgdata.lens.nikon.LensFStops / 12.0f;
+ if (fabsf(ilm.MinFocal) < 1.1f)
+ {
+ if ((imgdata.lens.nikon.LensType ^ (uchar)0x01) || LensData[i + 2])
+ ilm.MinFocal =
+ 5.0f * libraw_powf64l(2.0f, (float)LensData[i + 2] / 24.0f);
+ if ((imgdata.lens.nikon.LensType ^ (uchar)0x01) || LensData[i + 3])
+ ilm.MaxFocal =
+ 5.0f * libraw_powf64l(2.0f, (float)LensData[i + 3] / 24.0f);
+ if ((imgdata.lens.nikon.LensType ^ (uchar)0x01) || LensData[i + 4])
+ ilm.MaxAp4MinFocal =
+ libraw_powf64l(2.0f, (float)LensData[i + 4] / 24.0f);
+ if ((imgdata.lens.nikon.LensType ^ (uchar)0x01) || LensData[i + 5])
+ ilm.MaxAp4MaxFocal =
+ libraw_powf64l(2.0f, (float)LensData[i + 5] / 24.0f);
+ }
+ imgdata.lens.nikon.MCUVersion = LensData[i + 6];
+ if (i != 2)
+ {
+ if ((LensData[i - 1]) && (fabsf(ilm.CurFocal) < 1.1f))
+ ilm.CurFocal =
+ 5.0f * libraw_powf64l(2.0f, (float)LensData[i - 1] / 24.0f);
+ if (LensData[i + 7])
+ imgdata.lens.nikon.EffectiveMaxAp =
+ libraw_powf64l(2.0f, (float)LensData[i + 7] / 24.0f);
+ }
+ ilm.LensID = (unsigned long long)LensData[i] << 56 |
+ (unsigned long long)LensData[i + 1] << 48 |
+ (unsigned long long)LensData[i + 2] << 40 |
+ (unsigned long long)LensData[i + 3] << 32 |
+ (unsigned long long)LensData[i + 4] << 24 |
+ (unsigned long long)LensData[i + 5] << 16 |
+ (unsigned long long)LensData[i + 6] << 8 |
+ (unsigned long long)imgdata.lens.nikon.LensType;
+ }
+ else if ((len == 459) || (len == 590))
+ {
+ memcpy(ilm.Lens, LensData + 390, 64);
+ }
+ else if (len == 509)
+ {
+ memcpy(ilm.Lens, LensData + 391, 64);
+ }
+ else if (len == 879)
+ {
+ memcpy(ilm.Lens, LensData + 680, 64);
+ }
+
+ return;
+}
+
+void LibRaw::Nikon_NRW_WBtag(int wb, int skip)
+{
+
+ int r, g0, g1, b;
+ if (skip)
+ get4(); // skip wb "CCT", it is not unique
+ r = get4();
+ g0 = get4();
+ g1 = get4();
+ b = get4();
+ if (r && g0 && g1 && b)
+ {
+ icWBC[wb][0] = r << 1;
+ icWBC[wb][1] = g0;
+ icWBC[wb][2] = b << 1;
+ icWBC[wb][3] = g1;
+ }
+ return;
+}
+
+void LibRaw::parseNikonMakernote(int base, int uptag, unsigned /*dng_writer */)
+{
+
+ unsigned offset = 0, entries, tag, type, len, save;
+
+ unsigned c, i;
+ unsigned LensData_len = 0;
+ uchar *LensData_buf=0;
+ uchar ColorBalanceData_buf[324];
+ int ColorBalanceData_ready = 0;
+ uchar ci, cj, ck;
+ unsigned serial = 0;
+ unsigned custom_serial = 0;
+
+ unsigned ShotInfo_len = 0;
+ uchar *ShotInfo_buf=0;
+
+/* for dump:
+uchar *cj_block, *ck_block;
+*/
+
+ short morder, sorder = order;
+ char buf[10];
+ INT64 fsize = ifp->size();
+
+ fread(buf, 1, 10, ifp);
+
+ if (!strcmp(buf, "Nikon"))
+ {
+ if (buf[6] != '\2')
+ return;
+ base = ftell(ifp);
+ order = get2();
+ if (get2() != 42)
+ goto quit;
+ offset = get4();
+ fseek(ifp, INT64(offset) - 8LL, SEEK_CUR);
+ }
+ else
+ {
+ fseek(ifp, -10, SEEK_CUR);
+ }
+
+ entries = get2();
+ if (entries > 1000)
+ return;
+ morder = order;
+
+ while (entries--)
+ {
+ order = morder;
+ tiff_get(base, &tag, &type, &len, &save);
+
+ INT64 pos = ifp->tell();
+ if (len > 8 && pos + len > 2 * fsize)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+ tag |= uptag << 16;
+ if (len > 100 * 1024 * 1024)
+ goto next; // 100Mb tag? No!
+
+ if (tag == 0x0002)
+ {
+ if (!iso_speed)
+ iso_speed = (get2(), get2());
+ }
+ else if (tag == 0x000a)
+ {
+ ilm.LensMount = ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ }
+ else if ((tag == 0x000c) && (len == 4) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_RATIONAL))
+ {
+ cam_mul[0] = getreal(type);
+ cam_mul[2] = getreal(type);
+ cam_mul[1] = getreal(type);
+ cam_mul[3] = getreal(type);
+ }
+ else if (tag == 0x0011)
+ {
+ if (is_raw)
+ {
+ fseek(ifp, get4() + base, SEEK_SET);
+ parse_tiff_ifd(base);
+ }
+ }
+ else if (tag == 0x0012)
+ {
+ uchar uc1 = fgetc(ifp);
+ uchar uc2 = fgetc(ifp);
+ uchar uc3 = fgetc(ifp);
+ if (uc3)
+ imCommon.FlashEC = (float)(uc1 * uc2) / (float)uc3;
+ }
+ else if (tag == 0x0014)
+ {
+ if (tagtypeIs(LIBRAW_EXIFTOOLTAGTYPE_binary))
+ {
+ if (len == 2560)
+ { // E5400, E8400, E8700, E8800
+ fseek(ifp, 0x4e0L, SEEK_CUR);
+ order = 0x4d4d;
+ cam_mul[0] = get2() / 256.0;
+ cam_mul[2] = get2() / 256.0;
+ cam_mul[1] = cam_mul[3] = 1.0;
+ icWBC[LIBRAW_WBI_Auto][0] = get2();
+ icWBC[LIBRAW_WBI_Auto][2] = get2();
+ icWBC[LIBRAW_WBI_Daylight][0] = get2();
+ icWBC[LIBRAW_WBI_Daylight][2] = get2();
+ fseek(ifp, 0x18L, SEEK_CUR);
+ icWBC[LIBRAW_WBI_Tungsten][0] = get2();
+ icWBC[LIBRAW_WBI_Tungsten][2] = get2();
+ fseek(ifp, 0x18L, SEEK_CUR);
+ icWBC[LIBRAW_WBI_FL_W][0] = get2();
+ icWBC[LIBRAW_WBI_FL_W][2] = get2();
+ icWBC[LIBRAW_WBI_FL_N][0] = get2();
+ icWBC[LIBRAW_WBI_FL_N][2] = get2();
+ icWBC[LIBRAW_WBI_FL_D][0] = get2();
+ icWBC[LIBRAW_WBI_FL_D][2] = get2();
+ icWBC[LIBRAW_WBI_Cloudy][0] = get2();
+ icWBC[LIBRAW_WBI_Cloudy][2] = get2();
+ fseek(ifp, 0x18L, SEEK_CUR);
+ icWBC[LIBRAW_WBI_Flash][0] = get2();
+ icWBC[LIBRAW_WBI_Flash][2] = get2();
+
+ icWBC[LIBRAW_WBI_Auto][1] = icWBC[LIBRAW_WBI_Auto][3] =
+ icWBC[LIBRAW_WBI_Daylight][1] = icWBC[LIBRAW_WBI_Daylight][3] =
+ icWBC[LIBRAW_WBI_Tungsten][1] = icWBC[LIBRAW_WBI_Tungsten][3] =
+ icWBC[LIBRAW_WBI_FL_W][1] = icWBC[LIBRAW_WBI_FL_W][3] =
+ icWBC[LIBRAW_WBI_FL_N][1] = icWBC[LIBRAW_WBI_FL_N][3] =
+ icWBC[LIBRAW_WBI_FL_D][1] = icWBC[LIBRAW_WBI_FL_D][3] =
+ icWBC[LIBRAW_WBI_Cloudy][1] = icWBC[LIBRAW_WBI_Cloudy][3] =
+ icWBC[LIBRAW_WBI_Flash][1] = icWBC[LIBRAW_WBI_Flash][3] = 256;
+
+ if (strncmp(model, "E8700", 5))
+ {
+ fseek(ifp, 0x18L, SEEK_CUR);
+ icWBC[LIBRAW_WBI_Shade][0] = get2();
+ icWBC[LIBRAW_WBI_Shade][2] = get2();
+ icWBC[LIBRAW_WBI_Shade][1] = icWBC[LIBRAW_WBI_Shade][3] = 256;
+ }
+ }
+ else if (len == 1280)
+ { // E5000, E5700
+ cam_mul[0] = cam_mul[1] = cam_mul[2] = cam_mul[3] = 1.0;
+ }
+ else
+ {
+ fread(buf, 1, 10, ifp);
+ if (!strncmp(buf, "NRW ", 4))
+ { // P6000, P7000, P7100, B700, P1000
+ if (!strcmp(buf + 4, "0100"))
+ { // P6000
+ fseek(ifp, 0x13deL, SEEK_CUR);
+ cam_mul[0] = get4() << 1;
+ cam_mul[1] = get4();
+ cam_mul[3] = get4();
+ cam_mul[2] = get4() << 1;
+ Nikon_NRW_WBtag(LIBRAW_WBI_Daylight, 0);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Cloudy, 0);
+ fseek(ifp, 0x10L, SEEK_CUR);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Tungsten, 0);
+ Nikon_NRW_WBtag(LIBRAW_WBI_FL_W, 0);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Flash, 0);
+ fseek(ifp, 0x10L, SEEK_CUR);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Custom, 0);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Auto, 0);
+ }
+ else
+ { // P7000, P7100, B700, P1000
+ fseek(ifp, 0x16L, SEEK_CUR);
+ black = get2();
+ if (cam_mul[0] < 0.1f)
+ {
+ fseek(ifp, 0x16L, SEEK_CUR);
+ cam_mul[0] = get4() << 1;
+ cam_mul[1] = get4();
+ cam_mul[3] = get4();
+ cam_mul[2] = get4() << 1;
+ }
+ else
+ {
+ fseek(ifp, 0x26L, SEEK_CUR);
+ }
+ if (len != 332)
+ { // not A1000
+ Nikon_NRW_WBtag(LIBRAW_WBI_Daylight, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Cloudy, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Shade, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Tungsten, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_FL_W, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_FL_N, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_FL_D, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_HT_Mercury, 1);
+ fseek(ifp, 0x14L, SEEK_CUR);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Custom, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Auto, 1);
+ }
+ else
+ {
+ fseek(ifp, 0xc8L, SEEK_CUR);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Auto, 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (tag == 0x001b)
+ {
+ imNikon.HighSpeedCropFormat = get2();
+ imNikon.SensorHighSpeedCrop.cwidth = get2();
+ imNikon.SensorHighSpeedCrop.cheight = get2();
+ imNikon.SensorWidth = get2();
+ imNikon.SensorHeight = get2();
+ imNikon.SensorHighSpeedCrop.cleft = get2();
+ imNikon.SensorHighSpeedCrop.ctop = get2();
+ switch (imNikon.HighSpeedCropFormat)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
+ break;
+ case 11:
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
+ break;
+ case 12:
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
+ break;
+ case 3:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_5to4;
+ break;
+ case 6:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_16to9;
+ break;
+ case 17:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_1to1;
+ break;
+ default:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_OTHER;
+ break;
+ }
+ }
+ else if (tag == 0x001d)
+ { // serial number
+ if (len > 0)
+ {
+ int model_len = (int)strbuflen(model);
+ while ((c = fgetc(ifp)) && (len-- > 0) && (c != (unsigned)EOF))
+ {
+ if ((!custom_serial) && (!isdigit(c)))
+ {
+ if (((model_len == 3) && !strcmp(model, "D50")) ||
+ ((model_len >= 4) && !isalnum(model[model_len - 4]) &&
+ !strncmp(&model[model_len - 3], "D50", 3)))
+ {
+ custom_serial = 34;
+ }
+ else
+ {
+ custom_serial = 96;
+ }
+ break;
+ }
+ serial = serial * 10 + (isdigit(c) ? c - '0' : c % 10);
+ }
+ if (!imgdata.shootinginfo.BodySerial[0])
+ sprintf(imgdata.shootinginfo.BodySerial, "%d", serial);
+ }
+ }
+ else if (tag == 0x001e) {
+ switch (get2()) {
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 2:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ } else if (tag == 0x0025)
+ {
+ imCommon.real_ISO = int(100.0 * libraw_powf64l(2.0, double((uchar)fgetc(ifp)) / 12.0 - 5.0));
+ if (!iso_speed || (iso_speed == 65535))
+ {
+ iso_speed = imCommon.real_ISO;
+ }
+ }
+ else if (tag == 0x0022)
+ {
+ imNikon.Active_D_Lighting = get2();
+ }
+ else if (tag == 0x003b)
+ { // WB for multi-exposure (ME); all 1s for regular exposures
+ imNikon.ME_WB[0] = getreal(type);
+ imNikon.ME_WB[2] = getreal(type);
+ imNikon.ME_WB[1] = getreal(type);
+ imNikon.ME_WB[3] = getreal(type);
+ }
+ else if (tag == 0x003d)
+ { // not corrected for file bitcount, to be patched in open_datastream
+ FORC4 cblack[RGGB_2_RGBG(c)] = get2();
+ i = cblack[3];
+ FORC3 if (i > cblack[c]) i = cblack[c];
+ FORC4 cblack[c] -= i;
+ black += i;
+ }
+ else if (tag == 0x0045)
+ { /* upper left pixel (x,y), size (width,height) */
+ imgdata.sizes.raw_inset_crops[0].cleft = get2();
+ imgdata.sizes.raw_inset_crops[0].ctop = get2();
+ imgdata.sizes.raw_inset_crops[0].cwidth = get2();
+ imgdata.sizes.raw_inset_crops[0].cheight = get2();
+ }
+ else if (tag == 0x0051)
+ {
+ fseek(ifp, 10LL, SEEK_CUR);
+ imNikon.NEFCompression = get2();
+ }
+ else if (tag == 0x0082)
+ { // lens attachment
+ stmread(ilm.Attachment, len, ifp);
+ }
+ else if (tag == 0x0083)
+ { // lens type
+ imgdata.lens.nikon.LensType = fgetc(ifp);
+ }
+ else if (tag == 0x0084)
+ { // lens
+ ilm.MinFocal = getreal(type);
+ ilm.MaxFocal = getreal(type);
+ ilm.MaxAp4MinFocal = getreal(type);
+ ilm.MaxAp4MaxFocal = getreal(type);
+ }
+ else if (tag == 0x0088) // AFInfo
+ {
+ if (!imCommon.afcount)
+ {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ fread(imCommon.afdata[imCommon.afcount].AFInfoData, imCommon.afdata[imCommon.afcount].AFInfoData_length, 1, ifp);
+ imCommon.afcount = 1;
+ }
+ }
+ else if (tag == 0x008b) // lens f-stops
+ {
+ uchar uc1 = fgetc(ifp);
+ uchar uc2 = fgetc(ifp);
+ uchar uc3 = fgetc(ifp);
+ if (uc3)
+ {
+ imgdata.lens.nikon.LensFStops = uc1 * uc2 * (12 / uc3);
+ ilm.LensFStops = (float)imgdata.lens.nikon.LensFStops / 12.0f;
+ }
+ }
+ else if ((tag == 0x008c) || (tag == 0x0096))
+ {
+ meta_offset = ftell(ifp);
+ }
+ else if ((tag == 0x0091) && (len > 4))
+ {
+ ShotInfo_len = len;
+ ShotInfo_buf = (uchar *)malloc(ShotInfo_len);
+
+/* for dump:
+cj_block = (uchar *)malloc(ShotInfo_len);
+ck_block = (uchar *)malloc(ShotInfo_len);
+*/
+
+ fread(ShotInfo_buf, ShotInfo_len, 1, ifp);
+ FORC4 imNikon.ShotInfoVersion =
+ imNikon.ShotInfoVersion * 10 + ShotInfo_buf[c] - '0';
+ }
+ else if (tag == 0x0093)
+ {
+ imNikon.NEFCompression = i = get2();
+ if ((i == 7) || (i == 9))
+ {
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ }
+ else if (tag == 0x0097)
+ { // ver97
+ FORC4 imNikon.ColorBalanceVersion =
+ imNikon.ColorBalanceVersion * 10 + fgetc(ifp) - '0';
+ switch (imNikon.ColorBalanceVersion)
+ {
+ case 100: // NIKON D100
+ fseek(ifp, 0x44L, SEEK_CUR);
+ FORC4 cam_mul[RBGG_2_RGBG(c)] = get2();
+ break;
+ case 102: // NIKON D2H
+ fseek(ifp, 0x6L, SEEK_CUR);
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = get2();
+ break;
+ case 103: // NIKON D70, D70s
+ fseek(ifp, 0x10L, SEEK_CUR);
+ FORC4 cam_mul[c] = get2();
+ }
+ if (imNikon.ColorBalanceVersion >= 200)
+ {
+ /*
+ 204: NIKON D2X, D2Xs
+ 205: NIKON D50
+ 206: NIKON D2Hs
+ 207: NIKON D200
+ 208: NIKON D40, D40X, D80
+ 209: NIKON D3, D3X, D300, D700
+ 210: NIKON D60
+ 211: NIKON D90, D5000
+ 212: NIKON D300S
+ 213: NIKON D3000
+ 214: NIKON D3S
+ 215: NIKON D3100
+ 216: NIKON D5100, D7000
+ 217: NIKON D4, D600, D800, D800E, D3200
+ -= unknown =-
+ 218: NIKON D5200, D7100
+ 219: NIKON D5300
+ 220: NIKON D610, Df
+ 221: NIKON D3300
+ 222: NIKON D4S
+ 223: NIKON D750, D810
+ 224: NIKON D3400, D3500, D5500, D5600, D7200
+ 225: NIKON D5, D500
+ 226: NIKON D7500
+ 227: NIKON D850
+ */
+ if (imNikon.ColorBalanceVersion != 205)
+ {
+ fseek(ifp, 0x118L, SEEK_CUR);
+ }
+ ColorBalanceData_ready =
+ (fread(ColorBalanceData_buf, 324, 1, ifp) == 1);
+ }
+ if ((imNikon.ColorBalanceVersion >= 400) &&
+ (imNikon.ColorBalanceVersion <= 405))
+ { // 1 J1, 1 V1, 1 J2, 1 V2, 1 J3, 1 S1, 1 AW1, 1 S2, 1 J4, 1 V3, 1 J5
+ ilm.CameraFormat = LIBRAW_FORMAT_1INCH;
+ ilm.CameraMount = LIBRAW_MOUNT_Nikon_CX;
+ }
+ else if ((imNikon.ColorBalanceVersion >= 500) &&
+ (imNikon.ColorBalanceVersion <= 502))
+ { // P7700, P7800, P330, P340
+ ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ }
+ else if (imNikon.ColorBalanceVersion == 601)
+ { // Coolpix A
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ }
+ }
+ else if (tag == 0x0098) // contains lens data
+ {
+ FORC4 imNikon.LensDataVersion =
+ imNikon.LensDataVersion * 10 + fgetc(ifp) - '0';
+ switch (imNikon.LensDataVersion)
+ {
+ case 100:
+ LensData_len = 9;
+ break;
+ case 101:
+ case 201: // encrypted, starting from v.201
+ case 202:
+ case 203:
+ LensData_len = 15;
+ break;
+ case 204:
+ LensData_len = 16;
+ break;
+ case 400:
+ LensData_len = 459;
+ break;
+ case 401:
+ LensData_len = 590;
+ break;
+ case 402:
+ LensData_len = 509;
+ break;
+ case 403:
+ LensData_len = 879;
+ break;
+ case 800:
+ case 801:
+ LensData_len = 58;
+ break;
+ case 802:
+ LensData_len = 108;
+ break;
+ }
+ if (LensData_len)
+ {
+ LensData_buf = (uchar *)malloc(LensData_len);
+ fread(LensData_buf, LensData_len, 1, ifp);
+ }
+ }
+ else if (tag == 0x00a0)
+ {
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ }
+ else if (tag == 0x00a7) // shutter count
+ {
+ imNikon.key = fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp);
+ if (custom_serial)
+ {
+ ci = xlat[0][custom_serial];
+ }
+ else
+ {
+ ci = xlat[0][serial & 0xff];
+ }
+ cj = xlat[1][imNikon.key];
+ ck = 0x60;
+ if (((unsigned)(imNikon.ColorBalanceVersion - 200) < 18) &&
+ ColorBalanceData_ready)
+ {
+ for (i = 0; i < 324; i++)
+ ColorBalanceData_buf[i] ^= (cj += ci * ck++);
+ i = "66666>666;6A;:;555"[imNikon.ColorBalanceVersion - 200] - '0';
+ FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
+ sget2(ColorBalanceData_buf + (i & -2) + c * 2);
+ }
+
+ if (LensData_len)
+ {
+ if (imNikon.LensDataVersion > 200)
+ {
+ cj = xlat[1][imNikon.key];
+ ck = 0x60;
+ for (i = 0; i < LensData_len; i++)
+ {
+ LensData_buf[i] ^= (cj += ci * ck++);
+ }
+ }
+ processNikonLensData(LensData_buf, LensData_len);
+ LensData_len = 0;
+ free(LensData_buf);
+ }
+ if (ShotInfo_len && (imNikon.ShotInfoVersion >= 208)) {
+ unsigned RotationOffset = 0,
+ OrientationOffset = 0;
+
+ cj = xlat[1][imNikon.key];
+ ck = 0x60;
+ for (i = 4; i < ShotInfo_len; i++) {
+ ShotInfo_buf[i] ^= (cj += ci * ck++);
+
+/* for dump:
+cj_block[i-4] = cj;
+ck_block[i-4] = ck-1;
+*/
+ }
+/* for dump:
+printf ("==>> ci: 0x%02x, cj at start: 0x%02x\n",
+ci, xlat[1][imNikon.key]);
+hexDump("ck array:", ck_block, ShotInfo_len-4);
+hexDump("cj array:", cj_block, ShotInfo_len-4);
+free(cj_block);
+free(ck_block);
+*/
+
+ switch (imNikon.ShotInfoVersion) {
+ case 208: // ShotInfoD80, Rotation
+ RotationOffset = 590;
+ if (RotationOffset<ShotInfo_len) {
+ imNikon.MakernotesFlip = *(ShotInfo_buf+RotationOffset) & 0x07;
+ }
+ break;
+
+ case 231: // ShotInfoD4S, Rotation, Roll/Pitch/Yaw
+ OrientationOffset = 0x350b;
+ RotationOffset = 0x3693;
+ if (RotationOffset<ShotInfo_len) {
+ imNikon.MakernotesFlip = (*(ShotInfo_buf+RotationOffset)>>4) & 0x03;
+ }
+ break;
+
+ case 233: // ShotInfoD810, Roll/Pitch/Yaw
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0x84);
+ break;
+
+ case 238: // D5, ShotInfoD500, Rotation, Roll/Pitch/Yaw
+ case 239: // D500, ShotInfoD500, Rotation, Roll/Pitch/Yaw
+ RotationOffset = sget4_order(morder, ShotInfo_buf+0x10) + 0xca;
+ if (RotationOffset > 0xca) {
+ RotationOffset -= 0xb0;
+ }
+ if (RotationOffset<ShotInfo_len) {
+ imNikon.MakernotesFlip = *(ShotInfo_buf+RotationOffset) & 0x03;
+ }
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0xa0);
+ break;
+
+ case 243: // ShotInfoD850, Roll/Pitch/Yaw
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0xa0);
+ break;
+
+ case 246: // ShotInfoD6, Roll/Pitch/Yaw
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0x9c);
+ break;
+
+ case 800: // Z 6, Z 7, ShotInfoZ7II, Roll/Pitch/Yaw
+ case 801: // Z 50, ShotInfoZ7II, Roll/Pitch/Yaw
+ case 802: // Z 5, ShotInfoZ7II, Roll/Pitch/Yaw
+ case 803: // Z 6_2, Z 7_2, ShotInfoZ7II, Roll/Pitch/Yaw
+ case 804: // Z fc ShotInfoZ7II, Roll/Pitch/Yaw
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0x98);
+ break;
+
+ case 805: // Z 9, ShotInfoZ9, Roll/Pitch/Yaw
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0x84);
+ break;
+ }
+
+ if (OrientationOffset && ((OrientationOffset+12)<ShotInfo_len) && OrientationOffset < 0xffff) {
+ if (imNikon.ShotInfoVersion == 231) // ShotInfoD4S
+ imNikon.RollAngle = AngleConversion_a(morder, ShotInfo_buf+OrientationOffset);
+ else
+ imNikon.RollAngle = AngleConversion(morder, ShotInfo_buf+OrientationOffset);
+ imNikon.PitchAngle = AngleConversion (morder, ShotInfo_buf+OrientationOffset+4);
+ imNikon.YawAngle = AngleConversion (morder, ShotInfo_buf+OrientationOffset+8);
+ }
+ if ((RotationOffset) && (imNikon.MakernotesFlip < 4) && (imNikon.MakernotesFlip >= 0))
+ imNikon.MakernotesFlip = "0863"[imNikon.MakernotesFlip] - '0';
+ ShotInfo_len = 0;
+ free(ShotInfo_buf);
+ }
+ }
+ else if (tag == 0x00a8)
+ { // contains flash data
+ FORC4 imNikon.FlashInfoVersion =
+ imNikon.FlashInfoVersion * 10 + fgetc(ifp) - '0';
+ }
+ else if (tag == 0x00b0)
+ {
+ get4(); // ME (multi-exposure) tag version, 4 symbols
+ imNikon.ExposureMode = get4();
+ imNikon.nMEshots = get4();
+ imNikon.MEgainOn = get4();
+ }
+ else if (tag == 0x00b7) // AFInfo2
+ {
+ if (!imCommon.afcount && len > 4)
+ {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ int ver = 0;
+ FORC4 ver = ver * 10 + (fgetc(ifp) - '0');
+ imCommon.afdata[imCommon.afcount].AFInfoData_version = ver;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len-4;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ fread(imCommon.afdata[imCommon.afcount].AFInfoData, imCommon.afdata[imCommon.afcount].AFInfoData_length, 1, ifp);
+ imCommon.afcount = 1;
+ }
+ }
+ else if (tag == 0x00b9)
+ {
+ imNikon.AFFineTune = fgetc(ifp);
+ imNikon.AFFineTuneIndex = fgetc(ifp);
+ imNikon.AFFineTuneAdj = (int8_t)fgetc(ifp);
+ }
+ else if ((tag == 0x0100) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_UNDEFINED))
+ {
+ thumb_offset = ftell(ifp);
+ thumb_length = len;
+ }
+ else if (tag == 0x0e01)
+ { /* Nikon Software / in-camera edit Note */
+ int loopc = 0;
+ int WhiteBalanceAdj_active = 0;
+ order = 0x4949;
+ fseek(ifp, 22, SEEK_CUR);
+ for (offset = 22; offset + 22 < len; offset += 22 + i)
+ {
+ if (loopc++ > 1024)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ tag = get4();
+ fseek(ifp, 14, SEEK_CUR);
+ i = get4() - 4;
+
+ if (tag == 0x76a43204)
+ {
+ WhiteBalanceAdj_active = fgetc(ifp);
+ }
+ else if (tag == 0xbf3c6c20)
+ {
+ if (WhiteBalanceAdj_active)
+ {
+ union {
+ double dbl;
+ unsigned long long lng;
+ } un;
+ un.dbl = getreal(LIBRAW_EXIFTAG_TYPE_DOUBLE);
+ if ((un.lng != 0x3FF0000000000000ULL) &&
+ (un.lng != 0x000000000000F03FULL))
+ {
+ cam_mul[0] = un.dbl;
+ cam_mul[2] = getreal(LIBRAW_EXIFTAG_TYPE_DOUBLE);
+ cam_mul[1] = cam_mul[3] = 1.0;
+ i -= 16;
+ }
+ else
+ i -= 8;
+ }
+ fseek(ifp, i, SEEK_CUR);
+ }
+ else if (tag == 0x76a43207)
+ {
+ flip = get2();
+ }
+ else
+ {
+ fseek(ifp, i, SEEK_CUR);
+ }
+ }
+ }
+ else if (tag == 0x0e22)
+ {
+ FORC4 imNikon.NEFBitDepth[c] = get2();
+ }
+ next:
+ fseek(ifp, save, SEEK_SET);
+ }
+quit:
+ order = sorder;
+}
+
+unsigned sget4_order (short _order, uchar *s) {
+ unsigned v;
+ if (_order == 0x4949)
+ v= s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+ else
+ v= s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
+ return v;
+}
+
+double sget_fixed32u (short _order, uchar *s) {
+ unsigned v = sget4_order (_order, s);
+ return ((double)v / 6.5536 + 0.5) / 10000.0;
+}
+
+double AngleConversion_a (short _order, uchar *s) {
+ double v = sget_fixed32u(_order, s);
+ if (v < 180.0) return -v;
+ return 360.0-v;
+}
+
+double AngleConversion (short _order, uchar *s) {
+ double v = sget_fixed32u(_order, s);
+ if (v <= 180.0) return v;
+ return v-360.0;
+}
+
+/* ========= */
+/*
+void hexDump(char *title, void *addr, int len)
+{
+ int i;
+ unsigned char buff[17];
+ unsigned char *pc = (unsigned char*)addr;
+
+ // Output description if given.
+ if (title != NULL)
+ printf ("%s:\n", title);
+
+ // Process every byte in the data.
+ for (i = 0; i < len; i++) {
+ // Multiple of 16 means new line (with line offset).
+
+ if ((i % 16) == 0) {
+ // Just don't print ASCII for the zeroth line.
+ if (i != 0)
+ printf(" %s\n", buff);
+
+ // Output the offset.
+ printf(" %04x ", i);
+ }
+
+ // Now the hex code for the specific character.
+ printf(" %02x", pc[i]);
+
+ // And store a printable ASCII character for later.
+ if ((pc[i] < 0x20) || (pc[i] > 0x7e)) {
+ buff[i % 16] = '.';
+ } else {
+ buff[i % 16] = pc[i];
+ }
+
+ buff[(i % 16) + 1] = '\0';
+ }
+
+ // Pad out last line if not exactly 16 characters.
+ while ((i % 16) != 0) {
+ printf(" ");
+ i++;
+ }
+
+ // And print the final ASCII bit.
+ printf(" %s\n", buff);
+}
+*/
diff --git a/libkdcraw/libraw/src/metadata/normalize_model.cpp b/libkdcraw/libraw/src/metadata/normalize_model.cpp
new file mode 100644
index 0000000..064c4a5
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/normalize_model.cpp
@@ -0,0 +1,1451 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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_defs.h"
+#include "../../internal/libraw_cameraids.h"
+
+void LibRaw::GetNormalizedModel()
+{
+
+ int i, j;
+ char *ps;
+ int try_xml = 0;
+
+ static const struct
+ {
+ unsigned long long id;
+ char t_model[20];
+ } unique[] =
+// clang-format off
+ {
+ { CanonID_EOS_M50, "EOS M50"}, // Kiss M
+ { CanonID_EOS_M6_Mark_II, "EOS M6 Mark II"},
+ { CanonID_EOS_M200, "EOS M200"},
+ { CanonID_EOS_D30, "EOS D30"},
+ { CanonID_EOS_D60, "EOS D60"},
+ { CanonID_EOS_M3, "EOS M3"},
+ { CanonID_EOS_M10, "EOS M10"},
+ { CanonID_EOS_M5, "EOS M5"},
+ { CanonID_EOS_M100, "EOS M100"},
+ { CanonID_EOS_M6, "EOS M6"},
+ { CanonID_EOS_1D, "EOS-1D"},
+ { CanonID_EOS_1Ds, "EOS-1Ds"},
+ { CanonID_EOS_10D, "EOS 10D"},
+ { CanonID_EOS_1D_Mark_III, "EOS-1D Mark III"},
+ { CanonID_EOS_300D, "EOS 300D"}, // Digital Rebel / Kiss Digital
+ { CanonID_EOS_1D_Mark_II, "EOS-1D Mark II"},
+ { CanonID_EOS_20D, "EOS 20D"},
+ { CanonID_EOS_450D, "EOS 450D"}, // Digital Rebel XSi / Kiss X2
+ { CanonID_EOS_1Ds_Mark_II, "EOS-1Ds Mark II"},
+ { CanonID_EOS_350D, "EOS 350D"}, // Digital Rebel XT / Kiss Digital N
+ { CanonID_EOS_40D, "EOS 40D"},
+ { CanonID_EOS_5D, "EOS 5D"},
+ { CanonID_EOS_1Ds_Mark_III, "EOS-1Ds Mark III"},
+ { CanonID_EOS_5D_Mark_II, "EOS 5D Mark II"},
+ { CanonID_EOS_1D_Mark_II_N, "EOS-1D Mark II N"},
+ { CanonID_EOS_30D, "EOS 30D"},
+ { CanonID_EOS_400D, "EOS 400D"}, // Digital Rebel XTi / Kiss Digital X
+ { CanonID_EOS_7D, "EOS 7D"},
+ { CanonID_EOS_500D, "EOS 500D"}, // Rebel T1i / Kiss X3
+ { CanonID_EOS_1000D, "EOS 1000D"}, // Digital Rebel XS / Kiss F
+ { CanonID_EOS_50D, "EOS 50D"},
+ { CanonID_EOS_1D_X, "EOS-1D X"},
+ { CanonID_EOS_550D, "EOS 550D"}, // Rebel T2i / Kiss X4
+ { CanonID_EOS_1D_Mark_IV, "EOS-1D Mark IV"},
+ { CanonID_EOS_5D_Mark_III, "EOS 5D Mark III"},
+ { CanonID_EOS_600D, "EOS 600D"}, // Rebel T3i / Kiss X5
+ { CanonID_EOS_60D, "EOS 60D"},
+ { CanonID_EOS_1100D, "EOS 1100D"}, // Rebel T3 / Kiss X50
+ { CanonID_EOS_7D_Mark_II, "EOS 7D Mark II"},
+ { CanonID_EOS_650D, "EOS 650D"}, // Rebel T4i / Kiss X6i
+ { CanonID_EOS_6D, "EOS 6D"},
+ { CanonID_EOS_1D_C, "EOS-1D C"},
+ { CanonID_EOS_70D, "EOS 70D"},
+ { CanonID_EOS_700D, "EOS 700D"}, // Rebel T5i / Kiss X7i
+ { CanonID_EOS_1200D, "EOS 1200D"}, // Rebel T5 / Kiss X70 / Hi
+ { CanonID_EOS_1D_X_Mark_II, "EOS-1D X Mark II"},
+ { CanonID_EOS_M, "EOS M"},
+ { CanonID_EOS_100D, "EOS 100D"}, // Rebel SL1 / Kiss X7
+ { CanonID_EOS_760D, "EOS 760D"}, // Rebel T6s / 8000D
+ { CanonID_EOS_5D_Mark_IV, "EOS 5D Mark IV"},
+ { CanonID_EOS_80D, "EOS 80D"},
+ { CanonID_EOS_M2, "EOS M2"},
+ { CanonID_EOS_5DS, "EOS 5DS"},
+ { CanonID_EOS_750D, "EOS 750D"}, // Rebel T6i / Kiss X8i
+ { CanonID_EOS_5DS_R, "EOS 5DS R"},
+ { CanonID_EOS_1300D, "EOS 1300D"}, // Rebel T6 / Kiss X80
+ { CanonID_EOS_800D, "EOS 800D"}, // Rebel T7i / Kiss X9i
+ { CanonID_EOS_6D_Mark_II, "EOS 6D Mark II"},
+ { CanonID_EOS_77D, "EOS 77D"}, // 9000D
+ { CanonID_EOS_200D, "EOS 200D"}, // Rebel SL2 / Kiss X9
+ { CanonID_EOS_R5, "EOS R5"},
+ { CanonID_EOS_3000D, "EOS 3000D"}, // Rebel T100 / 4000D
+ { CanonID_EOS_R, "EOS R"},
+ { CanonID_EOS_1D_X_Mark_III, "EOS-1D X Mark III"},
+ { CanonID_EOS_1500D, "EOS 1500D"}, // Rebel T7 / 2000D / Kiss X90
+ { CanonID_EOS_RP, "EOS RP"},
+ { CanonID_EOS_850D, "EOS 850D"}, // EOS Rebel T8i / X10i
+ { CanonID_EOS_250D, "EOS 250D"}, // Rebel SL3 / 200D II / Kiss X10
+ { CanonID_EOS_90D, "EOS 90D"},
+ { CanonID_EOS_R3, "EOS R3"},
+ { CanonID_EOS_R6, "EOS R6"},
+ { CanonID_EOS_R7, "EOS R7"},
+ { CanonID_EOS_R10, "EOS R10"},
+ { CanonID_EOS_M50_Mark_II, "EOS M50 Mark II"}, // M50m2, Kiss M2
+ },
+#if 0
+ olyque[] = {
+ { OlyID_E_20, "E-20"},
+ { OlyID_E_20, "E-20,E-20N,E-20P"},
+ { OlyID_E_1, "E-1"},
+ { OlyID_E_300, "E-300"},
+ { OlyID_SP_550UZ, "SP-550UZ"},
+ { OlyID_SP_550UZ, "SP550UZ"},
+ { OlyID_SP_510UZ, "SP-510UZ"},
+ { OlyID_SP_510UZ, "SP510UZ"},
+ { OlyID_SP_560UZ, "SP-560UZ"},
+ { OlyID_SP_560UZ, "SP560UZ"},
+ { OlyID_SP_570UZ, "SP-570UZ"},
+ { OlyID_SP_570UZ, "SP570UZ"},
+ { OlyID_SP_565UZ, "SP-565UZ"},
+ { OlyID_SP_565UZ, "SP565UZ"},
+ { OlyID_XZ_1, "XZ-1"},
+ { OlyID_XZ_2, "XZ-2"},
+ { OlyID_XZ_10, "XZ-10"},
+ { OlyID_STYLUS_1, "Stylus 1"},
+ { OlyID_STYLUS_1, "STYLUS1"},
+ { OlyID_STYLUS_1, "STYLUS1,1s"},
+ { OlyID_SH_2, "SH-2"},
+ { OlyID_TG_4, "TG-4"},
+ { OlyID_TG_5, "TG-5"},
+ { OlyID_TG_6, "TG-6"},
+ { OlyID_E_10, "E-10"},
+ { OlyID_AIR_A01, "AIR A01"},
+ { OlyID_AIR_A01, "AIR-A01"},
+ { OlyID_E_330, "E-330"},
+ { OlyID_E_500, "E-500"},
+ { OlyID_E_400, "E-400"},
+ { OlyID_E_510, "E-510"},
+ { OlyID_E_3, "E-3"},
+ { OlyID_E_410, "E-410"},
+ { OlyID_E_420, "E-420"},
+ { OlyID_E_30, "E-30"},
+ { OlyID_E_520, "E-520"},
+ { OlyID_E_P1, "E-P1"},
+ { OlyID_E_620, "E-620"},
+ { OlyID_E_P2, "E-P2"},
+ { OlyID_E_PL1, "E-PL1"},
+ { OlyID_E_450, "E-450"},
+ { OlyID_E_600, "E-600"},
+ { OlyID_E_P3, "E-P3"},
+ { OlyID_E_5, "E-5"},
+ { OlyID_E_PL2, "E-PL2"},
+ { OlyID_E_M5, "E-M5"},
+ { OlyID_E_PL3, "E-PL3"},
+ { OlyID_E_PM1, "E-PM1"},
+ { OlyID_E_PL1s, "E-PL1s"},
+ { OlyID_E_PL5, "E-PL5"},
+ { OlyID_E_PM2, "E-PM2"},
+ { OlyID_E_P5, "E-P5"},
+ { OlyID_E_PL6, "E-PL6"},
+ { OlyID_E_PL7, "E-PL7"},
+ { OlyID_E_M1, "E-M1"},
+ { OlyID_E_M10, "E-M10"},
+ { OlyID_E_M5_Mark_II, "E-M5 Mark II"},
+ { OlyID_E_M5_Mark_II, "E-M5MarkII"},
+ { OlyID_E_M5_Mark_II, "E-M5_M2"},
+ { OlyID_E_M10_Mark_II, "E-M10 Mark II"}, // Clauss piX 5oo
+ { OlyID_E_M10_Mark_II, "E-M10MarkII"},
+ { OlyID_E_M10_Mark_II, "E-M10_M2"},
+ { OlyID_PEN_F, "PEN-F"},
+ { OlyID_E_PL8, "E-PL8"},
+ { OlyID_E_M1_Mark_II, "E-M1 Mark II"},
+ { OlyID_E_M1_Mark_II, "E-M1MarkII"},
+ { OlyID_E_M1_Mark_II, "E-M1_M2"},
+ { OlyID_E_M10_Mark_III, "E-M10 Mark III"},
+ { OlyID_E_M10_Mark_III, "E-M10_M3"},
+ { OlyID_E_PL9, "E-PL9"},
+ { OlyID_E_M1X, "E-M1X"},
+ { OlyID_E_PL10, "E-PL10"},
+ { OlyID_E_M10_Mark_IV, "E-M10 Mark IV"},
+ { OlyID_E_M10_Mark_IV, "E-M10MarkIV"},
+ { OlyID_E_M10_Mark_IV, "E-M10_M4"},
+ { OlyID_E_M5_Mark_III, "E-M5 Mark III"},
+ { OlyID_E_M5_Mark_III, "E-M5MarkIII"},
+ { OlyID_E_M5_Mark_III, "E-M5_M3"},
+ { OlyID_E_M1_Mark_III, "E-M1 Mark III"},
+ { OlyID_E_M1_Mark_III, "E-M1MarkIII"},
+ { OlyID_E_M1_Mark_III, "E-M1_M3"},
+ { OlyID_E_P7 "E-P7"},
+ { OlyID_C_3030Z, "C-3030Z"},
+ { OlyID_C_3030Z, "C3030Z"},
+ { OlyID_C_5050Z, "C-5050Z"},
+ { OlyID_C_5050Z, "C5050Z"},
+ { OlyID_C_350Z, "C-350Z"},
+ { OlyID_C_350Z, "X200,D560Z,C350Z"},
+ { OlyID_C_740UZ, "C-740UZ"},
+ { OlyID_C_740UZ, "C740UZ"},
+ { OlyID_C_5060WZ, "C-5060WZ"},
+ { OlyID_C_5060WZ, "C5060WZ"},
+ { OlyID_C_8080WZ, "C-8080WZ"},
+ { OlyID_C_8080WZ, "C8080WZ"},
+ { OlyID_C_770UZ, "C-770UZ"},
+ { OlyID_C_770UZ, "C770UZ"},
+ { OlyID_C_7070WZ, "C-7070WZ"},
+ { OlyID_C_7070WZ, "C7070WZ"},
+ { OlyID_C_7000Z, "C-7000Z"},
+ { OlyID_C_7000Z, "C70Z,C7000Z"},
+ { OlyID_SP_500UZ, "SP-500UZ"},
+ { OlyID_SP_500UZ, "SP500UZ"},
+ { OlyID_SP_310, "SP-310"},
+ { OlyID_SP_310, "SP310"},
+ { OlyID_SP_350, "SP-350"},
+ { OlyID_SP_350, "SP350"},
+ { OlyID_SP_320, "SP-320"},
+ { OlyID_SP_320, "SP320"},
+ },
+
+ penique[] = {
+ { PentaxID_Optio_S, "Optio S"},
+ { PentaxID_Optio_S_V101, "Optio S V1.01"},
+ { PentaxID_staristD, "*istD"},
+ { PentaxID_staristD, "*ist D"},
+ { PentaxID_Optio_33WR, "Optio 33WR"},
+ { PentaxID_Optio_S4, "Optio S4"},
+ { PentaxID_Optio_750Z, "Optio 750Z"},
+ { PentaxID_staristDS, "*istDS"},
+ { PentaxID_staristDS, "*ist DS"},
+ { PentaxID_staristDL, "*istDL"},
+ { PentaxID_staristDL, "*ist DL"},
+ { PentaxID_staristDS2, "*istDS2"},
+ { PentaxID_staristDS2, "*ist DS2"},
+ { PentaxID_GX_1S, "GX-1S"}, // Samsung
+ { PentaxID_staristDL2, "*istDL2"},
+ { PentaxID_staristDL2, "*ist DL2"},
+ { PentaxID_GX_1L, "GX-1L"}, // Samsung
+ { PentaxID_K100D, "K100D"},
+ { PentaxID_K110D, "K110D"},
+ { PentaxID_K100D_Super, "K100D Super"},
+ { PentaxID_K10D, "K10D"},
+ { PentaxID_GX10, "GX10"}, // Samsung
+ { PentaxID_GX10, "GX-10"}, // Samsung
+ { PentaxID_K20D, "K20D"},
+ { PentaxID_GX20, "GX20"}, // Samsung
+ { PentaxID_GX20, "GX-20"}, // Samsung
+ { PentaxID_K200D, "K200D"},
+ { PentaxID_K2000, "K2000"},
+ { PentaxID_K_m, "K-m"},
+ { PentaxID_K_7, "K-7"},
+ { PentaxID_K_x, "K-x"},
+ { PentaxID_645D, "645D"},
+ { PentaxID_K_r, "K-r"},
+ { PentaxID_K_5, "K-5"},
+ { PentaxID_Q, "Q"},
+ { PentaxID_K_01, "K-01"},
+ { PentaxID_K_30, "K-30"},
+ { PentaxID_Q10, "Q10"},
+ { PentaxID_K_5_II, "K-5 II"},
+ { PentaxID_K_5_II_s, "K-5 II s"},
+ { PentaxID_Q7, "Q7"},
+ { PentaxID_MX_1, "MX-1"},
+ { PentaxID_K_50, "K-50"},
+ { PentaxID_K_3, "K-3"},
+ { PentaxID_K_500, "K-500"},
+ { PentaxID_645Z, "645Z"},
+ { PentaxID_K_S1, "K-S1"},
+ { PentaxID_K_S2, "K-S2"}, // Ricoh
+ { PentaxID_Q_S1, "Q-S1"},
+ { PentaxID_K_1, "K-1"}, // Ricoh
+ { PentaxID_K_3_II, "K-3 II"}, // Ricoh
+ { PentaxID_GR_III, "GR III"}, // Ricoh
+ { PentaxID_K_70, "K-70"}, // Ricoh
+ { PentaxID_KP, "KP"}, // Ricoh
+ { PentaxID_K_1_Mark_II, "K-1 Mark II"}, // Ricoh
+ { PentaxID_K_3_III, "K-3 Mark III"}, // Ricoh
+ { PentaxID_GR_IIIx, "GR IIIx"},
+ },
+#endif
+ sonique[] = {
+ { SonyID_DSC_R1, "DSC-R1"},
+ { SonyID_DSLR_A100, "DSLR-A100"},
+ { SonyID_DSLR_A900, "DSLR-A900"},
+ { SonyID_DSLR_A700, "DSLR-A700"},
+ { SonyID_DSLR_A200, "DSLR-A200"},
+ { SonyID_DSLR_A350, "DSLR-A350"},
+ { SonyID_DSLR_A300, "DSLR-A300"},
+ { SonyID_DSLR_A900_APSC, "DSLR-A900"},
+ { SonyID_DSLR_A380, "DSLR-A380"}, // DSLR-A390
+ { SonyID_DSLR_A330, "DSLR-A330"},
+ { SonyID_DSLR_A230, "DSLR-A230"},
+ { SonyID_DSLR_A290, "DSLR-A290"},
+ { SonyID_DSLR_A850, "DSLR-A850"},
+ { SonyID_DSLR_A850_APSC, "DSLR-A850"},
+ { SonyID_DSLR_A550, "DSLR-A550"},
+ { SonyID_DSLR_A500, "DSLR-A500"},
+ { SonyID_DSLR_A450, "DSLR-A450"},
+ { SonyID_NEX_5, "NEX-5"},
+ { SonyID_NEX_3, "NEX-3"},
+ { SonyID_SLT_A33, "SLT-A33"},
+ { SonyID_SLT_A55, "SLT-A55"}, // SLT-A55V
+ { SonyID_DSLR_A560, "DSLR-A560"},
+ { SonyID_DSLR_A580, "DSLR-A580"},
+ { SonyID_NEX_C3, "NEX-C3"},
+ { SonyID_SLT_A35, "SLT-A35"},
+ { SonyID_SLT_A65, "SLT-A65"}, // SLT-A65V
+ { SonyID_SLT_A77, "SLT-A77"}, // SLT-A77V
+ { SonyID_NEX_5N, "NEX-5N"},
+ { SonyID_NEX_7, "NEX-7"}, // Hasselblad Lunar
+ { SonyID_NEX_VG20, "NEX-VG20"},
+ { SonyID_SLT_A37, "SLT-A37"},
+ { SonyID_SLT_A57, "SLT-A57"},
+ { SonyID_NEX_F3, "NEX-F3"},
+ { SonyID_SLT_A99, "SLT-A99"}, // SLT-A99V / Hasselblad HV
+ { SonyID_NEX_6, "NEX-6"},
+ { SonyID_NEX_5R, "NEX-5R"},
+ { SonyID_DSC_RX100, "DSC-RX100"}, // Hasselblad Stellar
+ { SonyID_DSC_RX1, "DSC-RX1"},
+ { SonyID_NEX_VG900, "NEX-VG900"},
+ { SonyID_NEX_VG30, "NEX-VG30"},
+ { SonyID_ILCE_3000, "ILCE-3000"}, // ILCE-3500
+ { SonyID_SLT_A58, "SLT-A58"},
+ { SonyID_NEX_3N, "NEX-3N"},
+ { SonyID_ILCE_7, "ILCE-7"},
+ { SonyID_NEX_5T, "NEX-5T"},
+ { SonyID_DSC_RX100M2, "DSC-RX100M2"}, // Hasselblad Stellar II
+ { SonyID_DSC_RX10, "DSC-RX10"},
+ { SonyID_DSC_RX1R, "DSC-RX1R"},
+ { SonyID_ILCE_7R, "ILCE-7R"}, // Hasselblad Lusso
+ { SonyID_ILCE_6000, "ILCE-6000"},
+ { SonyID_ILCE_5000, "ILCE-5000"},
+ { SonyID_DSC_RX100M3, "DSC-RX100M3"},
+ { SonyID_ILCE_7S, "ILCE-7S"},
+ { SonyID_ILCA_77M2, "ILCA-77M2"},
+ { SonyID_ILCE_5100, "ILCE-5100"},
+ { SonyID_ILCE_7M2, "ILCE-7M2"},
+ { SonyID_DSC_RX100M4, "DSC-RX100M4"},
+ { SonyID_DSC_RX10M2, "DSC-RX10M2"},
+ { SonyID_DSC_RX1RM2, "DSC-RX1RM2"},
+ { SonyID_ILCE_QX1, "ILCE-QX1"},
+ { SonyID_ILCE_7RM2, "ILCE-7RM2"},
+ { SonyID_ILCE_7SM2, "ILCE-7SM2"},
+ { SonyID_ILCA_68, "ILCA-68"},
+ { SonyID_ILCA_99M2, "ILCA-99M2"},
+ { SonyID_DSC_RX10M3, "DSC-RX10M3"},
+ { SonyID_DSC_RX100M5, "DSC-RX100M5"},
+ { SonyID_ILCE_6300, "ILCE-6300"},
+ { SonyID_ILCE_9, "ILCE-9"},
+ { SonyID_ILCE_6500, "ILCE-6500"},
+ { SonyID_ILCE_7RM3, "ILCE-7RM3"},
+ { SonyID_ILCE_7M3, "ILCE-7M3"},
+ { SonyID_DSC_RX0, "DSC-RX0"},
+ { SonyID_DSC_RX10M4, "DSC-RX10M4"},
+ { SonyID_DSC_RX100M6, "DSC-RX100M6"},
+ { SonyID_DSC_HX99, "DSC-HX99"},
+ { SonyID_DSC_RX100M5A, "DSC-RX100M5A"},
+ { SonyID_ILCE_6400, "ILCE-6400"},
+ { SonyID_DSC_RX0M2, "DSC-RX0M2"},
+ { SonyID_DSC_RX100M7, "DSC-RX100M7"},
+ { SonyID_ILCE_7RM4, "ILCE-7RM4"},
+ { SonyID_ILCE_9M2, "ILCE-9M2"},
+ { SonyID_ILCE_6600, "ILCE-6600"},
+ { SonyID_ILCE_6100, "ILCE-6100"},
+ { SonyID_ZV_1, "ZV-1"},
+ { SonyID_ILCE_7C, "ILCE-7C"},
+ { SonyID_ZV_E10, "ZV-E10"},
+ { SonyID_ILCE_7SM3, "ILCE-7SM3"},
+ { SonyID_ILCE_1, "ILCE-1"},
+ { SonyID_ILME_FX3, "ILME-FX3"},
+ { SonyID_ILCE_7RM3A, "ILCE-7RM3A"},
+ { SonyID_ILCE_7RM4A, "ILCE-7RM4A"},
+ { SonyID_ILCE_7M4, "ILCE-7M4"},
+ };
+
+ static const char *orig;
+
+ static const char fujialias[][16] = {
+ "@DBP for GX680", "DX-2000",
+ "@F500EXR", "F505EXR",
+ "@F600EXR", "F605EXR",
+ "@F770EXR", "F775EXR",
+ "@HS10", "HS10 HS11",
+ "@HS20EXR", "HS22EXR",
+ "@HS30EXR", "HS33EXR", "HS35EXR",
+ "@S5100", "S5500",
+ "@S5200", "S5600",
+ "@S6000fd", "S6500fd",
+ "@S9000", "S9500",
+ "@S9100", "S9600",
+ "@S200EXR", "S205EXR",
+ "@X-T1 IR", "X-T1IR",
+ "@GFX 100S", "GFX100S",
+ "@GFX 50S II", "GFX50S II"
+ };
+
+ static const char kodakalias[][16] = {
+ "@DCS Pro 14N", "Camerz ZDS 14", // Camerz rebadge make: "Photo Control"
+ "@DCS720X", "SCS2000",
+ "@DCS520C", "EOS D2000C", "EOS D2000", // EOS rebadge make: Canon
+ "@DCS560C", "EOS D6000C", "EOS D6000", // EOS rebadge make: Canon
+ "@DCS460M", "DCS460A", // 'A' was supposed to stand for 'achromatic', marketing changed it to 'M'
+ "@DCS460", "DCS460C", "DCS460D",
+ "@DCS465", "DCS465C", "DCS465D",
+ "@EOSDCS1", "EOSDCS1B", "EOSDCS1C",
+ "@EOSDCS3", "EOSDCS3B", "EOSDCS3C",
+ };
+
+ static const struct
+ {
+ const char *Kmodel;
+ ushort mount;
+ } Kodak_mounts[] = {
+ {"DCS465", LIBRAW_MOUNT_DigitalBack},
+ {"DCS5", LIBRAW_MOUNT_Canon_EF},
+ {"DCS Pro SLR/c", LIBRAW_MOUNT_Canon_EF},
+ {"DCS", LIBRAW_MOUNT_Nikon_F},
+ {"EOS", LIBRAW_MOUNT_Canon_EF},
+ {"NC2000", LIBRAW_MOUNT_Nikon_F}, // AP "News Camera"
+ {"Pixpro S-1", LIBRAW_MOUNT_mFT},
+ {"ProBack", LIBRAW_MOUNT_DigitalBack},
+ {"SCS1000", LIBRAW_MOUNT_Canon_EF},
+ };
+
+ static const char *KodakMonochrome[] = {
+ "DCS420M", "DCS420A", "DCS420I",
+ "DCS460M", "DCS460A", "DCS460I",
+ "DCS465M", "DCS465A", "DCS465I",
+ "DCS560M", "DCS660M", "DCS760M", "EOS D2000M", "EOS D6000M",
+ "EOSDCS1M", "EOSDCS1I",
+ "EOSDCS3M", "EOSDCS3I",
+ "EOSDCS5M", "EOSDCS5I",
+ "NC2000M", "NC2000A", "NC2000I",
+ };
+
+ static const char leafalias[][16] = {
+ // Leaf re-badged to Mamiya
+ "@Aptus-II 5", "DM22",
+ "@Aptus-II 6", "DM28",
+ "@Aptus-II 7", "DM33",
+ "@Aptus-II 8", "DM40",
+ "@Aptus-II 10", "DM56",
+ };
+
+ static const char KonicaMinolta_aliases[][24] = {
+ "@DG-5D", "DYNAX 5D", "MAXXUM 5D", "ALPHA-5 DIGITAL", "ALPHA SWEET DIGITAL",
+ "@DG-7D", "DYNAX 7D", "MAXXUM 7D", "ALPHA-7 DIGITAL",
+ };
+
+ static const char nikonalias[][16] = {
+ "@COOLPIX 2100", "E2100", "@COOLPIX 2500", "E2500",
+ "@COOLPIX 3200", "E3200", "@COOLPIX 3700", "E3700",
+ "@COOLPIX 4300", "E4300", "@COOLPIX 4500", "E4500",
+ "@COOLPIX 5000", "E5000", "@COOLPIX 5400", "E5400",
+ "@COOLPIX 5700", "E5700", "@COOLPIX 8400", "E8400",
+ "@COOLPIX 8700", "E8700", "@COOLPIX 8800", "E8800",
+ "@COOLPIX 700", "E700", "@COOLPIX 800", "E800",
+ "@COOLPIX 880", "E880", "@COOLPIX 900", "E900",
+ "@COOLPIX 950", "E950", "@COOLPIX 990", "E990",
+ "@COOLPIX 995", "E995", "@COOLPIX P7700", "COOLPIX Deneb",
+ "@COOLPIX P7800", "COOLPIX Kalon",
+ };
+
+ static const char olyalias[][32] = { // Olympus
+ "@AIR A01", "AIR-A01",
+ "@C-3030Z", "C3030Z",
+ "@C-5050Z", "C5050Z",
+ "@C-5060WZ", "C5060WZ",
+ "@C-7000Z", "C7000Z", "C70Z,C7000Z", "C70Z",
+ "@C-7070WZ", "C7070WZ",
+ "@C-8080WZ", "C8080WZ",
+ "@C-350Z", "C350Z", "X200,D560Z,C350Z", "X200", "D560Z",
+ "@C-740UZ", "C740UZ",
+ "@C-770UZ", "C770UZ",
+ "@E-20", "E-20,E-20N,E-20P", "E-20N", "E-20P",
+ "@E-M10 Mark II", "E-M10MarkII", "E-M10_M2", "piX 5oo",
+ "@E-M10 Mark III", "E-M10MarkIII", "E-M10_M3",
+ "@E-M10 Mark IV", "E-M10MarkIV", "E-M10_M4",
+ "@E-M1 Mark II", "E-M1MarkII", "E-M1_M2",
+ "@E-M1 Mark III", "E-M1MarkIII", "E-M1_M3",
+ "@E-M5 Mark II", "E-M5MarkII", "E-M5_M2",
+ "@E-M5 Mark III", "E-M5MarkIII", "E-M5_M3",
+ "@SH-2", "SH-3",
+ "@SP-310", "SP310",
+ "@SP-320", "SP320",
+ "@SP-350", "SP350",
+ "@SP-500UZ", "SP500UZ",
+ "@SP-510UZ", "SP510UZ",
+ "@SP-550UZ", "SP550UZ",
+ "@SP-560UZ", "SP560UZ",
+ "@SP-565UZ", "SP565UZ",
+ "@SP-570UZ", "SP570UZ",
+ "@Stylus 1", "STYLUS1", "STYLUS1s", "STYLUS1,1s",
+ };
+
+ static const char panalias[][16] = { // Panasonic, PanaLeica
+// fixed lens
+ "@DMC-FX150", "DMC-FX180",
+ "@DC-FZ1000M2", "DC-FZ10002", "V-Lux 5",
+ "@DMC-FZ1000", "V-LUX (Typ 114)",
+ "@DMC-FZ2500", "DMC-FZ2000", "DMC-FZH1",
+ "@DMC-FZ100", "V-LUX 2",
+ "@DMC-FZ150", "V-LUX 3",
+ "@DMC-FZ200", "V-LUX 4",
+ "@DMC-FZ300", "DMC-FZ330",
+ "@DMC-FZ35", "DMC-FZ38",
+ "@DMC-FZ40", "DMC-FZ42", "DMC-FZ45", "DC-FZ40", "DC-FZ42", "DC-FZ45",
+ "@DMC-FZ50", "V-LUX 1", "V-LUX1",
+ "@DMC-FZ70", "DMC-FZ72",
+ "@DC-FZ80", "DC-FZ81", "DC-FZ82", "DC-FZ83", "DC-FZ85",
+ "@DMC-LC1", "DIGILUX 2", "Digilux 2", "DIGILUX2",
+ "@DMC-LF1", "C (Typ 112)",
+ "@DC-LX100M2", "D-Lux 7",
+ "@DMC-LX100", "D-LUX (Typ 109)", "D-Lux (Typ 109)",
+ "@DMC-LX1", "D-Lux2", "D-LUX2", "D-LUX 2",
+ "@DMC-LX2", "D-LUX 3", "D-LUX3",
+ "@DMC-LX3", "D-LUX 4",
+ "@DMC-LX5", "D-LUX 5",
+ "@DMC-LX7", "D-LUX 6",
+ "@DMC-LX9", "DMC-LX10", "DMC-LX15",
+ "@DMC-ZS100", "DMC-ZS110", "DMC-TZ100", "DMC-TZ101", "DMC-TZ110", "DMC-TX1",
+ "@DC-ZS200", "DC-ZS220", "DC-TZ200", "DC-TZ202", "DC-TZ220", "DC-TX2", "C-Lux", "CAM-DC25",
+ "@DMC-ZS40", "DMC-TZ60", "DMC-TZ61",
+ "@DMC-ZS50", "DMC-TZ70", "DMC-TZ71",
+ "@DMC-ZS60", "DMC-TZ80", "DMC-TZ81", "DMC-TZ82", "DMC-TZ85",
+ "@DC-ZS70", "DC-TZ90", "DC-TZ91", "DC-TZ92", "DC-TZ93",
+ "@DC-ZS80", "DC-TZ95", "DC-TZ96", "DC-TZ97",
+
+// interchangeable lens
+ "@DC-G100", "DC-G110",
+ "@DC-G99", "DC-G90", "DC-G91", "DC-G95",
+ "@DMC-G7", "DMC-G70",
+ "@DMC-G8", "DMC-G80", "DMC-G81", "DMC-G85",
+ "@DMC-GH4", "AG-GH4", "CGO4",
+ "@DC-GF10", "DC-GF90", "DC-GX880",
+ "@DC-GF9", "DC-GX850", "DC-GX800",
+ "@DMC-GM1", "DMC-GM1S",
+ "@DMC-GX85", "DMC-GX80", "DMC-GX7MK2",
+ "@DC-GX9", "DC-GX7MK3",
+ "@DMC-L1", "DIGILUX 3", "DIGILUX3", // full 4/3 mount, not m43
+ };
+
+ static const char phase1alias[][16] = {
+ "@H20", "H 20",
+ "@H25", "H 25",
+ "@P20+", "P 20+",
+ "@P20", "P 20",
+ "@P21+", "P 21+", "M18", // "Mamiya M18"
+ "@P21", "P 21",
+ "@P25+", "P 25+", "M22", // "Mamiya M22"
+ "@P25", "P 25",
+ "@P30+", "P 30+", "M31", // "Mamiya M31"
+ "@P30", "P 30",
+ "@P40+", "P 40+",
+ "@P40", "P 40",
+ "@P45+", "P 45+",
+ "@P45", "P 45",
+ "@P65+", "P 65+",
+ "@P65", "P 65",
+ };
+
+ static const char SamsungPentax_aliases[][16] = {
+ "@*istDL2", "*ist DL2", "GX-1L",
+ "@*istDS2", "*ist DS2", "GX-1S",
+ "@*istDL", "*ist DL",
+ "@*istDS", "*ist DS",
+ "@*istD", "*ist D",
+ "@K10D", "GX10", "GX-10",
+ "@K20D", "GX20", "GX-20",
+ "@K-m", "K2000",
+ };
+
+ static const char samsungalias[][64] = {
+ "@EX1", "TL500",
+ "@NX U", "EK-GN100", "EK-GN110", "EK-GN120", "EK-KN120", "Galaxy NX",
+ "@NX mini", "NXF1",
+ "@WB2000", "TL350",
+ // "@WB5000", "WB5000/HZ25W", // no spaces around the slash separating names
+ // "@WB5500", "WB5500 / VLUU WB5500 / SAMSUNG HZ50W",
+ // "@WB500", "WB510 / VLUU WB500 / SAMSUNG HZ10W",
+ // "@WB550", "WB560 / VLUU WB550 / SAMSUNG HZ15W",
+ // "@WB650", "SAMSUNG WB650 / VLUU WB650 / SAMSUNG WB660" aka HZ35W
+ };
+
+//clang-format on
+ if (makeIs(LIBRAW_CAMERAMAKER_VLUU)) {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Samsung);
+ }
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Samsung) &&
+ (ilm.CameraMount == LIBRAW_MOUNT_Pentax_K)) {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Pentax);
+
+ } else if (makeIs(LIBRAW_CAMERAMAKER_Unknown)) {
+ if (strcasestr(model, "Google")) {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Google);
+ }
+#ifdef USE_6BY9RPI
+ else if(strcasestr(make,"RaspberryPi"))
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_RaspberryPi);
+#endif
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Hasselblad) && is_Sony)
+ {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Sony);
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_OmDigital))
+ {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Olympus);
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Clauss) && (OlyID == OlyID_E_M10_Mark_II))
+ {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Olympus);
+ } else if (makeIs(LIBRAW_CAMERAMAKER_Canon) &&
+ (!strncmp(model, "EOS D2000", 9) || // don't use unique_id here
+ !strncmp(model, "EOS D6000", 9) || // because ids for Monochrome models are unknown
+ !strncmp(model, "EOSDCS", 6))) {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Kodak);
+// if (unique_id == CanonID_EOS_D2000C) {
+//
+// } else if (unique_id == CanonID_EOS_D6000C) {
+///
+// }
+
+ } else if (makeIs(LIBRAW_CAMERAMAKER_PhotoControl) &&
+ !strncasecmp(model, "Camerz ZDS 14", 13)) {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Kodak);
+
+ } else {
+ strcpy(normalized_make, make);
+ }
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Apple)) {
+ if ((imgdata.color.UniqueCameraModel[0]) &&
+ (!strncmp(model, "iPad", 4) || !strncmp(model, "iPhone", 6)))
+ strcpy(model, imgdata.color.UniqueCameraModel);
+
+ } else if (makeIs(LIBRAW_CAMERAMAKER_Kodak)) {
+ if ((model[6] == ' ') &&
+ (!strncmp(model, "DCS4", 4) ||
+ !strncmp(model, "NC2000", 6)))
+ {
+ model[6] = 0;
+ }
+ if ((model[6] != 'A') &&
+ (model[6] != 'I') &&
+ (model[6] != 'M') &&
+ !strncmp(model, "NC2000", 6))
+ {
+ model[6] = 0;
+ }
+ }
+
+ else if (makeIs(LIBRAW_CAMERAMAKER_Ricoh) &&
+ !strncmp(model, "GXR", 3)) {
+ strcpy(ilm.body, "Ricoh GXR");
+ if (!imgdata.lens.Lens[0] && imgdata.color.UniqueCameraModel[0]) {
+ strcpy (imgdata.lens.Lens, imgdata.color.UniqueCameraModel);
+ remove_caseSubstr (imgdata.lens.Lens, (char *)"Ricoh");
+ remove_caseSubstr (imgdata.lens.Lens, (char *)"Lens");
+ removeExcessiveSpaces (imgdata.lens.Lens);
+ }
+ if (ilm.LensID == LIBRAW_LENS_NOT_SET) {
+ if (strstr(imgdata.lens.Lens, "50mm"))
+ ilm.LensID = 1;
+ else if (strstr(imgdata.lens.Lens, "S10"))
+ ilm.LensID = 2;
+ else if (strstr(imgdata.lens.Lens, "P10"))
+ ilm.LensID = 3;
+ else if (strstr(imgdata.lens.Lens, "28mm"))
+ ilm.LensID = 5;
+ else if (strstr(imgdata.lens.Lens, "A16"))
+ ilm.LensID = 6;
+ }
+ switch (ilm.LensID) {
+ case 1: // GR Lens A12 50mm F2.5 Macro
+ strcpy(model, "GXR A12 50mm");
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_RicohModule;
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ break;
+ case 2:
+ strcpy(model, "GXR S10");
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_1div1p7INCH;
+ ilm.CameraMount = LIBRAW_MOUNT_RicohModule;
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ break;
+ case 3: // Ricoh Lens P10 28-300mm F3.5-5.6 VC
+ strcpy(model, "GXR P10");
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_1div2p3INCH;
+ ilm.CameraMount = LIBRAW_MOUNT_RicohModule;
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ break;
+ case 5: // GR Lens A12 28mm F2.5
+ strcpy(model, "GXR A12 28mm");
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_RicohModule;
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ break;
+ case 6: // Ricoh Lens A16 24-85mm F3.5-5.5
+ strcpy(model, "GXR A16");
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_RicohModule;
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ break;
+ case 8: // Ricoh Mount A12 (Leica M lenses)
+ strcpy(model, "GXR Mount A12");
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_Leica_M;
+ ilm.LensID = LIBRAW_LENS_NOT_SET;
+ break;
+ }
+ }
+
+ strcpy(normalized_model, model);
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Canon))
+ {
+ if (unique_id)
+ {
+ if ((unique_id != CanonID_EOS_D2000C) &&
+ (unique_id != CanonID_EOS_D6000C))
+ {
+ for (i = 0; i < int(sizeof unique / sizeof *unique); i++)
+ {
+ if (unique_id == unique[i].id)
+ {
+ strcpy(model, unique[i].t_model);
+ strcpy(normalized_model, unique[i].t_model);
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ((dng_version) &&
+ (strlen(imgdata.color.UniqueCameraModel) > 6) &&
+ strncmp(imgdata.color.UniqueCameraModel+6, "PowerShot", 9))
+ {
+ for (i = 0; i < int(sizeof unique / sizeof *unique); i++)
+ {
+ if (!strcmp(unique[i].t_model, imgdata.color.UniqueCameraModel+6))
+ {
+ ilm.CamID = unique_id = unique[i].id;
+ strcpy(normalized_model, unique[i].t_model);
+ try_xml = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Fujifilm))
+ {
+ for (i = 0; i < int(sizeof fujialias / sizeof *fujialias); i++)
+ {
+ if (fujialias[i][0] == '@')
+ {
+ orig = fujialias[i] + 1;
+ if (!strcmp(model, orig)) break;
+ }
+ else if (!strcmp(model, fujialias[i]))
+ {
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+
+ } else if (makeIs(LIBRAW_CAMERAMAKER_Hasselblad)) {
+ parseHassyModel();
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Mamiya))
+ {
+ for (i = 0; i < int(sizeof phase1alias / sizeof *phase1alias); i++)
+ { // re-badged Phase One backs
+ if (phase1alias[i][0] == '@') orig = phase1alias[i] + 1;
+ else if (!strcmp(model, phase1alias[i]))
+ {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_PhaseOne);
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+ for (i = 0; i < int(sizeof leafalias / sizeof *leafalias); i++)
+ { // re-badged Leaf backs
+ if (leafalias[i][0] == '@') orig = leafalias[i] + 1;
+ else if (!strcmp(model, leafalias[i]))
+ {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Leaf);
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+
+ /* repeating, because make for some Mamiya re-badged Leaf backs is set to
+ * Leaf */
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Leaf))
+ {
+ for (i = 0; i < int(sizeof leafalias / sizeof *leafalias); i++)
+ { // re-badged Leaf backs
+ if (leafalias[i][0] == '@')
+ {
+ orig = leafalias[i] + 1;
+ if (!strcmp(model, orig)) break;
+ }
+ else if (!strcmp(model, leafalias[i]))
+ { // maybe to change regular "make" to "Mamiya" too
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+ if ((ps = strchr(normalized_model, '(')))
+ *ps = 0;
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Minolta) ||
+ makeIs(LIBRAW_CAMERAMAKER_Konica))
+ {
+ if (makeIs(LIBRAW_CAMERAMAKER_Konica) && !strncasecmp(model, "DiMAGE", 6))
+ {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Minolta);
+ strcpy(make, "Minolta");
+ }
+ else
+ {
+ for (i = 0;
+ i<int(sizeof KonicaMinolta_aliases / sizeof *KonicaMinolta_aliases);
+ i++)
+ {
+ if (KonicaMinolta_aliases[i][0] == '@')
+ {
+ orig = KonicaMinolta_aliases[i] + 1;
+ if (!strcmp(model, orig))
+ {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Minolta);
+ strcpy(make, "Minolta");
+ break;
+ }
+ }
+ else if (!strcasecmp(model, KonicaMinolta_aliases[i]))
+ {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Minolta);
+ strcpy(make, "Minolta");
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Nikon))
+ {
+ for (i = 0; i < int(sizeof nikonalias / sizeof *nikonalias); i++)
+ {
+ if (nikonalias[i][0] == '@')
+ {
+ orig = nikonalias[i] + 1;
+ if (!strcmp(model, orig)) break;
+ }
+ else if (!strcmp(model, nikonalias[i]))
+ {
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+
+ } else if (makeIs(LIBRAW_CAMERAMAKER_Olympus)) {
+ for (i = 0; i < int(sizeof olyalias / sizeof *olyalias); i++) {
+ if (olyalias[i][0] == '@') {
+ orig = olyalias[i] + 1;
+ if (!strcmp(model, orig)) break;
+ } else if (!strcmp(model, olyalias[i])) {
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+
+ if (!OlyID) {
+ if (!strcmp(normalized_model, "C-740UZ")) {
+ ilm.CamID = OlyID = unique_id = OlyID_C_740UZ;
+
+ } else if (!strcmp(normalized_model, "C-770UZ")) {
+ ilm.CamID = OlyID = unique_id = OlyID_C_770UZ;
+ }
+ }
+
+ } else if (makeIs(LIBRAW_CAMERAMAKER_Panasonic) ||
+ makeIs(LIBRAW_CAMERAMAKER_Leica) ||
+ makeIs(LIBRAW_CAMERAMAKER_Yuneec))
+ {
+ for (i = 0; i < int(sizeof panalias / sizeof *panalias); i++)
+ {
+ if (panalias[i][0] == '@')
+ {
+ orig = panalias[i] + 1;
+ if (!strcmp(model, orig)) break;
+ }
+ else if (!strcmp(model, panalias[i]))
+ {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Panasonic);
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+ } else if (makeIs(LIBRAW_CAMERAMAKER_Pentax)) {
+ if (!unique_id) {
+ if (!strcmp(model, "Optio S")) {
+ ilm.CamID = unique_id = PentaxID_Optio_S;
+ } else if (!strcmp(model, "Optio S V1.01")) {
+ ilm.CamID = unique_id = PentaxID_Optio_S_V101;
+ } else if (!strcmp(model, "Optio S4")) {
+ ilm.CamID = unique_id = PentaxID_Optio_S4;
+ } else if (!strcmp(model, "Optio 750Z")) {
+ ilm.CamID = unique_id = PentaxID_Optio_750Z;
+ } else if (!strcmp(model, "Optio 33WR")) {
+ ilm.CamID = unique_id = PentaxID_Optio_33WR;
+ }
+ }
+
+ for (i = 0;
+ i < int(sizeof SamsungPentax_aliases / sizeof *SamsungPentax_aliases);
+ i++) {
+ if (SamsungPentax_aliases[i][0] == '@') {
+ orig = SamsungPentax_aliases[i] + 1;
+ if (!strcmp(model, orig)) break;
+ } else if (!strcmp(model, SamsungPentax_aliases[i])) {
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+ if (!strncmp(model, "GR", 2)) {
+ setMakeFromIndex(LIBRAW_CAMERAMAKER_Ricoh);
+ strcpy(make, "Ricoh");
+ }
+
+ } else if (makeIs(LIBRAW_CAMERAMAKER_PhaseOne))
+ {
+ for (i = 0; i < int(sizeof phase1alias / sizeof *phase1alias); i++)
+ {
+ if (phase1alias[i][0] == '@')
+ {
+ orig = phase1alias[i] + 1;
+ if (!strcmp(model, orig)) break;
+ }
+ else if (!strcmp(model, phase1alias[i]))
+ {
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+ if (strstr(imPhaseOne.FirmwareString, "Achromatic"))
+ {
+ colors = 1;
+ filters = 0;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Samsung))
+ {
+ j = 0;
+ if (strstr(model, "WB5500") || strstr(model, "HZ50W"))
+ {
+ strcpy(model, "WB5500");
+ j++;
+ }
+ else if (strstr(model, "WB5000") || strstr(model, "HZ25W"))
+ {
+ strcpy(model, "WB5000");
+ j++;
+ }
+ else if (strstr(model, "WB550") || strstr(model, "HZ15W"))
+ {
+ strcpy(model, "WB550");
+ j++;
+ }
+ else if (strstr(model, "WB500") || strstr(model, "HZ10W"))
+ {
+ strcpy(model, "WB500");
+ j++;
+ }
+ if (j)
+ {
+ strcpy(normalized_model, model);
+ }
+ else
+ {
+ for (i = 0; i < int(sizeof samsungalias / sizeof *samsungalias); i++)
+ {
+ if (samsungalias[i][0] == '@')
+ {
+ orig = samsungalias[i] + 1;
+ if (!strcmp(model, orig)) break;
+ }
+ else if (!strcmp(model, samsungalias[i]))
+ {
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+ }
+
+ } else if (makeIs(LIBRAW_CAMERAMAKER_Sony)) {
+ if (unique_id)
+ {
+ for (i = 0; i < int(sizeof sonique / sizeof *sonique); i++)
+ {
+ if (unique_id == sonique[i].id)
+ {
+ if (!strcmp(make, "Sony"))
+ strcpy(model, sonique[i].t_model);
+ strcpy(normalized_model, sonique[i].t_model);
+ break;
+ }
+ }
+ }
+
+ } else if (makeIs(LIBRAW_CAMERAMAKER_Kodak)) {
+ remove_caseSubstr (normalized_model, (char *)"EasyShare");
+ remove_caseSubstr (normalized_model, (char *)"ZOOM");
+ removeExcessiveSpaces (normalized_model);
+ for (i = 0; i < int(sizeof kodakalias / sizeof *kodakalias); i++)
+ {
+ if (kodakalias[i][0] == '@')
+ {
+ orig = kodakalias[i] + 1;
+ if (!strcmp(model, orig)) break;
+ }
+ else if (!strcmp(model, kodakalias[i]))
+ {
+ strcpy(normalized_model, orig);
+ break;
+ }
+ }
+
+ if (strstr(model, "DC25"))
+ {
+ strcpy(model, "DC25");
+ strcpy(normalized_model, model);
+ }
+ else if (!strcmp(model, "40"))
+ {
+ strcpy(model, "DC40");
+ strcpy(normalized_model, model);
+ }
+ else if (strstr(model, "DC50"))
+ {
+ strcpy(model, "DC50");
+ strcpy(normalized_model, model);
+ }
+ else if (strstr(model, "DC120"))
+ {
+ strcpy(model, "DC120");
+ strcpy(normalized_model, model);
+ }
+
+ for (i = 0; i < int(sizeof KodakMonochrome / sizeof *KodakMonochrome); i++)
+ {
+ if (!strncmp(model, KodakMonochrome[i], strlen(KodakMonochrome[i])))
+ {
+ colors = 1;
+ filters = 0;
+ }
+ }
+ }
+
+ if (ilm.body[0])
+ {
+ if ((ilm.CameraMount != LIBRAW_MOUNT_Hasselblad_V) &&
+ !strncmp(ilm.body, "Hasselblad ", 11) &&
+ ((ilm.body[11] == 'C') || (ilm.body[11] == '2') ||
+ (ilm.body[11] == '5') || (ilm.body[11] == '9')))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_66;
+ ilm.CameraMount = LIBRAW_MOUNT_Hasselblad_V;
+ }
+ else if (!strncmp(ilm.body, "XF", 2) || !strncmp(ilm.body, "645DF", 5))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Mamiya645;
+ ilm.CameraFormat = LIBRAW_FORMAT_645;
+ }
+ else if (!strncmp(ilm.body, "Sinarcam", 2))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_LF;
+ ilm.CameraFormat = LIBRAW_FORMAT_LF;
+ strcat(ilm.body, " shutter system");
+ }
+ }
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Kodak))
+ {
+ if (((ilm.CameraMount == LIBRAW_MOUNT_DigitalBack) ||
+ (ilm.CameraMount == LIBRAW_MOUNT_Unknown)) &&
+ !strncmp(model2, "PB645", 5))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_645;
+ if (model2[5] == 'C')
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Contax645;
+ strcpy(ilm.body, "Contax 645");
+ }
+ else if (model2[5] == 'H')
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Hasselblad_H;
+ strcpy(ilm.body, "Hasselblad H1/H2");
+ }
+ else if (model2[5] == 'M')
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Mamiya645;
+ strcpy(ilm.body, "Mamiya 645");
+ }
+
+ } else if (!strncasecmp(model, "PIXPRO S-1", 10)) {
+ ilm.CameraFormat = LIBRAW_FORMAT_FT;
+ } else if (!strncasecmp(model, "PIXPRO ", 7)) {
+ ilm.CameraFormat = LIBRAW_FORMAT_1div2p3INCH;
+ }
+ }
+
+ else if (makeIs(LIBRAW_CAMERAMAKER_Fujifilm))
+ {
+ if (!strncmp(normalized_model, "DBP", 3))
+ {
+ strcpy(ilm.body, "Fujifilm GX680");
+ }
+ }
+
+ if ((ilm.CameraFormat == LIBRAW_FORMAT_Unknown) ||
+ (ilm.CameraMount == LIBRAW_MOUNT_Unknown) ||
+ (ilm.CameraMount == LIBRAW_MOUNT_IL_UM))
+ {
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Canon))
+ {
+ if (strncmp(normalized_model, "EOS", 3))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Nikon))
+ {
+ if (normalized_model[0] == 'D')
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Nikon_F;
+ }
+ else
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Panasonic))
+ {
+ if (!strncmp(normalized_model, "DC-S", 4))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ ilm.CameraMount = LIBRAW_MOUNT_LPS_L;
+ }
+ else if (!strncmp(normalized_model, "DMC-L1", 6) ||
+ !strncmp(normalized_model, "DMC-L10", 7))
+ {
+ ilm.CameraFormat = ilm.CameraMount = LIBRAW_FORMAT_FT;
+ }
+ else if (!strncmp(normalized_model + 2, "-G", 2) ||
+ !strncmp(normalized_model + 3, "-G", 2))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_FT;
+ ilm.CameraMount = LIBRAW_MOUNT_mFT;
+ }
+ else
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ if (!strncmp(normalized_model + 2, "-LX100", 6) || // DC-LX100M2
+ !strncmp(normalized_model + 3, "-LX100", 6))
+ { // DMC-LX100
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_FT;
+ }
+ else if (!strncmp(normalized_model, "DMC-CM1", 7))
+ {
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ }
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Fujifilm))
+ {
+ if (!strncmp(normalized_model, "GFX ", 4))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_CROP645;
+ ilm.CameraMount = LIBRAW_MOUNT_Fuji_GF;
+ }
+ else if (!strncmp(normalized_model, "X-", 2) &&
+ (strncmp(normalized_model, "X-S1", 4) || !strncmp(normalized_model, "X-S10", 5)))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_Fuji_X;
+ }
+ else if (((normalized_model[0] == 'S') && // S2Pro, S3Pro, S5Pro
+ (normalized_model[2] == 'P')) ||
+ !strncasecmp(normalized_model, "IS Pro", 6))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_Nikon_F;
+ }
+ else if (!strncmp(normalized_model, "DBP", 3))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_68;
+ ilm.CameraMount = LIBRAW_MOUNT_Fuji_GX;
+ }
+ else
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Samsung))
+ {
+ if ((normalized_model[0] == 'N') &&
+ (normalized_model[1] == 'X')) // DNG converters delete makernotes
+ {
+ if ((normalized_model[2] == 'F') && (normalized_model[3] == '1'))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Samsung_NX_M;
+ ilm.CameraFormat = LIBRAW_FORMAT_1INCH;
+ }
+ else
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Samsung_NX;
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ }
+ }
+ else
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Kodak))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ for (i = 0; i < int(sizeof Kodak_mounts / sizeof *Kodak_mounts); i++)
+ {
+ if (!strncmp(normalized_model, Kodak_mounts[i].Kmodel,
+ strlen(Kodak_mounts[i].Kmodel)))
+ {
+ ilm.CameraMount = Kodak_mounts[i].mount;
+ break;
+ }
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Minolta))
+ {
+ if (!strcmp(normalized_model, "DG-5D") ||
+ !strcmp(normalized_model, "DG-7D"))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = LIBRAW_MOUNT_Minolta_A;
+ }
+ else if (!strncasecmp(normalized_model, "DiMAGE", 6))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Casio) ||
+ makeIs(LIBRAW_CAMERAMAKER_Creative))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Sigma))
+ {
+ if (!strncmp(normalized_model, "fp", 2))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ ilm.CameraMount = LIBRAW_MOUNT_LPS_L;
+ }
+ else if (!strncasecmp(normalized_model, "SD", 2))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Sigma_X3F;
+ if (!strcmp(normalized_model, "SD1") || (normalized_model[4] == 'M'))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_SigmaMerrill;
+ }
+ else if (normalized_model[11] == 'H')
+ { // 'sd Quattro H'
+ ilm.CameraFormat = LIBRAW_FORMAT_SigmaAPSH;
+ }
+ else if (normalized_model[4] == 'Q')
+ { // 'sd Quattro'
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ }
+ else
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_SigmaAPSC;
+ }
+ }
+ else if (!strncasecmp(normalized_model, "DP", 2))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ if (normalized_model[4] == 'M')
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_SigmaMerrill;
+ }
+ else if (normalized_model[4] == 'Q')
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ }
+ else
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_SigmaAPSC;
+ }
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Konica))
+ {
+ if (!strncmp(model, "KD-", 3))
+ { // Konica KD-400Z, KD-510Z
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Mamiya))
+ {
+ if (!strncmp(normalized_model, "ZD", 2))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_3648;
+ ilm.CameraMount = LIBRAW_MOUNT_Mamiya645;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Sony))
+ {
+ if (!strncmp(normalized_model, "XCD-", 4))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_C;
+ }
+ else if (!strncmp(normalized_model, "DSC-V3", 6) ||
+ !strncmp(normalized_model, "DSC-F828", 8))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ imSony.CameraType = LIBRAW_SONY_DSC;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Polaroid) &&
+ !strncmp(normalized_model, "x530", 4))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Rollei) &&
+ !strncmp(normalized_model, "d530flex", 8))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
+ !strncmp(normalized_model, "Optio", 5)) {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Epson) &&
+ !strncmp(normalized_model, "R-D1", 4))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Leica_M;
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ }
+ }
+
+ if ((ilm.LensMount == LIBRAW_MOUNT_Canon_RF) &&
+ (ilm.LensID == 61182) &&
+ (imCanon.RF_lensID != 0)) {
+ ilm.LensID = imCanon.RF_lensID;
+ }
+
+ if (ilm.LensMount == LIBRAW_MOUNT_Unknown)
+ {
+ if (makeIs(LIBRAW_CAMERAMAKER_Samsung))
+ {
+ if ((imgdata.lens.Lens[0] == 'N') &&
+ (imgdata.lens.Lens[1] == 'X')) // same DNG problem
+ {
+ if (imgdata.lens.Lens[2] == '-')
+ {
+ ilm.LensMount = LIBRAW_MOUNT_Samsung_NX_M;
+ ilm.LensFormat = LIBRAW_FORMAT_1INCH;
+ }
+ else
+ {
+ ilm.LensMount = LIBRAW_MOUNT_Samsung_NX;
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ }
+ }
+ }
+ }
+
+ if ((ilm.LensID == LIBRAW_LENS_NOT_SET) &&
+ xmpdata &&
+ (strlen(xmpdata) > 9))
+ {
+ if (makeIs(LIBRAW_CAMERAMAKER_Canon) &&
+ try_xml &&
+ (ps = strstr(xmpdata, "LensID=\"")))
+ {
+ ilm.LensID = atoi(ps + 8);
+ if (ilm.LensID == 61182)
+ {
+ ilm.LensMount = ilm.CameraMount = LIBRAW_MOUNT_Canon_RF;
+ }
+ }
+ else if (makeIs(LIBRAW_CAMERAMAKER_Samsung))
+ {
+ if ((ilm.LensMount == LIBRAW_MOUNT_Samsung_NX) &&
+ (ps = strstr(xmpdata, "LensID=\"(")))
+ {
+ ilm.LensID = atoi(ps + 9);
+ }
+ }
+ }
+
+ if (ilm.CameraMount == LIBRAW_MOUNT_FixedLens)
+ {
+ if (ilm.CameraFormat)
+ ilm.LensFormat = ilm.CameraFormat;
+ if (ilm.LensMount == LIBRAW_MOUNT_Unknown)
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ }
+
+ if ((ilm.CameraMount != LIBRAW_MOUNT_Unknown) &&
+ (ilm.CameraMount != LIBRAW_MOUNT_FixedLens) &&
+ (ilm.LensMount == LIBRAW_MOUNT_Unknown)) {
+ if (ilm.LensID == LIBRAW_LENS_NOT_SET) ilm.LensMount = LIBRAW_MOUNT_IL_UM;
+ else ilm.LensMount = ilm.CameraMount;
+ }
+}
+
+void LibRaw::SetStandardIlluminants (unsigned makerIdx, const char* /*normModel*/) {
+ int i = -1;
+ int c;
+ if (!icWBC[LIBRAW_WBI_Ill_A][0] &&
+ !icWBC[LIBRAW_WBI_D65][0]) {
+ if (makerIdx == LIBRAW_CAMERAMAKER_Olympus ) {
+ while (++i, icWBCCTC[i][0]) {
+ if (icWBCCTC[i][0] == 3000)
+ FORC4 icWBC[LIBRAW_WBI_Ill_A][c] = icWBCCTC[i][c+1];
+ else if (icWBCCTC[i][0] == 6600)
+ FORC4 icWBC[LIBRAW_WBI_D65][c] = icWBCCTC[i][c+1];
+ }
+ }
+ }
+
+ if (!icWBC[LIBRAW_WBI_Ill_A][0] && icWBC[LIBRAW_WBI_Tungsten][0])
+ FORC4 icWBC[LIBRAW_WBI_Ill_A][c] = icWBC[LIBRAW_WBI_Tungsten][c];
+
+ if (!icWBC[LIBRAW_WBI_D65][0] && icWBC[LIBRAW_WBI_FL_N][0])
+ FORC4 icWBC[LIBRAW_WBI_D65][c] = icWBC[LIBRAW_WBI_FL_N][c];
+
+ return;
+}
diff --git a/libkdcraw/libraw/src/metadata/olympus.cpp b/libkdcraw/libraw/src/metadata/olympus.cpp
new file mode 100644
index 0000000..6c42713
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/olympus.cpp
@@ -0,0 +1,685 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+#include "../../internal/libraw_cameraids.h"
+
+void LibRaw::setOlympusBodyFeatures(unsigned long long id)
+{
+ ilm.CamID = id;
+
+ if ((id == OlyID_E_1) ||
+ (id == OlyID_E_300) ||
+ ((id & 0x00ffff0000ULL) == 0x0030300000ULL))
+ {
+ ilm.CameraFormat = LIBRAW_FORMAT_FT;
+
+ if ((id == OlyID_E_1) ||
+ (id == OlyID_E_300) ||
+ ((id >= OlyID_E_330) && (id <= OlyID_E_520)) ||
+ (id == OlyID_E_620) ||
+ (id == OlyID_E_450) ||
+ (id == OlyID_E_600) ||
+ (id == OlyID_E_5))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FT;
+ }
+ else
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_mFT;
+ }
+ }
+ else
+ {
+ ilm.LensMount = ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ return;
+}
+
+void LibRaw::getOlympus_CameraType2()
+{
+
+ if (OlyID != 0x0ULL)
+ return;
+
+ int i = 0;
+ fread(imOly.CameraType2, 6, 1, ifp);
+ imOly.CameraType2[5] = 0;
+ while ((i < 6) && imOly.CameraType2[i])
+ {
+ OlyID = OlyID << 8 | imOly.CameraType2[i];
+ if (i < 5 && isspace(imOly.CameraType2[i + 1])) {
+ imOly.CameraType2[i + 1] = '\0';
+ break;
+ }
+ i++;
+ }
+ if (OlyID == OlyID_NORMA) {
+ if (strcmp(model, "SP510UZ")) OlyID = OlyID_SP_510UZ;
+ else OlyID = 0x0ULL;
+ }
+ unique_id = OlyID;
+ setOlympusBodyFeatures(OlyID);
+ return;
+}
+
+void LibRaw::getOlympus_SensorTemperature(unsigned len)
+{
+ if (OlyID != 0x0ULL)
+ {
+ short temp = get2();
+ if ((OlyID == OlyID_E_1) ||
+ (OlyID == OlyID_E_M5) ||
+ (len != 1))
+ imCommon.SensorTemperature = (float)temp;
+ else if ((temp != -32768) && (temp != 0))
+ {
+ if (temp > 199)
+ imCommon.SensorTemperature = 86.474958f - 0.120228f * (float)temp;
+ else
+ imCommon.SensorTemperature = (float)temp;
+ }
+ }
+ return;
+}
+
+void LibRaw::parseOlympus_Equipment(unsigned tag, unsigned /*type */, unsigned len,
+ unsigned dng_writer)
+{
+ // uptag 2010
+
+ switch (tag)
+ {
+ case 0x0100:
+ getOlympus_CameraType2();
+ break;
+ case 0x0101:
+ if ((!imgdata.shootinginfo.BodySerial[0]) && (dng_writer == nonDNG))
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ break;
+ case 0x0102:
+ stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp);
+ break;
+ case 0x0201:
+ {
+ unsigned char bits[4];
+ fread(bits, 1, 4, ifp);
+ ilm.LensID = (unsigned long long)bits[0] << 16 |
+ (unsigned long long)bits[2] << 8 | (unsigned long long)bits[3];
+ ilm.LensMount = LIBRAW_MOUNT_FT;
+ ilm.LensFormat = LIBRAW_FORMAT_FT;
+ if (((ilm.LensID < 0x20000) || (ilm.LensID > 0x4ffff)) &&
+ (ilm.LensID & 0x10))
+ ilm.LensMount = LIBRAW_MOUNT_mFT;
+ }
+ break;
+ case 0x0202:
+ if ((!imgdata.lens.LensSerial[0]))
+ stmread(imgdata.lens.LensSerial, len, ifp);
+ break;
+ case 0x0203:
+ stmread(ilm.Lens, len, ifp);
+ break;
+ case 0x0205:
+ ilm.MaxAp4MinFocal = libraw_powf64l(sqrt(2.0f), get2() / 256.0f);
+ break;
+ case 0x0206:
+ ilm.MaxAp4MaxFocal = libraw_powf64l(sqrt(2.0f), get2() / 256.0f);
+ break;
+ case 0x0207:
+ ilm.MinFocal = (float)get2();
+ break;
+ case 0x0208:
+ ilm.MaxFocal = (float)get2();
+ if (ilm.MaxFocal > 1000.0f)
+ ilm.MaxFocal = ilm.MinFocal;
+ break;
+ case 0x020a:
+ ilm.MaxAp4CurFocal = libraw_powf64l(sqrt(2.0f), get2() / 256.0f);
+ break;
+ case 0x0301:
+ ilm.TeleconverterID = fgetc(ifp) << 8;
+ fgetc(ifp);
+ ilm.TeleconverterID = ilm.TeleconverterID | fgetc(ifp);
+ break;
+ case 0x0303:
+ stmread(ilm.Teleconverter, len, ifp);
+ if (!strlen(ilm.Teleconverter) && strchr(ilm.Lens, '+')) {
+ if (strstr(ilm.Lens, "MC-20"))
+ strcpy(ilm.Teleconverter, "MC-20");
+ else if (strstr(ilm.Lens, "MC-14"))
+ strcpy(ilm.Teleconverter, "MC-14");
+ else if (strstr(ilm.Lens, "EC-20"))
+ strcpy(ilm.Teleconverter, "EC-20");
+ else if (strstr(ilm.Lens, "EC-14"))
+ strcpy(ilm.Teleconverter, "EC-14"); }
+ break;
+ case 0x0403:
+ stmread(ilm.Attachment, len, ifp);
+ break;
+ }
+
+ return;
+}
+void LibRaw::parseOlympus_CameraSettings(int base, unsigned tag, unsigned type,
+ unsigned len, unsigned dng_writer)
+{
+ // uptag 0x2020
+
+ int c;
+ switch (tag)
+ {
+ case 0x0101:
+ if (dng_writer == nonDNG)
+ {
+ thumb_offset = get4() + base;
+ }
+ break;
+ case 0x0102:
+ if (dng_writer == nonDNG)
+ {
+ thumb_length = get4();
+ }
+ break;
+ case 0x0200:
+ imgdata.shootinginfo.ExposureMode = get2();
+ break;
+ case 0x0202:
+ imgdata.shootinginfo.MeteringMode = get2();
+ break;
+ case 0x0301:
+ imgdata.shootinginfo.FocusMode = imOly.FocusMode[0] = get2();
+ if (len == 2)
+ {
+ imOly.FocusMode[1] = get2();
+ }
+ break;
+ case 0x0304:
+ for (c = 0; c < 64; c++)
+ {
+ imOly.AFAreas[c] = get4();
+ }
+ break;
+ case 0x0305:
+ for (c = 0; c < 5; c++)
+ {
+ imOly.AFPointSelected[c] = getreal(type);
+ }
+ break;
+ case 0x0306:
+ imOly.AFFineTune = fgetc(ifp);
+ break;
+ case 0x0307:
+ FORC3 imOly.AFFineTuneAdj[c] = get2();
+ break;
+ case 0x0401:
+ imCommon.FlashEC = getreal(type);
+ break;
+ case 0x0507:
+ imOly.ColorSpace = get2();
+ switch (imOly.ColorSpace) {
+ case 0:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ case 2:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_ProPhotoRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ break;
+ case 0x0600:
+ imgdata.shootinginfo.DriveMode = imOly.DriveMode[0] = get2();
+ for (c = 1; c < (int)len && c < 5; c++)
+ {
+ imOly.DriveMode[c] = get2();
+ }
+ break;
+ case 0x0601:
+ imOly.Panorama_mode = get2();
+ imOly.Panorama_frameNum = get2();
+ break;
+ case 0x0604:
+ imgdata.shootinginfo.ImageStabilization = get4();
+ break;
+ case 0x0804:
+ imOly.StackedImage[0] = get4();
+ imOly.StackedImage[1] = get4();
+ if (imOly.StackedImage[0] == 3) {
+ imOly.isLiveND = 1;
+ imOly.LiveNDfactor = imOly.StackedImage[1];
+ } else {
+ imOly.isLiveND = 0;
+ }
+ break;
+ }
+
+ return;
+}
+
+void LibRaw::parseOlympus_ImageProcessing(unsigned tag, unsigned type,
+ unsigned len, unsigned dng_writer)
+{
+ // uptag 0x2040
+
+ int i, c, wb[4], nWB, tWB, wbG;
+ ushort CT;
+ short sorder;
+
+ if ((tag == 0x0100) && (dng_writer == nonDNG))
+ {
+ cam_mul[0] = get2() / 256.0;
+ cam_mul[2] = get2() / 256.0;
+ }
+ else if ((tag == 0x0101) && (len == 2) &&
+ ((OlyID == OlyID_E_410) || (OlyID == OlyID_E_510)))
+ {
+ for (i = 0; i < 64; i++)
+ {
+ icWBCCTC[i][2] = icWBCCTC[i][4] = icWBC[i][1] = icWBC[i][3] = 0x100;
+ }
+ for (i = 64; i < 256; i++)
+ {
+ icWBC[i][1] = icWBC[i][3] = 0x100;
+ }
+ }
+ else if ((tag > 0x0101) && (tag <= 0x0111))
+ {
+ nWB = tag - 0x0101;
+ tWB = Oly_wb_list2[nWB << 1];
+ CT = Oly_wb_list2[(nWB << 1) | 1];
+ wb[0] = get2();
+ wb[2] = get2();
+ if (tWB != 0x100)
+ {
+ icWBC[tWB][0] = wb[0];
+ icWBC[tWB][2] = wb[2];
+ }
+ if (CT)
+ {
+ icWBCCTC[nWB - 1][0] = CT;
+ icWBCCTC[nWB - 1][1] = wb[0];
+ icWBCCTC[nWB - 1][3] = wb[2];
+ }
+ if (len == 4)
+ {
+ wb[1] = get2();
+ wb[3] = get2();
+ if (tWB != 0x100)
+ {
+ icWBC[tWB][1] = wb[1];
+ icWBC[tWB][3] = wb[3];
+ }
+ if (CT)
+ {
+ icWBCCTC[nWB - 1][2] = wb[1];
+ icWBCCTC[nWB - 1][4] = wb[3];
+ }
+ }
+ }
+ else if ((tag >= 0x0112) && (tag <= 0x011e))
+ {
+ nWB = tag - 0x0112;
+ wbG = get2();
+ tWB = Oly_wb_list2[nWB << 1];
+ if (nWB)
+ icWBCCTC[nWB - 1][2] = icWBCCTC[nWB - 1][4] = wbG;
+ if (tWB != 0x100)
+ icWBC[tWB][1] = icWBC[tWB][3] = wbG;
+ }
+ else if (tag == 0x011f)
+ {
+ wbG = get2();
+ if (icWBC[LIBRAW_WBI_Flash][0])
+ icWBC[LIBRAW_WBI_Flash][1] =
+ icWBC[LIBRAW_WBI_Flash][3] = wbG;
+ FORC4 if (icWBC[LIBRAW_WBI_Custom1 + c][0])
+ icWBC[LIBRAW_WBI_Custom1 + c][1] =
+ icWBC[LIBRAW_WBI_Custom1 + c][3] = wbG;
+ }
+ else if (tag == 0x0121)
+ {
+ icWBC[LIBRAW_WBI_Flash][0] = get2();
+ icWBC[LIBRAW_WBI_Flash][2] = get2();
+ if (len == 4)
+ {
+ icWBC[LIBRAW_WBI_Flash][1] = get2();
+ icWBC[LIBRAW_WBI_Flash][3] = get2();
+ }
+ }
+ else if ((tag == 0x0200) && (dng_writer == nonDNG) &&
+ strcmp(software, "v757-71"))
+ {
+ for (i = 0; i < 3; i++)
+ {
+ if (!imOly.ColorSpace)
+ {
+ FORC3 cmatrix[i][c] = ((short)get2()) / 256.0;
+ }
+ else
+ {
+ FORC3 imgdata.color.ccm[i][c] = ((short)get2()) / 256.0;
+ }
+ }
+ }
+ else if ((tag == 0x0600) && (dng_writer == nonDNG))
+ {
+ FORC4 cblack[RGGB_2_RGBG(c)] = get2();
+ }
+ else if ((tag == 0x0611) && (dng_writer == nonDNG))
+ {
+ imOly.ValidBits = get2();
+ }
+ else if ((tag == 0x0612) && (dng_writer == nonDNG))
+ {
+ imgdata.sizes.raw_inset_crops[0].cleft = get2();
+ }
+ else if ((tag == 0x0613) && (dng_writer == nonDNG))
+ {
+ imgdata.sizes.raw_inset_crops[0].ctop = get2();
+ }
+ else if ((tag == 0x0614) && (dng_writer == nonDNG))
+ {
+ imgdata.sizes.raw_inset_crops[0].cwidth = get2();
+ }
+ else if ((tag == 0x0615) && (dng_writer == nonDNG))
+ {
+ imgdata.sizes.raw_inset_crops[0].cheight = get2();
+ }
+ else if ((tag == 0x0805) && (len == 2))
+ {
+ imOly.SensorCalibration[0] = getreal(type);
+ imOly.SensorCalibration[1] = getreal(type);
+ if ((dng_writer == nonDNG) && (OlyID != OlyID_XZ_1))
+ FORC4 imgdata.color.linear_max[c] = imOly.SensorCalibration[0];
+ }
+ else if (tag == 0x1112)
+ {
+ sorder = order;
+ order = 0x4d4d;
+ c = get2();
+ order = sorder;
+ switch (c) {
+ case 0x0101:
+ case 0x0901:
+ case 0x0909:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_4to3;
+ break;
+ case 0x0104:
+ case 0x0401:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_1to1;
+ break;
+ case 0x0201:
+ case 0x0202:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
+ break;
+ case 0x0301:
+ case 0x0303:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_16to9;
+ break;
+ case 0x0404:
+// imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_6to6;
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_1to1;
+ break;
+ case 0x0505:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_5to4;
+ break;
+ case 0x0606:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_7to6;
+ break;
+ case 0x0707:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_6to5;
+ break;
+ case 0x0808:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_7to5;
+ break;
+ default:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_OTHER;
+ break;
+ }
+ }
+ else if (tag == 0x1113)
+ {
+ imOly.AspectFrame[0] = get2();
+ imOly.AspectFrame[1] = get2();
+ imOly.AspectFrame[2] = get2();
+ imOly.AspectFrame[3] = get2();
+ }
+ else if (tag == 0x1306)
+ {
+ c = get2();
+ if ((c != 0) && (c != 100))
+ {
+ if (c < 61)
+ imCommon.CameraTemperature = (float)c;
+ else
+ imCommon.CameraTemperature = (float)(c - 32) / 1.8f;
+ if ((imCommon.exifAmbientTemperature > -273.15f) &&
+ ((OlyID == OlyID_TG_5) ||
+ (OlyID == OlyID_TG_6))
+ )
+ imCommon.CameraTemperature += imCommon.exifAmbientTemperature;
+ }
+ }
+
+ return;
+}
+
+void LibRaw::parseOlympus_RawInfo(unsigned tag, unsigned /*type */, unsigned len,
+ unsigned dng_writer)
+{
+ // uptag 0x3000
+
+ int wb_ind, c, i;
+
+ if ((tag == 0x0110) && strcmp(software, "v757-71"))
+ {
+ icWBC[LIBRAW_WBI_Auto][0] = get2();
+ icWBC[LIBRAW_WBI_Auto][2] = get2();
+ if (len == 2)
+ {
+ for (i = 0; i < 256; i++)
+ icWBC[i][1] = icWBC[i][3] = 0x100;
+ }
+ }
+ else if ((((tag >= 0x0120) && (tag <= 0x0124)) ||
+ ((tag >= 0x0130) && (tag <= 0x0133))) &&
+ strcmp(software, "v757-71"))
+ {
+ if (tag <= 0x0124)
+ wb_ind = tag - 0x0120;
+ else
+ wb_ind = tag - 0x0130 + 5;
+
+ icWBC[Oly_wb_list1[wb_ind]][0] = get2();
+ icWBC[Oly_wb_list1[wb_ind]][2] = get2();
+ }
+ else if ((tag == 0x0200) && (dng_writer == nonDNG))
+ {
+ for (i = 0; i < 3; i++)
+ {
+ if (!imOly.ColorSpace)
+ {
+ FORC3 cmatrix[i][c] = ((short)get2()) / 256.0;
+ }
+ else
+ {
+ FORC3 imgdata.color.ccm[i][c] = ((short)get2()) / 256.0;
+ }
+ }
+ }
+ else if ((tag == 0x0600) && (dng_writer == nonDNG))
+ {
+ FORC4 cblack[RGGB_2_RGBG(c)] = get2();
+ }
+ else if ((tag == 0x0612) && (dng_writer == nonDNG))
+ {
+ imgdata.sizes.raw_inset_crops[0].cleft = get2();
+ }
+ else if ((tag == 0x0613) && (dng_writer == nonDNG))
+ {
+ imgdata.sizes.raw_inset_crops[0].ctop = get2();
+ }
+ else if ((tag == 0x0614) && (dng_writer == nonDNG))
+ {
+ imgdata.sizes.raw_inset_crops[0].cwidth = get2();
+ }
+ else if ((tag == 0x0615) && (dng_writer == nonDNG))
+ {
+ imgdata.sizes.raw_inset_crops[0].cheight = get2();
+ }
+ return;
+}
+
+
+void LibRaw::parseOlympusMakernotes (int base, unsigned tag, unsigned type, unsigned len, unsigned dng_writer) {
+
+ int c;
+ unsigned a;
+ if ((tag >= 0x20100000) && (tag <= 0x2010ffff)) {
+ parseOlympus_Equipment((tag & 0x0000ffff), type, len, dng_writer);
+
+ } else if ((tag >= 0x20200000) && (tag <= 0x2020ffff)) {
+ parseOlympus_CameraSettings(base, (tag & 0x0000ffff), type, len, dng_writer);
+
+ } else if ((tag >= 0x20400000) && (tag <= 0x2040ffff)) {
+ parseOlympus_ImageProcessing((tag & 0x0000ffff), type, len, dng_writer);
+
+ } else if ((tag >= 0x30000000) && (tag <= 0x3000ffff)) {
+ parseOlympus_RawInfo((tag & 0x0000ffff), type, len, dng_writer);
+
+ } else {
+ switch (tag) {
+ case 0x0200:
+ FORC3 if ((imOly.SpecialMode[c] = get4()) >= 0xff) imOly.SpecialMode[c] = 0xffffffff;
+ break;
+ case 0x0207:
+ getOlympus_CameraType2();
+ break;
+ case 0x0404:
+ case 0x101a:
+ if (!imgdata.shootinginfo.BodySerial[0] && (dng_writer == nonDNG))
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ break;
+ case 0x1002:
+ ilm.CurAp = libraw_powf64l(2.0f, getreal(type) / 2);
+ break;
+ case 0x1007:
+ imCommon.SensorTemperature = (float)get2();
+ break;
+ case 0x1008:
+ imCommon.LensTemperature = (float)get2();
+ break;
+ case 0x100b:
+ if (imOly.FocusMode[0] == 0xffff) {
+ imgdata.shootinginfo.FocusMode = imOly.FocusMode[0] = get2();
+ if (imgdata.shootinginfo.FocusMode == 1)
+ imgdata.shootinginfo.FocusMode = imOly.FocusMode[0] = 10;
+ }
+ break;
+ case 0x100d:
+ if (imOly.ZoomStepCount == 0xffff) imOly.ZoomStepCount = get2();
+ break;
+ case 0x100e:
+ if (imOly.FocusStepCount == 0xffff) imOly.FocusStepCount = get2();
+ break;
+ case 0x1011:
+ if (strcmp(software, "v757-71") && (dng_writer == nonDNG)) {
+ for (int i = 0; i < 3; i++) {
+ if (!imOly.ColorSpace) {
+ FORC3 cmatrix[i][c] = ((short)get2()) / 256.0;
+ } else {
+ FORC3 imgdata.color.ccm[i][c] = ((short)get2()) / 256.0;
+ }
+ }
+ }
+ break;
+ case 0x1012:
+ if (dng_writer == nonDNG)
+ FORC4 cblack[RGGB_2_RGBG(c)] = get2();
+ break;
+ case 0x1017:
+ if (dng_writer == nonDNG)
+ cam_mul[0] = get2() / 256.0;
+ break;
+ case 0x1018:
+ if (dng_writer == nonDNG)
+ cam_mul[2] = get2() / 256.0;
+ break;
+ case 0x102c:
+ if (dng_writer == nonDNG)
+ imOly.ValidBits = get2();
+ break;
+ case 0x1038:
+ imOly.AFResult = get2();
+ break;
+ case 0x103b:
+ if (imOly.FocusStepInfinity == 0xffff) imOly.FocusStepInfinity = get2();
+ break;
+ case 0x103c:
+ if (imOly.FocusStepNear == 0xffff) imOly.FocusStepNear = get2();
+ break;
+ case 0x20300108:
+ case 0x20310109:
+ if (dng_writer == nonDNG) {
+ imOly.ColorSpace = get2();
+ switch (imOly.ColorSpace) {
+ case 0:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ case 2:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_ProPhotoRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ }
+ case 0x20500209:
+ imOly.AutoFocus = get2();
+ break;
+ case 0x20500300:
+ imOly.ZoomStepCount = get2();
+ break;
+ case 0x20500301:
+ imOly.FocusStepCount = get2();
+ break;
+ case 0x20500303:
+ imOly.FocusStepInfinity = get2();
+ break;
+ case 0x20500304:
+ imOly.FocusStepNear = get2();
+ break;
+ case 0x20500305:
+ a = get4();
+ /*b = */ get4(); // b is not used, so removed
+ if (a >= 0x7f000000) imOly.FocusDistance = -1.0; // infinity
+ else imOly.FocusDistance = (double) a / 1000.0; // convert to meters
+ break;
+ case 0x20500308:
+ imOly.AFPoint = get2();
+ break;
+ case 0x20501500:
+ getOlympus_SensorTemperature(len);
+ break;
+ }
+ }
+}
diff --git a/libkdcraw/libraw/src/metadata/p1.cpp b/libkdcraw/libraw/src/metadata/p1.cpp
new file mode 100644
index 0000000..a3867b8
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/p1.cpp
@@ -0,0 +1,192 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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_defs.h"
+
+void LibRaw::setPhaseOneFeatures(unsigned long long id)
+{
+
+ ushort i;
+ static const struct
+ {
+ unsigned long long id;
+ char t_model[32];
+ int CamMnt;
+ int CamFmt;
+ } p1_unique[] = {
+ // Phase One section:
+ {0x001ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x00aULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x00cULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x010ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x011ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x012ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x013ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x014ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x015ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x016ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x017ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x018ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x019ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x020ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x022ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x023ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x024ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x025ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x026ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x027ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x028ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x029ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x02aULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x02cULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x02dULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x02eULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x02fULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x030ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x031ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x032ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x033ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x034ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x035ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x036ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x037ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x043ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x044ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x045ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x046ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x047ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x048ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x049ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x04aULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x04cULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x04dULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x04eULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x04fULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x050ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x051ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x052ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x053ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x054ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x055ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x056ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x057ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x063ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x064ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x065ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x066ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x067ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x068ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x069ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x06aULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x070ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x071ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x072ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x073ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x083ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x084ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x085ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x086ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x087ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x088ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x089ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x08aULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x08cULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x08dULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x08eULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x08fULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x094ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x095ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x096ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x097ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x0a0ULL, "A-250", LIBRAW_MOUNT_Alpa, LIBRAW_FORMAT_69},
+ {0x0a1ULL, "A-260", LIBRAW_MOUNT_Alpa, LIBRAW_FORMAT_69},
+ {0x0a2ULL, "A-280", LIBRAW_MOUNT_Alpa, LIBRAW_FORMAT_69},
+ {0x0a7ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x0a8ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x0a9ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x0aaULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x0acULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x0adULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x0aeULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x0afULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x0b0ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x0b1ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x0b2ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x0b3ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x0b4ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x0b5ULL, "Hasselblad H", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x0b6ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x0b7ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x0d0ULL, "Hasselblad V", LIBRAW_MOUNT_Hasselblad_V, LIBRAW_FORMAT_66},
+ {0x0d3ULL, "PhaseOne/Mamiya", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x1c0ULL, "Phase One 645AF", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x1c9ULL, "Phase One 645DF", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x1d7ULL, "Phase One 645DF+", LIBRAW_MOUNT_Mamiya645, LIBRAW_FORMAT_645},
+ {0x2c0ULL, "Phase One iXA", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x2c1ULL, "Phase One iXA - R", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x2c2ULL, "Phase One iXU 150", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x2c3ULL, "Phase One iXU 150 - NIR", LIBRAW_MOUNT_Unknown,LIBRAW_FORMAT_Unknown},
+ {0x2c4ULL, "Phase One iXU 180", LIBRAW_MOUNT_Unknown,LIBRAW_FORMAT_Unknown},
+ {0x2d1ULL, "Phase One iXR", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ // Leaf section:
+ {0x140ULL, "Universal", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x141ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x142ULL, "Hasselblad H1/H2", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x143ULL, "Mamiya", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x144ULL, "Universal", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x145ULL, "Hasselblad H1/H2", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x146ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x147ULL, "Mamiya", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x149ULL, "Universal", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x14aULL, "Hasselblad H1/H2", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x14cULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x14dULL, "Mamiya", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x14eULL, "AFi", LIBRAW_MOUNT_Rollei_bayonet, LIBRAW_FORMAT_66},
+ {0x14fULL, "AFi", LIBRAW_MOUNT_Rollei_bayonet, LIBRAW_FORMAT_66},
+ {0x150ULL, "AFi", LIBRAW_MOUNT_Rollei_bayonet, LIBRAW_FORMAT_66},
+ {0x151ULL, "Universal", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x152ULL, "Hasselblad H1/H2", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x153ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x154ULL, "Mamiya", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+
+ {0x16cULL, "Phase One iXM-RS150F", LIBRAW_MOUNT_PhaseOne_iXM_RS, LIBRAW_FORMAT_645},
+
+ {0x171ULL, "Universal", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x172ULL, "Mamiya", LIBRAW_MOUNT_Unknown, LIBRAW_FORMAT_Unknown},
+ {0x173ULL, "Hasselblad H1/H2", LIBRAW_MOUNT_Hasselblad_H, LIBRAW_FORMAT_645},
+ {0x174ULL, "Contax 645", LIBRAW_MOUNT_Contax645, LIBRAW_FORMAT_645},
+ {0x175ULL, "AFi", LIBRAW_MOUNT_Rollei_bayonet, LIBRAW_FORMAT_66},
+ };
+ ilm.CamID = id;
+ if (id && !ilm.body[0])
+ {
+ for (i = 0; i < sizeof p1_unique / sizeof *p1_unique; i++)
+ if (id == p1_unique[i].id)
+ {
+ strcpy(ilm.body, p1_unique[i].t_model);
+ ilm.CameraFormat = p1_unique[i].CamFmt;
+ ilm.CameraMount = p1_unique[i].CamMnt;
+ if ((ilm.CameraMount == LIBRAW_MOUNT_PhaseOne_iXM_RS) ||
+ (ilm.CameraMount == LIBRAW_MOUNT_PhaseOne_iXM)) {
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ ilm.LensMount = ilm.CameraMount;
+ } else if (ilm.CameraMount == LIBRAW_MOUNT_PhaseOne_iXM_MV) {
+ ilm.LensMount = ilm.CameraMount;
+ }
+ break;
+ }
+ }
+ return;
+}
diff --git a/libkdcraw/libraw/src/metadata/pentax.cpp b/libkdcraw/libraw/src/metadata/pentax.cpp
new file mode 100644
index 0000000..705fd84
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/pentax.cpp
@@ -0,0 +1,675 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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_defs.h"
+#include "../../internal/libraw_cameraids.h"
+
+void LibRaw::setPentaxBodyFeatures(unsigned long long id)
+{
+
+ ilm.CamID = id;
+
+ switch (id) {
+ case PentaxID_staristD:
+ case PentaxID_staristDS:
+ case PentaxID_staristDL:
+ case PentaxID_staristDS2:
+ case PentaxID_GX_1S:
+ case PentaxID_staristDL2:
+ case PentaxID_GX_1L:
+ case PentaxID_K100D:
+ case PentaxID_K110D:
+ case PentaxID_K100D_Super:
+ case PentaxID_K10D:
+ case PentaxID_GX10:
+ case PentaxID_K20D:
+ case PentaxID_GX20:
+ case PentaxID_K200D:
+ case PentaxID_K2000:
+ case PentaxID_K_m:
+ case PentaxID_K_7:
+ case PentaxID_K_x:
+ case PentaxID_K_r:
+ case PentaxID_K_5:
+ case PentaxID_K_01:
+ case PentaxID_K_30:
+ case PentaxID_K_5_II:
+ case PentaxID_K_5_II_s:
+ case PentaxID_K_50:
+ case PentaxID_K_3:
+ case PentaxID_K_500:
+ case PentaxID_K_S1:
+ case PentaxID_K_S2:
+ case PentaxID_K_3_II:
+ case PentaxID_K_3_III:
+ case PentaxID_K_70:
+ case PentaxID_KP:
+ ilm.CameraMount = LIBRAW_MOUNT_Pentax_K;
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ break;
+ case PentaxID_K_1:
+ case PentaxID_K_1_Mark_II:
+ ilm.CameraMount = LIBRAW_MOUNT_Pentax_K;
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ break;
+ case PentaxID_645D:
+ case PentaxID_645Z:
+ ilm.CameraMount = LIBRAW_MOUNT_Pentax_645;
+ ilm.CameraFormat = LIBRAW_FORMAT_CROP645;
+ break;
+ case PentaxID_Q:
+ case PentaxID_Q10:
+ ilm.CameraMount = LIBRAW_MOUNT_Pentax_Q;
+ ilm.CameraFormat = LIBRAW_FORMAT_1div2p3INCH;
+ break;
+ case PentaxID_Q7:
+ case PentaxID_Q_S1:
+ ilm.CameraMount = LIBRAW_MOUNT_Pentax_Q;
+ ilm.CameraFormat = LIBRAW_FORMAT_1div1p7INCH;
+ break;
+ case PentaxID_MX_1:
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ ilm.CameraFormat = LIBRAW_FORMAT_1div1p7INCH;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ break;
+ case PentaxID_GR_III:
+ case PentaxID_GR_IIIx:
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ break;
+ default:
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ return;
+}
+
+void LibRaw::PentaxISO(ushort c)
+{
+ int code[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 50, 100, 200, 400, 800,
+ 1600, 3200, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278};
+ double value[] = {
+ 50, 64, 80, 100, 125, 160, 200, 250, 320,
+ 400, 500, 640, 800, 1000, 1250, 1600, 2000, 2500,
+ 3200, 4000, 5000, 6400, 8000, 10000, 12800, 16000, 20000,
+ 25600, 32000, 40000, 51200, 64000, 80000, 102400, 128000, 160000,
+ 204800, 258000, 325000, 409600, 516000, 650000, 819200, 50, 100,
+ 200, 400, 800, 1600, 3200, 50, 70, 100, 140,
+ 200, 280, 400, 560, 800, 1100, 1600, 2200, 3200,
+ 4500, 6400, 9000, 12800, 18000, 25600, 36000, 51200};
+#define numel (sizeof(code) / sizeof(code[0]))
+ int i;
+ for (i = 0; i < (int)numel; i++)
+ {
+ if (code[i] == c)
+ {
+ iso_speed = value[i];
+ return;
+ }
+ }
+ if (i == numel)
+ iso_speed = 65535.0f;
+}
+#undef numel
+
+void LibRaw::PentaxLensInfo(unsigned long long id, unsigned len) // tag 0x0207
+{
+ ushort iLensData = 0;
+ uchar *table_buf;
+ table_buf = (uchar *)malloc(MAX(len, 128));
+ fread(table_buf, len, 1, ifp);
+ if ((id < PentaxID_K100D) ||
+ (((id == PentaxID_K100D) ||
+ (id == PentaxID_K110D) ||
+ (id == PentaxID_K100D_Super)) &&
+ ((!table_buf[20] ||
+ (table_buf[20] == 0xff)))))
+ {
+ iLensData = 3;
+ if (ilm.LensID == LIBRAW_LENS_NOT_SET)
+ ilm.LensID = (((unsigned)table_buf[0]) << 8) + table_buf[1];
+ }
+ else
+ switch (len)
+ {
+ case 90: // LensInfo3
+ iLensData = 13;
+ if (ilm.LensID == LIBRAW_LENS_NOT_SET)
+ ilm.LensID = ((unsigned)((table_buf[1] & 0x0f) + table_buf[3]) << 8) +
+ table_buf[4];
+ break;
+ case 91: // LensInfo4
+ iLensData = 12;
+ if (ilm.LensID == LIBRAW_LENS_NOT_SET)
+ ilm.LensID = ((unsigned)((table_buf[1] & 0x0f) + table_buf[3]) << 8) +
+ table_buf[4];
+ break;
+ case 80: // LensInfo5
+ case 128:
+ iLensData = 15;
+ if (ilm.LensID == LIBRAW_LENS_NOT_SET)
+ ilm.LensID = ((unsigned)((table_buf[1] & 0x0f) + table_buf[4]) << 8) +
+ table_buf[5];
+ break;
+ case 168: // Ricoh GR III, id 0x1320e
+ break;
+ default:
+ if (id >= 0x12b9cULL) // LensInfo2
+ {
+ iLensData = 4;
+ if (ilm.LensID == LIBRAW_LENS_NOT_SET)
+ ilm.LensID = ((unsigned)((table_buf[0] & 0x0f) + table_buf[2]) << 8) +
+ table_buf[3];
+ }
+ }
+ if (iLensData)
+ {
+ if (table_buf[iLensData + 9] && (fabs(ilm.CurFocal) < 0.1f))
+ ilm.CurFocal = 10 * (table_buf[iLensData + 9] >> 2) *
+ libraw_powf64l(4, (table_buf[iLensData + 9] & 0x03) - 2);
+ if (table_buf[iLensData + 10] & 0xf0)
+ ilm.MaxAp4CurFocal = libraw_powf64l(
+ 2.0f, (float)((table_buf[iLensData + 10] & 0xf0) >> 4) / 4.0f);
+ if (table_buf[iLensData + 10] & 0x0f)
+ ilm.MinAp4CurFocal = libraw_powf64l(
+ 2.0f, (float)((table_buf[iLensData + 10] & 0x0f) + 10) / 4.0f);
+
+ if (iLensData != 12)
+ {
+ switch (table_buf[iLensData] & 0x06)
+ {
+ case 0:
+ ilm.MinAp4MinFocal = 22.0f;
+ break;
+ case 2:
+ ilm.MinAp4MinFocal = 32.0f;
+ break;
+ case 4:
+ ilm.MinAp4MinFocal = 45.0f;
+ break;
+ case 6:
+ ilm.MinAp4MinFocal = 16.0f;
+ break;
+ }
+ if (table_buf[iLensData] & 0x70)
+ ilm.LensFStops =
+ ((float)(((table_buf[iLensData] & 0x70) >> 4) ^ 0x07)) / 2.0f +
+ 5.0f;
+
+ ilm.MinFocusDistance = (float)(table_buf[iLensData + 3] & 0xf8);
+ ilm.FocusRangeIndex = (float)(table_buf[iLensData + 3] & 0x07);
+
+ if ((table_buf[iLensData + 14] > 1) && (fabs(ilm.MaxAp4CurFocal) < 0.7f))
+ ilm.MaxAp4CurFocal = libraw_powf64l(
+ 2.0f, (float)((table_buf[iLensData + 14] & 0x7f) - 1) / 32.0f);
+ }
+ else if ((id != 0x12e76ULL) && // K-5
+ (table_buf[iLensData + 15] > 1) &&
+ (fabs(ilm.MaxAp4CurFocal) < 0.7f))
+ {
+ ilm.MaxAp4CurFocal = libraw_powf64l(
+ 2.0f, (float)((table_buf[iLensData + 15] & 0x7f) - 1) / 32.0f);
+ }
+ }
+ free(table_buf);
+ return;
+}
+
+void LibRaw::parsePentaxMakernotes(int /*base*/, unsigned tag, unsigned type,
+ unsigned len, unsigned dng_writer)
+{
+
+ int c;
+// printf ("==>> =%s= tag:0x%x, type: %d, len:%d\n", model, tag, type, len);
+
+ if (tag == 0x0005)
+ {
+ unique_id = get4();
+ setPentaxBodyFeatures(unique_id);
+ }
+ else if (tag == 0x0008)
+ { /* 4 is raw, 7 is raw w/ pixel shift, 8 is raw w/ dynamic pixel shift */
+ imPentax.Quality = get2();
+ }
+ else if (tag == 0x000d)
+ {
+ imgdata.shootinginfo.FocusMode = imPentax.FocusMode[0] = get2();
+ }
+ else if (tag == 0x000e)
+ {
+ imgdata.shootinginfo.AFPoint = imPentax.AFPointSelected[0] = get2();
+ if (len == 2)
+ imPentax.AFPointSelected_Area = get2();
+ }
+ else if (tag == 0x000f)
+ {
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_LONG))
+ {
+ imPentax.AFPointsInFocus = get4();
+ if (!imPentax.AFPointsInFocus) imPentax.AFPointsInFocus = 0xffffffff;
+ else imPentax.AFPointsInFocus_version = 3;
+ }
+ else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT))
+ {
+ imPentax.AFPointsInFocus = (unsigned) get2();
+ if (imPentax.AFPointsInFocus == 0x0000ffff)
+ imPentax.AFPointsInFocus = 0xffffffff;
+ else imPentax.AFPointsInFocus_version = 2;
+ }
+ }
+ else if (tag == 0x0010)
+ {
+ imPentax.FocusPosition = get2();
+ }
+ else if (tag == 0x0013)
+ {
+ ilm.CurAp = (float)get2() / 10.0f;
+ }
+ else if (tag == 0x0014)
+ {
+ PentaxISO(get2());
+ }
+ else if (tag == 0x0017)
+ {
+ imgdata.shootinginfo.MeteringMode = get2();
+ }
+ else if (tag == 0x001b) {
+ cam_mul[2] = get2() / 256.0;
+ }
+ else if (tag == 0x001c) {
+ cam_mul[0] = get2() / 256.0;
+ }
+ else if (tag == 0x001d)
+ {
+ ilm.CurFocal = (float)get4() / 100.0f;
+ }
+ else if (tag == 0x0034)
+ {
+ uchar uc;
+ FORC4
+ {
+ fread(&uc, 1, 1, ifp);
+ imPentax.DriveMode[c] = uc;
+ }
+ imgdata.shootinginfo.DriveMode = imPentax.DriveMode[0];
+ }
+ else if (tag == 0x0037) {
+ switch (get2()) {
+ case 0:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ }
+ else if (tag == 0x0038)
+ {
+ imgdata.sizes.raw_inset_crops[0].cleft = get2();
+ imgdata.sizes.raw_inset_crops[0].ctop = get2();
+ }
+ else if (tag == 0x0039)
+ {
+ imgdata.sizes.raw_inset_crops[0].cwidth = get2();
+ imgdata.sizes.raw_inset_crops[0].cheight = get2();
+ }
+ else if (tag == 0x003c)
+ {
+ if ((len == 4) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_UNDEFINED)) {
+ imPentax.AFPointsInFocus = get4() & 0x7ff;
+ if (!imPentax.AFPointsInFocus) {
+ imPentax.AFPointsInFocus = 0xffffffff;
+ }
+ else {
+ imPentax.AFPointsInFocus_version = 1;
+ }
+ }
+ }
+ else if (tag == 0x003f)
+ {
+ unsigned a = unsigned(fgetc(ifp)) << 8;
+ ilm.LensID = a | fgetc(ifp);
+ }
+ else if (tag == 0x0047)
+ {
+ imCommon.CameraTemperature = (float)fgetc(ifp);
+ }
+ else if (tag == 0x004d)
+ {
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SLONG))
+ imCommon.FlashEC = getreal(type) / 256.0f;
+ else
+ imCommon.FlashEC = (float)((signed short)fgetc(ifp)) / 6.0f;
+ }
+ else if (tag == 0x005c)
+ {
+ fgetc(ifp);
+ imgdata.shootinginfo.ImageStabilization = (short)fgetc(ifp);
+ }
+ else if (tag == 0x0072)
+ {
+ imPentax.AFAdjustment = get2();
+ }
+ else if ((tag == 0x007e) && (dng_writer == nonDNG))
+ {
+ imgdata.color.linear_max[0] = imgdata.color.linear_max[1] =
+ imgdata.color.linear_max[2] = imgdata.color.linear_max[3] =
+ get4();
+ }
+ else if (tag == 0x0080)
+ {
+ short a = (short)fgetc(ifp);
+ switch (a)
+ {
+ case 0:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_4to3;
+ break;
+ case 1:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
+ break;
+ case 2:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_16to9;
+ break;
+ case 3:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_1to1;
+ break;
+ }
+ }
+
+ else if ((tag == 0x0200) && (dng_writer == nonDNG)) { // Pentax black level
+ FORC4 cblack[RGGB_2_RGBG(c)] = get2();
+ }
+
+ else if ((tag == 0x0201) && (dng_writer == nonDNG)) { // Pentax As Shot WB
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = get2();
+ }
+
+ else if ((tag == 0x0203) && (dng_writer == nonDNG))
+ {
+ for (int i = 0; i < 3; i++)
+ FORC3 cmatrix[i][c] = ((short)get2()) / 8192.0;
+ }
+ else if (tag == 0x0205)
+ {
+ if (imCommon.afcount < LIBRAW_AFDATA_MAXCOUNT)
+ {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ fread(imCommon.afdata[imCommon.afcount].AFInfoData, imCommon.afdata[imCommon.afcount].AFInfoData_length, 1, ifp);
+ if ((len < 25) && (len >= 11))
+ {
+ imPentax.AFPointMode = (imCommon.afdata[imCommon.afcount].AFInfoData[3] >>4) & 0x0f;
+ imPentax.FocusMode[1] = imCommon.afdata[imCommon.afcount].AFInfoData[3] & 0x0f;
+ imPentax.AFPointSelected[1] = sget2(imCommon.afdata[imCommon.afcount].AFInfoData+4);
+// Pentax K-m has multiexposure set to 8 when no multi-exposure is in effect
+ imPentax.MultiExposure = imCommon.afdata[imCommon.afcount].AFInfoData[10] & 0x0f;
+ }
+ imCommon.afcount++;
+ }
+ }
+ else if (tag == 0x0207)
+ {
+ if (len < 65535) // Safety belt
+ PentaxLensInfo(ilm.CamID, len);
+ }
+ else if ((tag >= 0x020d) && (tag <= 0x0214))
+ {
+ FORC4 icWBC[Pentax_wb_list1[tag - 0x020d]][RGGB_2_RGBG(c)] = get2();
+ }
+ else if ((tag == 0x021d) && (len == 18) &&
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_UNDEFINED) && (dng_writer == nonDNG))
+ {
+ for (int i = 0; i < 3; i++)
+ FORC3 cmatrix[i][c] = ((short)get2()) / 8192.0;
+ }
+ else if (tag == 0x021f)
+ {
+ if ((unique_id != PentaxID_K_1) &&
+ (unique_id != PentaxID_K_3) &&
+ (unique_id != PentaxID_K_3_II) &&
+ (unique_id != PentaxID_K_1_Mark_II))
+ {
+ fseek (ifp, 0x0b, SEEK_CUR);
+ imPentax.AFPointsInFocus = (unsigned) fgetc(ifp);
+ if (!imPentax.AFPointsInFocus) imPentax.AFPointsInFocus = 0xffffffff;
+ else imPentax.AFPointsInFocus_version = 4;
+ }
+ }
+ else if ((tag == 0x0220) && (dng_writer == nonDNG)) {
+ meta_offset = ftell(ifp);
+ }
+ else if (tag == 0x0221)
+ {
+ int nWB = get2();
+ if (nWB <= int(sizeof(icWBCCTC) / sizeof(icWBCCTC[0])))
+ FORC(nWB)
+ {
+ icWBCCTC[c][0] = (unsigned)0xcfc6 - get2();
+ fseek(ifp, 2, SEEK_CUR);
+ icWBCCTC[c][1] = get2();
+ icWBCCTC[c][2] = icWBCCTC[c][4] = 0x2000;
+ icWBCCTC[c][3] = get2();
+ }
+ }
+ else if (tag == 0x0215)
+ {
+ fseek(ifp, 16, SEEK_CUR);
+ sprintf(imgdata.shootinginfo.InternalBodySerial, "%d", get4());
+ }
+ else if (tag == 0x0229)
+ {
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ }
+ else if (tag == 0x022d)
+ {
+ int wb_ind;
+ getc(ifp);
+ for (int wb_cnt = 0; wb_cnt < (int)Pentax_wb_list2.size(); wb_cnt++)
+ {
+ wb_ind = getc(ifp);
+ if (wb_ind >= 0 && wb_ind < (int)Pentax_wb_list2.size() )
+ FORC4 icWBC[Pentax_wb_list2[wb_ind]][RGGB_2_RGBG(c)] = get2();
+ }
+ }
+ else if (tag == 0x0239) // Q-series lens info (LensInfoQ)
+ {
+ char LensInfo[20];
+ fseek(ifp, 12, SEEK_CUR);
+ stread(ilm.Lens, 30, ifp);
+ strcat(ilm.Lens, " ");
+ stread(LensInfo, 20, ifp);
+ strcat(ilm.Lens, LensInfo);
+ }
+ else if (tag == 0x0245)
+ {
+ if (imCommon.afcount < LIBRAW_AFDATA_MAXCOUNT) {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ fread(imCommon.afdata[imCommon.afcount].AFInfoData, imCommon.afdata[imCommon.afcount].AFInfoData_length, 1, ifp);
+ imCommon.afcount++;
+ }
+ }
+}
+
+void LibRaw::parseRicohMakernotes(int /*base*/, unsigned tag, unsigned type,
+ unsigned /*len*/, unsigned /*dng_writer */)
+{
+ char buffer[17];
+ if (tag == 0x0005)
+ {
+ int c;
+ int count = 0;
+ fread(buffer, 16, 1, ifp);
+ buffer[16] = 0;
+ FORC(16)
+ {
+ if ((isspace(buffer[c])) || (buffer[c] == 0x2D) || (isalnum(buffer[c])))
+ count++;
+ else
+ break;
+ }
+ if (count == 16)
+ {
+ if (strncmp(model, "GXR", 3))
+ {
+ sprintf(imgdata.shootinginfo.BodySerial, "%8s", buffer + 8);
+ }
+ buffer[8] = 0;
+ sprintf(imgdata.shootinginfo.InternalBodySerial, "%8s", buffer);
+ }
+ else
+ {
+ sprintf(imgdata.shootinginfo.BodySerial, "%02x%02x%02x%02x", buffer[4],
+ buffer[5], buffer[6], buffer[7]);
+ sprintf(imgdata.shootinginfo.InternalBodySerial, "%02x%02x%02x%02x",
+ buffer[8], buffer[9], buffer[10], buffer[11]);
+ }
+ }
+ else if ((tag == 0x1001) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT))
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ ilm.LensID = LIBRAW_LENS_NOT_SET;
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ imgdata.shootinginfo.ExposureProgram = get2();
+ }
+ else if ((tag == 0x1002) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT))
+ {
+ imgdata.shootinginfo.DriveMode = get2();
+ }
+ else if (tag == 0x1006)
+ {
+ imgdata.shootinginfo.FocusMode = get2();
+ }
+ else if (tag == 0x1007)
+ {
+ imRicoh.AutoBracketing = get2();
+ }
+ else if (tag == 0x1009)
+ {
+ imRicoh.MacroMode = get2();
+ }
+ else if (tag == 0x100a)
+ {
+ imRicoh.FlashMode = get2();
+ }
+ else if (tag == 0x100b)
+ {
+ imRicoh.FlashExposureComp = getreal(type);
+ }
+ else if (tag == 0x100c)
+ {
+ imRicoh.ManualFlashOutput = getreal(type);
+ }
+ else if ((tag == 0x100b) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_SRATIONAL))
+ {
+ imCommon.FlashEC = getreal(type);
+ }
+ else if ((tag == 0x1017) && ((imRicoh.WideAdapter = get2()) == 2))
+ {
+ strcpy(ilm.Attachment, "Wide-Angle Adapter");
+ }
+ else if (tag == 0x1018)
+ {
+ imRicoh.CropMode = get2();
+ }
+ else if (tag == 0x1019)
+ {
+ imRicoh.NDFilter = get2();
+ }
+ else if (tag == 0x1200)
+ {
+ imRicoh.AFStatus = get2();
+ }
+ else if (tag == 0x1201)
+ {
+ imRicoh.AFAreaXPosition[1] = get4();
+ }
+ else if (tag == 0x1202)
+ {
+ imRicoh.AFAreaYPosition[1] = get4();
+ }
+ else if (tag == 0x1203)
+ {
+ imRicoh.AFAreaXPosition[0] = get4();
+ }
+ else if (tag == 0x1204)
+ {
+ imRicoh.AFAreaYPosition[0] = get4();
+ }
+ else if (tag == 0x1205)
+ {
+ imRicoh.AFAreaMode = get2();
+ }
+ else if (tag == 0x1500)
+ {
+ ilm.CurFocal = getreal(type);
+ }
+ else if (tag == 0x1601)
+ {
+ imRicoh.SensorWidth = get4();
+ }
+ else if (tag == 0x1602)
+ {
+ imRicoh.SensorHeight = get4();
+ }
+ else if (tag == 0x1603)
+ {
+ imRicoh.CroppedImageWidth = get4();
+ }
+ else if (tag == 0x1604)
+ {
+ imRicoh.CroppedImageHeight= get4();
+ }
+ else if ((tag == 0x2001) && !strncmp(model, "GXR", 3))
+ {
+ short cur_tag;
+ fseek(ifp, 20, SEEK_CUR);
+ /*ntags =*/ get2();
+ cur_tag = get2();
+ while (cur_tag != 0x002c)
+ {
+ fseek(ifp, 10, SEEK_CUR);
+ cur_tag = get2();
+ }
+ fseek(ifp, 6, SEEK_CUR);
+ fseek(ifp, get4(), SEEK_SET);
+ for (int i=0; i<4; i++) {
+ stread(buffer, 16, ifp);
+ if ((buffer[0] == 'S') && (buffer[1] == 'I') && (buffer[2] == 'D'))
+ memcpy(imgdata.shootinginfo.BodySerial, buffer+4, 12);
+ else if ((buffer[0] == 'R') && (buffer[1] == 'L'))
+ ilm.LensID = buffer[2] - '0';
+ else if ((buffer[0] == 'L') && (buffer[1] == 'I') && (buffer[2] == 'D'))
+ memcpy(imgdata.lens.LensSerial, buffer+4, 12);
+ }
+ }
+}
diff --git a/libkdcraw/libraw/src/metadata/samsung.cpp b/libkdcraw/libraw/src/metadata/samsung.cpp
new file mode 100644
index 0000000..5c595e8
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/samsung.cpp
@@ -0,0 +1,182 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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_defs.h"
+
+void LibRaw::parseSamsungMakernotes(int /*base*/, unsigned tag, unsigned type,
+ unsigned len, unsigned dng_writer)
+{
+ int i, c;
+ if (tag == 0x0002)
+ {
+ imSamsung.DeviceType = get4();
+ if (imSamsung.DeviceType == 0x2000)
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_Samsung_NX;
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ }
+ else if (!strncmp(model, "NX mini", 7))
+ { // device type 0x1000: 'NX mini', EX2F, EX1, WB2000
+ ilm.CameraMount = LIBRAW_MOUNT_Samsung_NX_M;
+ ilm.CameraFormat = LIBRAW_FORMAT_1INCH;
+ }
+ else
+ {
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ }
+ }
+ else if (tag == 0x0003)
+ {
+ ilm.CamID = unique_id = get4();
+ }
+ else if (tag == 0x0043)
+ {
+ if ((i = get4()))
+ {
+ imCommon.CameraTemperature = (float)i;
+ if (get4() == 10)
+ imCommon.CameraTemperature /= 10.0f;
+ }
+ }
+ else if ((tag == 0xa002) && (dng_writer != AdobeDNG))
+ {
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ }
+ else if (tag == 0xa003)
+ {
+ ilm.LensID = get2();
+ if (ilm.LensID)
+ ilm.LensMount = LIBRAW_MOUNT_Samsung_NX;
+ }
+ else if (tag == 0xa004)
+ { // LensFirmware
+ stmread(imSamsung.LensFirmware, len, ifp);
+ }
+ else if (tag == 0xa005)
+ {
+ stmread(imgdata.lens.InternalLensSerial, len, ifp);
+ }
+ else if (tag == 0xa010)
+ {
+ FORC4 imSamsung.ImageSizeFull[c] = get4();
+ FORC4 imSamsung.ImageSizeCrop[c] = get4();
+ }
+ else if ((tag == 0xa011) && ((len == 1) || (len == 2)) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT))
+ {
+ imSamsung.ColorSpace[0] = (int)get2();
+ switch (imSamsung.ColorSpace[0]) {
+ case 0:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ if (len == 2)
+ imSamsung.ColorSpace[1] = (int)get2();
+ }
+ else if (tag == 0xa019)
+ {
+ ilm.CurAp = getreal(type);
+ }
+ else if ((tag == 0xa01a) && (unique_id != 0x5000000) &&
+ (!imgdata.lens.FocalLengthIn35mmFormat))
+ {
+ ilm.FocalLengthIn35mmFormat = get4();
+ if (ilm.FocalLengthIn35mmFormat >= 160)
+ ilm.FocalLengthIn35mmFormat /= 10.0f;
+ if ((ilm.CameraMount == LIBRAW_MOUNT_Samsung_NX_M) &&
+ (imSamsung.LensFirmware[10] < '6'))
+ ilm.FocalLengthIn35mmFormat *= 1.6f;
+ }
+ else if (tag == 0xa020)
+ {
+ FORC(11) imSamsung.key[c] = get4();
+ }
+ else if ((tag == 0xa021) && (dng_writer == nonDNG))
+ {
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = get4() - imSamsung.key[c];
+ }
+ else if (tag == 0xa022)
+ {
+ FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] =
+ get4() - imSamsung.key[c + 4];
+ if (icWBC[LIBRAW_WBI_Auto][0] <
+ (icWBC[LIBRAW_WBI_Auto][1] >> 1))
+ {
+ icWBC[LIBRAW_WBI_Auto][1] =
+ icWBC[LIBRAW_WBI_Auto][1] >> 4;
+ icWBC[LIBRAW_WBI_Auto][3] =
+ icWBC[LIBRAW_WBI_Auto][3] >> 4;
+ }
+ }
+ else if (tag == 0xa023)
+ {
+ ushort ki[4] = {8, 9, 10, 0};
+ FORC4 icWBC[LIBRAW_WBI_Ill_A][RGGB_2_RGBG(c)] =
+ get4() - imSamsung.key[ki[c]];
+ if (icWBC[LIBRAW_WBI_Ill_A][0] <
+ (icWBC[LIBRAW_WBI_Ill_A][1] >> 1))
+ {
+ icWBC[LIBRAW_WBI_Ill_A][1] =
+ icWBC[LIBRAW_WBI_Ill_A][1] >> 4;
+ icWBC[LIBRAW_WBI_Ill_A][3] =
+ icWBC[LIBRAW_WBI_Ill_A][3] >> 4;
+ }
+ }
+ else if (tag == 0xa024)
+ {
+ FORC4 icWBC[LIBRAW_WBI_D65][RGGB_2_RGBG(c)] =
+ get4() - imSamsung.key[c + 1];
+ if (icWBC[LIBRAW_WBI_D65][0] <
+ (icWBC[LIBRAW_WBI_D65][1] >> 1))
+ {
+ icWBC[LIBRAW_WBI_D65][1] =
+ icWBC[LIBRAW_WBI_D65][1] >> 4;
+ icWBC[LIBRAW_WBI_D65][3] =
+ icWBC[LIBRAW_WBI_D65][3] >> 4;
+ }
+ }
+ else if (tag == 0xa025)
+ {
+ unsigned t = get4() + imSamsung.key[0];
+ if (t == 4096)
+ imSamsung.DigitalGain = 1.0;
+ else
+ imSamsung.DigitalGain = ((double)t) / 4096.0;
+ }
+ else if ((tag == 0xa028) && (dng_writer == nonDNG))
+ {
+ FORC4 cblack[RGGB_2_RGBG(c)] = get4() - imSamsung.key[c];
+ }
+ else if ((tag == 0xa030) && (len == 9))
+ {
+ for (i = 0; i < 3; i++)
+ FORC3 imgdata.color.ccm[i][c] =
+ (float)((short)((get4() + imSamsung.key[i * 3 + c]))) / 256.0;
+ }
+ else if ((tag == 0xa032) && (len == 9) && (dng_writer == nonDNG))
+ {
+ double aRGB_cam[3][3];
+ FORC(9)
+ ((double *)aRGB_cam)[c] =
+ ((double)((short)((get4() + imSamsung.key[c])))) / 256.0;
+ aRGB_coeff(aRGB_cam);
+ }
+}
diff --git a/libkdcraw/libraw/src/metadata/sony.cpp b/libkdcraw/libraw/src/metadata/sony.cpp
new file mode 100644
index 0000000..ea568b5
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/sony.cpp
@@ -0,0 +1,2316 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+#include "../../internal/libraw_cameraids.h"
+
+static ushort saneSonyCameraInfo(uchar a, uchar b, uchar c, uchar d, uchar e,
+ uchar f)
+{
+ if ((a >> 4) > 9)
+ return 0;
+ else if ((a & 0x0f) > 9)
+ return 0;
+ else if ((b >> 4) > 9)
+ return 0;
+ else if ((b & 0x0f) > 9)
+ return 0;
+ else if ((c >> 4) > 9)
+ return 0;
+ else if ((c & 0x0f) > 9)
+ return 0;
+ else if ((d >> 4) > 9)
+ return 0;
+ else if ((d & 0x0f) > 9)
+ return 0;
+ else if ((e >> 4) > 9)
+ return 0;
+ else if ((e & 0x0f) > 9)
+ return 0;
+ else if ((f >> 4) > 9)
+ return 0;
+ else if ((f & 0x0f) > 9)
+ return 0;
+ return 1;
+}
+static float my_roundf(float x)
+{
+ float t;
+ if (x >= 0.0)
+ {
+ t = ceilf(x);
+ if (t - x > 0.5)
+ t -= 1.0;
+ return t;
+ }
+ else
+ {
+ t = ceilf(-x);
+ if (t + x > 0.5)
+ t -= 1.0;
+ return -t;
+ }
+}
+
+static ushort bcd2dec(uchar data)
+{
+ if ((data >> 4) > 9)
+ return 0;
+ else if ((data & 0x0f) > 9)
+ return 0;
+ else
+ return (data >> 4) * 10 + (data & 0x0f);
+}
+
+static uchar SonySubstitution[257] =
+ "\x00\x01\x32\xb1\x0a\x0e\x87\x28\x02\xcc\xca\xad\x1b\xdc\x08\xed\x64\x86"
+ "\xf0\x4f\x8c\x6c\xb8\xcb\x69\xc4\x2c\x03"
+ "\x97\xb6\x93\x7c\x14\xf3\xe2\x3e\x30\x8e\xd7\x60\x1c\xa1\xab\x37\xec\x75"
+ "\xbe\x23\x15\x6a\x59\x3f\xd0\xb9\x96\xb5"
+ "\x50\x27\x88\xe3\x81\x94\xe0\xc0\x04\x5c\xc6\xe8\x5f\x4b\x70\x38\x9f\x82"
+ "\x80\x51\x2b\xc5\x45\x49\x9b\x21\x52\x53"
+ "\x54\x85\x0b\x5d\x61\xda\x7b\x55\x26\x24\x07\x6e\x36\x5b\x47\xb7\xd9\x4a"
+ "\xa2\xdf\xbf\x12\x25\xbc\x1e\x7f\x56\xea"
+ "\x10\xe6\xcf\x67\x4d\x3c\x91\x83\xe1\x31\xb3\x6f\xf4\x05\x8a\x46\xc8\x18"
+ "\x76\x68\xbd\xac\x92\x2a\x13\xe9\x0f\xa3"
+ "\x7a\xdb\x3d\xd4\xe7\x3a\x1a\x57\xaf\x20\x42\xb2\x9e\xc3\x8b\xf2\xd5\xd3"
+ "\xa4\x7e\x1f\x98\x9c\xee\x74\xa5\xa6\xa7"
+ "\xd8\x5e\xb0\xb4\x34\xce\xa8\x79\x77\x5a\xc1\x89\xae\x9a\x11\x33\x9d\xf5"
+ "\x39\x19\x65\x78\x16\x71\xd2\xa9\x44\x63"
+ "\x40\x29\xba\xa0\x8f\xe4\xd6\x3b\x84\x0d\xc2\x4e\x58\xdd\x99\x22\x6b\xc9"
+ "\xbb\x17\x06\xe5\x7d\x66\x43\x62\xf6\xcd"
+ "\x35\x90\x2e\x41\x8d\x6d\xaa\x09\x73\x95\x0c\xf1\x1d\xde\x4c\x2f\x2d\xf7"
+ "\xd1\x72\xeb\xef\x48\xc7\xf8\xf9\xfa\xfb"
+ "\xfc\xfd\xfe\xff";
+
+void LibRaw::sony_decrypt(unsigned *data, int len, int start, int key)
+{
+#ifndef LIBRAW_NOTHREADS
+#define pad tls->sony_decrypt.pad
+#define p tls->sony_decrypt.p
+#else
+ static unsigned pad[128], p;
+#endif
+ if (start)
+ {
+ for (p = 0; p < 4; p++)
+ pad[p] = key = key * 48828125ULL + 1;
+ pad[3] = pad[3] << 1 | (pad[0] ^ pad[2]) >> 31;
+ for (p = 4; p < 127; p++)
+ pad[p] = (pad[p - 4] ^ pad[p - 2]) << 1 | (pad[p - 3] ^ pad[p - 1]) >> 31;
+ for (p = 0; p < 127; p++)
+ pad[p] = htonl(pad[p]);
+ }
+ while (len--)
+ {
+ *data++ ^= pad[p & 127] = pad[(p + 1) & 127] ^ pad[(p + 65) & 127];
+ p++;
+ }
+#ifndef LIBRAW_NOTHREADS
+#undef pad
+#undef p
+#endif
+}
+void LibRaw::setSonyBodyFeatures(unsigned long long id)
+{
+ static const struct
+ {
+ ushort scf[11];
+ /*
+ scf[0] camera id
+ scf[1] camera format
+ scf[2] camera mount: Minolta A, Sony E, fixed,
+ scf[3] camera type: DSLR, NEX, SLT, ILCE, ILCA, DSC
+ scf[4] lens mount, LIBRAW_MOUNT_FixedLens or LIBRAW_MOUNT_Unknown
+ scf[5] tag 0x2010 group (0 if not used)
+ scf[6] offset of Sony ISO in 0x2010 table, 0xffff if not valid
+ scf[7] offset of ShutterCount3 in 0x9050 table, 0xffff if not valid
+ scf[8] offset of MeteringMode in 0x2010 table, 0xffff if not valid
+ scf[9] offset of ExposureProgram in 0x2010 table, 0xffff if not valid
+ scf[10] offset of ReleaseMode2 in 0x2010 table, 0xffff if not valid
+ */
+ } SonyCamFeatures[] = {
+ {SonyID_DSLR_A100, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A900, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A700, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A200, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A350, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A300, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A900, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A380, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A330, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A230, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A290, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A850, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A850, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A550, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A500, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A450, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_NEX_5, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_NEX_3, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_SLT_A33, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_SLT_A55, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A560, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_DSLR_A580, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_NEX_C3, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_SLT_A35, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_SLT_A65, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010b, 0x1218, 0x01bd, 0x1178, 0x1179, 0x112c},
+ {SonyID_SLT_A77, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010b, 0x1218, 0x01bd, 0x1178, 0x1179, 0x112c},
+ {SonyID_NEX_5N, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010a, 0x113e, 0x01bd, 0x1174, 0x1175, 0x112c},
+ {SonyID_NEX_7, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010b, 0x1218, 0x01bd, 0x1178, 0x1179, 0x112c},
+ {SonyID_NEX_VG20, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010b, 0x1218, 0x01bd, 0x1178, 0x1179, 0x112c},
+ {SonyID_SLT_A37, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010c, 0x11f4, 0x01bd, 0x1154, 0x1155, 0x1108},
+ {SonyID_SLT_A57, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010c, 0x11f4, 0x01bd, 0x1154, 0x1155, 0x1108},
+ {SonyID_NEX_F3, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010c, 0x11f4, 0x01bd, 0x1154, 0x1155, 0x1108},
+ {SonyID_SLT_A99, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010e, 0x1254, 0x01aa, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_NEX_6, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010e, 0x1254, 0x01aa, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_NEX_5R, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010e, 0x1254, 0x01aa, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_DSC_RX100, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010e, 0x1254, 0xffff, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_DSC_RX1, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010e, 0x1258, 0xffff, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_NEX_VG900, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010e, 0x1254, 0x01aa, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_NEX_VG30, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010e, 0x1254, 0x01aa, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_ILCE_3000, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010e, 0x1280, 0x01aa, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_SLT_A58, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010e, 0x1280, 0x01aa, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_NEX_3N, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010e, 0x1280, 0x01aa, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_ILCE_7, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_NEX_5T, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010e, 0x1254, 0x01aa, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_DSC_RX100M2, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010f, 0x113c, 0xffff, 0x1064, 0x1065, 0x1018},
+ {SonyID_DSC_RX10, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_DSC_RX1R, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010e, 0x1258, 0xffff, 0x11ac, 0x11ad, 0x1160},
+ {SonyID_ILCE_7R, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_6000, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_5000, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0x01aa, 0x025c, 0x025d, 0x0210},
+ {SonyID_DSC_RX100M3, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_7S, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCA_77M2, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_ILCA, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0x01a0, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_5100, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0x01a0, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_7M2, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_DSC_RX100M4, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_DSC_RX10M2, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_DSC_RX1RM2, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_QX1, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0x01a0, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_7RM2, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0x01cb, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_7SM2, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0x01cb, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCA_68, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_ILCA, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010g, 0x0344, 0x01a0, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCA_99M2, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_ILCA, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0x01cd, 0x025c, 0x025d, 0x0210},
+ {SonyID_DSC_RX10M3, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_DSC_RX100M5, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_6300, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0x01cd, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_9, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+ {SonyID_ILCE_6500, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0x01cd, 0x025c, 0x025d, 0x0210},
+ {SonyID_ILCE_7RM3, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+ {SonyID_ILCE_7M3, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+ {SonyID_DSC_RX0, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010h, 0x0346, 0xffff, 0x025c, 0x025d, 0x0210},
+ {SonyID_DSC_RX10M4, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0xffff, 0x024b, 0x024c, 0x0208},
+ {SonyID_DSC_RX100M6, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0xffff, 0x024b, 0x024c, 0x0208},
+ {SonyID_DSC_HX99, LIBRAW_FORMAT_1div2p3INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0xffff, 0x024b, 0x024c, 0x0208},
+ {SonyID_DSC_RX100M5A, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0xffff, 0x024b, 0x024c, 0x0208},
+ {SonyID_ILCE_6400, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+ {SonyID_DSC_RX0M2, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0xffff, 0x024b, 0x024c, 0x0208},
+ {SonyID_DSC_RX100M7, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0xffff, 0x024b, 0x024c, 0x0208},
+ {SonyID_ILCE_7RM4, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+ {SonyID_ILCE_9M2, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+ {SonyID_ILCE_6600, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+ {SonyID_ILCE_6100, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+ {SonyID_ZV_1, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0xffff, 0x024b, 0x024c, 0x0208},
+ {SonyID_ILCE_7C, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+
+// a la SonyID_ILCE_6100
+ {SonyID_ZV_E10, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+
+ {SonyID_ILCE_7SM3, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_ILCE_1, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_ILME_FX3, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_ILCE_7RM3A, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+ {SonyID_ILCE_7RM4A, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010i, 0x0320, 0x019f, 0x024b, 0x024c, 0x0208},
+ {SonyID_ILCE_7M4, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, LIBRAW_MOUNT_Unknown,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ };
+ ilm.CamID = id;
+
+ if (id == SonyID_DSC_R1)
+ {
+ ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ imSony.CameraType = LIBRAW_SONY_DSC;
+ imSony.group2010 = LIBRAW_SONY_Tag2010None;
+ imSony.group9050 = LIBRAW_SONY_Tag9050None;
+ return;
+ }
+
+ for (unsigned i = 0; i < (sizeof SonyCamFeatures / sizeof *SonyCamFeatures); i++) {
+ if (SonyCamFeatures[i].scf[0] == id) {
+ ilm.CameraFormat = SonyCamFeatures[i].scf[1];
+ ilm.CameraMount = SonyCamFeatures[i].scf[2];
+ imSony.CameraType = SonyCamFeatures[i].scf[3];
+ if (SonyCamFeatures[i].scf[4])
+ ilm.LensMount = SonyCamFeatures[i].scf[4];
+ imSony.group2010 = SonyCamFeatures[i].scf[5];
+ imSony.real_iso_offset = SonyCamFeatures[i].scf[6];
+ imSony.ImageCount3_offset = SonyCamFeatures[i].scf[7];
+ imSony.MeteringMode_offset = SonyCamFeatures[i].scf[8];
+ imSony.ExposureProgram_offset = SonyCamFeatures[i].scf[9];
+ imSony.ReleaseMode2_offset = SonyCamFeatures[i].scf[10];
+ break;
+ }
+ }
+
+ switch (id) {
+ case SonyID_ILCE_6100:
+ case SonyID_ILCE_6300:
+ case SonyID_ILCE_6400:
+ case SonyID_ILCE_6500:
+ case SonyID_ILCE_6600:
+ case SonyID_ILCE_7C:
+ case SonyID_ILCE_7M3:
+ case SonyID_ILCE_7RM2:
+ case SonyID_ILCE_7RM3A:
+ case SonyID_ILCE_7RM3:
+ case SonyID_ILCE_7RM4:
+ case SonyID_ILCE_7RM4A:
+ case SonyID_ILCE_7SM2:
+ case SonyID_ILCE_9:
+ case SonyID_ILCE_9M2:
+ case SonyID_ILCA_99M2:
+ case SonyID_ZV_E10:
+ imSony.group9050 = LIBRAW_SONY_Tag9050b;
+ break;
+ case SonyID_ILCE_7SM3:
+ case SonyID_ILCE_1:
+ case SonyID_ILME_FX3:
+ case SonyID_ILCE_7M4:
+ imSony.group9050 = LIBRAW_SONY_Tag9050c;
+ break;
+ default:
+ if ((imSony.CameraType != LIBRAW_SONY_DSC) &&
+ (imSony.CameraType != LIBRAW_SONY_DSLR))
+ imSony.group9050 = LIBRAW_SONY_Tag9050a;
+ else
+ imSony.group9050 = LIBRAW_SONY_Tag9050None;
+ break;
+ }
+
+ char *sbstr = strstr(software, " v");
+ if (sbstr != NULL)
+ {
+ sbstr += 2;
+ strcpy(imCommon.firmware, sbstr);
+ imSony.firmware = atof(sbstr);
+
+ if ((id == SonyID_ILCE_7) ||
+ (id == SonyID_ILCE_7R))
+ {
+ if (imSony.firmware < 1.2f)
+ imSony.ImageCount3_offset = 0x01aa;
+ else
+ imSony.ImageCount3_offset = 0x01c0;
+ }
+ else if (id == SonyID_ILCE_6000)
+ {
+ if (imSony.firmware < 2.0f)
+ imSony.ImageCount3_offset = 0x01aa;
+ else
+ imSony.ImageCount3_offset = 0x01c0;
+ }
+ else if ((id == SonyID_ILCE_7S) ||
+ (id == SonyID_ILCE_7M2))
+ {
+ if (imSony.firmware < 1.2f)
+ imSony.ImageCount3_offset = 0x01a0;
+ else
+ imSony.ImageCount3_offset = 0x01b6;
+ }
+ }
+
+ if ((id == SonyID_ILCE_7SM3) &&
+ !strcmp(model, "MODEL-NAME")) {
+ imSony.group9050 = LIBRAW_SONY_Tag9050a;
+ }
+
+}
+
+void LibRaw::parseSonyLensType2(uchar a, uchar b)
+{
+ ushort lid2;
+ lid2 = (((ushort)a) << 8) | ((ushort)b);
+ if (!lid2)
+ return;
+ if (lid2 < 0x100)
+ {
+ if ((ilm.AdapterID != 0x4900) && (ilm.AdapterID != 0xef00))
+ {
+ ilm.AdapterID = lid2;
+ switch (lid2)
+ {
+ case 1: // Sony LA-EA1 or Sigma MC-11 Adapter
+ case 2: // Sony LA-EA2
+ case 3: // Sony LA-EA3
+ case 6: // Sony LA-EA4
+ case 7: // Sony LA-EA5
+ case 24593: // LA-EA4r MonsterAdapter, id = 0x6011
+ ilm.LensMount = LIBRAW_MOUNT_Minolta_A;
+ break;
+ case 44: // Metabones Canon EF Smart Adapter
+ case 78: // Metabones Canon EF Smart Adapter Mark III or Other Adapter
+ case 184: // Metabones Canon EF Speed Booster Ultra
+ case 234: // Metabones Canon EF Smart Adapter Mark IV
+ case 239: // Metabones Canon EF Speed Booster
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ break;
+ }
+ }
+ }
+ else
+ ilm.LensID = lid2;
+
+ if ((lid2 >= 50481) &&
+ (lid2 < 50500)) {
+ strcpy(ilm.Adapter, "MC-11");
+ ilm.AdapterID = 0x4900;
+ } else if ((lid2 > 0xef00) &&
+ (lid2 < 0xffff) &&
+ (lid2 != 0xff00)) {
+ ilm.AdapterID = 0xef00;
+ ilm.LensID -= ilm.AdapterID;
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ }
+
+ return;
+}
+
+void LibRaw::parseSonyLensFeatures(uchar a, uchar b)
+{
+
+ ushort features;
+ features = (((ushort)a) << 8) | ((ushort)b);
+
+ if ((ilm.LensMount == LIBRAW_MOUNT_Canon_EF) ||
+ (ilm.LensMount != LIBRAW_MOUNT_Sigma_X3F) || !features)
+ return;
+
+ ilm.LensFeatures_pre[0] = 0;
+ ilm.LensFeatures_suf[0] = 0;
+ if ((features & 0x0200) && (features & 0x0100))
+ strcpy(ilm.LensFeatures_pre, "E");
+ else if (features & 0x0200)
+ strcpy(ilm.LensFeatures_pre, "FE");
+ else if (features & 0x0100)
+ strcpy(ilm.LensFeatures_pre, "DT");
+
+ if (!ilm.LensFormat && !ilm.LensMount)
+ {
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ ilm.LensMount = LIBRAW_MOUNT_Minolta_A;
+
+ if ((features & 0x0200) && (features & 0x0100))
+ {
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ ilm.LensMount = LIBRAW_MOUNT_Sony_E;
+ }
+ else if (features & 0x0200)
+ {
+ ilm.LensMount = LIBRAW_MOUNT_Sony_E;
+ }
+ else if (features & 0x0100)
+ {
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ }
+ }
+
+ if (features & 0x4000)
+ strnXcat(ilm.LensFeatures_pre, " PZ");
+
+ if (features & 0x0008)
+ strnXcat(ilm.LensFeatures_suf, " G");
+ else if (features & 0x0004)
+ strnXcat(ilm.LensFeatures_suf, " ZA");
+
+ if ((features & 0x0020) && (features & 0x0040))
+ strnXcat(ilm.LensFeatures_suf, " Macro");
+ else if (features & 0x0020)
+ strnXcat(ilm.LensFeatures_suf, " STF");
+ else if (features & 0x0040)
+ strnXcat(ilm.LensFeatures_suf, " Reflex");
+ else if (features & 0x0080)
+ strnXcat(ilm.LensFeatures_suf, " Fisheye");
+
+ if (features & 0x0001)
+ strnXcat(ilm.LensFeatures_suf, " SSM");
+ else if (features & 0x0002)
+ strnXcat(ilm.LensFeatures_suf, " SAM");
+
+ if (features & 0x8000)
+ strnXcat(ilm.LensFeatures_suf, " OSS");
+
+ if (features & 0x2000)
+ strnXcat(ilm.LensFeatures_suf, " LE");
+
+ if (features & 0x0800)
+ strnXcat(ilm.LensFeatures_suf, " II");
+
+ if (ilm.LensFeatures_suf[0] == ' ')
+ memmove(ilm.LensFeatures_suf, ilm.LensFeatures_suf + 1,
+ strbuflen(ilm.LensFeatures_suf) - 1);
+
+ return;
+}
+
+void LibRaw::process_Sony_0x0116(uchar *buf, ushort len, unsigned long long id)
+{
+ int i = 0;
+
+ if (((id == SonyID_DSLR_A900) ||
+ (id == SonyID_DSLR_A900_APSC) ||
+ (id == SonyID_DSLR_A850) ||
+ (id == SonyID_DSLR_A850_APSC)) &&
+ (len >= 2))
+ i = 1;
+ else if ((id >= SonyID_DSLR_A550) && (len >= 3))
+ i = 2;
+ else
+ return;
+
+ imCommon.BatteryTemperature = (float)(buf[i] - 32) / 1.8f;
+}
+
+void LibRaw::process_Sony_0x2010(uchar *buf, ushort len)
+{
+
+ if (imSony.group2010 == LIBRAW_SONY_Tag2010None) return;
+
+ if ((imSony.real_iso_offset != 0xffff) &&
+ (len >= (imSony.real_iso_offset + 2)) && (imCommon.real_ISO < 0.1f))
+ {
+ uchar s[2];
+ s[0] = SonySubstitution[buf[imSony.real_iso_offset]];
+ s[1] = SonySubstitution[buf[imSony.real_iso_offset + 1]];
+ imCommon.real_ISO =
+ 100.0f * libraw_powf64l(2.0f, (16 - ((float)sget2(s)) / 256.0f));
+ }
+
+ if ((imSony.MeteringMode_offset != 0xffff) &&
+ (imSony.ExposureProgram_offset != 0xffff) &&
+ (len >= (imSony.MeteringMode_offset + 2)))
+ {
+ imgdata.shootinginfo.MeteringMode =
+ SonySubstitution[buf[imSony.MeteringMode_offset]];
+ imgdata.shootinginfo.ExposureProgram =
+ SonySubstitution[buf[imSony.ExposureProgram_offset]];
+ }
+
+ if ((imSony.ReleaseMode2_offset != 0xffff) &&
+ (len >= (imSony.ReleaseMode2_offset + 2)))
+ {
+ imgdata.shootinginfo.DriveMode =
+ SonySubstitution[buf[imSony.ReleaseMode2_offset]];
+ }
+}
+
+void LibRaw::process_Sony_0x9050(uchar *buf, ushort len, unsigned long long id)
+{
+ ushort lid;
+ uchar s[4];
+ int c;
+
+ if ((imSony.group9050 == LIBRAW_SONY_Tag9050None) &&
+ (imSony.CameraType != LIBRAW_SONY_DSC) &&
+ (imSony.CameraType != LIBRAW_SONY_DSLR))
+ imSony.group9050 = LIBRAW_SONY_Tag9050a;
+
+ if (imSony.group9050 == LIBRAW_SONY_Tag9050None) return;
+
+ if ((ilm.CameraMount != LIBRAW_MOUNT_Sony_E) &&
+ (imSony.CameraType != LIBRAW_SONY_DSC))
+ {
+ if (len < 2)
+ return;
+ if (buf[0])
+ ilm.MaxAp4CurFocal =
+ my_roundf(
+ libraw_powf64l(2.0f, ((float)SonySubstitution[buf[0]] / 8.0 - 1.06f) / 2.0f) *
+ 10.0f) / 10.0f;
+
+ if (buf[1])
+ ilm.MinAp4CurFocal =
+ my_roundf(
+ libraw_powf64l(2.0f, ((float)SonySubstitution[buf[1]] / 8.0 - 1.06f) / 2.0f) *
+ 10.0f) / 10.0f;
+ }
+
+ if ((imSony.group9050 == LIBRAW_SONY_Tag9050b) ||
+ (imSony.group9050 == LIBRAW_SONY_Tag9050c)) {
+ if (len <= 0x8d) return;
+ unsigned long long b88 = SonySubstitution[buf[0x88]];
+ unsigned long long b89 = SonySubstitution[buf[0x89]];
+ unsigned long long b8a = SonySubstitution[buf[0x8a]];
+ unsigned long long b8b = SonySubstitution[buf[0x8b]];
+ unsigned long long b8c = SonySubstitution[buf[0x8c]];
+ unsigned long long b8d = SonySubstitution[buf[0x8d]];
+ sprintf(imgdata.shootinginfo.InternalBodySerial, "%06llx",
+ (b88 << 40) + (b89 << 32) + (b8a << 24) + (b8b << 16) + (b8c << 8) + b8d);
+
+ } else if (imSony.group9050 == LIBRAW_SONY_Tag9050a) {
+ if ((ilm.CameraMount == LIBRAW_MOUNT_Sony_E) &&
+ (id != SonyID_NEX_5N) &&
+ (id != SonyID_NEX_7) &&
+ (id != SonyID_NEX_VG20)) {
+ if (len <= 0x7f) return;
+ unsigned b7c = SonySubstitution[buf[0x7c]];
+ unsigned b7d = SonySubstitution[buf[0x7d]];
+ unsigned b7e = SonySubstitution[buf[0x7e]];
+ unsigned b7f = SonySubstitution[buf[0x7f]];
+ sprintf(imgdata.shootinginfo.InternalBodySerial, "%04x",
+ (b7c << 24) + (b7d << 16) + (b7e << 8) + b7f);
+
+ } else if (ilm.CameraMount == LIBRAW_MOUNT_Minolta_A) {
+ if (len <= 0xf4) return;
+ unsigned long long bf0 = SonySubstitution[buf[0xf0]];
+ unsigned long long bf1 = SonySubstitution[buf[0xf1]];
+ unsigned long long bf2 = SonySubstitution[buf[0xf2]];
+ unsigned long long bf3 = SonySubstitution[buf[0xf3]];
+ unsigned long long bf4 = SonySubstitution[buf[0xf4]];
+ sprintf(imgdata.shootinginfo.InternalBodySerial, "%05llx",
+ (bf0 << 32) + (bf1 << 24) + (bf2 << 16) + (bf3 << 8) + bf4);
+ }
+ }
+
+ if (imSony.CameraType != LIBRAW_SONY_DSC)
+ {
+ if (len <= 0x106)
+ return;
+ if (buf[0x3d] | buf[0x3c])
+ {
+ lid = SonySubstitution[buf[0x3d]] << 8 | SonySubstitution[buf[0x3c]];
+ ilm.CurAp = libraw_powf64l(2.0f, ((float)lid / 256.0f - 16.0f) / 2.0f);
+ }
+ if (buf[0x105] &&
+ (ilm.LensMount != LIBRAW_MOUNT_Canon_EF) &&
+ (ilm.LensMount != LIBRAW_MOUNT_Sigma_X3F)) {
+ switch (SonySubstitution[buf[0x105]]) {
+ case 1:
+ ilm.LensMount = LIBRAW_MOUNT_Minolta_A;
+ break;
+ case 2:
+ ilm.LensMount = LIBRAW_MOUNT_Sony_E;
+ break;
+ }
+ }
+ if (buf[0x106]) {
+ switch (SonySubstitution[buf[0x106]]) {
+ case 1:
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ break;
+ case 2:
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ break;
+ }
+ }
+ }
+
+ if (ilm.CameraMount == LIBRAW_MOUNT_Sony_E)
+ {
+ if (len <= 0x108)
+ return;
+ parseSonyLensType2(
+ SonySubstitution[buf[0x0108]], // LensType2 - Sony lens ids
+ SonySubstitution[buf[0x0107]]);
+ }
+
+ if (len <= 0x10a)
+ return;
+ if ((ilm.LensID == LIBRAW_LENS_NOT_SET) &&
+ (ilm.CameraMount == LIBRAW_MOUNT_Minolta_A) &&
+ (buf[0x010a] | buf[0x0109]))
+ {
+ ilm.LensID = // LensType - Minolta/Sony lens ids
+ SonySubstitution[buf[0x010a]] << 8 | SonySubstitution[buf[0x0109]];
+
+ if ((ilm.LensID > 0x4900) && (ilm.LensID <= 0x5900))
+ {
+ ilm.AdapterID = 0x4900;
+ ilm.LensID -= ilm.AdapterID;
+ ilm.LensMount = LIBRAW_MOUNT_Sigma_X3F;
+ strcpy(ilm.Adapter, "MC-11");
+ }
+
+ else if ((ilm.LensID > 0xef00) && (ilm.LensID < 0xffff) &&
+ (ilm.LensID != 0xff00))
+ {
+ ilm.AdapterID = 0xef00;
+ ilm.LensID -= ilm.AdapterID;
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ }
+ }
+
+ if ((id >= SonyID_SLT_A65) && (id <= SonyID_NEX_F3))
+ {
+ if (len <= 0x116)
+ return;
+ // "SLT-A65", "SLT-A77", "NEX-7", "NEX-VG20",
+ // "SLT-A37", "SLT-A57", "NEX-F3", "Lunar"
+ parseSonyLensFeatures(SonySubstitution[buf[0x115]],
+ SonySubstitution[buf[0x116]]);
+ }
+ else if (ilm.CameraMount != LIBRAW_MOUNT_FixedLens)
+ {
+ if (len <= 0x117)
+ return;
+ parseSonyLensFeatures(SonySubstitution[buf[0x116]],
+ SonySubstitution[buf[0x117]]);
+ }
+
+ if ((imSony.ImageCount3_offset != 0xffff) &&
+ (len >= (imSony.ImageCount3_offset + 4)))
+ {
+ FORC4 s[c] = SonySubstitution[buf[imSony.ImageCount3_offset + c]];
+ imSony.ImageCount3 = sget4(s);
+ }
+
+ return;
+}
+
+void LibRaw::process_Sony_0x9400(uchar *buf, ushort len, unsigned long long /*id*/)
+{
+
+ uchar s[4];
+ int c;
+ uchar bufx = buf[0];
+
+ if (((bufx == 0x23) ||
+ (bufx == 0x24) ||
+ (bufx == 0x26) ||
+ (bufx == 0x28) ||
+ (bufx == 0x31)) &&
+ (len >= 0x1f)) // 0x9400 'c' version
+ {
+ imSony.Sony0x9400_version = 0xc;
+ imSony.Sony0x9400_ReleaseMode2 = SonySubstitution[buf[0x09]];
+
+ if ((imSony.group2010 == LIBRAW_SONY_Tag2010g) ||
+ (imSony.group2010 == LIBRAW_SONY_Tag2010h)) {
+ FORC4 s[c] = SonySubstitution[buf[0x0a + c]];
+ imSony.ShotNumberSincePowerUp = sget4(s);
+ } else {
+ imSony.ShotNumberSincePowerUp = SonySubstitution[buf[0x0a]];
+ }
+
+ FORC4 s[c] = SonySubstitution[buf[0x12 + c]];
+ imSony.Sony0x9400_SequenceImageNumber = sget4(s);
+
+ imSony.Sony0x9400_SequenceLength1 = SonySubstitution[buf[0x16]]; // shots
+
+ FORC4 s[c] = SonySubstitution[buf[0x1a + c]];
+ imSony.Sony0x9400_SequenceFileNumber = sget4(s);
+
+ imSony.Sony0x9400_SequenceLength2 = SonySubstitution[buf[0x1e]]; // files
+ }
+
+ else if ((bufx == 0x0c) && (len >= 0x1f)) // 0x9400 'b' version
+ {
+ imSony.Sony0x9400_version = 0xb;
+
+ FORC4 s[c] = SonySubstitution[buf[0x08 + c]];
+ imSony.Sony0x9400_SequenceImageNumber = sget4(s);
+
+ FORC4 s[c] = SonySubstitution[buf[0x0c + c]];
+ imSony.Sony0x9400_SequenceFileNumber = sget4(s);
+
+ imSony.Sony0x9400_ReleaseMode2 = SonySubstitution[buf[0x10]];
+
+ imSony.Sony0x9400_SequenceLength1 = SonySubstitution[buf[0x1e]];
+ }
+
+ else if ((bufx == 0x0a) && (len >= 0x23)) // 0x9400 'a' version
+ {
+ imSony.Sony0x9400_version = 0xa;
+
+ FORC4 s[c] = SonySubstitution[buf[0x08 + c]];
+ imSony.Sony0x9400_SequenceImageNumber = sget4(s);
+
+ FORC4 s[c] = SonySubstitution[buf[0x0c + c]];
+ imSony.Sony0x9400_SequenceFileNumber = sget4(s);
+
+ imSony.Sony0x9400_ReleaseMode2 = SonySubstitution[buf[0x10]];
+
+ imSony.Sony0x9400_SequenceLength1 = SonySubstitution[buf[0x22]];
+ }
+
+ else
+ return;
+}
+
+void LibRaw::process_Sony_0x9402(uchar *buf, ushort len)
+{
+
+ if (len < 0x17)
+ return;
+
+ if ((imSony.CameraType == LIBRAW_SONY_SLT) ||
+ (imSony.CameraType == LIBRAW_SONY_ILCA) ||
+ (buf[0x00] == 0x05) ||
+ (buf[0x00] == 0xff))
+ return;
+
+ if (buf[0x02] == 0xff)
+ {
+ imCommon.AmbientTemperature =
+ (float)((short)SonySubstitution[buf[0x04]]);
+ }
+
+ if (imgdata.shootinginfo.FocusMode == LIBRAW_SONY_FOCUSMODE_UNKNOWN)
+ {
+ imgdata.shootinginfo.FocusMode = SonySubstitution[buf[0x16]]&0x7f;
+ }
+ if (len >= 0x18)
+ imSony.AFAreaMode = (uint16_t)SonySubstitution[buf[0x17]];
+
+ if ((len >= 0x2e) &&
+ (imSony.CameraType != LIBRAW_SONY_DSC))
+ {
+ imSony.FocusPosition = (ushort)SonySubstitution[buf[0x2d]]; // FocusPosition2
+ }
+ return;
+}
+
+void LibRaw::process_Sony_0x9403(uchar *buf, ushort len)
+{
+ if ((len < 6) || (unique_id == SonyID_ILCE_7C))
+ return;
+ uchar bufx = SonySubstitution[buf[4]];
+ if ((bufx == 0x00) || (bufx == 0x94))
+ return;
+
+ imCommon.SensorTemperature = (float)((short)SonySubstitution[buf[5]]);
+
+ return;
+}
+
+void LibRaw::process_Sony_0x9406(uchar *buf, ushort len)
+{
+ if (len < 6)
+ return;
+ uchar bufx = buf[0];
+ if ((bufx != 0x01) && (bufx != 0x08) && (bufx != 0x1b))
+ return;
+ bufx = buf[2];
+ if ((bufx != 0x08) && (bufx != 0x1b))
+ return;
+
+ imCommon.BatteryTemperature =
+ (float)(SonySubstitution[buf[5]] - 32) / 1.8f;
+
+ return;
+}
+
+void LibRaw::process_Sony_0x940c(uchar *buf, ushort len)
+{
+ if ((imSony.CameraType != LIBRAW_SONY_ILCE) &&
+ (imSony.CameraType != LIBRAW_SONY_NEX))
+ return;
+ if (len <= 0x000a)
+ return;
+ ushort lid2;
+ if ((ilm.LensMount != LIBRAW_MOUNT_Canon_EF) &&
+ (ilm.LensMount != LIBRAW_MOUNT_Sigma_X3F))
+ {
+ switch (SonySubstitution[buf[0x0008]])
+ {
+ case 1:
+ case 5:
+ ilm.LensMount = LIBRAW_MOUNT_Minolta_A;
+ break;
+ case 4:
+ ilm.LensMount = LIBRAW_MOUNT_Sony_E;
+ break;
+ }
+ }
+ if (ilm.LensMount != LIBRAW_MOUNT_Unknown) {
+ lid2 = (((ushort)SonySubstitution[buf[0x000a]]) << 8) |
+ ((ushort)SonySubstitution[buf[0x0009]]);
+ if ((lid2 > 0) &&
+ ((lid2 < 32784) || (ilm.LensID == 0x1999) || (ilm.LensID == 0xffff)))
+ parseSonyLensType2(
+ SonySubstitution[buf[0x000a]], // LensType2 - Sony lens ids
+ SonySubstitution[buf[0x0009]]);
+ if ((lid2 == 44) || (lid2 == 78) || (lid2 == 184) || (lid2 == 234) ||
+ (lid2 == 239))
+ ilm.AdapterID = lid2;
+ }
+ return;
+}
+
+void LibRaw::process_Sony_0x940e(uchar *buf, ushort len, unsigned long long id)
+{
+ if (len < 3)
+ return;
+
+ if (((imSony.CameraType != LIBRAW_SONY_SLT) &&
+ (imSony.CameraType != LIBRAW_SONY_ILCA)) ||
+ (id == SonyID_SLT_A33) ||
+ (id == SonyID_SLT_A35) ||
+ (id == SonyID_SLT_A55))
+ return;
+
+ int c;
+ imSony.AFType = SonySubstitution[buf[0x02]];
+
+ if (imCommon.afcount < LIBRAW_AFDATA_MAXCOUNT)
+ {
+ unsigned tag = 0x940e;
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ FORC((int)imCommon.afdata[imCommon.afcount].AFInfoData_length)
+ imCommon.afdata[imCommon.afcount].AFInfoData[c] = SonySubstitution[buf[c]];
+ imCommon.afcount++;
+ }
+
+ if (imSony.CameraType == LIBRAW_SONY_ILCA)
+ {
+ if (len >= 0x0051)
+ {
+ imgdata.shootinginfo.FocusMode = SonySubstitution[buf[0x05]];
+ imSony.nAFPointsUsed =
+ MIN(10, sizeof imSony.AFPointsUsed);
+ FORC(imSony.nAFPointsUsed) imSony.AFPointsUsed[c] = SonySubstitution[buf[0x10 +c]];
+ imSony.AFAreaMode = (uint16_t)SonySubstitution[buf[0x3a]];
+ imSony.AFMicroAdjValue = SonySubstitution[buf[0x0050]];
+ if (!imSony.AFMicroAdjValue) imSony.AFMicroAdjValue = 0x7f;
+ else imSony.AFMicroAdjOn = 1;
+ }
+ }
+ else
+ {
+ if (len >= 0x017e)
+ {
+ imSony.AFAreaMode = (uint16_t)SonySubstitution[buf[0x0a]];
+ imgdata.shootinginfo.FocusMode = SonySubstitution[buf[0x0b]];
+ imSony.nAFPointsUsed =
+ MIN(4, sizeof imSony.AFPointsUsed);
+ FORC(imSony.nAFPointsUsed) imSony.AFPointsUsed[c] = SonySubstitution[buf[0x016e +c]];
+ imSony.AFMicroAdjValue = SonySubstitution[buf[0x017d]];
+ if (!imSony.AFMicroAdjValue) imSony.AFMicroAdjValue = 0x7f;
+ else imSony.AFMicroAdjOn = 1;
+ }
+ }
+
+}
+
+void LibRaw::parseSonyMakernotes(
+ int base, unsigned tag, unsigned type, unsigned len, unsigned dng_writer,
+ uchar *&table_buf_0x0116, ushort &table_buf_0x0116_len,
+ uchar *&table_buf_0x2010, ushort &table_buf_0x2010_len,
+ uchar *&table_buf_0x9050, ushort &table_buf_0x9050_len,
+ uchar *&table_buf_0x9400, ushort &table_buf_0x9400_len,
+ uchar *&table_buf_0x9402, ushort &table_buf_0x9402_len,
+ uchar *&table_buf_0x9403, ushort &table_buf_0x9403_len,
+ uchar *&table_buf_0x9406, ushort &table_buf_0x9406_len,
+ uchar *&table_buf_0x940c, ushort &table_buf_0x940c_len,
+ uchar *&table_buf_0x940e, ushort &table_buf_0x940e_len)
+{
+
+ ushort lid, a, c, d;
+ uchar *table_buf;
+ uchar uc;
+ uchar s[2];
+ int LensDataValid = 0;
+ unsigned uitemp;
+
+// printf ("==>> tag 0x%x, len %d, type %d, model =%s=, cam.id 0x%llx, cam.type %d, =%s=\n",
+// tag, len, type, model, ilm.CamID, imSony.CameraType, imSony.MetaVersion);
+
+ if (tag == 0xb001) // Sony ModelID
+ {
+ unique_id = get2();
+ setSonyBodyFeatures(unique_id);
+
+ if (table_buf_0x0116_len)
+ {
+ process_Sony_0x0116(table_buf_0x0116, table_buf_0x0116_len, unique_id);
+ free(table_buf_0x0116);
+ table_buf_0x0116_len = 0;
+ }
+
+ if (table_buf_0x2010_len)
+ {
+ process_Sony_0x2010(table_buf_0x2010, table_buf_0x2010_len);
+ free(table_buf_0x2010);
+ table_buf_0x2010_len = 0;
+ }
+
+ if (table_buf_0x9050_len)
+ {
+ process_Sony_0x9050(table_buf_0x9050, table_buf_0x9050_len, unique_id);
+ free(table_buf_0x9050);
+ table_buf_0x9050_len = 0;
+ }
+
+ if (table_buf_0x9400_len)
+ {
+ process_Sony_0x9400(table_buf_0x9400, table_buf_0x9400_len, unique_id);
+ free(table_buf_0x9400);
+ table_buf_0x9400_len = 0;
+ }
+
+ if (table_buf_0x9402_len)
+ {
+ process_Sony_0x9402(table_buf_0x9402, table_buf_0x9402_len);
+ free(table_buf_0x9402);
+ table_buf_0x9402_len = 0;
+ }
+
+ if (table_buf_0x9403_len)
+ {
+ process_Sony_0x9403(table_buf_0x9403, table_buf_0x9403_len);
+ free(table_buf_0x9403);
+ table_buf_0x9403_len = 0;
+ }
+
+ if (table_buf_0x9406_len)
+ {
+ process_Sony_0x9406(table_buf_0x9406, table_buf_0x9406_len);
+ free(table_buf_0x9406);
+ table_buf_0x9406_len = 0;
+ }
+
+ if (table_buf_0x940c_len)
+ {
+ process_Sony_0x940c(table_buf_0x940c, table_buf_0x940c_len);
+ free(table_buf_0x940c);
+ table_buf_0x940c_len = 0;
+ }
+
+ if (table_buf_0x940e_len)
+ {
+ process_Sony_0x940e(table_buf_0x940e, table_buf_0x940e_len, unique_id);
+ free(table_buf_0x940e);
+ table_buf_0x940e_len = 0;
+ }
+ }
+ else if (tag == 0xb000)
+ {
+ FORC4 imSony.FileFormat = imSony.FileFormat * 10 + fgetc(ifp);
+ }
+ else if (tag == 0xb026)
+ {
+ uitemp = get4();
+ if (uitemp != 0xffffffff)
+ imgdata.shootinginfo.ImageStabilization = uitemp;
+ }
+ else if (((tag == 0x0001) || // Minolta CameraSettings, big endian
+ (tag == 0x0003)) &&
+ (len >= 196))
+ {
+ table_buf = (uchar *)malloc(len);
+ fread(table_buf, len, 1, ifp);
+
+ lid = 0x01 << 2;
+ imgdata.shootinginfo.ExposureMode =
+ (unsigned)table_buf[lid] << 24 | (unsigned)table_buf[lid + 1] << 16 |
+ (unsigned)table_buf[lid + 2] << 8 | (unsigned)table_buf[lid + 3];
+
+ lid = 0x06 << 2;
+ imgdata.shootinginfo.DriveMode =
+ (unsigned)table_buf[lid] << 24 | (unsigned)table_buf[lid + 1] << 16 |
+ (unsigned)table_buf[lid + 2] << 8 | (unsigned)table_buf[lid + 3];
+
+ lid = 0x07 << 2;
+ imgdata.shootinginfo.MeteringMode =
+ (unsigned)table_buf[lid] << 24 | (unsigned)table_buf[lid + 1] << 16 |
+ (unsigned)table_buf[lid + 2] << 8 | (unsigned)table_buf[lid + 3];
+
+ lid = 0x25 << 2;
+ imSony.MinoltaCamID =
+ (unsigned)table_buf[lid] << 24 | (unsigned)table_buf[lid + 1] << 16 |
+ (unsigned)table_buf[lid + 2] << 8 | (unsigned)table_buf[lid + 3];
+ if (imSony.MinoltaCamID != 0xffffffff)
+ ilm.CamID = imSony.MinoltaCamID;
+
+ lid = 0x30 << 2;
+ imgdata.shootinginfo.FocusMode =
+ table_buf[lid + 3]?LIBRAW_SONY_FOCUSMODE_MF:LIBRAW_SONY_FOCUSMODE_AF;
+ free(table_buf);
+ }
+ else if ((tag == 0x0004) && // Minolta CameraSettings7D, big endian
+ (len >= 227))
+ {
+ table_buf = (uchar *)malloc(len);
+ fread(table_buf, len, 1, ifp);
+
+ lid = 0x0;
+ imgdata.shootinginfo.ExposureMode =
+ (ushort)table_buf[lid] << 8 | (ushort)table_buf[lid + 1];
+
+ lid = 0x0e << 1;
+ imgdata.shootinginfo.FocusMode = (short)table_buf[lid + 1];
+ switch (imgdata.shootinginfo.FocusMode) {
+ case 0: case 1: imgdata.shootinginfo.FocusMode += 2; break;
+ case 3: imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_MF; break;
+ }
+ lid = 0x10 << 1;
+ imgdata.shootinginfo.AFPoint =
+ (ushort)table_buf[lid] << 8 | (ushort)table_buf[lid + 1];
+
+ lid = 0x25 << 1;
+ switch ((ushort)table_buf[lid] << 8 | (ushort)table_buf[lid + 1]) {
+ case 0:
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 4:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+
+ lid = 0x71 << 1;
+ imgdata.shootinginfo.ImageStabilization =
+ (ushort)table_buf[lid] << 8 | (ushort)table_buf[lid + 1];
+
+ free(table_buf);
+ }
+ else if ((tag == 0x0010) && // CameraInfo
+ strncasecmp(model, "DSLR-A100", 9) &&
+ !strncasecmp(make, "SONY", 4) &&
+ ((len == 368) || // a700 : CameraInfo
+ (len == 5478) || // a850, a900 : CameraInfo
+ (len == 5506) || // a200, a300, a350 : CameraInfo2
+ (len == 6118) || // a230, a290, a330, a380, a390 : CameraInfo2
+ (len == 15360)) // a450, a500, a550, a560, a580 : CameraInfo3
+ // a33, a35, a55
+ // NEX-3, NEX-5, NEX-5C, NEX-C3, NEX-VG10E
+
+ )
+ {
+ table_buf = (uchar *)malloc(len);
+ fread(table_buf, len, 1, ifp);
+ if (imCommon.afcount < LIBRAW_AFDATA_MAXCOUNT)
+ {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ memcpy(imCommon.afdata[imCommon.afcount].AFInfoData, table_buf, imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ imCommon.afcount++;
+ }
+ if (memcmp(table_buf, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) &&
+ memcmp(table_buf, "\x00\x00\x00\x00\x00\x00\x00\x00", 8))
+ {
+ LensDataValid = 1;
+ }
+ switch (len)
+ {
+ case 368: // a700: CameraInfo
+ case 5478: // a850, a900: CameraInfo
+ if ((!dng_writer) ||
+ (saneSonyCameraInfo(table_buf[0], table_buf[3], table_buf[2],
+ table_buf[5], table_buf[4], table_buf[7])))
+ {
+ if (LensDataValid)
+ {
+ if (table_buf[0] | table_buf[3])
+ ilm.MinFocal = bcd2dec(table_buf[0]) * 100 + bcd2dec(table_buf[3]);
+ if (table_buf[2] | table_buf[5])
+ ilm.MaxFocal = bcd2dec(table_buf[2]) * 100 + bcd2dec(table_buf[5]);
+ if (table_buf[4])
+ ilm.MaxAp4MinFocal = bcd2dec(table_buf[4]) / 10.0f;
+ if (table_buf[4])
+ ilm.MaxAp4MaxFocal = bcd2dec(table_buf[7]) / 10.0f;
+ parseSonyLensFeatures(table_buf[1], table_buf[6]);
+ }
+
+ imSony.AFPointSelected = table_buf[21];
+ imgdata.shootinginfo.AFPoint = (ushort)table_buf[25];
+
+ if (len == 5478)
+ {
+ imSony.AFMicroAdjValue = table_buf[0x130] - 20;
+ imSony.AFMicroAdjOn = (((table_buf[0x131] & 0x80) == 0x80) ? 1 : 0);
+ imSony.AFMicroAdjRegisteredLenses = table_buf[0x131] & 0x7f;
+ }
+ }
+ break;
+ default:
+ // CameraInfo2 & 3
+ if ((!dng_writer) ||
+ (saneSonyCameraInfo(table_buf[1], table_buf[2], table_buf[3],
+ table_buf[4], table_buf[5], table_buf[6])))
+ {
+ if ((LensDataValid) && strncasecmp(model, "NEX-5C", 6))
+ {
+ if (table_buf[1] | table_buf[2])
+ ilm.MinFocal = bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]);
+ if (table_buf[3] | table_buf[4])
+ ilm.MaxFocal = bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]);
+ if (table_buf[5])
+ ilm.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f;
+ if (table_buf[6])
+ ilm.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f;
+ parseSonyLensFeatures(table_buf[0], table_buf[7]);
+ }
+
+ if ( // CameraInfo2
+ (len == 5506) || // a200, a300, a350
+ (len == 6118)) // a230, a290, a330, a380, a390
+ {
+ imSony.AFPointSelected = table_buf[0x14];
+ }
+ else if (!strncasecmp(model, "DSLR-A450", 9) ||
+ !strncasecmp(model, "DSLR-A500", 9) ||
+ !strncasecmp(model, "DSLR-A550", 9))
+ {
+ imSony.AFPointSelected = table_buf[0x14];
+ if (table_buf[0x15]) /* focus mode values translated to values in tag 0x201b */
+ imgdata.shootinginfo.FocusMode = table_buf[0x15]+1;
+ else imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_MF;
+ imgdata.shootinginfo.AFPoint = (ushort)table_buf[0x18];
+ }
+ else if (!strncasecmp(model, "SLT-", 4) ||
+ !strncasecmp(model, "DSLR-A560", 9) ||
+ !strncasecmp(model, "DSLR-A580", 9))
+ {
+ imSony.AFPointSelected = table_buf[0x1c];
+ if (table_buf[0x1d])
+ imgdata.shootinginfo.FocusMode = table_buf[0x1d]+1;
+ else imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_MF;
+ imgdata.shootinginfo.AFPoint = (ushort)table_buf[0x20];
+ }
+ }
+ }
+ free(table_buf);
+ }
+ else if ((!dng_writer) &&
+ ((tag == 0x0020) || (tag == 0xb0280020)))
+ {
+ if (!strncasecmp(model, "DSLR-A100", 9)) // WBInfoA100
+ {
+ fseek(ifp, 0x49dc, SEEK_CUR);
+ stmread(imgdata.shootinginfo.InternalBodySerial, 13, ifp);
+ }
+ else if ((len == 19154) || // a200 a230 a290 a300 a330 a350 a380 a390 : FocusInfo
+ (len == 19148)) // a700 a850 a900 : FocusInfo
+ {
+ table_buf = (uchar *)malloc(0x0080);
+ fread(table_buf, 0x0080, 1, ifp);
+ imgdata.shootinginfo.DriveMode = table_buf[14];
+ imgdata.shootinginfo.ExposureProgram = table_buf[63];
+ free(table_buf);
+ fseek (ifp, 0x09bb - 0x0080, SEEK_CUR); // offset 2491 from the start of tag 0x0020
+ imSony.FocusPosition = (ushort)fgetc(ifp);
+ }
+ else if (len == 20480) // a450 a500 a550 a560 a580 a33 a35 a55 : MoreInfo
+ // NEX-3 NEX-5 NEX-C3 NEX-VG10E : MoreInfo
+ {
+ a = get2();
+ /*b =*/ get2();
+ c = get2();
+ d = get2();
+ if ((a) && (c == 1))
+ {
+ fseek(ifp, INT64(d) - 8LL, SEEK_CUR);
+ table_buf = (uchar *)malloc(256);
+ fread(table_buf, 256, 1, ifp);
+ imgdata.shootinginfo.DriveMode = table_buf[1];
+ imgdata.shootinginfo.ExposureProgram = table_buf[2];
+ imgdata.shootinginfo.MeteringMode = table_buf[3];
+ switch (table_buf[6]) {
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 2:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ if (strncasecmp(model, "DSLR-A450", 9) &&
+ strncasecmp(model, "DSLR-A500", 9) &&
+ strncasecmp(model, "DSLR-A550", 9))
+ { // NEX-3, NEX-5, NEX-5C??, NEX-C3, NEX-VG10(E), a560, a580, a33, a35, a55
+ imgdata.shootinginfo.FocusMode = table_buf[0x13];
+ switch (table_buf[0x13]) {
+ case 17: imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_AF_S; break;
+ case 18: imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_AF_C; break;
+ case 19: imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_AF_A; break;
+ case 32: imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_MF; break;
+ case 48: imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_DMF; break;
+ default: imgdata.shootinginfo.FocusMode = table_buf[0x13]; break;
+ }
+ if (!strncasecmp(model, "DSLR-A560", 9) ||
+ !strncasecmp(model, "DSLR-A580", 9) ||
+ !strncasecmp(model, "SLT-A33", 7) ||
+ !strncasecmp(model, "SLT-A35", 7) ||
+ !strncasecmp(model, "SLT-A55", 7) ||
+ !strncasecmp(model, "NEX-VG10", 8) ||
+ !strncasecmp(model, "NEX-C3", 6))
+ imSony.FocusPosition = (ushort)table_buf[0x2f]; // FocusPosition2
+ else // NEX-3, NEX-5, NEX-5C
+ imSony.FocusPosition = (ushort)table_buf[0x2b]; // FocusPosition2
+ }
+ else // a450 a500 a550
+ {
+ imSony.FocusPosition = (ushort)table_buf[0x29]; // FocusPosition2
+ }
+ free(table_buf);
+ }
+ }
+ }
+ else if (tag == 0x0102)
+ {
+ imSony.Quality = get4();
+ }
+ else if (tag == 0x0104)
+ {
+ imCommon.FlashEC = getreal(type);
+ }
+ else if (tag == 0x0105) // Teleconverter
+ {
+ ilm.TeleconverterID = get4();
+ }
+ else if (tag == 0x0107)
+ {
+ uitemp = get4();
+ if (uitemp == 1)
+ imgdata.shootinginfo.ImageStabilization = 0;
+ else if (uitemp == 5)
+ imgdata.shootinginfo.ImageStabilization = 1;
+ else
+ imgdata.shootinginfo.ImageStabilization = uitemp;
+ }
+ else if ((tag == 0xb0280088) && (dng_writer == nonDNG))
+ {
+ thumb_offset = get4() + base;
+ }
+ else if ((tag == 0xb0280089) && (dng_writer == nonDNG))
+ {
+ thumb_length = get4();
+ }
+ else if (((tag == 0x0114) || // CameraSettings
+ (tag == 0xb0280114)) &&
+ (len < 256000))
+ {
+ table_buf = (uchar *)malloc(len);
+ fread(table_buf, len, 1, ifp);
+ switch (len)
+ {
+ case 260: // Sony a100, big endian
+ imgdata.shootinginfo.ExposureMode =
+ ((ushort)table_buf[0]) << 8 | ((ushort)table_buf[1]);
+ lid = 0x0a << 1;
+ imgdata.shootinginfo.DriveMode =
+ ((ushort)table_buf[lid]) << 8 | ((ushort)table_buf[lid + 1]);
+ lid = 0x0c << 1;
+ imgdata.shootinginfo.FocusMode =
+ ((ushort)table_buf[lid]) << 8 | ((ushort)table_buf[lid + 1]);
+ switch (imgdata.shootinginfo.FocusMode) {
+ case 0: imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_AF_S; break;
+ case 1: imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_AF_C; break;
+ case 5: imgdata.shootinginfo.FocusMode = LIBRAW_SONY_FOCUSMODE_MF; break;
+ }
+ lid = 0x0d << 1;
+ imSony.AFPointSelected = table_buf[lid + 1];
+ lid = 0x0e << 1;
+ imSony.AFAreaMode = (uint16_t)table_buf[lid + 1];
+ lid = 0x12 << 1;
+ imgdata.shootinginfo.MeteringMode =
+ ((ushort)table_buf[lid]) << 8 | ((ushort)table_buf[lid + 1]);
+
+ lid = 0x17 << 1;
+ switch ((ushort)table_buf[lid] << 8 | (ushort)table_buf[lid + 1]) {
+ case 0:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 2:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_MonochromeGamma;
+ break;
+ case 5:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+
+ break;
+ case 448: // Minolta "DYNAX 5D" and its aliases, big endian
+ lid = 0x0a << 1;
+ imgdata.shootinginfo.ExposureMode =
+ ((ushort)table_buf[lid]) << 8 | ((ushort)table_buf[lid + 1]);
+ lid = 0x25 << 1;
+ imgdata.shootinginfo.MeteringMode =
+ ((ushort)table_buf[lid]) << 8 | ((ushort)table_buf[lid + 1]);
+
+ lid = 0x2f << 1;
+ switch ((ushort)table_buf[lid] << 8 | (ushort)table_buf[lid + 1]) {
+ case 0:
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 2:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_MonochromeGamma;
+ break;
+ case 4:
+ case 5:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+
+ lid = 0xbd << 1;
+ imgdata.shootinginfo.ImageStabilization =
+ ((ushort)table_buf[lid]) << 8 | ((ushort)table_buf[lid + 1]);
+ break;
+ case 280: // a200 a300 a350 a700
+ case 364: // a850 a900
+ // CameraSettings and CameraSettings2 are big endian
+ if (table_buf[2] | table_buf[3])
+ {
+ lid = (((ushort)table_buf[2]) << 8) | ((ushort)table_buf[3]);
+ ilm.CurAp = libraw_powf64l(2.0f, ((float)lid / 8.0f - 1.0f) / 2.0f);
+ }
+ lid = 0x04 << 1;
+ imgdata.shootinginfo.DriveMode = table_buf[lid + 1];
+ lid = 0x11 << 1;
+ imSony.AFAreaMode = (uint16_t)table_buf[lid + 1];
+ lid = 0x1b << 1;
+ switch (((ushort)table_buf[lid]) << 8 | ((ushort)table_buf[lid + 1])) {
+ case 0:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 1:
+ case 5:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ lid = 0x4d << 1;
+ imgdata.shootinginfo.FocusMode =
+ ((ushort)table_buf[lid]) << 8 | ((ushort)table_buf[lid + 1]);
+ switch (imgdata.shootinginfo.FocusMode) {
+ case 1: case 2: case 3: imgdata.shootinginfo.FocusMode++; break;
+ case 4: imgdata.shootinginfo.FocusMode +=2; break;
+ }
+ if (!imCommon.ColorSpace ||
+ (imCommon.ColorSpace == LIBRAW_COLORSPACE_Unknown)) {
+ lid = 0x83 << 1;
+ switch (((ushort)table_buf[lid]) << 8 | ((ushort)table_buf[lid + 1])) {
+ case 6:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 5:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ }
+ break;
+ case 332: // a230 a290 a330 a380 a390
+ // CameraSettings and CameraSettings2 are big endian
+ if (table_buf[2] | table_buf[3])
+ {
+ lid = (((ushort)table_buf[2]) << 8) | ((ushort)table_buf[3]);
+ ilm.CurAp = libraw_powf64l(2.0f, ((float)lid / 8.0f - 1.0f) / 2.0f);
+ }
+ lid = 0x10 << 1;
+ imSony.AFAreaMode = (uint16_t)table_buf[lid + 1];
+ lid = 0x4d << 1;
+ imgdata.shootinginfo.FocusMode =
+ ((ushort)table_buf[lid]) << 8 | ((ushort)table_buf[lid + 1]);
+ switch (imgdata.shootinginfo.FocusMode) {
+ case 1: case 2: case 3: imgdata.shootinginfo.FocusMode++; break;
+ case 4: imgdata.shootinginfo.FocusMode +=2; break;
+ }
+ lid = 0x7e << 1;
+ imgdata.shootinginfo.DriveMode = table_buf[lid + 1];
+ break;
+ case 1536: // a560 a580 a33 a35 a55 NEX-3 NEX-5 NEX-5C NEX-C3 NEX-VG10E
+ case 2048: // a450 a500 a550
+ // CameraSettings3 are little endian
+ switch (table_buf[0x0e]) {
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 2:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ imSony.AFAreaMode = (uint16_t)table_buf[0x24];
+ imgdata.shootinginfo.DriveMode = table_buf[0x34];
+ parseSonyLensType2(table_buf[1016], table_buf[1015]);
+ if (ilm.LensMount != LIBRAW_MOUNT_Canon_EF)
+ {
+ switch (table_buf[153])
+ {
+ case 16:
+ ilm.LensMount = LIBRAW_MOUNT_Minolta_A;
+ break;
+ case 17:
+ ilm.LensMount = LIBRAW_MOUNT_Sony_E;
+ break;
+ }
+ }
+ break;
+ }
+ free(table_buf);
+ }
+ else if ((tag == 0x3000) && (len < 256000))
+ {
+ table_buf = (uchar *)malloc(len);
+ fread(table_buf, len, 1, ifp);
+ if (len >= 0x19)
+ {
+ for (int i = 0; i < 20; i++)
+ imSony.SonyDateTime[i] = table_buf[6 + i];
+ }
+ if (len >= 0x43) // MetaVersion: (unique_id >= 286)
+ {
+ memcpy (imSony.MetaVersion, table_buf+0x34, 15);
+ imSony.MetaVersion[15] = 0;
+ }
+ free(table_buf);
+ }
+ else if (tag == 0x0116 && len < 256000)
+ {
+ table_buf_0x0116 = (uchar *)malloc(len);
+ table_buf_0x0116_len = len;
+ fread(table_buf_0x0116, len, 1, ifp);
+ if (ilm.CamID)
+ {
+ process_Sony_0x0116(table_buf_0x0116, table_buf_0x0116_len, ilm.CamID);
+ free(table_buf_0x0116);
+ table_buf_0x0116_len = 0;
+ }
+ }
+ else if (tag == 0x2008)
+ {
+ imSony.LongExposureNoiseReduction = get4();
+ }
+ else if (tag == 0x2009)
+ {
+ imSony.HighISONoiseReduction = get2();
+ }
+ else if (tag == 0x200a)
+ {
+ imSony.HDR[0] = get2();
+ imSony.HDR[1] = get2();
+ }
+ else if (tag == 0x2010 && len < 256000)
+ {
+ table_buf_0x2010 = (uchar *)malloc(len);
+ table_buf_0x2010_len = len;
+ fread(table_buf_0x2010, len, 1, ifp);
+ if (ilm.CamID)
+ {
+ process_Sony_0x2010(table_buf_0x2010, table_buf_0x2010_len);
+ free(table_buf_0x2010);
+ table_buf_0x2010_len = 0;
+ }
+ }
+ else if (tag == 0x201a)
+ {
+ imSony.ElectronicFrontCurtainShutter = get4();
+ }
+ else if (tag == 0x201b)
+ {
+ if ((imSony.CameraType != LIBRAW_SONY_DSC) ||
+ (imSony.group2010 == LIBRAW_SONY_Tag2010i))
+ {
+ short t = (short)fgetc(ifp);
+ if (imgdata.shootinginfo.FocusMode != t)
+ {
+ imgdata.shootinginfo.FocusMode = t;
+ }
+ }
+ }
+ else if ((tag == 0x201c) &&
+ (len == 1) &&
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_BYTE))
+ {
+ imSony.AFAreaModeSetting = (uint8_t)fgetc(ifp);
+ }
+ else if ((tag == 0x201d) &&
+ (len == 2) &&
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT))
+ {
+ imSony.FlexibleSpotPosition[0] = get2();
+ imSony.FlexibleSpotPosition[1] = get2();
+ }
+ else if (tag == 0x201e)
+ {
+ if (imSony.CameraType != LIBRAW_SONY_DSC)
+ {
+ imSony.AFPointSelected = imSony.AFPointSelected_0x201e = fgetc(ifp);
+ }
+ }
+ else if (tag == 0x2020) // AFPointsUsed
+ {
+ if (imSony.CameraType != LIBRAW_SONY_DSC)
+ {
+ if (imCommon.afcount < LIBRAW_AFDATA_MAXCOUNT)
+ {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ fread(imCommon.afdata[imCommon.afcount].AFInfoData, imCommon.afdata[imCommon.afcount].AFInfoData_length, 1, ifp);
+ imSony.nAFPointsUsed =
+ short(MIN(imCommon.afdata[imCommon.afcount].AFInfoData_length, sizeof imSony.AFPointsUsed));
+ memcpy(imSony.AFPointsUsed, imCommon.afdata[imCommon.afcount].AFInfoData, imSony.nAFPointsUsed);
+ imCommon.afcount++;
+ }
+ }
+ }
+ else if (tag == 0x2021) // AFTracking
+ {
+ if ((imSony.CameraType != LIBRAW_SONY_DSC) ||
+ (imSony.group2010 == LIBRAW_SONY_Tag2010i))
+ {
+ imSony.AFTracking = fgetc(ifp);
+ }
+ }
+ else if (tag == 0x2022) // FocalPlaneAFPointsUsed
+ {
+ if (imCommon.afcount < LIBRAW_AFDATA_MAXCOUNT)
+ {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ fread(imCommon.afdata[imCommon.afcount].AFInfoData, imCommon.afdata[imCommon.afcount].AFInfoData_length, 1, ifp);
+ imCommon.afcount++;
+ }
+ }
+ else if (tag == 0x2027)
+ {
+ FORC4 imSony.FocusLocation[c] = get2();
+ }
+ else if (tag == 0x2028)
+ {
+ if (get2())
+ {
+ imSony.VariableLowPassFilter = get2();
+ }
+ }
+ else if (tag == 0x2029)
+ {
+ imSony.RAWFileType = get2();
+ }
+ else if (tag == 0x202c)
+ {
+ imSony.MeteringMode2 = get2();
+ }
+
+ else if (tag == 0x202a) // FocalPlaneAFPointsUsed, newer??
+ {
+ if (imCommon.afcount < LIBRAW_AFDATA_MAXCOUNT)
+ {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ fread(imCommon.afdata[imCommon.afcount].AFInfoData, imCommon.afdata[imCommon.afcount].AFInfoData_length, 1, ifp);
+ imCommon.afcount++;
+ }
+ }
+ else if (tag == 0x202e)
+ {
+ imSony.RawSizeType = get2();
+ }
+ else if (tag == 0x202f)
+ {
+ imSony.PixelShiftGroupID = get4();
+ imSony.PixelShiftGroupPrefix = imSony.PixelShiftGroupID >> 22;
+ imSony.PixelShiftGroupID =
+ ((imSony.PixelShiftGroupID >> 17) & (unsigned)0x1f) *
+ (unsigned)1000000 +
+ ((imSony.PixelShiftGroupID >> 12) & (unsigned)0x1f) * (unsigned)10000 +
+ ((imSony.PixelShiftGroupID >> 6) & (unsigned)0x3f) * (unsigned)100 +
+ (imSony.PixelShiftGroupID & (unsigned)0x3f);
+
+ imSony.numInPixelShiftGroup = fgetc(ifp);
+ imSony.nShotsInPixelShiftGroup = fgetc(ifp);
+ }
+ else if (tag == 0x9050 && len < 256000) // little endian
+ {
+ table_buf_0x9050 = (uchar *)malloc(len);
+ table_buf_0x9050_len = len;
+ fread(table_buf_0x9050, len, 1, ifp);
+
+ if (ilm.CamID)
+ {
+ process_Sony_0x9050(table_buf_0x9050, table_buf_0x9050_len, ilm.CamID);
+ free(table_buf_0x9050);
+ table_buf_0x9050_len = 0;
+ }
+ }
+ else if (tag == 0x9400 && len < 256000)
+ {
+ table_buf_0x9400 = (uchar *)malloc(len);
+ table_buf_0x9400_len = len;
+ fread(table_buf_0x9400, len, 1, ifp);
+ if (ilm.CamID)
+ {
+ process_Sony_0x9400(table_buf_0x9400, table_buf_0x9400_len, unique_id);
+ free(table_buf_0x9400);
+ table_buf_0x9400_len = 0;
+ }
+ }
+ else if (tag == 0x9402 && len < 256000)
+ {
+ table_buf_0x9402 = (uchar *)malloc(len);
+ table_buf_0x9402_len = len;
+ fread(table_buf_0x9402, len, 1, ifp);
+ if (ilm.CamID)
+ {
+ process_Sony_0x9402(table_buf_0x9402, table_buf_0x9402_len);
+ free(table_buf_0x9402);
+ table_buf_0x9402_len = 0;
+ }
+ }
+ else if (tag == 0x9403 && len < 256000)
+ {
+ table_buf_0x9403 = (uchar *)malloc(len);
+ table_buf_0x9403_len = len;
+ fread(table_buf_0x9403, len, 1, ifp);
+ if (ilm.CamID)
+ {
+ process_Sony_0x9403(table_buf_0x9403, table_buf_0x9403_len);
+ free(table_buf_0x9403);
+ table_buf_0x9403_len = 0;
+ }
+ }
+ else if ((tag == 0x9405) && (len < 256000) && (len > 0x64))
+ {
+ table_buf = (uchar *)malloc(len);
+ fread(table_buf, len, 1, ifp);
+ uc = table_buf[0x0];
+ if (imCommon.real_ISO < 0.1f)
+ {
+ if ((uc == 0x25) || (uc == 0x3a) || (uc == 0x76) || (uc == 0x7e) ||
+ (uc == 0x8b) || (uc == 0x9a) || (uc == 0xb3) || (uc == 0xe1))
+ {
+ s[0] = SonySubstitution[table_buf[0x04]];
+ s[1] = SonySubstitution[table_buf[0x05]];
+ imCommon.real_ISO =
+ 100.0f * libraw_powf64l(2.0f, (16 - ((float)sget2(s)) / 256.0f));
+ }
+ }
+ free(table_buf);
+ }
+ else if ((tag == 0x9404) && (len < 256000) && (len > 0x21))
+ {
+ table_buf = (uchar *)malloc(len);
+ fread(table_buf, len, 1, ifp);
+ uc = table_buf[0x00];
+ if (((uc == 0x70) ||
+ (uc == 0x8a) ||
+ (uc == 0xcd) ||
+ (uc == 0xe7) ||
+ (uc == 0xea)) &&
+ (table_buf[0x03] == 0x08))
+ {
+ if ((imSony.CameraType == LIBRAW_SONY_ILCA) ||
+ (imSony.CameraType == LIBRAW_SONY_SLT))
+ {
+ imSony.FocusPosition = (ushort)SonySubstitution[table_buf[0x20]]; // FocusPosition2
+ }
+ }
+ free(table_buf);
+ }
+ else if (tag == 0x9406 && len < 256000)
+ {
+ table_buf_0x9406 = (uchar *)malloc(len);
+ table_buf_0x9406_len = len;
+ fread(table_buf_0x9406, len, 1, ifp);
+ if (ilm.CamID)
+ {
+ process_Sony_0x9406(table_buf_0x9406, table_buf_0x9406_len);
+ free(table_buf_0x9406);
+ table_buf_0x9406_len = 0;
+ }
+ }
+ else if (tag == 0x940c && len < 256000)
+ {
+ table_buf_0x940c = (uchar *)malloc(len);
+ table_buf_0x940c_len = len;
+ fread(table_buf_0x940c, len, 1, ifp);
+ if (ilm.CamID)
+ {
+ process_Sony_0x940c(table_buf_0x940c, table_buf_0x940c_len);
+ free(table_buf_0x940c);
+ table_buf_0x940c_len = 0;
+ }
+ }
+ else if (tag == 0x940e && len < 256000)
+ {
+ table_buf_0x940e = (uchar *)malloc(len);
+ table_buf_0x940e_len = len;
+ fread(table_buf_0x940e, len, 1, ifp);
+ if (ilm.CamID)
+ {
+ process_Sony_0x940e(table_buf_0x940e, table_buf_0x940e_len, ilm.CamID);
+ free(table_buf_0x940e);
+ table_buf_0x940e_len = 0;
+ }
+ }
+ else if ((tag == 0x9416) && (len < 256000) && (len > 0x0076)) {
+ table_buf = (uchar *)malloc(len);
+ fread(table_buf, len, 1, ifp);
+ if (imCommon.real_ISO < 0.1f) {
+ s[0] = SonySubstitution[table_buf[0x04]];
+ s[1] = SonySubstitution[table_buf[0x05]];
+ imCommon.real_ISO =
+ 100.0f * libraw_powf64l(2.0f, (16 - ((float)sget2(s)) / 256.0f));
+ }
+ imgdata.shootinginfo.ExposureProgram = SonySubstitution[table_buf[0x35]];
+ if ((ilm.LensMount != LIBRAW_MOUNT_Canon_EF) &&
+ (ilm.LensMount != LIBRAW_MOUNT_Sigma_X3F)) {
+ switch (SonySubstitution[table_buf[0x0048]]) {
+ case 1:
+ case 3:
+ ilm.LensMount = LIBRAW_MOUNT_Minolta_A;
+ break;
+ case 2:
+ ilm.LensMount = LIBRAW_MOUNT_Sony_E;
+ break;
+ }
+ }
+ switch (SonySubstitution[table_buf[0x0049]]) {
+ case 1:
+ ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ break;
+ case 2:
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ break;
+ }
+ if (ilm.LensMount == LIBRAW_MOUNT_Sony_E)
+ parseSonyLensType2(SonySubstitution[table_buf[0x4c]], SonySubstitution[table_buf[0x4b]]);
+ free(table_buf);
+ }
+ else if (((tag == 0xb027) ||
+ (tag == 0x010c)) &&
+ (ilm.LensID == LIBRAW_LENS_NOT_SET))
+ {
+ ilm.LensID = get4();
+ if ((ilm.LensID > 0x4900) && (ilm.LensID <= 0x5900))
+ {
+ ilm.AdapterID = 0x4900;
+ ilm.LensID -= ilm.AdapterID;
+ ilm.LensMount = LIBRAW_MOUNT_Sigma_X3F;
+ strcpy(ilm.Adapter, "MC-11");
+ }
+
+ else if ((ilm.LensID > 0xef00) &&
+ (ilm.LensID < 0xffff) &&
+ (ilm.LensID != 0xff00))
+ {
+ ilm.AdapterID = 0xef00;
+ ilm.LensID -= ilm.AdapterID;
+ ilm.LensMount = LIBRAW_MOUNT_Canon_EF;
+ }
+
+ else if (((ilm.LensID != LIBRAW_LENS_NOT_SET) && (ilm.LensID < 0xef00)) ||
+ (ilm.LensID == 0xff00))
+ ilm.LensMount = LIBRAW_MOUNT_Minolta_A;
+ /*
+ if (tag == 0x010c)
+ ilm.CameraMount = LIBRAW_MOUNT_Minolta_A;
+ */
+ }
+ else if (tag == 0xb02a && len < 256000) // Sony LensSpec
+ {
+ table_buf = (uchar *)malloc(len);
+ fread(table_buf, len, 1, ifp);
+ if ((!dng_writer) ||
+ (saneSonyCameraInfo(table_buf[1], table_buf[2], table_buf[3],
+ table_buf[4], table_buf[5], table_buf[6])))
+ {
+ if (table_buf[1] | table_buf[2])
+ ilm.MinFocal = bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]);
+ if (table_buf[3] | table_buf[4])
+ ilm.MaxFocal = bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]);
+ if (table_buf[5])
+ ilm.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f;
+ if (table_buf[6])
+ ilm.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f;
+ parseSonyLensFeatures(table_buf[0], table_buf[7]);
+ }
+ free(table_buf);
+ }
+ else if ((tag == 0xb02b) && !imgdata.sizes.raw_inset_crops[0].cwidth &&
+ (len == 2))
+ {
+ imgdata.sizes.raw_inset_crops[0].cheight = get4();
+ imgdata.sizes.raw_inset_crops[0].cwidth = get4();
+ }
+ else if (tag == 0xb041)
+ {
+ imgdata.shootinginfo.ExposureMode = get2();
+ }
+ else if ((tag == 0xb043) &&
+ (len == 1) &&
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT))
+ {
+ imSony.AFAreaMode = get2();
+ }
+}
+
+class checked_buffer_t
+{
+public:
+ // create with internal storage
+ checked_buffer_t(short ord, int size) : _order(ord), storage(size+64) {
+ _data = storage.data();
+ _len = size;
+ }
+ checked_buffer_t(short ord, unsigned char *dd, int ss): _order(ord), _data(dd),_len(ss){}
+
+ ushort sget2(int offset)
+ {
+ checkoffset(offset + 2);
+ return libraw_sget2_static(_order, _data + offset);
+ }
+ void checkoffset(int off)
+ {
+ if (off >= _len) throw LIBRAW_EXCEPTION_IO_EOF;
+ }
+ unsigned char operator [] (int idx)
+ {
+ checkoffset(idx);
+ return _data[idx];
+ }
+ unsigned sget4(int offset)
+ {
+ checkoffset(offset+4);
+ return libraw_sget4_static(_order, _data + offset);
+ }
+ double sgetreal(int type, int offset)
+ {
+ int sz = libraw_tagtype_dataunit_bytes(type);
+ checkoffset(offset + sz);
+ return libraw_sgetreal_static(_order, type, _data + offset);
+ }
+
+ unsigned char *data() { return _data; }
+
+ int tiff_sget(unsigned save, INT64 *tag_offset,
+ unsigned *tag_id, unsigned *tag_type, INT64 *tag_dataoffset,
+ unsigned *tag_datalen, int *tag_dataunitlen)
+ {
+ if ((((*tag_offset) + 12) > _len) || (*tag_offset < 0)) { // abnormal, tag buffer overrun
+ return -1;
+ }
+ int pos = *tag_offset;
+ *tag_id = sget2(pos); pos += 2;
+ *tag_type = sget2(pos); pos += 2;
+ *tag_datalen = sget4(pos); pos += 4;
+ *tag_dataunitlen = libraw_tagtype_dataunit_bytes(*tag_type);
+ if ((*tag_datalen * (*tag_dataunitlen)) > 4) {
+ *tag_dataoffset = sget4(pos) - save;
+ if ((*tag_dataoffset + *tag_datalen) > _len) { // abnormal, tag data buffer overrun
+ return -2;
+ }
+ }
+ else *tag_dataoffset = *tag_offset + 8;
+ *tag_offset += 12;
+ return 0;
+ }
+
+private:
+ short _order;
+ unsigned char *_data;
+ int _len;
+ std::vector<unsigned char> storage;
+};
+
+void LibRaw::parseSonySR2(uchar *_cbuf_SR2, unsigned SR2SubIFDOffset,
+ unsigned SR2SubIFDLength, unsigned dng_writer)
+{
+ unsigned c;
+ unsigned entries, tag_id, tag_type, tag_datalen;
+ INT64 tag_offset, tag_dataoffset;
+ int TagProcessed;
+ int tag_dataunitlen;
+ float num;
+ int i;
+ int WBCTC_count;
+ try
+ {
+ checked_buffer_t cbuf_SR2(order, _cbuf_SR2, SR2SubIFDLength);
+ entries = cbuf_SR2.sget2(0);
+ if (entries > 1000)
+ return;
+ tag_offset = 2;
+ WBCTC_count = 0;
+ while (entries--) {
+ if (cbuf_SR2.tiff_sget(SR2SubIFDOffset,
+ &tag_offset, &tag_id, &tag_type, &tag_dataoffset,
+ &tag_datalen, &tag_dataunitlen) == 0) {
+ TagProcessed = 0;
+ if (dng_writer == nonDNG) {
+ switch (tag_id) {
+ case 0x7300:
+ FORC4 cblack[c] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ TagProcessed = 1;
+ break;
+ case 0x7303:
+ FORC4 cam_mul[GRBG_2_RGBG(c)] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ TagProcessed = 1;
+ break;
+ case 0x7310:
+ FORC4 cblack[RGGB_2_RGBG(c)] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ i = cblack[3];
+ FORC3 if (i > (int)cblack[c]) i = cblack[c];
+ FORC4 cblack[c] -= i;
+ black = i;
+ TagProcessed = 1;
+ break;
+ case 0x7313:
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ TagProcessed = 1;
+ break;
+ case 0x74a0:
+ ilm.MaxAp4MaxFocal = cbuf_SR2.sgetreal(tag_type, tag_dataoffset);
+ TagProcessed = 1;
+ break;
+ case 0x74a1:
+ ilm.MaxAp4MinFocal = cbuf_SR2.sgetreal(tag_type, tag_dataoffset);
+ TagProcessed = 1;
+ break;
+ case 0x74a2:
+ ilm.MaxFocal = cbuf_SR2.sgetreal(tag_type, tag_dataoffset);
+ TagProcessed = 1;
+ break;
+ case 0x74a3:
+ ilm.MinFocal = cbuf_SR2.sgetreal(tag_type, tag_dataoffset);
+ TagProcessed = 1;
+ break;
+ case 0x7800:
+ for (i = 0; i < 3; i++)
+ {
+ num = 0.0;
+ for (c = 0; c < 3; c++)
+ {
+ imgdata.color.ccm[i][c] =
+ (float)((short)cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * (i * 3 + c)));
+ num += imgdata.color.ccm[i][c];
+ }
+ if (num > 0.01)
+ FORC3 imgdata.color.ccm[i][c] = imgdata.color.ccm[i][c] / num;
+ }
+ TagProcessed = 1;
+ break;
+ case 0x787f:
+ if (tag_datalen == 3)
+ {
+ FORC3 imgdata.color.linear_max[c] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ imgdata.color.linear_max[3] = imgdata.color.linear_max[1];
+ }
+ else if (tag_datalen == 1)
+ {
+ imgdata.color.linear_max[0] = imgdata.color.linear_max[1] =
+ imgdata.color.linear_max[2] = imgdata.color.linear_max[3] =
+ cbuf_SR2.sget2(tag_dataoffset);
+ }
+ TagProcessed = 1;
+ break;
+ }
+ }
+
+ if (!TagProcessed) {
+ if ((tag_id >= 0x7480) && (tag_id <= 0x7486)) {
+ i = tag_id - 0x7480;
+ if (Sony_SR2_wb_list[i] > 255) {
+ icWBCCTC[WBCTC_count][0] = Sony_SR2_wb_list[i];
+ FORC3 icWBCCTC[WBCTC_count][c + 1] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ icWBCCTC[WBCTC_count][4] = icWBCCTC[WBCTC_count][2];
+ WBCTC_count++;
+ }
+ else {
+ FORC3 icWBC[Sony_SR2_wb_list[i]][c] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ icWBC[Sony_SR2_wb_list[i]][3] = icWBC[Sony_SR2_wb_list[i]][1];
+ }
+ }
+ else if ((tag_id >= 0x7820) && (tag_id <= 0x782d)) {
+ i = tag_id - 0x7820;
+ if (Sony_SR2_wb_list1[i] > 255) {
+ icWBCCTC[WBCTC_count][0] = Sony_SR2_wb_list1[i];
+ FORC3 icWBCCTC[WBCTC_count][c + 1] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ icWBCCTC[WBCTC_count][4] = icWBCCTC[WBCTC_count][2];
+ if (Sony_SR2_wb_list1[i] == 3200) {
+ FORC3 icWBC[LIBRAW_WBI_StudioTungsten][c] = icWBCCTC[WBCTC_count][c + 1];
+ icWBC[LIBRAW_WBI_StudioTungsten][3] = icWBC[LIBRAW_WBI_StudioTungsten][1];
+ }
+ WBCTC_count++;
+ }
+ else {
+ FORC3 icWBC[Sony_SR2_wb_list1[i]][c] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ icWBC[Sony_SR2_wb_list1[i]][3] = icWBC[Sony_SR2_wb_list1[i]][1];
+ }
+ }
+ else if (tag_id == 0x7302) {
+ FORC4 icWBC[LIBRAW_WBI_Auto][GRBG_2_RGBG(c)] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ }
+ else if (tag_id == 0x7312) {
+ FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = cbuf_SR2.sget2(tag_dataoffset + tag_dataunitlen * c);
+ }
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ return;
+ }
+}
+
+void LibRaw::parseSonySRF(unsigned len)
+{
+
+ if ((len > 0xfffff) || (len == 0))
+ return;
+
+ INT64 save = ftell(ifp);
+ INT64 offset = 0x0310c0 - save; /* for non-DNG this value normally is 0x8ddc */
+ if (len < offset || offset < 0)
+ return;
+ try {
+
+ INT64 decrypt_len = offset >> 2; /* master key offset value is the next
+ un-encrypted metadata field after SRF0 */
+
+ unsigned i, nWB;
+ unsigned MasterKey, SRF2Key=0;
+ INT64 srf_offset, tag_offset, tag_dataoffset;
+ int tag_dataunitlen;
+ //uchar *srf_buf;
+ ushort entries;
+ unsigned tag_id, tag_type, tag_datalen;
+
+ //srf_buf = (uchar *)malloc(len+64);
+ checked_buffer_t srf_buf(order, len);
+ fread(srf_buf.data(), len, 1, ifp);
+
+ offset += srf_buf[offset] << 2;
+
+ /* master key is stored in big endian */
+ MasterKey = ((unsigned)srf_buf[offset] << 24) |
+ ((unsigned)srf_buf[offset + 1] << 16) |
+ ((unsigned)srf_buf[offset + 2] << 8) |
+ (unsigned)srf_buf[offset + 3];
+
+ /* skip SRF0 */
+ srf_offset = 0;
+ entries = srf_buf.sget2(srf_offset);
+ if (entries > 1000)
+ goto restore_after_parseSonySRF;
+ offset = srf_offset + 2;
+ srf_offset = srf_buf.sget4(offset + 12 * entries) - save; /* SRF0 ends with SRF1 abs. position */
+
+ /* get SRF1, it has fixed 40 bytes length and contains keys to decode metadata
+ * and raw data */
+ if (srf_offset < 0 || decrypt_len < srf_offset / 4)
+ goto restore_after_parseSonySRF;
+ sony_decrypt((unsigned *)(srf_buf.data() + srf_offset), decrypt_len - srf_offset / 4,
+ 1, MasterKey);
+ entries = srf_buf.sget2(srf_offset);
+ if (entries > 1000)
+ goto restore_after_parseSonySRF;
+ offset = srf_offset + 2;
+ tag_offset = offset;
+
+ while (entries--) {
+ if (tiff_sget(save, srf_buf.data(), len,
+ &tag_offset, &tag_id, &tag_type, &tag_dataoffset,
+ &tag_datalen, &tag_dataunitlen) == 0) {
+ if (tag_id == 0x0000) {
+ SRF2Key = srf_buf.sget4(tag_dataoffset);
+ }
+ else if (tag_id == 0x0001) {
+ /*RawDataKey =*/ srf_buf.sget4(tag_dataoffset);
+ }
+ }
+ else goto restore_after_parseSonySRF;
+ }
+ offset = tag_offset;
+
+ /* get SRF2 */
+ srf_offset = srf_buf.sget4(offset) - save; /* SRFn ends with SRFn+1 position */
+ if (srf_offset < 0 || decrypt_len < srf_offset / 4)
+ goto restore_after_parseSonySRF;
+ sony_decrypt((unsigned *)(srf_buf.data() + srf_offset), decrypt_len - srf_offset / 4,
+ 1, SRF2Key);
+
+ entries = srf_buf.sget2(srf_offset);
+ if (entries > 1000)
+ goto restore_after_parseSonySRF;
+ offset = srf_offset + 2;
+ tag_offset = offset;
+
+ while (entries--) {
+ if (srf_buf.tiff_sget(save,
+ &tag_offset, &tag_id, &tag_type, &tag_dataoffset,
+ &tag_datalen, &tag_dataunitlen) == 0) {
+ if ((tag_id >= 0x00c0) && (tag_id <= 0x00ce)) {
+ i = (tag_id - 0x00c0) % 3;
+ nWB = (tag_id - 0x00c0) / 3;
+ icWBC[Sony_SRF_wb_list[nWB]][i] = srf_buf.sget4(tag_dataoffset);
+ if (i == 1) {
+ icWBC[Sony_SRF_wb_list[nWB]][3] =
+ icWBC[Sony_SRF_wb_list[nWB]][i];
+ }
+ }
+ else if ((tag_id >= 0x00d0) && (tag_id <= 0x00d2)) {
+ i = (tag_id - 0x00d0) % 3;
+ cam_mul[i] = srf_buf.sget4(tag_dataoffset);
+ if (i == 1) {
+ cam_mul[3] = cam_mul[i];
+ }
+ }
+ else switch (tag_id) {
+ /*
+ 0x0002 SRF6Offset
+ 0x0003 SRFDataOffset (?)
+ 0x0004 RawDataOffset
+ 0x0005 RawDataLength
+ */
+ case 0x0043:
+ ilm.MaxAp4MaxFocal = srf_buf.sgetreal(tag_type, tag_dataoffset);
+ break;
+ case 0x0044:
+ ilm.MaxAp4MinFocal = srf_buf.sgetreal(tag_type, tag_dataoffset);
+ break;
+ case 0x0045:
+ ilm.MinFocal = srf_buf.sgetreal(tag_type, tag_dataoffset);
+ break;
+ case 0x0046:
+ ilm.MaxFocal = srf_buf.sgetreal(tag_type, tag_dataoffset);
+ break;
+ }
+ }
+ else goto restore_after_parseSonySRF;
+ }
+ offset = tag_offset;
+
+ restore_after_parseSonySRF:;
+ }
+ catch (...) // srf_buf can raise IO_EOF exception, catch it and return usual way
+ {
+ fseek(ifp, save, SEEK_SET);
+ return;
+ }
+ fseek(ifp, save, SEEK_SET);
+}
diff --git a/libkdcraw/libraw/src/metadata/tiff.cpp b/libkdcraw/libraw/src/metadata/tiff.cpp
new file mode 100644
index 0000000..c34b864
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/tiff.cpp
@@ -0,0 +1,2188 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+#include "../../internal/libraw_cameraids.h"
+
+int LibRaw::parse_tiff_ifd(int base)
+{
+ unsigned entries, tag, type, len, plen = 16, save, utmp;
+ int ifd, use_cm = 0, cfa, i, j, c, ima_len = 0;
+ char *cbuf, *cp;
+ uchar cfa_pat[16], cfa_pc[] = {0, 1, 2, 3}, tab[256];
+ double fm[3][4], cc[4][4], cm[4][3], cam_xyz[4][3], num;
+ double ab[] = {1, 1, 1, 1}, asn[] = {0, 0, 0, 0}, xyz[] = {1, 1, 1};
+ unsigned sony_curve[] = {0, 0, 0, 0, 0, 4095};
+ unsigned *buf, sony_offset = 0, sony_length = 0, sony_key = 0;
+ struct jhead jh;
+
+ ushort *rafdata;
+
+ if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
+ return 1;
+ ifd = tiff_nifds++;
+ for (j = 0; j < 4; j++)
+ for (i = 0; i < 4; i++)
+ cc[j][i] = i == j;
+
+ if (libraw_internal_data.unpacker_data.ifd0_offset == -1LL)
+ libraw_internal_data.unpacker_data.ifd0_offset = base;
+
+ entries = get2();
+ if (entries > 512)
+ return 1;
+
+ INT64 fsize = ifp->size();
+
+ while (entries--)
+ {
+ tiff_get(base, &tag, &type, &len, &save);
+ INT64 savepos = ftell(ifp);
+ if (len > 8 && savepos + len > 2 * fsize)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+ if (callbacks.exif_cb)
+ {
+ callbacks.exif_cb(callbacks.exifparser_data,
+ tag | (is_pana_raw ? 0x30000 : ((ifd + 1) << 20)), type,
+ len, order, ifp, base);
+ fseek(ifp, savepos, SEEK_SET);
+ }
+
+ if (!is_pana_raw)
+ { /* processing of EXIF tags that collide w/ PanasonicRaw tags */
+ switch (tag)
+ {
+ case 0x0001:
+ if (len == 4)
+ is_pana_raw = get4();
+ break;
+ case 0x000b: /* 11, Std. EXIF Software tag */
+ fgets(software, 64, ifp);
+ if (!strncmp(software, "Adobe", 5) || !strncmp(software, "dcraw", 5) ||
+ !strncmp(software, "UFRaw", 5) || !strncmp(software, "Bibble", 6) ||
+ !strcmp(software, "Digital Photo Professional"))
+ is_raw = 0;
+ break;
+ case 0x001c: /* 28, safeguard, probably not needed */
+ case 0x001d: /* 29, safeguard, probably not needed */
+ case 0x001e: /* 30, safeguard, probably not needed */
+ cblack[tag - 0x001c] = get2();
+ cblack[3] = cblack[1];
+ break;
+
+ case 0x0111: /* 273, StripOffset */
+ if (len > 1 && len < 16384)
+ {
+ off_t sav = ftell(ifp);
+ tiff_ifd[ifd].strip_offsets = (int *)calloc(len, sizeof(int));
+ tiff_ifd[ifd].strip_offsets_count = len;
+ for (int ii = 0; ii < (int)len; ii++)
+ tiff_ifd[ifd].strip_offsets[ii] = get4() + base;
+ fseek(ifp, sav, SEEK_SET); // restore position
+ }
+ /* fallback */
+ case 0x0201: /* 513, JpegIFOffset */
+ case 0xf007: // 61447
+ tiff_ifd[ifd].offset = get4() + base;
+ if (!tiff_ifd[ifd].bps && tiff_ifd[ifd].offset > 0)
+ {
+ fseek(ifp, tiff_ifd[ifd].offset, SEEK_SET);
+ if (ljpeg_start(&jh, 1))
+ {
+ if (!dng_version && !strcasecmp(make, "SONY") && tiff_ifd[ifd].phint == 32803 &&
+ tiff_ifd[ifd].comp == 7) // Sony/lossless compressed IFD
+ {
+ tiff_ifd[ifd].comp = 6;
+ tiff_ifd[ifd].bps = jh.bits;
+ tiff_ifd[ifd].samples = 1;
+ }
+ else
+ {
+ tiff_ifd[ifd].comp = 6;
+ tiff_ifd[ifd].bps = jh.bits;
+ tiff_ifd[ifd].t_width = jh.wide;
+ tiff_ifd[ifd].t_height = jh.high;
+ tiff_ifd[ifd].samples = jh.clrs;
+ if (!(jh.sraw || (jh.clrs & 1)))
+ tiff_ifd[ifd].t_width *= jh.clrs;
+ if ((tiff_ifd[ifd].t_width > 4 * tiff_ifd[ifd].t_height) & ~jh.clrs)
+ {
+ tiff_ifd[ifd].t_width /= 2;
+ tiff_ifd[ifd].t_height *= 2;
+ }
+ i = order;
+ parse_tiff(tiff_ifd[ifd].offset + 12);
+ order = i;
+ }
+ }
+ }
+ break;
+ }
+ }
+ else
+ { /* processing Panasonic-specific "PanasonicRaw" tags */
+ switch (tag)
+ {
+ case 0x0004: /* 4, SensorTopBorder */
+ imgdata.sizes.raw_inset_crops[0].ctop = get2();
+ break;
+ case 0x000a: /* 10, BitsPerSample */
+ pana_bpp = get2();
+ pana_bpp = LIM(pana_bpp, 8, 16);
+ break;
+ case 0x000b: /* 11, Compression */
+ imPana.Compression = get2();
+ break;
+ case 0x000e: /* 14, LinearityLimitRed */
+ case 0x000f: /* 15, LinearityLimitGreen */
+ case 0x0010: /* 16, LinearityLimitBlue */
+ imgdata.color.linear_max[tag - 14] = get2();
+ if (imgdata.color.linear_max[tag - 14] == 16383)
+ imgdata.color.linear_max[tag - 14] -= 64;
+ if (imgdata.color.linear_max[tag - 14] == 4095)
+ imgdata.color.linear_max[tag - 14] -= 16;
+ if (tag == 0x000f) // 15, LinearityLimitGreen
+ imgdata.color.linear_max[3] = imgdata.color.linear_max[1];
+ break;
+ case 0x0013: /* 19, WBInfo */
+ if ((i = get2()) > 0x100)
+ break;
+ for (c = 0; c < i; c++)
+ {
+ if ((j = get2()) < 0x100)
+ {
+ icWBC[j][0] = get2();
+ icWBC[j][2] = get2();
+ icWBC[j][1] = icWBC[j][3] =
+ 0x100;
+ }
+ else // light source out of EXIF numbers range
+ get4();
+ }
+ break;
+ case 0x0018: /* 24, HighISOMultiplierRed */
+ case 0x0019: /* 25, HighISOMultiplierGreen */
+ case 0x001a: /* 26, HighISOMultiplierBlue */
+ imPana.HighISOMultiplier[tag - 0x0018] = get2();
+ break;
+ case 0x001c: /* 28, BlackLevelRed */
+ case 0x001d: /* 29, BlackLevelGreen */
+ case 0x001e: /* 30, BlackLevelBlue */
+ pana_black[tag - 0x001c] = get2();
+ break;
+ case 0x002d: /* 45, RawFormat */
+ /* pana_encoding: tag 0x002d (45dec)
+ not used - DMC-LX1/FZ30/FZ50/L1/LX1/LX2
+ 2 - RAW DMC-FZ8/FZ18
+ 3 - RAW DMC-L10
+ 4 - RW2 for most other models, including G9 in "pixel shift off"
+ mode and YUNEEC CGO4 (must add 15 to black levels for
+ RawFormat == 4) 5 - RW2 DC-GH5s; G9 in "pixel shift on"
+ mode 6 - RW2 DC-S1, DC-S1R in "pixel shift off"
+ mode 7 - RW2 DC-S1R (probably DC-S1 too) in
+ "pixel shift on" mode
+ */
+ pana_encoding = get2();
+ break;
+ case 0x002f: /* 47, CropTop */
+ imgdata.sizes.raw_inset_crops[0].ctop = get2();
+ break;
+ case 0x0030: /* 48, CropLeft */
+ imgdata.sizes.raw_inset_crops[0].cleft = get2();
+ break;
+ case 0x0031: /* 49, CropBottom */
+ imgdata.sizes.raw_inset_crops[0].cheight =
+ get2() - imgdata.sizes.raw_inset_crops[0].ctop;
+ break;
+ case 0x0032: /* 50, CropRight */
+ imgdata.sizes.raw_inset_crops[0].cwidth =
+ get2() - imgdata.sizes.raw_inset_crops[0].cleft;
+ break;
+ case 0x0037: /* 55, ISO if ISO in 0x8827 & ISO in 0x0017 == 65535 */
+ if (iso_speed == 65535)
+ iso_speed = get4();
+ break;
+ case 0x011c: /* 284, Gamma */
+ {
+ int n = get2();
+ if (n >= 1024)
+ imPana.gamma = (float)n / 1024.0f;
+ else if (n >= 256)
+ imPana.gamma = (float)n / 256.0f;
+ else
+ imPana.gamma = (float)n / 100.0f;
+ }
+ break;
+ case 0x0120: /* 288, CameraIFD, contains tags 0x1xxx, 0x2xxx, 0x3xxx */
+ {
+ unsigned sorder = order;
+ unsigned long sbase = base;
+ base = ftell(ifp);
+ order = get2();
+ fseek(ifp, 2, SEEK_CUR);
+ fseek(ifp, INT64(get4()) - 8LL, SEEK_CUR);
+ parse_tiff_ifd(base);
+ base = sbase;
+ order = sorder;
+ }
+ break;
+ case 0x0121: /* 289, Multishot, 0 is Off, 65536 is Pixel Shift */
+ imPana.Multishot = get4();
+ break;
+ case 0x1001:
+ if (imPana.Multishot == 0) {
+ imPana.Multishot = get4();
+ if (imPana.Multishot)
+ imPana.Multishot += 65535;
+ }
+ break;
+ case 0x1100:
+ imPana.FocusStepNear = get2();
+ break;
+ case 0x1101:
+ imPana.FocusStepCount = get2();
+ break;
+ case 0x1105:
+ imPana.ZoomPosition = get4();
+ break;
+ case 0x1201:
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT)) {
+ imPana.LensManufacturer = fgetc(ifp);
+ } else if (type == 258) {
+ imPana.LensManufacturer = get4();
+ if (imPana.LensManufacturer >= 257) {
+ ilm.LensMount = LIBRAW_MOUNT_LPS_L;
+ ilm.LensFormat = LIBRAW_FORMAT_FF;
+ }
+ }
+ break;
+ case 0x1202:
+ if (ilm.LensMount == LIBRAW_MOUNT_LPS_L) {
+ if ((utmp = get2())) ilm.LensID = utmp;
+ } else if ((imPana.LensManufacturer != 0xff) &&
+ (imPana.LensManufacturer != 0xffffffff)) {
+ if ((utmp = (fgetc(ifp) << 8) | fgetc(ifp)))
+ ilm.LensID = (imPana.LensManufacturer << 16) + utmp;
+ }
+ break;
+ case 0x1203: /* 4611, FocalLengthIn35mmFormat, contained in 0x0120
+ CameraIFD */
+ if (imgdata.lens.FocalLengthIn35mmFormat < 0.65f)
+ imgdata.lens.FocalLengthIn35mmFormat = get2();
+ break;
+ case 0x2009: /* 8201, contained in 0x0120 CameraIFD */
+ if ((pana_encoding == 4) || (pana_encoding == 5))
+ {
+ i = MIN(8, len);
+ int permut[8] = {3, 2, 1, 0, 3 + 4, 2 + 4, 1 + 4, 0 + 4};
+ imPana.BlackLevelDim = len;
+ for (j = 0; j < i; j++)
+ {
+ imPana.BlackLevel[permut[j]] =
+ (float)(get2()) / (float)(powf(2.f, 14.f - pana_bpp));
+ }
+ }
+ break;
+ case 0x3420: /* 13344, WB_RedLevelAuto, contained in 0x0120 CameraIFD */
+ icWBC[LIBRAW_WBI_Auto][0] = get2();
+ icWBC[LIBRAW_WBI_Auto][1] = icWBC[LIBRAW_WBI_Auto][3] = 1024.0f;
+ break;
+ case 0x3421: /* 13345, WB_BlueLevelAuto, contained in 0x0120 CameraIFD */
+ icWBC[LIBRAW_WBI_Auto][2] = get2();
+ break;
+ case 0x0002: /* 2, ImageWidth */
+ tiff_ifd[ifd].t_width = getint(type);
+ break;
+ case 0x0003: /* 3, ImageHeight */
+ tiff_ifd[ifd].t_height = getint(type);
+ break;
+ case 0x0005: /* 5, SensorLeftBorder */
+ width = get2();
+ imgdata.sizes.raw_inset_crops[0].cleft = width;
+ break;
+ case 0x0006: /* 6, SensorBottomBorder */
+ height = get2();
+ imgdata.sizes.raw_inset_crops[0].cheight =
+ height - imgdata.sizes.raw_inset_crops[0].ctop;
+ break;
+ case 0x0007: /* 7, SensorRightBorder */
+ i = get2();
+ width += i;
+ imgdata.sizes.raw_inset_crops[0].cwidth =
+ i - imgdata.sizes.raw_inset_crops[0].cleft;
+ break;
+ case 0x0009: /* 9, CFAPattern */
+ if ((i = get2()))
+ filters = i;
+ break;
+ case 0x0011: /* 17, RedBalance */
+ case 0x0012: /* 18, BlueBalance */
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) && len == 1)
+ cam_mul[(tag - 0x0011) * 2] = get2() / 256.0;
+ break;
+ case 0x0017: /* 23, ISO */
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT))
+ iso_speed = get2();
+ break;
+ case 0x0024: /* 36, WBRedLevel */
+ case 0x0025: /* 37, WBGreenLevel */
+ case 0x0026: /* 38, WBBlueLevel */
+ cam_mul[tag - 0x0024] = get2();
+ break;
+ case 0x0027: /* 39, WBInfo2 */
+ if ((i = get2()) > 0x100)
+ break;
+ for (c = 0; c < i; c++)
+ {
+ if ((j = get2()) < 0x100)
+ {
+ icWBC[j][0] = get2();
+ icWBC[j][1] = icWBC[j][3] = get2();
+ icWBC[j][2] = get2();
+ if (c == 1 && i > 6 && cam_mul[0] <= 0.001f)
+ for (int q = 0; q < 4; q++)
+ cam_mul[q] = icWBC[j][q];
+ }
+ else
+ fseek(ifp, 6, SEEK_CUR);
+ }
+ break;
+ case 0x002e: /* 46, JpgFromRaw */
+ if ((type != LIBRAW_EXIFTAG_TYPE_UNDEFINED) || (fgetc(ifp) != 0xff) || (fgetc(ifp) != 0xd8))
+ break;
+ thumb_offset = ftell(ifp) - 2;
+ thumb_length = len;
+ break;
+
+ case 0x0118: /* 280, Panasonic RW2 offset */
+ if (type != LIBRAW_EXIFTAG_TYPE_LONG)
+ break;
+ load_raw = &LibRaw::panasonic_load_raw;
+ load_flags = 0x2008;
+ case 0x0111: /* 273, StripOffset */
+ if (len > 1 && len < 16384)
+ {
+ off_t sav = ftell(ifp);
+ tiff_ifd[ifd].strip_offsets = (int *)calloc(len, sizeof(int));
+ tiff_ifd[ifd].strip_offsets_count = len;
+ for (int ii = 0; ii < (int)len; ii++)
+ tiff_ifd[ifd].strip_offsets[ii] = get4() + base;
+ fseek(ifp, sav, SEEK_SET); // restore position
+ }
+ /* fallthrough */
+ tiff_ifd[ifd].offset = get4() + base;
+ if (!tiff_ifd[ifd].bps && tiff_ifd[ifd].offset > 0)
+ {
+ fseek(ifp, tiff_ifd[ifd].offset, SEEK_SET);
+ if (ljpeg_start(&jh, 1))
+ {
+ tiff_ifd[ifd].comp = 6;
+ tiff_ifd[ifd].t_width = jh.wide;
+ tiff_ifd[ifd].t_height = jh.high;
+ tiff_ifd[ifd].bps = jh.bits;
+ tiff_ifd[ifd].samples = jh.clrs;
+ if (!(jh.sraw || (jh.clrs & 1)))
+ tiff_ifd[ifd].t_width *= jh.clrs;
+ if ((tiff_ifd[ifd].t_width > 4 * tiff_ifd[ifd].t_height) & ~jh.clrs)
+ {
+ tiff_ifd[ifd].t_width /= 2;
+ tiff_ifd[ifd].t_height *= 2;
+ }
+ i = order;
+ parse_tiff(tiff_ifd[ifd].offset + 12);
+ order = i;
+ }
+ }
+ break;
+ }
+
+ } /* processing of Panasonic-specific tags finished */
+
+ switch (tag)
+ { /* processing of general EXIF tags */
+ case 0xf000: /* 61440, Fuji HS10 table */
+ fseek(ifp, get4() + base, SEEK_SET);
+ parse_tiff_ifd(base);
+ break;
+ case 0x00fe: /* NewSubfileType */
+ tiff_ifd[ifd].newsubfiletype = getreal(type);
+ break;
+ case 0x0100: /* 256, ImageWidth */
+ case 0xf001: /* 61441, Fuji RAF RawImageFullWidth */
+ tiff_ifd[ifd].t_width = getint(type);
+ break;
+ case 0x0101: /* 257, ImageHeight */
+ case 0xf002: /* 61442, Fuji RAF RawImageFullHeight */
+ tiff_ifd[ifd].t_height = getint(type);
+ break;
+ case 0x0102: /* 258, BitsPerSample */
+ case 0xf003: /* 61443, Fuji RAF 0xf003 */
+ if(!tiff_ifd[ifd].samples || tag != 0x0102) // ??? already set by tag 0x115
+ tiff_ifd[ifd].samples = len & 7;
+ tiff_ifd[ifd].bps = getint(type);
+ if (tiff_bps < (unsigned)tiff_ifd[ifd].bps)
+ tiff_bps = tiff_ifd[ifd].bps;
+ break;
+ case 0xf006: /* 61446, Fuji RAF 0xf006 */
+ raw_height = 0;
+ if (tiff_ifd[ifd].bps > 12)
+ break;
+ load_raw = &LibRaw::packed_load_raw;
+ load_flags = get4() ? 24 : 80;
+ break;
+ case 0x0103: /* 259, Compression */
+ /*
+ 262 = Kodak 262
+ 32767 = Sony ARW Compressed
+ 32769 = Packed RAW
+ 32770 = Samsung SRW Compressed
+ 32772 = Samsung SRW Compressed 2
+ 32867 = Kodak KDC Compressed
+ 34713 = Nikon NEF Compressed
+ 65000 = Kodak DCR Compressed
+ 65535 = Pentax PEF Compressed
+ */
+ tiff_ifd[ifd].comp = getint(type);
+ break;
+ case 0x0106: /* 262, PhotometricInterpretation */
+ tiff_ifd[ifd].phint = get2();
+ break;
+ case 0x010e: /* 270, ImageDescription */
+ fread(desc, 512, 1, ifp);
+ break;
+ case 0x010f: /* 271, Make */
+ fgets(make, 64, ifp);
+ break;
+ case 0x0110: /* 272, Model */
+ if (!strncmp(make, "Hasselblad", 10) && model[0] &&
+ (imHassy.format != LIBRAW_HF_Imacon))
+ break;
+ fgets(model, 64, ifp);
+ break;
+ case 0x0116: // 278
+ tiff_ifd[ifd].rows_per_strip = getint(type);
+ break;
+ case 0x0112: /* 274, Orientation */
+ tiff_ifd[ifd].t_flip = "50132467"[get2() & 7] - '0';
+ break;
+ case 0x0115: /* 277, SamplesPerPixel */
+ tiff_ifd[ifd].samples = getint(type) & 7;
+ break;
+ case 0x0152: /* Extrasamples */
+ tiff_ifd[ifd].extrasamples = (getint(type) & 0xff) + 1024;
+ break;
+ case 0x0117: /* 279, StripByteCounts */
+ if (len > 1 && len < 16384)
+ {
+ off_t sav = ftell(ifp);
+ tiff_ifd[ifd].strip_byte_counts = (int *)calloc(len, sizeof(int));
+ tiff_ifd[ifd].strip_byte_counts_count = len;
+ for (int ii = 0; ii < (int)len; ii++)
+ tiff_ifd[ifd].strip_byte_counts[ii] = get4();
+ fseek(ifp, sav, SEEK_SET); // restore position
+ }
+ /* fallback */
+ case 0x0202: // 514
+ case 0xf008: // 61448
+ tiff_ifd[ifd].bytes = get4();
+ break;
+ case 0xf00e: // 61454, FujiFilm "As Shot"
+ FORC3 cam_mul[GRBG_2_RGBG(c)] = getint(type);
+ break;
+ case 0x0131: /* 305, Software */
+ fgets(software, 64, ifp);
+ if (!strncmp(software, "Adobe", 5) || !strncmp(software, "dcraw", 5) ||
+ !strncmp(software, "UFRaw", 5) || !strncmp(software, "Bibble", 6) ||
+ !strcmp(software, "Digital Photo Professional"))
+ is_raw = 0;
+ break;
+ case 0x0132: /* 306, DateTime */
+ get_timestamp(0);
+ break;
+ case 0x013b: /* 315, Artist */
+ fread(artist, 64, 1, ifp);
+ break;
+ case 0x013d: // 317
+ tiff_ifd[ifd].predictor = getint(type);
+ break;
+ case 0x0142: /* 322, TileWidth */
+ tiff_ifd[ifd].t_tile_width = getint(type);
+ break;
+ case 0x0143: /* 323, TileLength */
+ tiff_ifd[ifd].t_tile_length = getint(type);
+ break;
+ case 0x0144: /* 324, TileOffsets */
+ tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
+ if (len == 1)
+ tiff_ifd[ifd].t_tile_width = tiff_ifd[ifd].t_tile_length = 0;
+ if (len == 4)
+ {
+ load_raw = &LibRaw::sinar_4shot_load_raw;
+ is_raw = 5;
+ }
+ break;
+ case 0x0145: // 325
+ tiff_ifd[ifd].bytes = len > 1 ? ftell(ifp) : get4();
+ break;
+ case 0x014a: /* 330, SubIFDs */
+ if (!strcmp(model, "DSLR-A100") && tiff_ifd[ifd].t_width == 3872)
+ {
+ load_raw = &LibRaw::sony_arw_load_raw;
+ data_offset = get4() + base;
+ ifd++;
+ if (ifd >= int(sizeof tiff_ifd / sizeof tiff_ifd[0]))
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ break;
+ }
+ if (!strncmp(make, "Hasselblad", 10) &&
+ libraw_internal_data.unpacker_data.hasselblad_parser_flag)
+ {
+ fseek(ifp, ftell(ifp) + 4, SEEK_SET);
+ fseek(ifp, get4() + base, SEEK_SET);
+ parse_tiff_ifd(base);
+ break;
+ }
+ if (len > 1000)
+ len = 1000; /* 1000 SubIFDs is enough */
+ while (len--)
+ {
+ i = ftell(ifp);
+ fseek(ifp, get4() + base, SEEK_SET);
+ if (parse_tiff_ifd(base))
+ break;
+ fseek(ifp, i + 4, SEEK_SET);
+ }
+ break;
+ case 0x0153: // 339
+ tiff_ifd[ifd].sample_format = getint(type);
+ break;
+ case 0x0190: // 400
+ strcpy(make, "Sarnoff");
+ maximum = 0xfff;
+ break;
+ case 0x02bc: // 700
+ if ((tagtypeIs(LIBRAW_EXIFTAG_TYPE_BYTE) ||
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII) ||
+ tagtypeIs(LIBRAW_EXIFTAG_TYPE_SBYTE) ||
+ tagtypeIs(LIBRAW_EXIFTOOLTAGTYPE_binary)) &&
+ (len > 1) && (len < 5100000))
+ {
+ xmpdata = (char *)malloc(xmplen = len + 1);
+ fread(xmpdata, len, 1, ifp);
+ xmpdata[len] = 0;
+ }
+ break;
+ case 0x7000:
+ imSony.SonyRawFileType = get2();
+ break;
+ case 0x7010: // 28688
+ FORC4 sony_curve[c + 1] = get2() >> 2 & 0xfff;
+ for (i = 0; i < 5; i++)
+ for (j = sony_curve[i] + 1; j <= (int)sony_curve[i + 1]; j++)
+ curve[j] = curve[j - 1] + (1 << i);
+ break;
+ case 0x7200: // 29184, Sony SR2Private
+ sony_offset = get4();
+ break;
+ case 0x7201: // 29185, Sony SR2Private
+ sony_length = get4();
+ break;
+ case 0x7221: // 29217, Sony SR2Private
+ sony_key = get4();
+ break;
+ case 0x7250: // 29264, Sony SR2Private
+ parse_minolta(ftell(ifp));
+ raw_width = 0;
+ break;
+ case 0x7303: // 29443, Sony SR2SubIFD
+ FORC4 cam_mul[GRBG_2_RGBG(c)] = get2();
+ break;
+ case 0x7313: // 29459, Sony SR2SubIFD
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = get2();
+ break;
+ case 0x7310: // 29456, Sony SR2SubIFD
+ FORC4 cblack[RGGB_2_RGBG(c)] = get2();
+ i = cblack[3];
+ FORC3 if (i > (int)cblack[c]) i = cblack[c];
+ FORC4 cblack[c] -= i;
+ black = i;
+ break;
+ case 0x827d: /* 33405, Model2 */
+ /*
+ for Kodak ProBack 645 PB645x-yyyy 'x' is:
+ 'M' for Mamiya 645
+ 'C' for Contax 645
+ 'H' for Hasselblad H-series
+ */
+ fgets(model2, 64, ifp);
+ break;
+ case 0x828d: /* 33421, CFARepeatPatternDim */
+ if (get2() == 6 && get2() == 6)
+ tiff_ifd[ifd].t_filters = filters = 9;
+ break;
+ case 0x828e: /* 33422, CFAPattern */
+ if (filters == 9)
+ {
+ FORC(36)((char *)xtrans)[c] = fgetc(ifp) & 3;
+ break;
+ }
+ case 0xfd09: /* 64777, Kodak P-series */
+ if (len == 36)
+ {
+ tiff_ifd[ifd].t_filters = filters = 9;
+ colors = 3;
+ FORC(36)((char *)xtrans)[c] = fgetc(ifp) & 3;
+ }
+ else if (len > 0)
+ {
+ if ((plen = len) > 16)
+ plen = 16;
+ fread(cfa_pat, 1, plen, ifp);
+ for (colors = cfa = i = 0; i < (int)plen && colors < 4; i++)
+ {
+ if (cfa_pat[i] > 31)
+ continue; // Skip wrong data
+ colors += !(cfa & (1 << cfa_pat[i]));
+ cfa |= 1 << cfa_pat[i];
+ }
+ if (cfa == 070)
+ memcpy(cfa_pc, "\003\004\005", 3); /* CMY */
+ if (cfa == 072)
+ memcpy(cfa_pc, "\005\003\004\001", 4); /* GMCY */
+ goto guess_cfa_pc;
+ }
+ break;
+ case 0x8290: // 33424
+ case 0xfe00: // 65024
+ fseek(ifp, get4() + base, SEEK_SET);
+ parse_kodak_ifd(base);
+ break;
+ case 0x829a: /* 33434, ExposureTime */
+ tiff_ifd[ifd].t_shutter = shutter = getreal(type);
+ break;
+ case 0x829d: /* 33437, FNumber */
+ aperture = getreal(type);
+ break;
+ case 0x9400:
+ imCommon.exifAmbientTemperature = getreal(type);
+ if ((imCommon.CameraTemperature > -273.15f) &&
+ ((OlyID == OlyID_TG_5) || (OlyID == OlyID_TG_6)))
+ imCommon.CameraTemperature +=
+ imCommon.exifAmbientTemperature;
+ break;
+ case 0x9401:
+ imCommon.exifHumidity = getreal(type);
+ break;
+ case 0x9402:
+ imCommon.exifPressure = getreal(type);
+ break;
+ case 0x9403:
+ imCommon.exifWaterDepth = getreal(type);
+ break;
+ case 0x9404:
+ imCommon.exifAcceleration = getreal(type);
+ break;
+ case 0x9405:
+ imCommon.exifCameraElevationAngle = getreal(type);
+ break;
+ case 0xa405: // FocalLengthIn35mmFormat
+ imgdata.lens.FocalLengthIn35mmFormat = get2();
+ break;
+ case 0xa431: // BodySerialNumber
+ case 0xc62f:
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ break;
+ case 0xa432: // LensInfo, 42034dec, Lens Specification per EXIF standard
+ imgdata.lens.MinFocal = getreal(type);
+ imgdata.lens.MaxFocal = getreal(type);
+ imgdata.lens.MaxAp4MinFocal = getreal(type);
+ imgdata.lens.MaxAp4MaxFocal = getreal(type);
+ break;
+ case 0xa435: // LensSerialNumber
+ stmread(imgdata.lens.LensSerial, len, ifp);
+ break;
+ case 0xc630: // DNG LensInfo, Lens Specification per EXIF standard
+ imgdata.lens.MinFocal = getreal(type);
+ imgdata.lens.MaxFocal = getreal(type);
+ imgdata.lens.MaxAp4MinFocal = getreal(type);
+ imgdata.lens.MaxAp4MaxFocal = getreal(type);
+ break;
+ case 0xa420: /* 42016, ImageUniqueID */
+ stmread(imgdata.color.ImageUniqueID, len, ifp);
+ break;
+ case 0xc65d: /* 50781, RawDataUniqueID */
+ imgdata.color.RawDataUniqueID[16] = 0;
+ fread(imgdata.color.RawDataUniqueID, 1, 16, ifp);
+ break;
+ case 0xa433: // LensMake
+ stmread(imgdata.lens.LensMake, len, ifp);
+ break;
+ case 0xa434: // LensModel
+ stmread(imgdata.lens.Lens, len, ifp);
+ if (!strncmp(imgdata.lens.Lens, "----", 4))
+ imgdata.lens.Lens[0] = 0;
+ break;
+ case 0x9205:
+ imgdata.lens.EXIF_MaxAp = libraw_powf64l(2.0f, (getreal(type) / 2.0f));
+ break;
+ case 0x8602: /* 34306, Leaf white balance */
+ FORC4
+ {
+ int q = get2();
+ if (q)
+ cam_mul[GRGB_2_RGBG(c)] = 4096.0 / q;
+ }
+ break;
+ case 0x8603: /* 34307, Leaf CatchLight color matrix */
+ fread(software, 1, 7, ifp);
+ if (strncmp(software, "MATRIX", 6))
+ break;
+ colors = 4;
+ for (raw_color = i = 0; i < 3; i++)
+ {
+ FORC4 fscanf(ifp, "%f", &rgb_cam[i][GRGB_2_RGBG(c)]);
+ if (!use_camera_wb)
+ continue;
+ num = 0;
+ FORC4 num += rgb_cam[i][c];
+ FORC4 rgb_cam[i][c] /= MAX(1, num);
+ }
+ break;
+ case 0x8606: /* 34310, Leaf metadata */
+ parse_mos(ftell(ifp));
+ case 0x85ff: // 34303
+ strcpy(make, "Leaf");
+ break;
+ case 0x8769: /* 34665, EXIF tag */
+ fseek(ifp, get4() + base, SEEK_SET);
+ parse_exif(base);
+ break;
+ case 0x8825: /* 34853, GPSInfo tag */
+ {
+ unsigned pos;
+ fseek(ifp, pos = (get4() + base), SEEK_SET);
+ parse_gps(base);
+ fseek(ifp, pos, SEEK_SET);
+ parse_gps_libraw(base);
+ }
+ break;
+ case 0x8773: /* 34675, InterColorProfile */
+ case 0xc68f: /* 50831, AsShotICCProfile */
+ profile_offset = ftell(ifp);
+ profile_length = len;
+ break;
+ case 0x9102: /* 37122, CompressedBitsPerPixel */
+ kodak_cbpp = get4();
+ break;
+ case 0x920a: /* 37386, FocalLength */
+ focal_len = getreal(type);
+ break;
+ case 0x9211: /* 37393, ImageNumber */
+ shot_order = getint(type);
+ break;
+ case 0x9215: /* 37397, ExposureIndex */
+ imCommon.exifExposureIndex = getreal(type);
+ break;
+ case 0x9218: /* 37400, old Kodak KDC tag */
+ for (raw_color = i = 0; i < 3; i++)
+ {
+ getreal(type);
+ FORC3 rgb_cam[i][c] = getreal(type);
+ }
+ break;
+ case 0xa010: // 40976
+ strip_offset = get4();
+ switch (tiff_ifd[ifd].comp)
+ {
+ case 0x8002: // 32770
+ load_raw = &LibRaw::samsung_load_raw;
+ break;
+ case 0x8004: // 32772
+ load_raw = &LibRaw::samsung2_load_raw;
+ break;
+ case 0x8005: // 32773
+ load_raw = &LibRaw::samsung3_load_raw;
+ break;
+ }
+ break;
+ case 0xb4c3: /* 46275, Imacon tags */
+ imHassy.format = LIBRAW_HF_Imacon;
+ strcpy(make, "Imacon");
+ data_offset = ftell(ifp);
+ ima_len = len;
+ break;
+ case 0xb4c7: // 46279
+ if (!ima_len)
+ break;
+ fseek(ifp, 38, SEEK_CUR);
+ case 0xb4c2: // 46274
+ fseek(ifp, 40, SEEK_CUR);
+ raw_width = get4();
+ raw_height = get4();
+ left_margin = get4() & 7;
+ width = raw_width - left_margin - (get4() & 7);
+ top_margin = get4() & 7;
+ height = raw_height - top_margin - (get4() & 7);
+ if (raw_width == 7262 && ima_len == 234317952)
+ {
+ height = 5412;
+ width = 7216;
+ left_margin = 7;
+ filters = 0;
+ }
+ else if (raw_width == 7262)
+ {
+ height = 5444;
+ width = 7244;
+ left_margin = 7;
+ }
+ fseek(ifp, 52, SEEK_CUR);
+ FORC3 cam_mul[c] = getreal(LIBRAW_EXIFTAG_TYPE_FLOAT);
+ fseek(ifp, 114, SEEK_CUR);
+ flip = (get2() >> 7) * 90;
+ if (width * (height * 6l) == ima_len)
+ {
+ if (flip % 180 == 90)
+ SWAP(width, height);
+ raw_width = width;
+ raw_height = height;
+ left_margin = top_margin = filters = flip = 0;
+ }
+ c = unsigned(height) * unsigned(width) / 1000000;
+ if (c == 32)
+ c--;
+ sprintf(model, "Ixpress %d-Mp", c);
+ load_raw = &LibRaw::imacon_full_load_raw;
+ if (filters)
+ {
+ if (left_margin & 1)
+ filters = 0x61616161;
+ load_raw = &LibRaw::unpacked_load_raw;
+ }
+ maximum = 0xffff;
+ break;
+ case 0xc516: /* 50454, Sinar tag */
+ case 0xc517: // 50455
+ if (len < 1 || len > 2560000 || !(cbuf = (char *)malloc(len)))
+ break;
+ if (fread(cbuf, 1, len, ifp) != (int)len)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT; // cbuf to be free'ed in recycle
+ cbuf[len - 1] = 0;
+ for (cp = cbuf - 1; cp && cp < cbuf + len; cp = strchr(cp, '\n'))
+ if (!strncmp(++cp, "Neutral ", 8))
+ sscanf(cp + 8, "%f %f %f", cam_mul, cam_mul + 1, cam_mul + 2);
+ free(cbuf);
+ break;
+ case 0xc51a: // 50458
+ if (!make[0])
+ strcpy(make, "Hasselblad");
+ break;
+ case 0xc51b: /* 50459, Hasselblad tag */
+ if (!libraw_internal_data.unpacker_data.hasselblad_parser_flag)
+ {
+ libraw_internal_data.unpacker_data.hasselblad_parser_flag = 1;
+ i = order;
+ j = ftell(ifp);
+ c = tiff_nifds;
+ order = get2();
+ fseek(ifp, j + (get2(), get4()), SEEK_SET);
+ parse_tiff_ifd(j);
+ maximum = 0xffff;
+ tiff_nifds = c;
+ order = i;
+ break;
+ }
+ case 0xc612: /* 50706, DNGVersion */
+ FORC4 dng_version = (dng_version << 8) + fgetc(ifp);
+ if (!make[0])
+ strcpy(make, "DNG");
+ is_raw = 1;
+ break;
+ case 0xc614: /* 50708, UniqueCameraModel */
+ stmread(imgdata.color.UniqueCameraModel, len, ifp);
+ if (model[0])
+ break;
+ strncpy(make, imgdata.color.UniqueCameraModel,
+ MIN(len, sizeof(imgdata.color.UniqueCameraModel)));
+ if ((cp = strchr(make, ' ')))
+ {
+ strcpy(model, cp + 1);
+ *cp = 0;
+ }
+ break;
+ case 0xc616: /* 50710, CFAPlaneColor */
+ if (filters == 9)
+ break;
+ if (len > 4)
+ len = 4;
+ colors = len;
+ fread(cfa_pc, 1, colors, ifp);
+ guess_cfa_pc:
+ FORCC tab[cfa_pc[c]] = c;
+ cdesc[c] = 0;
+ for (i = 16; i--;)
+ filters = filters << 2 | tab[cfa_pat[i % plen]];
+ filters -= !filters;
+ tiff_ifd[ifd].t_filters = filters;
+ break;
+ case 0xc617: /* 50711, CFALayout */
+ if (get2() == 2)
+ tiff_ifd[ifd].t_fuji_width = fuji_width = 1;
+ break;
+ case 0x0123: // 291
+ case 0xc618: /* 50712, LinearizationTable */
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_LINTABLE;
+ tiff_ifd[ifd].lineartable_offset = ftell(ifp);
+ tiff_ifd[ifd].lineartable_len = len;
+ linear_table(len);
+ break;
+ case 0xc619: /* 50713, BlackLevelRepeatDim */
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK;
+ tiff_ifd[ifd].dng_levels.dng_fcblack[4] =
+ tiff_ifd[ifd].dng_levels.dng_cblack[4] = cblack[4] = get2();
+ tiff_ifd[ifd].dng_levels.dng_fcblack[5] =
+ tiff_ifd[ifd].dng_levels.dng_cblack[5] = cblack[5] = get2();
+ if (cblack[4] * cblack[5] >
+ (LIBRAW_CBLACK_SIZE -
+ 7)) // Use last cblack item as DNG black level count
+ tiff_ifd[ifd].dng_levels.dng_fcblack[4] =
+ tiff_ifd[ifd].dng_levels.dng_fcblack[5] =
+ tiff_ifd[ifd].dng_levels.dng_cblack[4] =
+ tiff_ifd[ifd].dng_levels.dng_cblack[5] = cblack[4] =
+ cblack[5] = 1;
+ break;
+
+ case 0xf00c:
+ if (imFuji.RAFDataGeneration != 4096)
+ {
+ unsigned fwb[4];
+ FORC4 fwb[c] = get4();
+ if (fwb[3] < 0x100)
+ {
+ FORC3 icWBC[fwb[3]][GRBG_2_RGBG(c)] = fwb[c];
+ icWBC[fwb[3]][3] = icWBC[fwb[3]][1];
+ if ((fwb[3] == 17) && // Tungsten WB
+ (libraw_internal_data.unpacker_data.lenRAFData > 3) &&
+ (libraw_internal_data.unpacker_data.lenRAFData < 10240000))
+ {
+ INT64 f_save = ftell(ifp);
+ rafdata = (ushort *)malloc(
+ sizeof(ushort) * libraw_internal_data.unpacker_data.lenRAFData);
+ fseek(ifp, libraw_internal_data.unpacker_data.posRAFData, SEEK_SET);
+ fread(rafdata, sizeof(ushort),
+ libraw_internal_data.unpacker_data.lenRAFData, ifp);
+ fseek(ifp, f_save, SEEK_SET);
+
+ uchar *PrivateMknBuf = (uchar *)rafdata;
+ int PrivateMknLength = libraw_internal_data.unpacker_data.lenRAFData
+ << 1;
+ for (int pos = 0; pos < PrivateMknLength - 16; pos++)
+ {
+ if (!memcmp(PrivateMknBuf + pos, "TSNERDTS", 8)) // STDRENST
+ {
+ imFuji.isTSNERDTS = 1;
+ break;
+ }
+ }
+ int fj; // 31? (fj<<1)-0x3c : 34? (fj<<1)-0x4e : undef
+ int is34 = 0;
+ if ((imFuji.RAFDataVersion == 0x0260) || // X-Pro3, GFX 100S
+ (imFuji.RAFDataVersion == 0x0261) || // X100V, GFX 50S II
+ (imFuji.RAFDataVersion == 0x0262) || // X-T4
+ (imFuji.RAFDataVersion == 0x0263) || // X-H2S
+ (imFuji.RAFDataVersion == 0x0264) || // X-S10
+ (imFuji.RAFDataVersion == 0x0265) || // X-E4
+ (imFuji.RAFDataVersion == 0x0266) || // X-T30 II
+ !strcmp(model, "X-Pro3") ||
+ !strcmp(model, "GFX 100S") ||
+ !strcmp(model, "GFX100S") ||
+ !strcmp(model, "GFX 50S II") ||
+ !strcmp(model, "GFX50S II") ||
+ !strcmp(model, "X100V") ||
+ !strcmp(model, "X-T4") ||
+ !strcmp(model, "X-H2S") ||
+ !strcmp(model, "X-E4") ||
+ !strcmp(model, "X-T30 II") ||
+ !strcmp(model, "X-S10"))
+// is34 cameras have 34 CCT values instead of 31, manual still claims 2500 to 10000 K
+// aligned 3000 K to Incandescent, as it is usual w/ other Fujifilm cameras
+ is34 = 1;
+
+ for (int fi = 0;
+ fi < int(libraw_internal_data.unpacker_data.lenRAFData - 3); fi++) // looking for Tungsten WB
+ {
+ if ((fwb[0] == rafdata[fi]) && (fwb[1] == rafdata[fi + 1]) &&
+ (fwb[2] == rafdata[fi + 2])) // found Tungsten WB
+ {
+ if (rafdata[fi - 15] !=
+ fwb[0]) // 15 is offset of Tungsten WB from the first
+ // preset, Fine Weather WB
+ continue;
+ for (int wb_ind = 0, ofst = fi - 15; wb_ind < (int)Fuji_wb_list1.size();
+ wb_ind++, ofst += 3)
+ {
+ icWBC[Fuji_wb_list1[wb_ind]][1] =
+ icWBC[Fuji_wb_list1[wb_ind]][3] = rafdata[ofst];
+ icWBC[Fuji_wb_list1[wb_ind]][0] = rafdata[ofst + 1];
+ icWBC[Fuji_wb_list1[wb_ind]][2] = rafdata[ofst + 2];
+ }
+
+ if (is34)
+ fi += 24;
+ fi += 96;
+ for (fj = fi; fj < (fi + 15); fj += 3) // looking for the end of the WB table
+ {
+ if (rafdata[fj] != rafdata[fi])
+ {
+ fj -= 93;
+ if (is34)
+ fj -= 9;
+// printf ("wb start in DNG: 0x%04x\n", fj*2-0x4e);
+ for (int iCCT = 0, ofst = fj; iCCT < 31;
+ iCCT++, ofst += 3)
+ {
+ icWBCCTC[iCCT][0] = FujiCCT_K[iCCT];
+ icWBCCTC[iCCT][1] = rafdata[ofst + 1];
+ icWBCCTC[iCCT][2] = icWBCCTC[iCCT][4] = rafdata[ofst];
+ icWBCCTC[iCCT][3] = rafdata[ofst + 2];
+ }
+ break;
+ }
+ }
+ free(rafdata);
+ break;
+ }
+ }
+ }
+ }
+ FORC4 fwb[c] = get4();
+ if (fwb[3] < 0x100) {
+ FORC3 icWBC[fwb[3]][GRBG_2_RGBG(c)] = fwb[c];
+ icWBC[fwb[3]][3] = icWBC[fwb[3]][1];
+ }
+ }
+ break;
+ case 0xf00d:
+ if (imFuji.RAFDataGeneration != 4096)
+ {
+ FORC3 icWBC[LIBRAW_WBI_Auto][GRBG_2_RGBG(c)] = getint(type);
+ icWBC[LIBRAW_WBI_Auto][3] = icWBC[LIBRAW_WBI_Auto][1];
+ }
+ break;
+ case 0xc615: /* 50709, LocalizedCameraModel */
+ stmread(imgdata.color.LocalizedCameraModel, len, ifp);
+ break;
+ case 0xf00a: // 61450
+ cblack[4] = cblack[5] = MIN(sqrt((double)len), 64);
+ case 0xc61a: /* 50714, BlackLevel */
+ if (tiff_ifd[ifd].samples > 1 &&
+ tiff_ifd[ifd].samples == (int)len) // LinearDNG, per-channel black
+ {
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK;
+ for (i = 0; i < 4 && i < (int)len; i++)
+ {
+ tiff_ifd[ifd].dng_levels.dng_fcblack[i] = getreal(type);
+ tiff_ifd[ifd].dng_levels.dng_cblack[i] = cblack[i] =
+ tiff_ifd[ifd].dng_levels.dng_fcblack[i] + 0.5;
+ }
+ // Record len in last cblack field
+ tiff_ifd[ifd].dng_levels.dng_cblack[LIBRAW_CBLACK_SIZE - 1] = len;
+
+ tiff_ifd[ifd].dng_levels.dng_fblack =
+ tiff_ifd[ifd].dng_levels.dng_black = black = 0;
+ }
+ else if (tiff_ifd[ifd].samples > 1 // Linear DNG w repeat dim
+ && (tiff_ifd[ifd].samples * cblack[4] * cblack[5] == len))
+ {
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK;
+ tiff_ifd[ifd].dng_levels.dng_cblack[LIBRAW_CBLACK_SIZE - 1] =
+ cblack[LIBRAW_CBLACK_SIZE - 1] = len;
+ for (i = 0; i < (int)len && i < LIBRAW_CBLACK_SIZE - 7; i++)
+ {
+ tiff_ifd[ifd].dng_levels.dng_fcblack[i + 6] = getreal(type);
+ tiff_ifd[ifd].dng_levels.dng_cblack[i + 6] = cblack[i + 6] =
+ tiff_ifd[ifd].dng_levels.dng_fcblack[i + 6] + 0.5;
+ }
+ }
+ else if ((cblack[4] * cblack[5] < 2) && len == 1)
+ {
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK;
+ tiff_ifd[ifd].dng_levels.dng_fblack = getreal(type);
+ black = tiff_ifd[ifd].dng_levels.dng_black =
+ tiff_ifd[ifd].dng_levels.dng_fblack;
+ }
+ else if (cblack[4] * cblack[5] <= len)
+ {
+ FORC(int(cblack[4] * cblack[5]))
+ {
+ tiff_ifd[ifd].dng_levels.dng_fcblack[6 + c] = getreal(type);
+ cblack[6 + c] = tiff_ifd[ifd].dng_levels.dng_fcblack[6 + c];
+ }
+ black = 0;
+ FORC4
+ cblack[c] = 0;
+
+ if (tag == 0xc61a)
+ {
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK;
+ FORC(int(cblack[4] * cblack[5]))
+ tiff_ifd[ifd].dng_levels.dng_cblack[6 + c] = cblack[6 + c];
+ tiff_ifd[ifd].dng_levels.dng_fblack = 0;
+ tiff_ifd[ifd].dng_levels.dng_black = 0;
+ FORC4
+ tiff_ifd[ifd].dng_levels.dng_fcblack[c] =
+ tiff_ifd[ifd].dng_levels.dng_cblack[c] = 0;
+ }
+ }
+ break;
+ case 0xc61b: /* 50715, BlackLevelDeltaH */
+ case 0xc61c: /* 50716, BlackLevelDeltaV */
+ for (num = i = 0; i < (int)len && i < 65536; i++)
+ num += getreal(type);
+ if (len > 0)
+ {
+ black += num / len + 0.5;
+ tiff_ifd[ifd].dng_levels.dng_fblack += num / float(len);
+ tiff_ifd[ifd].dng_levels.dng_black += num / len + 0.5;
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK;
+ }
+ break;
+ case 0xc61d: /* 50717, WhiteLevel */
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_WHITE;
+ tiff_ifd[ifd].dng_levels.dng_whitelevel[0] = maximum = getint(type);
+ if (tiff_ifd[ifd].samples > 1) // Linear DNG case
+ for (i = 1; i < 4 && i < (int)len; i++)
+ tiff_ifd[ifd].dng_levels.dng_whitelevel[i] = getint(type);
+ break;
+ case 0xc61e: /* DefaultScale */
+ {
+ float q1 = getreal(type);
+ float q2 = getreal(type);
+ if (q1 > 0.00001f && q2 > 0.00001f)
+ {
+ pixel_aspect = q1 / q2;
+ if (pixel_aspect > 0.995 && pixel_aspect < 1.005)
+ pixel_aspect = 1.0;
+ }
+ }
+ break;
+ case 0xc61f: /* 50719, DefaultCropOrigin */
+ if (len == 2)
+ {
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_CROPORIGIN;
+ tiff_ifd[ifd].dng_levels.default_crop[0] = getreal(type);
+ tiff_ifd[ifd].dng_levels.default_crop[1] = getreal(type);
+ if (!strncasecmp(make, "SONY", 4))
+ {
+ imgdata.sizes.raw_inset_crops[0].cleft =
+ tiff_ifd[ifd].dng_levels.default_crop[0];
+ imgdata.sizes.raw_inset_crops[0].ctop =
+ tiff_ifd[ifd].dng_levels.default_crop[1];
+ }
+ }
+ break;
+
+ case 0xc620: /* 50720, DefaultCropSize */
+ if (len == 2)
+ {
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_CROPSIZE;
+ tiff_ifd[ifd].dng_levels.default_crop[2] = getreal(type);
+ tiff_ifd[ifd].dng_levels.default_crop[3] = getreal(type);
+ if (!strncasecmp(make, "SONY", 4))
+ {
+ imgdata.sizes.raw_inset_crops[0].cwidth =
+ tiff_ifd[ifd].dng_levels.default_crop[2];
+ imgdata.sizes.raw_inset_crops[0].cheight =
+ tiff_ifd[ifd].dng_levels.default_crop[3];
+ }
+ }
+ break;
+
+ case 0xc7b5: /* 51125 DefaultUserCrop */
+ if (len == 4)
+ {
+ int cnt = 0;
+ FORC4
+ {
+ float v = getreal(type);
+ if (v >= 0.f && v <= 1.f)
+ {
+ tiff_ifd[ifd].dng_levels.user_crop[c] = v;
+ cnt++;
+ }
+ }
+ if(cnt == 4 // valid values
+ && tiff_ifd[ifd].dng_levels.user_crop[0] < tiff_ifd[ifd].dng_levels.user_crop[2] // top < bottom
+ && tiff_ifd[ifd].dng_levels.user_crop[1] < tiff_ifd[ifd].dng_levels.user_crop[3] // left < right
+ )
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_USERCROP;
+ }
+ break;
+ case 0x74c7:
+ if ((len == 2) && !strncasecmp(make, "SONY", 4))
+ {
+ imgdata.sizes.raw_inset_crops[0].cleft = get4();
+ imgdata.sizes.raw_inset_crops[0].ctop = get4();
+ }
+ break;
+
+ case 0x74c8:
+ if ((len == 2) && !strncasecmp(make, "SONY", 4))
+ {
+ imgdata.sizes.raw_inset_crops[0].cwidth = get4();
+ imgdata.sizes.raw_inset_crops[0].cheight = get4();
+ }
+ break;
+
+ case 0xc65a: // 50778
+ tiff_ifd[ifd].dng_color[0].illuminant = get2();
+ tiff_ifd[ifd].dng_color[0].parsedfields |= LIBRAW_DNGFM_ILLUMINANT;
+ break;
+ case 0xc65b: // 50779
+ tiff_ifd[ifd].dng_color[1].illuminant = get2();
+ tiff_ifd[ifd].dng_color[1].parsedfields |= LIBRAW_DNGFM_ILLUMINANT;
+ break;
+
+ case 0xc621: /* 50721, ColorMatrix1 */
+ case 0xc622: /* 50722, ColorMatrix2 */
+ {
+ int chan = (len == 9) ? 3 : (len == 12 ? 4 : 0);
+ i = tag == 0xc621 ? 0 : 1;
+ if (chan)
+ {
+ tiff_ifd[ifd].dng_color[i].parsedfields |= LIBRAW_DNGFM_COLORMATRIX;
+ imHassy.nIFD_CM[i] = ifd;
+ }
+ FORC(chan) for (j = 0; j < 3; j++)
+ {
+ tiff_ifd[ifd].dng_color[i].colormatrix[c][j] = cm[c][j] = getreal(type);
+ }
+ use_cm = 1;
+ }
+ break;
+
+ case 0xc714: /* ForwardMatrix1 */
+ case 0xc715: /* ForwardMatrix2 */
+ {
+ int chan = (len == 9) ? 3 : (len == 12 ? 4 : 0);
+ i = tag == 0xc714 ? 0 : 1;
+ if (chan)
+ tiff_ifd[ifd].dng_color[i].parsedfields |= LIBRAW_DNGFM_FORWARDMATRIX;
+ for (j = 0; j < 3; j++)
+ FORC(chan)
+ {
+ tiff_ifd[ifd].dng_color[i].forwardmatrix[j][c] = fm[j][c] =
+ getreal(type);
+ }
+ }
+ break;
+
+ case 0xc623: /* 50723, CameraCalibration1 */
+ case 0xc624: /* 50724, CameraCalibration2 */
+ {
+ int chan = (len == 9) ? 3 : (len == 16 ? 4 : 0);
+ j = tag == 0xc623 ? 0 : 1;
+ if (chan)
+ tiff_ifd[ifd].dng_color[j].parsedfields |= LIBRAW_DNGFM_CALIBRATION;
+ for (i = 0; i < chan; i++)
+ FORC(chan)
+ {
+ tiff_ifd[ifd].dng_color[j].calibration[i][c] = cc[i][c] =
+ getreal(type);
+ }
+ }
+ break;
+ case 0xc627: /* 50727, AnalogBalance */
+ if (len >= 3)
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_ANALOGBALANCE;
+ for (c = 0; c < (int)len && c < 4; c++)
+ {
+ tiff_ifd[ifd].dng_levels.analogbalance[c] = ab[c] = getreal(type);
+ }
+ break;
+ case 0xc628: /* 50728, AsShotNeutral */
+ if (len >= 3)
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_ASSHOTNEUTRAL;
+ for (c = 0; c < (int)len && c < 4; c++)
+ tiff_ifd[ifd].dng_levels.asshotneutral[c] = asn[c] = getreal(type);
+ break;
+ case 0xc629: /* 50729, AsShotWhiteXY */
+ xyz[0] = getreal(type);
+ xyz[1] = getreal(type);
+ xyz[2] = 1 - xyz[0] - xyz[1];
+ FORC3 xyz[c] /= LibRaw_constants::d65_white[c];
+ break;
+ case 0xc62a: /* DNG: 50730 BaselineExposure */
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BASELINEEXPOSURE;
+ tiff_ifd[ifd].dng_levels.baseline_exposure = getreal(type);
+ break;
+ case 0xc62e: /* DNG: 50734 LinearResponseLimit */
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_LINEARRESPONSELIMIT;
+ tiff_ifd[ifd].dng_levels.LinearResponseLimit = getreal(type);
+ break;
+
+ case 0xc634: /* 50740 : DNG Adobe, DNG Pentax, Sony SR2, DNG Private */
+ {
+ char mbuf[64];
+ INT64 curr_pos, start_pos = ftell(ifp);
+ unsigned MakN_order, m_sorder = order;
+ unsigned MakN_length;
+ unsigned pos_in_original_raw;
+ fread(mbuf, 1, 6, ifp);
+
+ if (!strcmp(mbuf, "Adobe"))
+ {
+ order = 0x4d4d; // Adobe header is always in "MM" / big endian
+ curr_pos = start_pos + 6;
+ while (curr_pos + 8 - start_pos <= len)
+ {
+ fread(mbuf, 1, 4, ifp);
+ curr_pos += 8;
+
+ if (!strncmp(mbuf, "Pano", 4))
+ { // PanasonicRaw, yes, they use "Pano" as signature
+ parseAdobePanoMakernote();
+ }
+
+ if (!strncmp(mbuf, "MakN", 4))
+ {
+ MakN_length = get4();
+ MakN_order = get2();
+ pos_in_original_raw = get4();
+ order = MakN_order;
+
+ INT64 save_pos = ifp->tell();
+ parse_makernote_0xc634(curr_pos + 6 - pos_in_original_raw, 0,
+ AdobeDNG);
+
+ curr_pos = save_pos + MakN_length - 6;
+ fseek(ifp, curr_pos, SEEK_SET);
+
+ fread(mbuf, 1, 4, ifp);
+ curr_pos += 8;
+
+ if (!strncmp(mbuf, "Pano ", 4))
+ {
+ parseAdobePanoMakernote();
+ }
+
+ if (!strncmp(mbuf, "RAF ", 4))
+ { // Fujifilm Raw, AdobeRAF
+ parseAdobeRAFMakernote();
+ }
+
+ if (!strncmp(mbuf, "SR2 ", 4))
+ {
+ order = 0x4d4d;
+ MakN_length = get4();
+ MakN_order = get2();
+ pos_in_original_raw = get4();
+ order = MakN_order;
+
+ unsigned *buf_SR2;
+ unsigned SR2SubIFDOffset = 0;
+ unsigned SR2SubIFDLength = 0;
+ unsigned SR2SubIFDKey = 0;
+ {
+ int _base = curr_pos + 6 - pos_in_original_raw;
+ unsigned _entries, _tag, _type, _len, _save;
+ _entries = get2();
+ while (_entries--)
+ {
+ tiff_get(_base, &_tag, &_type, &_len, &_save);
+
+ if (_tag == 0x7200)
+ {
+ SR2SubIFDOffset = get4();
+ }
+ else if (_tag == 0x7201)
+ {
+ SR2SubIFDLength = get4();
+ }
+ else if (_tag == 0x7221)
+ {
+ SR2SubIFDKey = get4();
+ }
+ fseek(ifp, _save, SEEK_SET);
+ }
+ }
+
+ if (SR2SubIFDLength && (SR2SubIFDLength < 10240000) &&
+ (buf_SR2 = (unsigned *)malloc(SR2SubIFDLength + 1024)))
+ { // 1024b for safety
+ fseek(ifp, SR2SubIFDOffset + base, SEEK_SET);
+ fread(buf_SR2, SR2SubIFDLength, 1, ifp);
+ sony_decrypt(buf_SR2, SR2SubIFDLength / 4, 1, SR2SubIFDKey);
+ parseSonySR2((uchar *)buf_SR2, SR2SubIFDOffset,
+ SR2SubIFDLength, AdobeDNG);
+
+ free(buf_SR2);
+ }
+
+ } /* SR2 processed */
+ break;
+ }
+ }
+ }
+ else
+ {
+ fread(mbuf + 6, 1, 2, ifp);
+ if (!strcmp(mbuf, "RICOH") && ((sget2((uchar *)mbuf + 6) == 0x4949) ||
+ (sget2((uchar *)mbuf + 6) == 0x4d4d)))
+ {
+ is_PentaxRicohMakernotes = 1;
+ }
+ if (!strcmp(mbuf, "PENTAX ") || !strcmp(mbuf, "SAMSUNG") ||
+ is_PentaxRicohMakernotes)
+ {
+ fseek(ifp, start_pos, SEEK_SET);
+ parse_makernote_0xc634(base, 0, CameraDNG);
+ }
+ }
+ fseek(ifp, start_pos, SEEK_SET);
+ order = m_sorder;
+ }
+ if (dng_version)
+ {
+ break;
+ }
+ parse_minolta(j = get4() + base);
+ fseek(ifp, j, SEEK_SET);
+ parse_tiff_ifd(base);
+ break;
+ case 0xc640: // 50752
+ read_shorts(cr2_slice, 3);
+ break;
+ case 0xc68b: /* 50827, OriginalRawFileName */
+ stmread(imgdata.color.OriginalRawFileName, len, ifp);
+ break;
+ case 0xc68d: /* 50829 ActiveArea */
+ tiff_ifd[ifd].t_tm = top_margin = getint(type);
+ tiff_ifd[ifd].t_lm = left_margin = getint(type);
+ tiff_ifd[ifd].t_vheight = height = getint(type) - top_margin;
+ tiff_ifd[ifd].t_vwidth = width = getint(type) - left_margin;
+ break;
+ case 0xc68e: /* 50830 MaskedAreas */
+ for (i = 0; i < (int)len && i < 32; i++)
+ ((int *)mask)[i] = getint(type);
+ black = 0;
+ break;
+ case 0xc71a: /* 50970, PreviewColorSpace */
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_PREVIEWCS;
+ tiff_ifd[ifd].dng_levels.preview_colorspace = getint(type);
+ break;
+ case 0xc740: /* 51008, OpcodeList1 */
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_OPCODE1;
+ break;
+ case 0xc741: /* 51009, OpcodeList2 */
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_OPCODE2;
+ tiff_ifd[ifd].opcode2_offset = meta_offset = ftell(ifp);
+ break;
+ case 0xc74e: /* 51022, OpcodeList3 */
+ tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_OPCODE3;
+ break;
+ case 0xfd04: /* 64772, Kodak P-series */
+ if (len < 13)
+ break;
+ fseek(ifp, 16, SEEK_CUR);
+ data_offset = get4();
+ fseek(ifp, 28, SEEK_CUR);
+ data_offset += get4();
+ load_raw = &LibRaw::packed_load_raw;
+ break;
+ case 0xfe02: // 65026
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII))
+ fgets(model2, 64, ifp);
+ }
+ fseek(ifp, save, SEEK_SET);
+ }
+ if (sony_length && sony_length < 10240000 &&
+ (buf = (unsigned *)malloc(sony_length)))
+ {
+ fseek(ifp, sony_offset, SEEK_SET);
+ fread(buf, sony_length, 1, ifp);
+ sony_decrypt(buf, sony_length / 4, 1, sony_key);
+ parseSonySR2((uchar *)buf, sony_offset, sony_length, nonDNG);
+ free(buf);
+ }
+ for (i = 0; i < colors && i < 4; i++)
+ FORCC cc[i][c] *= ab[i];
+ if (use_cm)
+ {
+ FORCC for (i = 0; i < 3; i++) for (cam_xyz[c][i] = j = 0; j < colors; j++)
+ cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i];
+ cam_xyz_coeff(cmatrix, cam_xyz);
+ }
+ if (asn[0])
+ {
+ cam_mul[3] = 0;
+ FORCC
+ if (fabs(asn[c]) > 0.0001)
+ cam_mul[c] = 1 / asn[c];
+ }
+ if (!use_cm)
+ FORCC if (fabs(cc[c][c]) > 0.0001) pre_mul[c] /= cc[c][c];
+ return 0;
+}
+
+int LibRaw::parse_tiff(int _base)
+{
+ INT64 base = _base;
+ int doff;
+ fseek(ifp, base, SEEK_SET);
+ order = get2();
+ if (order != 0x4949 && order != 0x4d4d)
+ return 0;
+ get2();
+ while ((doff = get4()))
+ {
+ INT64 doff64 = doff;
+ if (doff64 + base > ifp->size()) break;
+ fseek(ifp, doff64 + base, SEEK_SET);
+ if (parse_tiff_ifd(_base))
+ break;
+ }
+ return 1;
+}
+
+struct ifd_size_t
+{
+ int ifdi;
+ INT64 databits;
+};
+
+int ifd_size_t_cmp(const void *a, const void *b)
+{
+ if (!a || !b)
+ return 0;
+ const ifd_size_t *ai = (ifd_size_t *)a;
+ const ifd_size_t *bi = (ifd_size_t *)b;
+ return bi->databits > ai->databits ? 1
+ : (bi->databits < ai->databits ? -1 : 0);
+}
+
+static LibRaw_internal_thumbnail_formats tiff2thumbformat(int _comp, int _phint, int _bps, const char *_make);
+
+void LibRaw::apply_tiff()
+{
+ int max_samp = 0, ties = 0, raw = -1, thm = -1, i;
+ unsigned long long ns, os;
+ struct jhead jh;
+
+ thumb_misc = 16;
+ if (thumb_offset)
+ {
+ fseek(ifp, thumb_offset, SEEK_SET);
+ if (ljpeg_start(&jh, 1))
+ {
+ if ((unsigned)jh.bits < 17 && (unsigned)jh.wide < 0x10000 &&
+ (unsigned)jh.high < 0x10000)
+ {
+ thumb_misc = jh.bits;
+ thumb_width = jh.wide;
+ thumb_height = jh.high;
+ }
+ }
+ }
+ for (i = tiff_nifds; i--;)
+ {
+ if (tiff_ifd[i].t_shutter)
+ shutter = tiff_ifd[i].t_shutter;
+ tiff_ifd[i].t_shutter = shutter;
+ }
+
+ if (dng_version)
+ {
+ int ifdc = 0;
+ for (i = 0; i < (int)tiff_nifds; i++)
+ {
+ if (tiff_ifd[i].t_width < 1 || tiff_ifd[i].t_width > 65535 ||
+ tiff_ifd[i].t_height < 1 || tiff_ifd[i].t_height > 65535)
+ continue; /* wrong image dimensions */
+
+ int samp = tiff_ifd[i].samples;
+ if (samp == 2)
+ samp = 1; // Fuji 2-frame
+ max_samp = LIM(MAX(max_samp, samp), 1,
+ 3); // max_samp is needed for thumbnail selection below
+
+ if ( // Check phint only for RAW subfiletype
+ (tiff_ifd[i].newsubfiletype == 16
+ || tiff_ifd[i].newsubfiletype == 0
+ || (tiff_ifd[i].newsubfiletype & 0xffff) == 1)
+ &&
+ (tiff_ifd[i].phint != 32803 && tiff_ifd[i].phint != 34892)
+ )
+ continue;
+
+ if ((tiff_ifd[i].newsubfiletype == 0) // main image
+ // Enhanced demosaiced:
+ || (tiff_ifd[i].newsubfiletype == 16 &&
+ (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_ADD_ENHANCED))
+ // Preview: 0x1 or 0x10001
+ || ((tiff_ifd[i].newsubfiletype & 0xffff) == 1 &&
+ (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_ADD_PREVIEWS))
+ // Transparency mask: 0x4
+ || ((tiff_ifd[i].newsubfiletype & 0xffff) == 4 &&
+ (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_ADD_MASKS)))
+ {
+ // Add this IFD to dng_frames
+ libraw_internal_data.unpacker_data.dng_frames[ifdc] =
+ ((tiff_ifd[i].newsubfiletype & 0xffff) << 16) | ((i << 8) & 0xff00);
+ ifdc++;
+ // Fuji SuperCCD: second frame:
+ if ((tiff_ifd[i].newsubfiletype == 0) && tiff_ifd[i].samples == 2)
+ {
+ libraw_internal_data.unpacker_data.dng_frames[ifdc] =
+ ((tiff_ifd[i].newsubfiletype & 0xffff) << 16) |
+ ((i << 8) & 0xff00) | 1;
+ ifdc++;
+ }
+ }
+ }
+ if (ifdc)
+ {
+ if (ifdc > 1 && (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_PREFER_LARGEST_IMAGE))
+ {
+ ifd_size_t arr[LIBRAW_IFD_MAXCOUNT * 2];
+ memset(arr, 0, sizeof(arr));
+ for (int q = 0; q < ifdc && q < LIBRAW_IFD_MAXCOUNT * 2; q++)
+ {
+ int ifdidx =
+ (libraw_internal_data.unpacker_data.dng_frames[q] >> 8) & 0xff;
+ arr[q].ifdi = libraw_internal_data.unpacker_data.dng_frames[q];
+ arr[q].databits =
+ tiff_ifd[ifdidx].t_width * tiff_ifd[ifdidx].t_height *
+ tiff_ifd[ifdidx].samples * tiff_ifd[ifdidx].bps +
+ (0x100 -
+ (arr[q].ifdi & 0xff)); // add inverted frame # to ensure same
+ // sort order for similar sized frames.
+ if (tiff_ifd[ifdidx].phint == 4)
+ arr[q].databits /= 4; // Force lower bit count for Transp. mask images
+ }
+ qsort(arr, MIN(ifdc, LIBRAW_IFD_MAXCOUNT * 2), sizeof(arr[0]),
+ ifd_size_t_cmp);
+ for (int q = 0; q < ifdc && q < LIBRAW_IFD_MAXCOUNT * 2; q++)
+ libraw_internal_data.unpacker_data.dng_frames[q] = arr[q].ifdi;
+ }
+
+ int idx = LIM((int)shot_select, 0, ifdc - 1);
+ i = (libraw_internal_data.unpacker_data.dng_frames[idx] >> 8) &
+ 0xff; // extract frame# back
+
+ raw_width = tiff_ifd[i].t_width;
+ raw_height = tiff_ifd[i].t_height;
+ tiff_bps = tiff_ifd[i].bps;
+ tiff_compress = tiff_ifd[i].comp;
+ tiff_sampleformat = tiff_ifd[i].sample_format;
+ data_offset = tiff_ifd[i].offset;
+ data_size = tiff_ifd[i].bytes;
+ tiff_flip = tiff_ifd[i].t_flip;
+ tiff_samples = tiff_ifd[i].samples;
+ tile_width = tiff_ifd[i].t_tile_width;
+ tile_length = tiff_ifd[i].t_tile_length;
+ fuji_width = tiff_ifd[i].t_fuji_width;
+ if (tiff_samples != 2) /* special case: Fuji SuperCCD */
+ {
+ if (tiff_ifd[i].phint == 34892)
+ filters = 0;
+ else if (i > 0 && tiff_ifd[i].phint == 32803 &&
+ tiff_ifd[0].phint == 32803 && !tiff_ifd[i].t_filters &&
+ tiff_ifd[0].t_filters)
+ filters = tiff_ifd[0].t_filters;
+ else
+ filters = tiff_ifd[i].t_filters;
+ width = tiff_ifd[i].t_vwidth;
+ height = tiff_ifd[i].t_vheight;
+ top_margin = tiff_ifd[i].t_tm;
+ left_margin = tiff_ifd[i].t_lm;
+ shutter = tiff_ifd[i].t_shutter;
+ if (tiff_ifd[i].dng_levels.dng_whitelevel[0])
+ maximum = tiff_ifd[i].dng_levels.dng_whitelevel[0];
+ else if (tiff_ifd[i].sample_format <= 2 && tiff_bps > 0 &&
+ tiff_bps < 32) // SampleFormat: 0-default(1), 1 - Uint, 2 - Int
+ maximum = (1 << tiff_bps) - 1;
+ else if (tiff_ifd[i].sample_format == 3)
+ maximum = 1; // Defaults for FP
+ }
+ raw = i;
+ is_raw = ifdc;
+ }
+ else
+ is_raw = 0;
+ }
+ else
+ {
+ // Fix for broken Sony bps tag
+ if (!strncasecmp(make, "Sony", 4))
+ {
+ for (i = 0; i < (int)tiff_nifds; i++)
+ {
+ if (tiff_ifd[i].bps > 33 && tiff_ifd[i].samples == 1)
+ {
+ int bps = 14; // default
+ if (tiff_ifd[i].dng_levels.dng_whitelevel[0] > 0)
+ {
+ for(int c = 0,j=1; c < 16; c++, j<<=1)
+ if (j > (int)tiff_ifd[i].dng_levels.dng_whitelevel[0])
+ {
+ bps = c; break;
+ }
+ }
+ tiff_ifd[i].bps = bps;
+ }
+ }
+ }
+
+ for (i = 0; i < (int)tiff_nifds; i++)
+ {
+ if (tiff_ifd[i].t_width < 1 || tiff_ifd[i].t_width > 65535 ||
+ tiff_ifd[i].t_height < 1 || tiff_ifd[i].t_height > 65535)
+ continue; /* wrong image dimensions */
+ if (max_samp < tiff_ifd[i].samples)
+ max_samp = tiff_ifd[i].samples;
+ if (max_samp > 3)
+ max_samp = 3;
+
+ os = unsigned(raw_width) * unsigned(raw_height);
+ ns = unsigned(tiff_ifd[i].t_width) * unsigned(tiff_ifd[i].t_height);
+ if (tiff_bps)
+ {
+ os *= tiff_bps;
+ ns *= tiff_ifd[i].bps;
+ }
+ /* too complex if below, so separate if to skip RGB+Alpha TIFFs*/
+ if (tiff_ifd[i].phint == 2 && tiff_ifd[i].extrasamples > 0 && tiff_ifd[i].samples > 3)
+ continue; // SKIP RGB+Alpha IFDs
+
+ if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) &&
+ unsigned(tiff_ifd[i].t_width | tiff_ifd[i].t_height) < 0x10000 &&
+ (unsigned)tiff_ifd[i].bps < 33 &&
+ (unsigned)tiff_ifd[i].samples < 13 && ns &&
+ ((ns > os && (ties = 1)) || (ns == os && (int)shot_select == ties++)))
+ {
+ raw_width = tiff_ifd[i].t_width;
+ raw_height = tiff_ifd[i].t_height;
+ tiff_bps = tiff_ifd[i].bps;
+ tiff_compress = tiff_ifd[i].comp;
+ tiff_sampleformat = tiff_ifd[i].sample_format;
+ data_offset = tiff_ifd[i].offset;
+ data_size = tiff_ifd[i].bytes;
+ tiff_flip = tiff_ifd[i].t_flip;
+ tiff_samples = tiff_ifd[i].samples;
+ tile_width = tiff_ifd[i].t_tile_width;
+ tile_length = tiff_ifd[i].t_tile_length;
+ shutter = tiff_ifd[i].t_shutter;
+ raw = i;
+ }
+ }
+ if (is_raw == 1 && ties)
+ is_raw = ties;
+ }
+ if (is_NikonTransfer && raw >= 0)
+ {
+ if (tiff_ifd[raw].bps == 16)
+ {
+ if (tiff_compress == 1)
+ {
+ if ((raw_width * raw_height * 3) == (tiff_ifd[raw].bytes << 1))
+ {
+ tiff_bps = tiff_ifd[raw].bps = 12;
+ }
+ else
+ {
+ tiff_bps = tiff_ifd[raw].bps = 14;
+ }
+ }
+ }
+ else if (tiff_ifd[raw].bps == 8)
+ {
+ if (tiff_compress == 1)
+ {
+ is_NikonTransfer = 2; // 8-bit debayered TIFF, like CoolScan NEFs
+ imgdata.rawparams.coolscan_nef_gamma = 2.2f;
+ }
+ }
+ }
+
+ if (!tile_width)
+ tile_width = INT_MAX;
+ if (!tile_length)
+ tile_length = INT_MAX;
+ for (i = tiff_nifds; i--;)
+ if (tiff_ifd[i].t_flip)
+ tiff_flip = tiff_ifd[i].t_flip;
+
+#if 0
+ if (raw < 0 && is_raw)
+ is_raw = 0;
+#endif
+
+ if (raw >= 0 && !load_raw)
+ switch (tiff_compress)
+ {
+ case 32767:
+ if (!dng_version &&
+ INT64(tiff_ifd[raw].bytes) == INT64(raw_width) * INT64(raw_height))
+ {
+ tiff_bps = 14;
+ load_raw = &LibRaw::sony_arw2_load_raw;
+ break;
+ }
+ if (!dng_version && !strncasecmp(make, "Sony", 4) &&
+ INT64(tiff_ifd[raw].bytes) ==
+ INT64(raw_width) * INT64(raw_height) * 2LL)
+ {
+ tiff_bps = 14;
+ load_raw = &LibRaw::unpacked_load_raw;
+ break;
+ }
+ if (INT64(tiff_ifd[raw].bytes) * 8LL !=
+ INT64(raw_width) * INT64(raw_height) * INT64(tiff_bps))
+ {
+ raw_height += 8;
+ load_raw = &LibRaw::sony_arw_load_raw;
+ break;
+ }
+ load_flags = 79;
+ case 32769:
+ load_flags++;
+ case 32770:
+ case 32773:
+ goto slr;
+ case 0:
+ case 1:
+ if (dng_version && tiff_sampleformat == 3 &&
+ (tiff_bps > 8 && (tiff_bps % 8 == 0) && (tiff_bps <= 32))) // only 16,24, and 32 are allowed
+ {
+ load_raw = &LibRaw::uncompressed_fp_dng_load_raw;
+ break;
+ }
+ // Sony 14-bit uncompressed
+ if (!dng_version && !strncasecmp(make, "Sony", 4) &&
+ INT64(tiff_ifd[raw].bytes) ==
+ INT64(raw_width) * INT64(raw_height) * 2LL)
+ {
+ tiff_bps = 14;
+ load_raw = &LibRaw::unpacked_load_raw;
+ break;
+ }
+ if (!dng_version && !strncasecmp(make, "Sony", 4) &&
+ tiff_ifd[raw].samples == 4 &&
+ INT64(tiff_ifd[raw].bytes) ==
+ INT64(raw_width) * INT64(raw_height) * 8LL) // Sony ARQ
+ {
+ // maybe to detect ARQ with the following:
+ // if (tiff_ifd[raw].phint == 32892)
+ tiff_bps = 14;
+ tiff_samples = 4;
+ load_raw = &LibRaw::sony_arq_load_raw;
+ filters = 0;
+ strcpy(cdesc, "RGBG");
+ break;
+ }
+ if (!strncasecmp(make, "Nikon", 5) &&
+ (!strncmp(software, "Nikon Scan", 10) || (is_NikonTransfer == 2) ||
+ strcasestr(model, "COOLSCAN")))
+ {
+ load_raw = &LibRaw::nikon_coolscan_load_raw;
+ raw_color = 1;
+ colors = (tiff_samples == 3) ? 3 : 1;
+ filters = 0;
+ break;
+ }
+ if ((!strncmp(make, "OLYMPUS", 7) || !strncmp(make, "OM Digi", 7) ||
+ (!strncasecmp(make, "CLAUSS", 6) &&
+ !strncasecmp(model, "piX 5oo", 7))) && // 0x5330303539 works here
+ (INT64(tiff_ifd[raw].bytes) * 2ULL ==
+ INT64(raw_width) * INT64(raw_height) * 3ULL))
+ load_flags = 24;
+ if (!dng_version && INT64(tiff_ifd[raw].bytes) * 5ULL ==
+ INT64(raw_width) * INT64(raw_height) * 8ULL)
+ {
+ load_flags = 81;
+ tiff_bps = 12;
+ }
+ slr:
+ switch (tiff_bps)
+ {
+ case 8:
+ load_raw = &LibRaw::eight_bit_load_raw;
+ break;
+ case 12:
+ if (tiff_ifd[raw].phint == 2)
+ load_flags = 6;
+ if (!strncasecmp(make, "NIKON", 5) &&
+ !strncasecmp(model, "COOLPIX A1000", 13) &&
+ data_size == raw_width * raw_height * 2u)
+ load_raw = &LibRaw::unpacked_load_raw;
+ else
+ load_raw = &LibRaw::packed_load_raw;
+ break;
+ case 14:
+ load_flags = 0;
+ case 16:
+ load_raw = &LibRaw::unpacked_load_raw;
+ if ((!strncmp(make, "OLYMPUS", 7) || !strncmp(make, "OM Digi", 7) ||
+ (!strncasecmp(make, "CLAUSS", 6) &&
+ !strncasecmp(model, "piX 5oo", 7))) && // 0x5330303539 works here
+ (INT64(tiff_ifd[raw].bytes) * 7LL >
+ INT64(raw_width) * INT64(raw_height)))
+ load_raw = &LibRaw::olympus_load_raw;
+ }
+ break;
+ case 6:
+ case 7:
+ case 99:
+ if (!dng_version && tiff_compress == 6 && !strcasecmp(make, "SONY"))
+ load_raw = &LibRaw::sony_ljpeg_load_raw;
+ else
+ load_raw = &LibRaw::lossless_jpeg_load_raw;
+ break;
+ case 262:
+ load_raw = &LibRaw::kodak_262_load_raw;
+ break;
+ case 34713:
+ if ((INT64(raw_width) + 9LL) / 10LL * 16LL * INT64(raw_height) ==
+ INT64(tiff_ifd[raw].bytes))
+ {
+ load_raw = &LibRaw::packed_load_raw;
+ load_flags = 1;
+ }
+ else if (INT64(raw_width) * INT64(raw_height) * 3LL ==
+ INT64(tiff_ifd[raw].bytes) * 2LL)
+ {
+ load_raw = &LibRaw::packed_load_raw;
+ if (model[0] == 'N')
+ load_flags = 80;
+ }
+ else if (INT64(raw_width) * INT64(raw_height) * 3LL ==
+ INT64(tiff_ifd[raw].bytes))
+ {
+ load_raw = &LibRaw::nikon_yuv_load_raw;
+ gamma_curve(1 / 2.4, 12.92, 1, 4095);
+ memset(cblack, 0, sizeof cblack);
+ filters = 0;
+ }
+ else if (INT64(raw_width) * INT64(raw_height) * 2LL ==
+ INT64(tiff_ifd[raw].bytes))
+ {
+ load_raw = &LibRaw::unpacked_load_raw;
+ load_flags = 4;
+ order = 0x4d4d;
+ }
+#if 0 /* Never used because of same condition above, but need to recheck */
+ else if (INT64(raw_width) * INT64(raw_height) * 3LL ==
+ INT64(tiff_ifd[raw].bytes) * 2LL)
+ {
+ load_raw = &LibRaw::packed_load_raw;
+ load_flags = 80;
+ }
+#endif
+ else if (tiff_ifd[raw].rows_per_strip &&
+ tiff_ifd[raw].strip_offsets_count &&
+ tiff_ifd[raw].strip_offsets_count ==
+ tiff_ifd[raw].strip_byte_counts_count)
+ {
+ int fit = 1;
+ for (int q = 0; q < tiff_ifd[raw].strip_byte_counts_count - 1;
+ q++) // all but last
+ if (INT64(tiff_ifd[raw].strip_byte_counts[q]) * 2LL !=
+ INT64(tiff_ifd[raw].rows_per_strip) * INT64(raw_width) * 3LL)
+ {
+ fit = 0;
+ break;
+ }
+ if (fit)
+ load_raw = &LibRaw::nikon_load_striped_packed_raw;
+ else
+ load_raw = &LibRaw::nikon_load_raw; // fallback
+ }
+ else if ((((INT64(raw_width) * 3LL / 2LL) + 15LL) / 16LL) * 16LL *
+ INT64(raw_height) ==
+ INT64(tiff_ifd[raw].bytes))
+ {
+ load_raw = &LibRaw::nikon_load_padded_packed_raw;
+ load_flags = (((INT64(raw_width) * 3ULL / 2ULL) + 15ULL) / 16ULL) *
+ 16ULL; // bytes per row
+ }
+ else if (!strncmp(model, "NIKON Z 9", 9) && tiff_ifd[raw].offset)
+ {
+ INT64 pos = ftell(ifp);
+ unsigned char cmp[] = "CONTACT_INTOPIX"; // 15
+ unsigned char buf[16];
+ fseek(ifp, INT64(tiff_ifd[raw].offset) + 6LL, SEEK_SET);
+ fread(buf, 1, 16, ifp);
+ fseek(ifp, pos, SEEK_SET);
+ if(!memcmp(buf,cmp,15))
+ load_raw = &LibRaw::nikon_he_load_raw_placeholder;
+ else
+ load_raw = &LibRaw::nikon_load_raw;
+ }
+ else
+ load_raw = &LibRaw::nikon_load_raw;
+ break;
+ case 65535:
+ load_raw = &LibRaw::pentax_load_raw;
+ break;
+ case 65000:
+ switch (tiff_ifd[raw].phint)
+ {
+ case 2:
+ load_raw = &LibRaw::kodak_rgb_load_raw;
+ filters = 0;
+ break;
+ case 6:
+ load_raw = &LibRaw::kodak_ycbcr_load_raw;
+ filters = 0;
+ break;
+ case 32803:
+ load_raw = &LibRaw::kodak_65000_load_raw;
+ }
+ case 32867:
+ case 34892:
+ break;
+ case 8:
+ break;
+#ifdef USE_GPRSDK
+ case 9:
+ if (dng_version)
+ break; /* Compression=9 supported for dng if we compiled with GPR SDK */
+ /* Else: fallthrough */
+#endif
+ default:
+ is_raw = 0;
+ }
+ if (!dng_version)
+ {
+ if (((tiff_samples == 3 && tiff_ifd[raw].bytes &&
+ !(tiff_bps == 16 &&
+ !strncmp(make, "Leaf", 4)) && // Allow Leaf/16bit/3color files
+ tiff_bps != 14 &&
+ (tiff_compress & -16) != 32768) ||
+ (tiff_bps == 8 && strncmp(make, "Phase", 5) &&
+ strncmp(make, "Leaf", 4) && !strcasestr(make, "Kodak") &&
+ !strstr(model2, "DEBUG RAW"))) &&
+ !strcasestr(model, "COOLSCAN") && strncmp(software, "Nikon Scan", 10) &&
+ is_NikonTransfer != 2)
+ is_raw = 0;
+
+ if (is_raw && raw >= 0 && tiff_ifd[raw].phint == 2 && tiff_ifd[raw].extrasamples > 0 && tiff_ifd[raw].samples > 3)
+ is_raw = 0; // SKIP RGB+Alpha IFDs
+ }
+
+ INT64 fsizecheck = 0ULL;
+
+ if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CHECK_THUMBNAILS_ALL_VENDORS)
+ fsizecheck = ifp->size();
+ else if ((imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CHECK_THUMBNAILS_KNOWN_VENDORS)
+ && !strncasecmp(make,"Ricoh",5))
+ fsizecheck = ifp->size();
+
+ for (i = 0; i < (int)tiff_nifds; i++)
+ if (i != raw &&
+ (tiff_ifd[i].samples == max_samp ||
+ (tiff_ifd[i].comp == 7 &&
+ tiff_ifd[i].samples == 1)) /* Allow 1-bps JPEGs */
+ && tiff_ifd[i].bps > 0 && tiff_ifd[i].bps < 33 &&
+ tiff_ifd[i].phint != 32803 && tiff_ifd[i].phint != 34892 &&
+ unsigned(tiff_ifd[i].t_width | tiff_ifd[i].t_height) < 0x10000 &&
+ tiff_ifd[i].comp != 34892)
+ {
+ if (fsizecheck > 0LL)
+ {
+ bool ok = true;
+ if (tiff_ifd[i].strip_byte_counts_count && tiff_ifd[i].strip_offsets_count)
+ for (int s = 0; s < MIN(tiff_ifd[i].strip_byte_counts_count, tiff_ifd[i].strip_offsets_count); s++)
+ {
+ if (tiff_ifd[i].strip_offsets[s] + tiff_ifd[i].strip_byte_counts[s] > fsizecheck)
+ {
+ ok = false;
+ break;
+ }
+ }
+ else if (tiff_ifd[i].bytes > 0)
+ if (tiff_ifd[i].offset + tiff_ifd[i].bytes > fsizecheck)
+ ok = false;
+
+ if(!ok)
+ continue;
+ }
+ if ( (INT64(tiff_ifd[i].t_width) * INT64(tiff_ifd[i].t_height) / INT64(SQR(tiff_ifd[i].bps) + 1)) >
+ (INT64(thumb_width) * INT64(thumb_height) / INT64(SQR(thumb_misc) + 1)) )
+ {
+
+ thumb_width = tiff_ifd[i].t_width;
+ thumb_height = tiff_ifd[i].t_height;
+ thumb_offset = tiff_ifd[i].offset;
+ thumb_length = tiff_ifd[i].bytes;
+ thumb_misc = tiff_ifd[i].bps;
+ thm = i;
+ }
+ if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT && tiff_ifd[i].bytes > 0)
+ {
+ bool already = false;
+ for(int idx = 0; idx < imgdata.thumbs_list.thumbcount ; idx++)
+ if (imgdata.thumbs_list.thumblist[idx].toffset == tiff_ifd[i].offset)
+ {
+ already = true;
+ break;
+ }
+ if (!already)
+ {
+ int idx = imgdata.thumbs_list.thumbcount;
+ imgdata.thumbs_list.thumblist[idx].tformat = tiff2thumbformat(tiff_ifd[i].comp, tiff_ifd[i].phint,
+ tiff_ifd[i].bps, make);
+ imgdata.thumbs_list.thumblist[idx].twidth = tiff_ifd[i].t_width;
+ imgdata.thumbs_list.thumblist[idx].theight = tiff_ifd[i].t_height;
+ imgdata.thumbs_list.thumblist[idx].tflip = tiff_ifd[i].t_flip;
+ imgdata.thumbs_list.thumblist[idx].tlength = tiff_ifd[i].bytes;
+ imgdata.thumbs_list.thumblist[idx].tmisc = tiff_ifd[i].bps | (tiff_ifd[i].samples << 5);
+ imgdata.thumbs_list.thumblist[idx].toffset = tiff_ifd[i].offset;
+ imgdata.thumbs_list.thumbcount++;
+ }
+ }
+ }
+ if (thm >= 0)
+ {
+ thumb_misc |= tiff_ifd[thm].samples << 5;
+ thumb_format = tiff2thumbformat(tiff_ifd[thm].comp, tiff_ifd[thm].phint, tiff_ifd[thm].bps, make);
+ }
+}
+
+static LibRaw_internal_thumbnail_formats tiff2thumbformat(int _comp, int _phint, int _bps, const char *_make)
+{
+ switch (_comp)
+ {
+ case 0:
+ return LIBRAW_INTERNAL_THUMBNAIL_LAYER;
+ case 1:
+ if (_bps <= 8)
+ return LIBRAW_INTERNAL_THUMBNAIL_PPM;
+ else if (!strncmp(_make, "Imacon", 6))
+ return LIBRAW_INTERNAL_THUMBNAIL_PPM16;
+ else
+ return LIBRAW_INTERNAL_THUMBNAIL_KODAK_THUMB;
+ case 65000:
+ return _phint == 6 ? LIBRAW_INTERNAL_THUMBNAIL_KODAK_YCBCR : LIBRAW_INTERNAL_THUMBNAIL_KODAK_RGB;
+ }
+ return LIBRAW_INTERNAL_THUMBNAIL_JPEG; // default
+}
diff --git a/libkdcraw/libraw/src/postprocessing/aspect_ratio.cpp b/libkdcraw/libraw/src/postprocessing/aspect_ratio.cpp
new file mode 100644
index 0000000..7e0dfd0
--- /dev/null
+++ b/libkdcraw/libraw/src/postprocessing/aspect_ratio.cpp
@@ -0,0 +1,113 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::fuji_rotate()
+{
+ int i, row, col;
+ double step;
+ float r, c, fr, fc;
+ unsigned ur, uc;
+ ushort wide, high, (*img)[4], (*pix)[4];
+
+ if (!fuji_width)
+ return;
+ fuji_width = (fuji_width - 1 + shrink) >> shrink;
+ step = sqrt(0.5);
+ wide = fuji_width / step;
+ high = (height - fuji_width) / step;
+
+ // All real fuji/rotated images are small, so check against max_raw_memory_mb here is safe
+ if (INT64(wide) * INT64(high) * INT64(sizeof(*img)) >
+ INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_TOOBIG;
+
+ img = (ushort(*)[4])calloc(high, wide * sizeof *img);
+
+ RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE, 0, 2);
+
+ for (row = 0; row < high; row++)
+ for (col = 0; col < wide; col++)
+ {
+ ur = r = fuji_width + (row - col) * step;
+ uc = c = (row + col) * step;
+ if (ur > (unsigned)height - 2 || uc > (unsigned)width - 2)
+ continue;
+ fr = r - ur;
+ fc = c - uc;
+ pix = image + ur * width + uc;
+ for (i = 0; i < colors; i++)
+ img[row * wide + col][i] =
+ (pix[0][i] * (1 - fc) + pix[1][i] * fc) * (1 - fr) +
+ (pix[width][i] * (1 - fc) + pix[width + 1][i] * fc) * fr;
+ }
+
+ free(image);
+ width = wide;
+ height = high;
+ image = img;
+ fuji_width = 0;
+ RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE, 1, 2);
+}
+
+void LibRaw::stretch()
+{
+ ushort newdim, (*img)[4], *pix0, *pix1;
+ int row, col, c;
+ double rc, frac;
+
+ if (pixel_aspect == 1)
+ return;
+ RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH, 0, 2);
+ if (pixel_aspect < 1)
+ {
+ newdim = height / pixel_aspect + 0.5;
+ img = (ushort(*)[4])calloc(width, newdim * sizeof *img);
+ for (rc = row = 0; row < newdim; row++, rc += pixel_aspect)
+ {
+ frac = rc - (c = rc);
+ pix0 = pix1 = image[c * width];
+ if (c + 1 < height)
+ pix1 += width * 4;
+ for (col = 0; col < width; col++, pix0 += 4, pix1 += 4)
+ FORCC img[row * width + col][c] =
+ pix0[c] * (1 - frac) + pix1[c] * frac + 0.5;
+ }
+ height = newdim;
+ }
+ else
+ {
+ newdim = width * pixel_aspect + 0.5;
+ img = (ushort(*)[4])calloc(height, newdim * sizeof *img);
+ for (rc = col = 0; col < newdim; col++, rc += 1 / pixel_aspect)
+ {
+ frac = rc - (c = rc);
+ pix0 = pix1 = image[c];
+ if (c + 1 < width)
+ pix1 += 4;
+ for (row = 0; row < height; row++, pix0 += width * 4, pix1 += width * 4)
+ FORCC img[row * newdim + col][c] =
+ pix0[c] * (1 - frac) + pix1[c] * frac + 0.5;
+ }
+ width = newdim;
+ }
+ free(image);
+ image = img;
+ RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH, 1, 2);
+}
diff --git a/libkdcraw/libraw/src/postprocessing/dcraw_process.cpp b/libkdcraw/libraw/src/postprocessing/dcraw_process.cpp
new file mode 100644
index 0000000..e8eff13
--- /dev/null
+++ b/libkdcraw/libraw/src/postprocessing/dcraw_process.cpp
@@ -0,0 +1,259 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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::dcraw_process(void)
+{
+ int quality, i;
+
+ int iterations = -1, dcb_enhance = 1, noiserd = 0;
+ float preser = 0;
+ float expos = 1.0;
+
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+ // CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+ try
+ {
+
+ int no_crop = 1;
+
+ if (~O.cropbox[2] && ~O.cropbox[3])
+ no_crop = 0;
+
+ libraw_decoder_info_t di;
+ get_decoder_info(&di);
+
+ bool is_bayer = (imgdata.idata.filters || P1.colors == 1);
+ int subtract_inline =
+ !O.bad_pixels && !O.dark_frame && is_bayer && !IO.zero_is_bad;
+
+ int rc = raw2image_ex(subtract_inline); // allocate imgdata.image and copy data!
+ if (rc != LIBRAW_SUCCESS)
+ return rc;
+
+ // Adjust sizes
+
+ int save_4color = O.four_color_rgb;
+
+ if (IO.zero_is_bad)
+ {
+ remove_zeroes();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
+ }
+
+ if (O.bad_pixels && no_crop)
+ {
+ bad_pixels(O.bad_pixels);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
+ }
+
+ if (O.dark_frame && no_crop)
+ {
+ subtract(O.dark_frame);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
+ }
+ /* pre subtract black callback: check for it above to disable subtract
+ * inline */
+
+ if (callbacks.pre_subtractblack_cb)
+ (callbacks.pre_subtractblack_cb)(this);
+
+ quality = 2 + !IO.fuji_width;
+
+ if (O.user_qual >= 0)
+ quality = O.user_qual;
+
+ if (!subtract_inline || !C.data_maximum)
+ {
+ adjust_bl();
+ subtract_black_internal();
+ }
+
+ if (!(di.decoder_flags & LIBRAW_DECODER_FIXEDMAXC))
+ adjust_maximum();
+
+ if (O.user_sat > 0)
+ C.maximum = O.user_sat;
+
+ if (P1.is_foveon)
+ {
+ if (load_raw == &LibRaw::x3f_load_raw)
+ {
+ // Filter out zeroes
+ for (int q = 0; q < S.height * S.width; q++)
+ {
+ for (int c = 0; c < 4; c++)
+ if ((short)imgdata.image[q][c] < 0)
+ imgdata.image[q][c] = 0;
+ }
+ }
+ SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE);
+ }
+
+ if (O.green_matching && !O.half_size)
+ {
+ green_matching();
+ }
+
+ if (callbacks.pre_scalecolors_cb)
+ (callbacks.pre_scalecolors_cb)(this);
+
+ if (!O.no_auto_scale)
+ {
+ scale_colors();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS);
+ }
+
+ if (callbacks.pre_preinterpolate_cb)
+ (callbacks.pre_preinterpolate_cb)(this);
+
+ pre_interpolate();
+
+ SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+ if (O.dcb_iterations >= 0)
+ iterations = O.dcb_iterations;
+ if (O.dcb_enhance_fl >= 0)
+ dcb_enhance = O.dcb_enhance_fl;
+ if (O.fbdd_noiserd >= 0)
+ noiserd = O.fbdd_noiserd;
+
+ /* pre-exposure correction callback */
+
+ if (O.exp_correc > 0)
+ {
+ expos = O.exp_shift;
+ preser = O.exp_preser;
+ exp_bef(expos, preser);
+ }
+
+ if (callbacks.pre_interpolate_cb)
+ (callbacks.pre_interpolate_cb)(this);
+
+ /* post-exposure correction fallback */
+ if (P1.filters && !O.no_interpolation)
+ {
+ if (noiserd > 0 && P1.colors == 3 && P1.filters > 1000)
+ fbdd(noiserd);
+
+ if (P1.filters > 1000 && callbacks.interpolate_bayer_cb)
+ (callbacks.interpolate_bayer_cb)(this);
+ else if (P1.filters == 9 && callbacks.interpolate_xtrans_cb)
+ (callbacks.interpolate_xtrans_cb)(this);
+ else if (quality == 0)
+ lin_interpolate();
+ else if (quality == 1 || P1.colors > 3)
+ vng_interpolate();
+ else if (quality == 2 && P1.filters > 1000)
+ ppg_interpolate();
+ else if (P1.filters == LIBRAW_XTRANS)
+ {
+ // Fuji X-Trans
+ xtrans_interpolate(quality > 2 ? 3 : 1);
+ }
+ else if (quality == 3)
+ ahd_interpolate(); // really don't need it here due to fallback op
+ else if (quality == 4)
+ dcb(iterations, dcb_enhance);
+
+ else if (quality == 11)
+ dht_interpolate();
+ else if (quality == 12)
+ aahd_interpolate();
+ // fallback to AHD
+ else
+ {
+ ahd_interpolate();
+ imgdata.process_warnings |= LIBRAW_WARN_FALLBACK_TO_AHD;
+ }
+
+ SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE);
+ }
+ if (IO.mix_green)
+ {
+ for (P1.colors = 3, i = 0; i < S.height * S.width; i++)
+ imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
+ }
+
+ if (callbacks.post_interpolate_cb)
+ (callbacks.post_interpolate_cb)(this);
+ else if (!P1.is_foveon && P1.colors == 3 && O.med_passes > 0)
+ {
+ median_filter();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
+ }
+
+ if (O.highlight == 2)
+ {
+ blend_highlights();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+ }
+
+ if (O.highlight > 2)
+ {
+ recover_highlights();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+ }
+
+ if (O.use_fuji_rotate)
+ {
+ fuji_rotate();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+ }
+
+ if (!libraw_internal_data.output_data.histogram)
+ {
+ libraw_internal_data.output_data.histogram =
+ (int(*)[LIBRAW_HISTOGRAM_SIZE])malloc(
+ sizeof(*libraw_internal_data.output_data.histogram) * 4);
+ }
+#ifndef NO_LCMS
+ if (O.camera_profile)
+ {
+ apply_profile(O.camera_profile, O.output_profile);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
+ }
+#endif
+
+ if (callbacks.pre_converttorgb_cb)
+ (callbacks.pre_converttorgb_cb)(this);
+
+ convert_to_rgb();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
+
+ if (callbacks.post_converttorgb_cb)
+ (callbacks.post_converttorgb_cb)(this);
+
+ if (O.use_fuji_rotate)
+ {
+ stretch();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
+ }
+ O.four_color_rgb = save_4color; // also, restore
+
+ return 0;
+ }
+ catch (const std::bad_alloc&)
+ {
+ recycle();
+ return LIBRAW_UNSUFFICIENT_MEMORY;
+ }
+ catch (const LibRaw_exceptions& err)
+ {
+ EXCEPTION_HANDLER(err);
+ }
+}
diff --git a/libkdcraw/libraw/src/postprocessing/mem_image.cpp b/libkdcraw/libraw/src/postprocessing/mem_image.cpp
new file mode 100644
index 0000000..9f70d67
--- /dev/null
+++ b/libkdcraw/libraw/src/postprocessing/mem_image.cpp
@@ -0,0 +1,292 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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"
+
+libraw_processed_image_t *LibRaw::dcraw_make_mem_thumb(int *errcode)
+{
+ if (!T.thumb)
+ {
+ if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 &&
+ load_raw == &LibRaw::broadcom_load_raw) // RPi
+ )
+ {
+ if (errcode)
+ *errcode = LIBRAW_NO_THUMBNAIL;
+ }
+ else
+ {
+ if (errcode)
+ *errcode = LIBRAW_OUT_OF_ORDER_CALL;
+ }
+ return NULL;
+ }
+
+ if (T.tlength < 64u)
+ {
+ if (errcode)
+ *errcode = EINVAL;
+ return NULL;
+ }
+
+ if (INT64(T.tlength) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB)
+ {
+ if (errcode)
+ *errcode = LIBRAW_TOO_BIG;
+ return NULL;
+ }
+
+ if (T.tformat == LIBRAW_THUMBNAIL_BITMAP)
+ {
+ libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(
+ sizeof(libraw_processed_image_t) + T.tlength);
+
+ if (!ret)
+ {
+ if (errcode)
+ *errcode = ENOMEM;
+ return NULL;
+ }
+
+ memset(ret, 0, sizeof(libraw_processed_image_t));
+ ret->type = LIBRAW_IMAGE_BITMAP;
+ ret->height = T.theight;
+ ret->width = T.twidth;
+ if (T.tcolors > 0 && T.tcolors < 4)
+ ret->colors = T.tcolors;
+ else
+ ret->colors = 3; // defaults
+ ret->bits = 8;
+ ret->data_size = T.tlength;
+ memmove(ret->data, T.thumb, T.tlength);
+ if (errcode)
+ *errcode = 0;
+ return ret;
+ }
+ else if (T.tformat == LIBRAW_THUMBNAIL_JPEG)
+ {
+ ushort exif[5];
+ int mk_exif = 0;
+ if (strcmp(T.thumb + 6, "Exif"))
+ mk_exif = 1;
+
+ int dsize = T.tlength + mk_exif * (sizeof(exif) + sizeof(tiff_hdr));
+
+ libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(
+ sizeof(libraw_processed_image_t) + dsize);
+
+ if (!ret)
+ {
+ if (errcode)
+ *errcode = ENOMEM;
+ return NULL;
+ }
+
+ memset(ret, 0, sizeof(libraw_processed_image_t));
+
+ ret->type = LIBRAW_IMAGE_JPEG;
+ ret->data_size = dsize;
+
+ ret->data[0] = 0xff;
+ ret->data[1] = 0xd8;
+ if (mk_exif)
+ {
+ struct tiff_hdr th;
+ memcpy(exif, "\xff\xe1 Exif\0\0", 10);
+ exif[1] = htons(8 + sizeof th);
+ memmove(ret->data + 2, exif, sizeof(exif));
+ tiff_head(&th, 0);
+ memmove(ret->data + (2 + sizeof(exif)), &th, sizeof(th));
+ memmove(ret->data + (2 + sizeof(exif) + sizeof(th)), T.thumb + 2,
+ T.tlength - 2);
+ }
+ else
+ {
+ memmove(ret->data + 2, T.thumb + 2, T.tlength - 2);
+ }
+ if (errcode)
+ *errcode = 0;
+ return ret;
+ }
+ else
+ {
+ if (errcode)
+ *errcode = LIBRAW_UNSUPPORTED_THUMBNAIL;
+ return NULL;
+ }
+}
+
+// jlb
+// macros for copying pixels to either BGR or RGB formats
+#define FORBGR for (c = P1.colors - 1; c >= 0; c--)
+#define FORRGB for (c = 0; c < P1.colors; c++)
+
+void LibRaw::get_mem_image_format(int *width, int *height, int *colors,
+ int *bps) const
+
+{
+ *width = S.width;
+ *height = S.height;
+ if (imgdata.progress_flags < LIBRAW_PROGRESS_FUJI_ROTATE)
+ {
+ if (O.use_fuji_rotate)
+ {
+ if (IO.fuji_width)
+ {
+ int fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink;
+ *width = (ushort)(fuji_width / sqrt(0.5));
+ *height = (ushort)((*height - fuji_width) / sqrt(0.5));
+ }
+ else
+ {
+ if (S.pixel_aspect < 0.995)
+ *height = (ushort)(*height / S.pixel_aspect + 0.5);
+ if (S.pixel_aspect > 1.005)
+ *width = (ushort)(*width * S.pixel_aspect + 0.5);
+ }
+ }
+ }
+ if (S.flip & 4)
+ {
+ std::swap(*width, *height);
+ }
+ *colors = P1.colors;
+ *bps = O.output_bps;
+}
+
+int LibRaw::copy_mem_image(void *scan0, int stride, int bgr)
+
+{
+ // the image memory pointed to by scan0 is assumed to be in the format
+ // returned by get_mem_image_format
+ if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) <
+ LIBRAW_PROGRESS_PRE_INTERPOLATE)
+ return LIBRAW_OUT_OF_ORDER_CALL;
+
+ if (libraw_internal_data.output_data.histogram)
+ {
+ int perc, val, total, t_white = 0x2000, c;
+ perc = S.width * S.height * O.auto_bright_thr;
+ if (IO.fuji_width)
+ perc /= 2;
+ if (!((O.highlight & ~2) || O.no_auto_bright))
+ for (t_white = c = 0; c < P1.colors; c++)
+ {
+ for (val = 0x2000, total = 0; --val > 32;)
+ if ((total += libraw_internal_data.output_data.histogram[c][val]) >
+ perc)
+ break;
+ if (t_white < val)
+ t_white = val;
+ }
+ gamma_curve(O.gamm[0], O.gamm[1], 2, (t_white << 3) / O.bright);
+ }
+
+ int s_iheight = S.iheight;
+ int s_iwidth = S.iwidth;
+ int s_width = S.width;
+ int s_hwight = S.height;
+
+ S.iheight = S.height;
+ S.iwidth = S.width;
+
+ if (S.flip & 4)
+ SWAP(S.height, S.width);
+ uchar *ppm;
+ ushort *ppm2;
+ int c, row, col, soff, rstep, cstep;
+
+ soff = flip_index(0, 0);
+ cstep = flip_index(0, 1) - soff;
+ rstep = flip_index(1, 0) - flip_index(0, S.width);
+
+ for (row = 0; row < S.height; row++, soff += rstep)
+ {
+ uchar *bufp = ((uchar *)scan0) + row * stride;
+ ppm2 = (ushort *)(ppm = bufp);
+ // keep trivial decisions in the outer loop for speed
+ if (bgr)
+ {
+ if (O.output_bps == 8)
+ {
+ for (col = 0; col < S.width; col++, soff += cstep)
+ FORBGR *ppm++ = imgdata.color.curve[imgdata.image[soff][c]] >> 8;
+ }
+ else
+ {
+ for (col = 0; col < S.width; col++, soff += cstep)
+ FORBGR *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]];
+ }
+ }
+ else
+ {
+ if (O.output_bps == 8)
+ {
+ for (col = 0; col < S.width; col++, soff += cstep)
+ FORRGB *ppm++ = imgdata.color.curve[imgdata.image[soff][c]] >> 8;
+ }
+ else
+ {
+ for (col = 0; col < S.width; col++, soff += cstep)
+ FORRGB *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]];
+ }
+ }
+
+ // bufp += stride; // go to the next line
+ }
+
+ S.iheight = s_iheight;
+ S.iwidth = s_iwidth;
+ S.width = s_width;
+ S.height = s_hwight;
+
+ return 0;
+}
+#undef FORBGR
+#undef FORRGB
+
+libraw_processed_image_t *LibRaw::dcraw_make_mem_image(int *errcode)
+
+{
+ int width, height, colors, bps;
+ get_mem_image_format(&width, &height, &colors, &bps);
+ int stride = width * (bps / 8) * colors;
+ unsigned ds = height * stride;
+ libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(
+ sizeof(libraw_processed_image_t) + ds);
+ if (!ret)
+ {
+ if (errcode)
+ *errcode = ENOMEM;
+ return NULL;
+ }
+ memset(ret, 0, sizeof(libraw_processed_image_t));
+
+ // metadata init
+ ret->type = LIBRAW_IMAGE_BITMAP;
+ ret->height = height;
+ ret->width = width;
+ ret->colors = colors;
+ ret->bits = bps;
+ ret->data_size = ds;
+ copy_mem_image(ret->data, stride, 0);
+
+ return ret;
+}
+
+void LibRaw::dcraw_clear_mem(libraw_processed_image_t *p)
+{
+ if (p)
+ ::free(p);
+}
diff --git a/libkdcraw/libraw/src/postprocessing/postprocessing_aux.cpp b/libkdcraw/libraw/src/postprocessing/postprocessing_aux.cpp
new file mode 100644
index 0000000..5747340
--- /dev/null
+++ b/libkdcraw/libraw/src/postprocessing/postprocessing_aux.cpp
@@ -0,0 +1,406 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::hat_transform(float *temp, float *base, int st, int size, int sc)
+{
+ int i;
+ for (i = 0; i < sc; i++)
+ temp[i] = 2 * base[st * i] + base[st * (sc - i)] + base[st * (i + sc)];
+ for (; i + sc < size; i++)
+ temp[i] = 2 * base[st * i] + base[st * (i - sc)] + base[st * (i + sc)];
+ for (; i < size; i++)
+ temp[i] = 2 * base[st * i] + base[st * (i - sc)] +
+ base[st * (2 * size - 2 - (i + sc))];
+}
+
+#if !defined(LIBRAW_USE_OPENMP)
+void LibRaw::wavelet_denoise()
+{
+ float *fimg = 0, *temp, thold, mul[2], avg, diff;
+ int scale = 1, size, lev, hpass, lpass, row, col, nc, c, i, wlast, blk[2];
+ ushort *window[4];
+ static const float noise[] = {0.8002f, 0.2735f, 0.1202f, 0.0585f,
+ 0.0291f, 0.0152f, 0.0080f, 0.0044f};
+
+
+ while (maximum << scale < 0x10000)
+ scale++;
+ maximum <<= --scale;
+ black <<= scale;
+ FORC4 cblack[c] <<= scale;
+ if ((size = iheight * iwidth) < 0x15550000)
+ fimg = (float *)malloc((size * 3 + iheight + iwidth + 128) * sizeof *fimg);
+ temp = fimg + size * 3;
+ if ((nc = colors) == 3 && filters)
+ nc++;
+ FORC(nc)
+ { /* denoise R,G1,B,G3 individually */
+ for (i = 0; i < size; i++)
+ fimg[i] = 256 * sqrt((double)(image[i][c] << scale));
+ for (hpass = lev = 0; lev < 5; lev++)
+ {
+ lpass = size * ((lev & 1) + 1);
+ for (row = 0; row < iheight; row++)
+ {
+ hat_transform(temp, fimg + hpass + row * iwidth, 1, iwidth, 1 << lev);
+ for (col = 0; col < iwidth; col++)
+ fimg[lpass + row * iwidth + col] = temp[col] * 0.25;
+ }
+ for (col = 0; col < iwidth; col++)
+ {
+ hat_transform(temp, fimg + lpass + col, iwidth, iheight, 1 << lev);
+ for (row = 0; row < iheight; row++)
+ fimg[lpass + row * iwidth + col] = temp[row] * 0.25;
+ }
+ thold = threshold * noise[lev];
+ for (i = 0; i < size; i++)
+ {
+ fimg[hpass + i] -= fimg[lpass + i];
+ if (fimg[hpass + i] < -thold)
+ fimg[hpass + i] += thold;
+ else if (fimg[hpass + i] > thold)
+ fimg[hpass + i] -= thold;
+ else
+ fimg[hpass + i] = 0;
+ if (hpass)
+ fimg[i] += fimg[hpass + i];
+ }
+ hpass = lpass;
+ }
+ for (i = 0; i < size; i++)
+ image[i][c] = CLIP(SQR(fimg[i] + fimg[lpass + i]) / 0x10000);
+ }
+ if (filters && colors == 3)
+ { /* pull G1 and G3 closer together */
+ for (row = 0; row < 2; row++)
+ {
+ mul[row] = 0.125 * pre_mul[FC(row + 1, 0) | 1] / pre_mul[FC(row, 0) | 1];
+ blk[row] = cblack[FC(row, 0) | 1];
+ }
+ for (i = 0; i < 4; i++)
+ window[i] = (ushort *)fimg + width * i;
+ for (wlast = -1, row = 1; row < height - 1; row++)
+ {
+ while (wlast < row + 1)
+ {
+ for (wlast++, i = 0; i < 4; i++)
+ window[(i + 3) & 3] = window[i];
+ for (col = FC(wlast, 1) & 1; col < width; col += 2)
+ window[2][col] = BAYER(wlast, col);
+ }
+ thold = threshold / 512;
+ for (col = (FC(row, 0) & 1) + 1; col < width - 1; col += 2)
+ {
+ avg = (window[0][col - 1] + window[0][col + 1] + window[2][col - 1] +
+ window[2][col + 1] - blk[~row & 1] * 4) *
+ mul[row & 1] +
+ (window[1][col] + blk[row & 1]) * 0.5;
+ avg = avg < 0 ? 0 : sqrt(avg);
+ diff = sqrt((double)BAYER(row, col)) - avg;
+ if (diff < -thold)
+ diff += thold;
+ else if (diff > thold)
+ diff -= thold;
+ else
+ diff = 0;
+ BAYER(row, col) = CLIP(SQR(avg + diff) + 0.5);
+ }
+ }
+ }
+ free(fimg);
+}
+#else /* LIBRAW_USE_OPENMP */
+void LibRaw::wavelet_denoise()
+{
+ float *fimg = 0, *temp, thold, mul[2], avg, diff;
+ int scale = 1, size, lev, hpass, lpass, row, col, nc, c, i, wlast, blk[2];
+ ushort *window[4];
+ static const float noise[] = {0.8002, 0.2735, 0.1202, 0.0585,
+ 0.0291, 0.0152, 0.0080, 0.0044};
+
+ while (maximum << scale < 0x10000)
+ scale++;
+ maximum <<= --scale;
+ black <<= scale;
+ FORC4 cblack[c] <<= scale;
+ if ((size = iheight * iwidth) < 0x15550000)
+ fimg = (float *)malloc((size * 3 + iheight + iwidth) * sizeof *fimg);
+ temp = fimg + size * 3;
+ if ((nc = colors) == 3 && filters)
+ nc++;
+#pragma omp parallel default(shared) private( \
+ i, col, row, thold, lev, lpass, hpass, temp, c) firstprivate(scale, size)
+ {
+ temp = (float *)malloc((iheight + iwidth) * sizeof *fimg);
+ FORC(nc)
+ { /* denoise R,G1,B,G3 individually */
+#pragma omp for
+ for (i = 0; i < size; i++)
+ fimg[i] = 256 * sqrt((double)(image[i][c] << scale));
+ for (hpass = lev = 0; lev < 5; lev++)
+ {
+ lpass = size * ((lev & 1) + 1);
+#pragma omp for
+ for (row = 0; row < iheight; row++)
+ {
+ hat_transform(temp, fimg + hpass + row * iwidth, 1, iwidth, 1 << lev);
+ for (col = 0; col < iwidth; col++)
+ fimg[lpass + row * iwidth + col] = temp[col] * 0.25;
+ }
+#pragma omp for
+ for (col = 0; col < iwidth; col++)
+ {
+ hat_transform(temp, fimg + lpass + col, iwidth, iheight, 1 << lev);
+ for (row = 0; row < iheight; row++)
+ fimg[lpass + row * iwidth + col] = temp[row] * 0.25;
+ }
+ thold = threshold * noise[lev];
+#pragma omp for
+ for (i = 0; i < size; i++)
+ {
+ fimg[hpass + i] -= fimg[lpass + i];
+ if (fimg[hpass + i] < -thold)
+ fimg[hpass + i] += thold;
+ else if (fimg[hpass + i] > thold)
+ fimg[hpass + i] -= thold;
+ else
+ fimg[hpass + i] = 0;
+ if (hpass)
+ fimg[i] += fimg[hpass + i];
+ }
+ hpass = lpass;
+ }
+#pragma omp for
+ for (i = 0; i < size; i++)
+ image[i][c] = CLIP(SQR(fimg[i] + fimg[lpass + i]) / 0x10000);
+ }
+ free(temp);
+ } /* end omp parallel */
+ /* the following loops are hard to parallelize, no idea yes,
+ * problem is wlast which is carrying dependency
+ * second part should be easier, but did not yet get it right.
+ */
+ if (filters && colors == 3)
+ { /* pull G1 and G3 closer together */
+ for (row = 0; row < 2; row++)
+ {
+ mul[row] = 0.125 * pre_mul[FC(row + 1, 0) | 1] / pre_mul[FC(row, 0) | 1];
+ blk[row] = cblack[FC(row, 0) | 1];
+ }
+ for (i = 0; i < 4; i++)
+ window[i] = (ushort *)fimg + width * i;
+ for (wlast = -1, row = 1; row < height - 1; row++)
+ {
+ while (wlast < row + 1)
+ {
+ for (wlast++, i = 0; i < 4; i++)
+ window[(i + 3) & 3] = window[i];
+ for (col = FC(wlast, 1) & 1; col < width; col += 2)
+ window[2][col] = BAYER(wlast, col);
+ }
+ thold = threshold / 512;
+ for (col = (FC(row, 0) & 1) + 1; col < width - 1; col += 2)
+ {
+ avg = (window[0][col - 1] + window[0][col + 1] + window[2][col - 1] +
+ window[2][col + 1] - blk[~row & 1] * 4) *
+ mul[row & 1] +
+ (window[1][col] + blk[row & 1]) * 0.5;
+ avg = avg < 0 ? 0 : sqrt(avg);
+ diff = sqrt((double)BAYER(row, col)) - avg;
+ if (diff < -thold)
+ diff += thold;
+ else if (diff > thold)
+ diff -= thold;
+ else
+ diff = 0;
+ BAYER(row, col) = CLIP(SQR(avg + diff) + 0.5);
+ }
+ }
+ }
+ free(fimg);
+}
+
+#endif
+void LibRaw::median_filter()
+{
+ ushort(*pix)[4];
+ int pass, c, i, j, k, med[9];
+ static const uchar opt[] = /* Optimal 9-element median search */
+ {1, 2, 4, 5, 7, 8, 0, 1, 3, 4, 6, 7, 1, 2, 4, 5, 7, 8, 0,
+ 3, 5, 8, 4, 7, 3, 6, 1, 4, 2, 5, 4, 7, 4, 2, 6, 4, 4, 2};
+
+ for (pass = 1; pass <= med_passes; pass++)
+ {
+ RUN_CALLBACK(LIBRAW_PROGRESS_MEDIAN_FILTER, pass - 1, med_passes);
+ for (c = 0; c < 3; c += 2)
+ {
+ for (pix = image; pix < image + width * height; pix++)
+ pix[0][3] = pix[0][c];
+ for (pix = image + width; pix < image + width * (height - 1); pix++)
+ {
+ if ((pix - image + 1) % width < 2)
+ continue;
+ for (k = 0, i = -width; i <= width; i += width)
+ for (j = i - 1; j <= i + 1; j++)
+ med[k++] = pix[j][3] - pix[j][1];
+ for (i = 0; i < int(sizeof opt); i += 2)
+ if (med[opt[i]] > med[opt[i + 1]])
+ SWAP(med[opt[i]], med[opt[i + 1]]);
+ pix[0][c] = CLIP(med[4] + pix[0][1]);
+ }
+ }
+ }
+}
+
+void LibRaw::blend_highlights()
+{
+ int clip = INT_MAX, row, col, c, i, j;
+ static const float trans[2][4][4] = {
+ {{1, 1, 1}, {1.7320508f, -1.7320508f, 0}, {-1, -1, 2}},
+ {{1, 1, 1, 1}, {1, -1, 1, -1}, {1, 1, -1, -1}, {1, -1, -1, 1}}};
+ static const float itrans[2][4][4] = {
+ {{1, 0.8660254f, -0.5}, {1, -0.8660254f, -0.5}, {1, 0, 1}},
+ {{1, 1, 1, 1}, {1, -1, 1, -1}, {1, 1, -1, -1}, {1, -1, -1, 1}}};
+ float cam[2][4], lab[2][4], sum[2], chratio;
+
+ if ((unsigned)(colors - 3) > 1)
+ return;
+ RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS, 0, 2);
+ FORCC if (clip > (i = 65535 * pre_mul[c])) clip = i;
+ for (row = 0; row < height; row++)
+ for (col = 0; col < width; col++)
+ {
+ FORCC if (image[row * width + col][c] > clip) break;
+ if (c == colors)
+ continue;
+ FORCC
+ {
+ cam[0][c] = image[row * width + col][c];
+ cam[1][c] = MIN(cam[0][c], clip);
+ }
+ for (i = 0; i < 2; i++)
+ {
+ FORCC for (lab[i][c] = j = 0; j < colors; j++) lab[i][c] +=
+ trans[colors - 3][c][j] * cam[i][j];
+ for (sum[i] = 0, c = 1; c < colors; c++)
+ sum[i] += SQR(lab[i][c]);
+ }
+ chratio = sqrt(sum[1] / sum[0]);
+ for (c = 1; c < colors; c++)
+ lab[0][c] *= chratio;
+ FORCC for (cam[0][c] = j = 0; j < colors; j++) cam[0][c] +=
+ itrans[colors - 3][c][j] * lab[0][j];
+ FORCC image[row * width + col][c] = cam[0][c] / colors;
+ }
+ RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS, 1, 2);
+}
+
+#define SCALE (4 >> shrink)
+void LibRaw::recover_highlights()
+{
+ float *map, sum, wgt, grow;
+ int hsat[4], count, spread, change, val, i;
+ unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x;
+ ushort *pixel;
+ static const signed char dir[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, 1},
+ {1, 1}, {1, 0}, {1, -1}, {0, -1}};
+
+ grow = pow(2.0, 4 - highlight);
+ FORC(unsigned(colors)) hsat[c] = 32000 * pre_mul[c];
+ for (kc = 0, c = 1; c < (unsigned)colors; c++)
+ if (pre_mul[kc] < pre_mul[c])
+ kc = c;
+ high = height / SCALE;
+ wide = width / SCALE;
+ map = (float *)calloc(high, wide * sizeof *map);
+ FORC(unsigned(colors)) if (c != kc)
+ {
+ RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS, c - 1, colors - 1);
+ memset(map, 0, high * wide * sizeof *map);
+ for (mrow = 0; mrow < high; mrow++)
+ for (mcol = 0; mcol < wide; mcol++)
+ {
+ sum = wgt = count = 0;
+ for (row = mrow * SCALE; row < (mrow + 1) * SCALE; row++)
+ for (col = mcol * SCALE; col < (mcol + 1) * SCALE; col++)
+ {
+ pixel = image[row * width + col];
+ if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000)
+ {
+ sum += pixel[c];
+ wgt += pixel[kc];
+ count++;
+ }
+ }
+ if (count == SCALE * SCALE)
+ map[mrow * wide + mcol] = sum / wgt;
+ }
+ for (spread = 32 / grow; spread--;)
+ {
+ for (mrow = 0; mrow < high; mrow++)
+ for (mcol = 0; mcol < wide; mcol++)
+ {
+ if (map[mrow * wide + mcol])
+ continue;
+ sum = count = 0;
+ for (d = 0; d < 8; d++)
+ {
+ y = mrow + dir[d][0];
+ x = mcol + dir[d][1];
+ if (y < high && x < wide && map[y * wide + x] > 0)
+ {
+ sum += (1 + (d & 1)) * map[y * wide + x];
+ count += 1 + (d & 1);
+ }
+ }
+ if (count > 3)
+ map[mrow * wide + mcol] = -(sum + grow) / (count + grow);
+ }
+ for (change = i = 0; i < int(high * wide); i++)
+ if (map[i] < 0)
+ {
+ map[i] = -map[i];
+ change = 1;
+ }
+ if (!change)
+ break;
+ }
+ for (i = 0; i < int(high * wide); i++)
+ if (map[i] == 0)
+ map[i] = 1;
+ for (mrow = 0; mrow < high; mrow++)
+ for (mcol = 0; mcol < wide; mcol++)
+ {
+ for (row = mrow * SCALE; row < (mrow + 1) * SCALE; row++)
+ for (col = mcol * SCALE; col < (mcol + 1) * SCALE; col++)
+ {
+ pixel = image[row * width + col];
+ if (pixel[c] / hsat[c] > 1)
+ {
+ val = pixel[kc] * map[mrow * wide + mcol];
+ if (pixel[c] < val)
+ pixel[c] = CLIP(val);
+ }
+ }
+ }
+ }
+ free(map);
+}
+#undef SCALE
diff --git a/libkdcraw/libraw/src/postprocessing/postprocessing_ph.cpp b/libkdcraw/libraw/src/postprocessing/postprocessing_ph.cpp
new file mode 100644
index 0000000..3af0939
--- /dev/null
+++ b/libkdcraw/libraw/src/postprocessing/postprocessing_ph.cpp
@@ -0,0 +1,31 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ Placeholder functions to build LibRaw w/o postprocessing tools
+
+ 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::dcraw_process(void)
+{
+ return LIBRAW_NOT_IMPLEMENTED;
+}
+
+void LibRaw::fuji_rotate() {}
+void LibRaw::convert_to_rgb_loop(float /*out_cam*/ [3][4]) {}
+libraw_processed_image_t *LibRaw::dcraw_make_mem_image(int *) {
+ return NULL;
+}
+libraw_processed_image_t *LibRaw::dcraw_make_mem_thumb(int *){ return NULL;}
+void LibRaw::lin_interpolate_loop(int * /*code*/, int /*size*/) {}
+void LibRaw::scale_colors_loop(float /*scale_mul*/[4]) {}
diff --git a/libkdcraw/libraw/src/postprocessing/postprocessing_utils.cpp b/libkdcraw/libraw/src/postprocessing/postprocessing_utils.cpp
new file mode 100644
index 0000000..986b5bb
--- /dev/null
+++ b/libkdcraw/libraw/src/postprocessing/postprocessing_utils.cpp
@@ -0,0 +1,190 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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"
+
+#define TBLN 65535
+
+void LibRaw::exp_bef(float shift, float smooth)
+{
+ // params limits
+ if (shift > 8)
+ shift = 8;
+ if (shift < 0.25)
+ shift = 0.25;
+ if (smooth < 0.0)
+ smooth = 0.0;
+ if (smooth > 1.0)
+ smooth = 1.0;
+
+ unsigned short *lut = (ushort *)malloc((TBLN + 1) * sizeof(unsigned short));
+
+ if (shift <= 1.0)
+ {
+ for (int i = 0; i <= TBLN; i++)
+ lut[i] = (unsigned short)((float)i * shift);
+ }
+ else
+ {
+ float x1, x2, y1, y2;
+
+ float cstops = log(shift) / log(2.0f);
+ float room = cstops * 2;
+ float roomlin = powf(2.0f, room);
+ x2 = (float)TBLN;
+ x1 = (x2 + 1) / roomlin - 1;
+ y1 = x1 * shift;
+ y2 = x2 * (1 + (1 - smooth) * (shift - 1));
+ float sq3x = powf(x1 * x1 * x2, 1.0f / 3.0f);
+ float B = (y2 - y1 + shift * (3 * x1 - 3.0f * sq3x)) /
+ (x2 + 2.0f * x1 - 3.0f * sq3x);
+ float A = (shift - B) * 3.0f * powf(x1 * x1, 1.0f / 3.0f);
+ float CC = y2 - A * powf(x2, 1.0f / 3.0f) - B * x2;
+ for (int i = 0; i <= TBLN; i++)
+ {
+ float X = (float)i;
+ float Y = A * powf(X, 1.0f / 3.0f) + B * X + CC;
+ if (i < x1)
+ lut[i] = (unsigned short)((float)i * shift);
+ else
+ lut[i] = Y < 0 ? 0 : (Y > TBLN ? TBLN : (unsigned short)(Y));
+ }
+ }
+ for (int i = 0; i < S.height * S.width; i++)
+ {
+ imgdata.image[i][0] = lut[imgdata.image[i][0]];
+ imgdata.image[i][1] = lut[imgdata.image[i][1]];
+ imgdata.image[i][2] = lut[imgdata.image[i][2]];
+ imgdata.image[i][3] = lut[imgdata.image[i][3]];
+ }
+
+ if (C.data_maximum <= TBLN)
+ C.data_maximum = lut[C.data_maximum];
+ if (C.maximum <= TBLN)
+ C.maximum = lut[C.maximum];
+ free(lut);
+}
+
+void LibRaw::convert_to_rgb_loop(float out_cam[3][4])
+{
+ int row, col, c;
+ float out[3];
+ ushort *img;
+ memset(libraw_internal_data.output_data.histogram, 0,
+ sizeof(int) * LIBRAW_HISTOGRAM_SIZE * 4);
+ if (libraw_internal_data.internal_output_params.raw_color)
+ {
+ for (img = imgdata.image[0], row = 0; row < S.height; row++)
+ {
+ for (col = 0; col < S.width; col++, img += 4)
+ {
+ for (c = 0; c < imgdata.idata.colors; c++)
+ {
+ libraw_internal_data.output_data.histogram[c][img[c] >> 3]++;
+ }
+ }
+ }
+ }
+ else if (imgdata.idata.colors == 3)
+ {
+ for (img = imgdata.image[0], row = 0; row < S.height; row++)
+ {
+ for (col = 0; col < S.width; col++, img += 4)
+ {
+ out[0] = out_cam[0][0] * img[0] + out_cam[0][1] * img[1] +
+ out_cam[0][2] * img[2];
+ out[1] = out_cam[1][0] * img[0] + out_cam[1][1] * img[1] +
+ out_cam[1][2] * img[2];
+ out[2] = out_cam[2][0] * img[0] + out_cam[2][1] * img[1] +
+ out_cam[2][2] * img[2];
+ img[0] = CLIP((int)out[0]);
+ img[1] = CLIP((int)out[1]);
+ img[2] = CLIP((int)out[2]);
+ libraw_internal_data.output_data.histogram[0][img[0] >> 3]++;
+ libraw_internal_data.output_data.histogram[1][img[1] >> 3]++;
+ libraw_internal_data.output_data.histogram[2][img[2] >> 3]++;
+ }
+ }
+ }
+ else if (imgdata.idata.colors == 4)
+ {
+ for (img = imgdata.image[0], row = 0; row < S.height; row++)
+ {
+ for (col = 0; col < S.width; col++, img += 4)
+ {
+ out[0] = out_cam[0][0] * img[0] + out_cam[0][1] * img[1] +
+ out_cam[0][2] * img[2] + out_cam[0][3] * img[3];
+ out[1] = out_cam[1][0] * img[0] + out_cam[1][1] * img[1] +
+ out_cam[1][2] * img[2] + out_cam[1][3] * img[3];
+ out[2] = out_cam[2][0] * img[0] + out_cam[2][1] * img[1] +
+ out_cam[2][2] * img[2] + out_cam[2][3] * img[3];
+ img[0] = CLIP((int)out[0]);
+ img[1] = CLIP((int)out[1]);
+ img[2] = CLIP((int)out[2]);
+ libraw_internal_data.output_data.histogram[0][img[0] >> 3]++;
+ libraw_internal_data.output_data.histogram[1][img[1] >> 3]++;
+ libraw_internal_data.output_data.histogram[2][img[2] >> 3]++;
+ libraw_internal_data.output_data.histogram[3][img[3] >> 3]++;
+ }
+ }
+ }
+}
+
+void LibRaw::scale_colors_loop(float scale_mul[4])
+{
+ unsigned size = S.iheight * S.iwidth;
+
+ if (C.cblack[4] && C.cblack[5])
+ {
+ int val;
+ for (unsigned i = 0; i < size; i++)
+ {
+ for (unsigned c = 0; c < 4; c++)
+ {
+ if (!(val = imgdata.image[i][c])) continue;
+ val -= C.cblack[6 + i / S.iwidth % C.cblack[4] * C.cblack[5] +
+ i % S.iwidth % C.cblack[5]];
+ val -= C.cblack[c];
+ val *= scale_mul[c];
+ imgdata.image[i][c] = CLIP(val);
+ }
+ }
+ }
+ else if (C.cblack[0] || C.cblack[1] || C.cblack[2] || C.cblack[3])
+ {
+ for (unsigned i = 0; i < size; i++)
+ {
+ for (unsigned c = 0; c < 4; c++)
+ {
+ int val = imgdata.image[i][c];
+ if (!val) continue;
+ val -= C.cblack[c];
+ val *= scale_mul[c];
+ imgdata.image[i][c] = CLIP(val);
+ }
+ }
+ }
+ else // BL is zero
+ {
+ for (unsigned i = 0; i < size; i++)
+ {
+ for (unsigned c = 0; c < 4; c++)
+ {
+ int val = imgdata.image[i][c];
+ val *= scale_mul[c];
+ imgdata.image[i][c] = CLIP(val);
+ }
+ }
+ }
+}
diff --git a/libkdcraw/libraw/src/postprocessing/postprocessing_utils_dcrdefs.cpp b/libkdcraw/libraw/src/postprocessing/postprocessing_utils_dcrdefs.cpp
new file mode 100644
index 0000000..98ea061
--- /dev/null
+++ b/libkdcraw/libraw/src/postprocessing/postprocessing_utils_dcrdefs.cpp
@@ -0,0 +1,308 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::convert_to_rgb()
+{
+ 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,
+ LibRaw_constants::dcip3d65_rgb, LibRaw_constants::rec2020_rgb};
+ static const char *name[] = {"sRGB", "Adobe RGB (1998)",
+ "WideGamut D65", "ProPhoto D65",
+ "XYZ", "ACES",
+ "DCI-P3 D65", "Rec. 2020"};
+ 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, /* cprt */
+ 0x64657363, 0, 60, /* desc, len is strlen(longest_string) + 12 */
+ 0x77747074, 0, 20, /* wtpt */
+ 0x626b7074, 0, 20, /* bkpt */
+ 0x72545243, 0, 14, /* rTRC */
+ 0x67545243, 0, 14, /* gTRC */
+ 0x62545243, 0, 14, /* bTRC */
+ 0x7258595a, 0, 20, /* rXYZ */
+ 0x6758595a, 0, 20, /* gXYZ */
+ 0x6258595a, 0, 20}; /* bXYZ */
+ static const unsigned pwhite[] = {0xf351, 0x10000, 0x116cc};
+ unsigned pcurve[] = {0x63757276, 0, 1, 0x1000000};
+
+ RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB, 0, 2);
+
+ 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 > 8;
+ if (!raw_color)
+ {
+ size_t prof_desc_len;
+ std::vector<char> prof_desc;
+ int i, j, k;
+ 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.resize(prof_desc_len);
+ sprintf(prof_desc.data(), "%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);
+
+ oprof = (unsigned *)calloc(phead[0], 1);
+ 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] = unsigned(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");
+ if (pbody[5] + 12 + prof_desc.size() < phead[0])
+ strcpy((char *)oprof + pbody[5] + 12, prof_desc.data());
+ 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 // LibRaw 0.19 and older: fallback to auto only if cam_mul[0] is set to -1
+ || (cam_mul[0] <= 0.00001f // New default: fallback to auto if no cam_mul parsed from metadata
+ && !(imgdata.rawparams.options & LIBRAW_RAWOPTIONS_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)
+ {
+ // Nikon sRAW: camera WB already 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;
+ }
+ }
+ // Nikon sRAW, daylight
+ 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);
+ 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);
+}
+
+// green equilibration
+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);
+ 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);
+}
diff --git a/libkdcraw/libraw/src/preprocessing/ext_preprocess.cpp b/libkdcraw/libraw/src/preprocessing/ext_preprocess.cpp
new file mode 100644
index 0000000..8f2ec49
--- /dev/null
+++ b/libkdcraw/libraw/src/preprocessing/ext_preprocess.cpp
@@ -0,0 +1,127 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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);
+}
diff --git a/libkdcraw/libraw/src/preprocessing/preprocessing_ph.cpp b/libkdcraw/libraw/src/preprocessing/preprocessing_ph.cpp
new file mode 100644
index 0000000..44868ed
--- /dev/null
+++ b/libkdcraw/libraw/src/preprocessing/preprocessing_ph.cpp
@@ -0,0 +1,24 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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(){}
+
diff --git a/libkdcraw/libraw/src/preprocessing/raw2image.cpp b/libkdcraw/libraw/src/preprocessing/raw2image.cpp
new file mode 100644
index 0000000..e65e2ad
--- /dev/null
+++ b/libkdcraw/libraw/src/preprocessing/raw2image.cpp
@@ -0,0 +1,558 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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);
+ }
+}
diff --git a/libkdcraw/libraw/src/preprocessing/subtract_black.cpp b/libkdcraw/libraw/src/preprocessing/subtract_black.cpp
new file mode 100644
index 0000000..42bbe4f
--- /dev/null
+++ b/libkdcraw/libraw/src/preprocessing/subtract_black.cpp
@@ -0,0 +1,91 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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);
+ }
+}
diff --git a/libkdcraw/libraw/src/tables/cameralist.cpp b/libkdcraw/libraw/src/tables/cameralist.cpp
new file mode 100644
index 0000000..da7f481
--- /dev/null
+++ b/libkdcraw/libraw/src/tables/cameralist.cpp
@@ -0,0 +1,1269 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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"
+#ifdef USE_RAWSPEED
+/* we need separate file for that */
+#include "../../RawSpeed/rawspeed_xmldata.cpp"
+const int RAWSPEED_DATA_COUNT =
+ (sizeof(_rawspeed_data_xml) / sizeof(_rawspeed_data_xml[0]));
+#endif
+// clang-format off
+// Supported cameras:
+static const char *static_camera_list[] = {
+ "Adobe Digital Negative (DNG)",
+ "AgfaPhoto DC-833m",
+ "Alcatel 5035D",
+ "Apple iPad Pro",
+ "Apple iPhone SE",
+ "Apple iPhone 6s",
+ "Apple iPhone 6 plus",
+ "Apple iPhone 7",
+ "Apple iPhone 7 plus",
+ "Apple iPhone 8",
+ "Apple iPhone 8 plus",
+ "Apple iPhone X",
+ "Apple iPhone 12 Pro",
+ "Apple iPhone 12 Pro Max",
+ "Apple iPhone 13 Pro",
+ "Apple QuickTake 100",
+ "Apple QuickTake 150",
+ "Apple QuickTake 200",
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ "ARRI ALEXA",
+ "ARRI ALEXA65",
+ "ARRI ALEXA LF",
+ "ARRI ALEXA XT",
+ "ARRI ALEXA SXT",
+#endif
+ "ASUS ZenPhone4",
+ "ASUS ZenPhone6",
+ "AutelRobotics XB015",
+ "AutelRobotics XT705 (EVO II)",
+ "AVT F-080C",
+ "AVT F-145C",
+ "AVT F-201C",
+ "AVT F-510C",
+ "AVT F-810C",
+ "Baumer TXG14",
+ "BlackMagic Cinema Camera",
+ "BlackMagic Micro Cinema Camera",
+ "BlackMagic Pocket Cinema Camera",
+ "BlackMagic Production Camera 4k",
+ "BlackMagic URSA",
+ "BlackMagic URSA Mini 4k",
+ "BlackMagic URSA Mini 4.6k",
+ "BlackMagic URSA Mini Pro 4.6k",
+ "BQ Aquarius U",
+ "Canon PowerShot 600",
+ "Canon PowerShot A5",
+ "Canon PowerShot A5 Zoom",
+ "Canon PowerShot A50",
+ "Canon PowerShot A410 (CHDK hack)",
+ "Canon PowerShot A460 (CHDK hack)",
+ "Canon PowerShot A470 (CHDK hack)",
+ "Canon PowerShot A480 (CHDK hack)",
+ "Canon PowerShot A530 (CHDK hack)",
+ "Canon PowerShot A540 (CHDK hack)",
+ "Canon PowerShot A550 (CHDK hack)",
+ "Canon PowerShot A560 (CHDK hack)",
+ "Canon PowerShot A570 IS (CHDK hack)",
+ "Canon PowerShot A590 IS (CHDK hack)",
+ "Canon PowerShot A610 (CHDK hack)",
+ "Canon PowerShot A620 (CHDK hack)",
+ "Canon PowerShot A630 (CHDK hack)",
+ "Canon PowerShot A640 (CHDK hack)",
+ "Canon PowerShot A650 IS (CHDK hack)",
+ "Canon PowerShot A710 IS (CHDK hack)",
+ "Canon PowerShot A720 IS (CHDK hack)",
+ "Canon PowerShot A3300 IS (CHDK hack)",
+ "Canon PowerShot D10 (CHDK hack)",
+ "Canon PowerShot ELPH 130 IS / IXUS 140 / IXY 110F (CHDK hack)",
+ "Canon PowerShot ELPH 160 / IXUS 160 (CHDK hack)",
+ "Canon PowerShot Pro70",
+ "Canon PowerShot Pro90 IS",
+ "Canon PowerShot Pro1",
+ "Canon PowerShot G1",
+ "Canon PowerShot G1 X",
+ "Canon PowerShot G1 X Mark II",
+ "Canon PowerShot G1 X Mark III",
+ "Canon PowerShot G2",
+ "Canon PowerShot G3",
+ "Canon PowerShot G3 X",
+ "Canon PowerShot G5",
+ "Canon PowerShot G5 X",
+ "Canon PowerShot G5 X Mark II",
+ "Canon PowerShot G6",
+ "Canon PowerShot G7 (CHDK hack)",
+ "Canon PowerShot G7 X",
+ "Canon PowerShot G7 X Mark II",
+ "Canon PowerShot G7 X Mark III",
+ "Canon PowerShot G9",
+ "Canon PowerShot G9 X",
+ "Canon PowerShot G9 X Mark II",
+ "Canon PowerShot G10",
+ "Canon PowerShot G11",
+ "Canon PowerShot G12",
+ "Canon PowerShot G15",
+ "Canon PowerShot G16",
+ "Canon PowerShot S2 IS (CHDK hack)",
+ "Canon PowerShot S3 IS (CHDK hack)",
+ "Canon PowerShot S5 IS (CHDK hack)",
+ "Canon PowerShot SD300 / IXUS 40 / IXY Digital 50 (CHDK hack)",
+ "Canon PowerShot SD750 / IXUS 75 / IXY Digital 90 (CHDK hack)",
+ "Canon PowerShot SD900 / Digital IXUS 900 Ti / IXY Digital 1000 (CHDK hack)",
+ "Canon PowerShot SD950 IS / Digital IXUS 960 IS / IXY Digital 2000 IS (CHDK hack)",
+ "Canon PowerShot SD1200 IS / Digital IXUS 95 IS / IXY Digital 110 IS (CHDK hack)",
+ "Canon PowerShot S30",
+ "Canon PowerShot S40",
+ "Canon PowerShot S45",
+ "Canon PowerShot S50",
+ "Canon PowerShot S60",
+ "Canon PowerShot S70",
+ "Canon PowerShot S90",
+ "Canon PowerShot S95",
+ "Canon PowerShot S100",
+ "Canon PowerShot S110",
+ "Canon PowerShot S120",
+ "Canon PowerShot SX1 IS",
+ "Canon PowerShot SX40 HS (CHDK hack, CR2)",
+ "Canon PowerShot SX50 HS",
+ "Canon PowerShot SX60 HS",
+ "Canon PowerShot SX70 HS",
+ "Canon PowerShot SX100 IS (CHDK hack)",
+ "Canon PowerShot SX110 IS (CHDK hack)",
+ "Canon PowerShot SX120 IS (CHDK hack)",
+ "Canon PowerShot SX130 IS (CHDK hack)",
+ "Canon PowerShot SX160 IS (CHDK hack)",
+ "Canon PowerShot SX220 HS (CHDK hack)",
+ "Canon PowerShot SX510 HS (CHDK hack)",
+ "Canon PowerShot SX710 HS (CHDK hack)",
+ "Canon PowerShot SX10 IS (CHDK hack)",
+ "Canon PowerShot SX20 IS (CHDK hack)",
+ "Canon PowerShot SX30 IS (CHDK hack)",
+ "Canon EOS R",
+ "Canon EOS RP",
+ "Canon EOS R3",
+ "Canon EOS R5",
+ "Canon EOS R6",
+ "Canon EOS R7",
+ "Canon EOS R10",
+ "Canon EOS D30",
+ "Canon EOS D60",
+ "Canon EOS 5DS",
+ "Canon EOS 5DS R",
+ "Canon EOS 5D",
+ "Canon EOS 5D Mark II",
+ "Canon EOS 5D Mark III",
+ "Canon EOS 5D Mark IV",
+ "Canon EOS 6D",
+ "Canon EOS 6D Mark II",
+ "Canon EOS 7D",
+ "Canon EOS 7D Mark II",
+ "Canon EOS 10D",
+ "Canon EOS 20D",
+ "Canon EOS 20Da",
+ "Canon EOS 30D",
+ "Canon EOS 40D",
+ "Canon EOS 50D",
+ "Canon EOS 60D",
+ "Canon EOS 60Da",
+ "Canon EOS 70D",
+ "Canon EOS 77D / 9000D",
+ "Canon EOS 80D",
+ "Canon EOS 90D",
+ "Canon EOS 100D / Rebel SL1 / Kiss X7",
+ "Canon EOS 200D / Rebel SL2 / Kiss X9",
+ "Canon EOS 250D / 200D II / Rebel SL3 / Kiss X10",
+ "Canon EOS 300D / Digital Rebel / Kiss Digital",
+ "Canon EOS 350D / Digital Rebel XT / Kiss Digital N",
+ "Canon EOS 400D / Digital Rebel XTi / Kiss Digital X",
+ "Canon EOS 450D / Digital Rebel XSi / Kiss X2",
+ "Canon EOS 500D / Rebel T1i / Kiss X3",
+ "Canon EOS 550D / Rebel T2i / Kiss X4",
+ "Canon EOS 600D / Rebel T3i / Kiss X5",
+ "Canon EOS 650D / Rebel T4i / Kiss X6i",
+ "Canon EOS 700D / Rebel T5i / Kiss X7i",
+ "Canon EOS 750D / Rebel T6i / Kiss X8i",
+ "Canon EOS 760D / Rebel T6S / 8000D",
+ "Canon EOS 800D / Rebel T7i / Kiss X9i",
+ "Canon EOS 850D / Rebel T8i / Kiss X10i",
+ "Canon EOS 1000D / Digital Rebel XS / Kiss F",
+ "Canon EOS 1100D / Rebel T3 / Kiss X50",
+ "Canon EOS 1200D / Kiss X70 / REBEL T5 / Hi",
+ "Canon EOS 1300D / Rebel T6 / Kiss X80",
+ "Canon EOS 1500D / 2000D / Rebel T7 / Kiss X90",
+ "Canon EOS 3000D / 4000D / Rebel T100",
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ "Canon EOS C500",
+#endif
+ "Canon EOS D2000",
+ "Canon EOS M",
+ "Canon EOS M2",
+ "Canon EOS M3",
+ "Canon EOS M5",
+ "Canon EOS M6",
+ "Canon EOS M6 Mark II",
+ "Canon EOS M10",
+ "Canon EOS M50 / Kiss M",
+ "Canon EOS M50 Mark II",
+ "Canon EOS M100",
+ "Canon EOS M200",
+ "Canon EOS-1D C",
+ "Canon EOS-1D X",
+ "Canon EOS-1D X Mark II",
+ "Canon EOS-1D X Mark III",
+ "Canon EOS-1D",
+ "Canon EOS-1D Mark II",
+ "Canon EOS-1D Mark II N",
+ "Canon EOS-1D Mark III",
+ "Canon EOS-1D Mark IV",
+ "Canon EOS-1Ds",
+ "Canon EOS-1Ds Mark II",
+ "Canon EOS-1Ds Mark III",
+ "Casio QV-2000UX (secret menu hack)",
+ "Casio QV-3000EX (secret menu hack)",
+ "Casio QV-3500EX (secret menu hack)",
+ "Casio QV-4000 (secret menu hack)",
+ "Casio QV-5700 (secret menu hack)",
+ "Casio QV-R41",
+ "Casio QV-R51",
+ "Casio QV-R61",
+ "Casio EX-F1",
+ "Casio EX-FC300S",
+ "Casio EX-FC400S",
+ "Casio EX-FH20",
+ "Casio EX-FH25",
+ "Casio EX-FH100",
+ "Casio EX-S20 / M20",
+ "Casio EX-S100",
+ "Casio EX-Z4",
+ "Casio EX-Z50",
+ "Casio EX-Z500",
+ "Casio EX-Z55",
+ "Casio EX-Z60",
+ "Casio EX-Z75",
+ "Casio EX-Z750",
+ "Casio EX-Z8",
+ "Casio EX-Z850",
+ "Casio EX-Z1050",
+ "Casio EX-ZR100",
+ "Casio EX-Z1080",
+ "Casio EX-ZR700",
+ "Casio EX-ZR710",
+ "Casio EX-ZR750",
+ "Casio EX-ZR800",
+ "Casio EX-ZR850",
+ "Casio EX-ZR1000",
+ "Casio EX-ZR1100",
+ "Casio EX-ZR1200",
+ "Casio EX-ZR1300",
+ "Casio EX-ZR1500",
+ "Casio EX-ZR3000",
+ "Casio EX-ZR3100",
+ "Casio EX-ZR3200",
+ "Casio EX-ZR3500",
+ "Casio EX-ZR3600",
+ "Casio EX-ZR3700",
+ "Casio EX-ZR4000 / 5000",
+ "Casio EX-ZR4100 / 5100",
+ "Casio EX-100",
+ "Casio EX-100F",
+ "Casio EX-100PRO",
+ "Casio EX-10",
+ "Casio EX-P505 (secret menu hack)",
+ "Casio EX-P600 (secret menu hack)",
+ "Casio EX-P700 (secret menu hack)",
+ "CLAUSS pix500",
+ "Contax N Digital",
+ "Creative PC-CAM 600",
+ "Digital Bolex D16",
+ "Digital Bolex D16M",
+ "DJI 4384x3288",
+ "DJI Mavic Air",
+ "DJI Mavic Air2",
+ "DJI Mavic Air 2S",
+ "DJI Mavic Mini2",
+ "DJI Mavic 3",
+ "DJI Osmo Action",
+ "DJI Pocket",
+ "DJI Phantom4 Pro/Pro+",
+ "DJI Zenmuse X5",
+ "DJI Zenmuse X5R",
+ "DXO One",
+ "Epson R-D1",
+ "Epson R-D1s",
+ "Epson R-D1x",
+ "Eyedeas E1",
+ "Foculus 531C",
+ "FujiFilm DBP for GX680 / DX-2000",
+ "FujiFilm E550",
+ "FujiFilm E900",
+ "FujiFilm F500EXR / F505EXR",
+ "FujiFilm F550EXR",
+ "FujiFilm F600EXR / F605EXR",
+ "FujiFilm F700",
+ "FujiFilm F710",
+ "FujiFilm F770EXR / F775EXR",
+ "FujiFilm F800EXR",
+ "FujiFilm F810",
+ "FujiFilm F900EXR",
+ "FujiFilm S2Pro",
+ "FujiFilm S3Pro",
+ "FujiFilm S5Pro",
+ "FujiFilm S20Pro",
+ "FujiFilm S1",
+ "FujiFilm S100FS",
+ "FujiFilm S5000",
+ "FujiFilm S5100 / S5500",
+ "FujiFilm S5200 / S5600",
+ "FujiFilm S6000fd / S6500fd",
+ "FujiFilm S7000",
+ "FujiFilm S9000 / S9500",
+ "FujiFilm S9100 / S9600",
+ "FujiFilm S200EXR / S205EXR",
+ "FujiFilm SL1000",
+ "FujiFilm HS10/HS11",
+ "FujiFilm HS20EXR / HS22EXR",
+ "FujiFilm HS30EXR / HS33EXR / HS35EXR",
+ "FujiFilm HS50EXR",
+ "FujiFilm GFX 50S",
+ "FujiFilm GFX 50S II",
+ "FujiFilm GFX 50R",
+ "FujiFilm GFX 100",
+ "FujiFilm GFX 100S",
+ "FujiFilm X-Pro1",
+ "FujiFilm X-Pro2",
+ "FujiFilm X-Pro3",
+ "FujiFilm X-S1",
+ "FujiFilm XQ1",
+ "FujiFilm XQ2",
+ "FujiFilm X100",
+ "FujiFilm X100F",
+ "FujiFilm X100S",
+ "FujiFilm X100T",
+ "FujiFilm X100V",
+ "FujiFilm X10",
+ "FujiFilm X20",
+ "FujiFilm X30",
+ "FujiFilm X70",
+ "FujiFilm X-A1",
+ "FujiFilm X-A2",
+ "FujiFilm X-A3",
+ "FujiFilm X-A5",
+ "FujiFilm X-A7",
+ "FujiFilm X-A10",
+ "FujiFilm X-A20",
+ "FujiFilm X-E1",
+ "FujiFilm X-E2",
+ "FujiFilm X-E2S",
+ "FujiFilm X-E3",
+ "FujiFilm X-E4",
+ "FujiFilm X-M1",
+ "FujiFilm XF1",
+ "FujiFilm XF10",
+ "FujiFilm X-H1",
+ "FujiFilm X-H2S",
+ "FujiFilm X-T1",
+ "FujiFilm X-S10",
+ "FujiFilm X-T1 Graphite Silver",
+ "FujiFilm X-T2",
+ "FujiFilm X-T3",
+ "FujiFilm X-T4",
+ "FujiFilm X-T10",
+ "FujiFilm X-T20",
+ "FujiFilm X-T30",
+ "FujiFilm X-T30 II",
+ "FujiFilm X-T100",
+ "FujiFilm X-T200",
+ "FujiFilm IS-1",
+ "Gione E7",
+ "GITUP GIT2",
+ "GITUP GIT2P",
+ "GITUP G3 DUO (16:9 mode only)",
+ "Google Pixel",
+ "Google Pixel XL",
+ "Google Pixel 3a",
+ "Google Pixel 4 XL",
+ "Google Pixel 4a (5G)",
+ "Google Pixel 5",
+#ifdef USE_GPRSDK
+ "GoPro Fusion",
+ "GoPro HERO5",
+ "GoPro HERO6",
+ "GoPro HERO7",
+ "GoPro HERO8",
+ "GoPro HERO9",
+ "GoPro HERO10",
+#endif
+ "Hasselblad H2D-22",
+ "Hasselblad H2D-39",
+ "Hasselblad H3DII-22",
+ "Hasselblad H3DII-31",
+ "Hasselblad H3DII-39",
+ "Hasselblad H3DII-50",
+ "Hasselblad H3D-22",
+ "Hasselblad H3D-31",
+ "Hasselblad H3D-39",
+ "Hasselblad H4D-60",
+ "Hasselblad H4D-50",
+ "Hasselblad H4D-40",
+ "Hasselblad H4D-31",
+ "Hasselblad H5D-60",
+ "Hasselblad H5D-50",
+ "Hasselblad H5D-50c",
+ "Hasselblad H5D-40",
+ "Hasselblad H6D-100c",
+ "Hasselblad A6D-100c", // Aerial camera
+ "Hasselblad CFV",
+ "Hasselblad CFV-50",
+ "Hasselblad CFV II 50C",
+ "Hasselblad CFH",
+ "Hasselblad CF-22",
+ "Hasselblad CF-31",
+ "Hasselblad CF-39",
+ "Hasselblad V96C",
+ "Hasselblad L1D-20c (DJI Mavic 2 Pro)",
+ "Hasselblad Lusso",
+ "Hasselblad Lunar",
+ "Hasselblad True Zoom",
+ "Hasselblad Stellar",
+ "Hasselblad Stellar II",
+ "Hasselblad HV",
+ "Hasselblad X1D",
+ "Hasselblad X1D II 50C",
+ "HTC UltraPixel",
+ "HTC MyTouch 4G",
+ "HTC One (A9)",
+ "HTC One (M9)",
+ "HTC 10",
+ "HTC U12",
+ "Huawei P8 Lite (PRA-LX1)",
+ "Huawei P9 (EVA-L09/AL00)",
+ "Huawei P10 (VTR-L09)",
+ "Huawei P10+ (VKY-L09)",
+ "Huawei P10 Lite (WAS-LX1A)",
+ "Huawei P20 (EML-L09)",
+ "Huawei P20 Lite (ANE-LX1)",
+ "Huawei P20 Pro (CLT-L29/L09)",
+ "Huawei P30 Pro (VOG-L29)",
+ "Huawei Honor6a",
+ "Huawei Honor7a pro",
+ "Huawei Honor8 (FRD-L09)",
+ "Huawei Honor9",
+ "Huawei Honor10",
+ "Huawei Honor20",
+ "Huawei Honor View 10 (BKL-L09)",
+ "Huawei Honor View 20 (PCT-L29)",
+ "Huawei Honor 20 Pro (YAL-L41)",
+ "Huawei Mate8 (NXT-L29)",
+ "Huawei Mate10 (BLA-L29)",
+ "Huawei Mate20 Pro (LYA-L29)",
+ "Huawei Mate20 Lite (SNE-LX1)",
+ "Imacon Ixpress 96, 96C",
+ "Imacon Ixpress 384, 384C (single shot only)",
+ "Imacon Ixpress 132C",
+ "Imacon Ixpress 528C (single shot only)",
+ "ISG 2020x1520",
+ "Ikonoskop A-Cam dII Panchromatic",
+ "Ikonoskop A-Cam dII",
+ "Kandao QooCam 8K",
+ "Kinefinity KineMINI",
+ "Kinefinity KineRAW Mini",
+ "Kinefinity KineRAW S35",
+ "Kodak DC20",
+ "Kodak DC25",
+ "Kodak DC40",
+ "Kodak DC50",
+ "Kodak DC120",
+ "Kodak DCS200",
+ "Kodak DCS315C",
+ "Kodak DCS330C",
+ "Kodak DCS420",
+ "Kodak DCS460",
+ "Kodak DCS460M",
+ "Kodak DCS460",
+ "Kodak DCS520C",
+ "Kodak DCS560C",
+ "Kodak DCS620C",
+ "Kodak DCS620X",
+ "Kodak DCS660C",
+ "Kodak DCS660M",
+ "Kodak DCS720X",
+ "Kodak DCS760C",
+ "Kodak DCS760M",
+ "Kodak EOSDCS1",
+ "Kodak EOSDCS3",
+ "Kodak NC2000",
+ "Kodak ProBack",
+ "Kodak PB645C",
+ "Kodak PB645H",
+ "Kodak PB645M",
+ "Kodak DCS Pro 14n",
+ "Kodak DCS Pro 14nx",
+ "Kodak DCS Pro SLR/c",
+ "Kodak DCS Pro SLR/n",
+ "Kodak C330",
+ "Kodak C603",
+ "Kodak P850",
+ "Kodak P880",
+ "Kodak PIXPRO AZ901",
+ "Kodak PIXPRO S-1",
+ "Kodak Z980",
+ "Kodak Z981",
+ "Kodak Z990",
+ "Kodak Z1015",
+ "Kodak KAI-0340",
+ "Konica KD-400Z",
+ "Konica KD-510Z",
+ "Leaf AFi 5",
+ "Leaf AFi 6",
+ "Leaf AFi 7",
+ "Leaf AFi-II 6",
+ "Leaf AFi-II 7",
+ "Leaf AFi-II 10",
+ "Leaf AFi-II 10R",
+ "Leaf Aptus-II 5",
+ "Leaf Aptus-II 6",
+ "Leaf Aptus-II 7",
+ "Leaf Aptus-II 8",
+ "Leaf Aptus-II 10",
+ "Leaf Aptus-II 12",
+ "Leaf Aptus-II 12R",
+ "Leaf Aptus 17",
+ "Leaf Aptus 22",
+ "Leaf Aptus 54S",
+ "Leaf Aptus 65",
+ "Leaf Aptus 65S",
+ "Leaf Aptus 75",
+ "Leaf Aptus 75S",
+ "Leaf Cantare",
+ "Leaf Cantare XY",
+ "Leaf CatchLight",
+ "Leaf CMost",
+ "Leaf Credo 40",
+ "Leaf Credo 50",
+ "Leaf Credo 60",
+ "Leaf Credo 80",
+ "Leaf DCB-II",
+ "Leaf Valeo 6",
+ "Leaf Valeo 11",
+ "Leaf Valeo 17",
+ "Leaf Valeo 17wi",
+ "Leaf Valeo 22",
+ "Leaf Valeo 22wi",
+ "Leaf Volare",
+ "Lenovo a820",
+ "Leica C (Typ 112)",
+ "Leica CL",
+ "Leica C-Lux / CAM-DC25",
+ "Leica Digilux 2",
+ "Leica Digilux 3",
+ "Leica Digital-Modul-R",
+ "Leica D-LUX2",
+ "Leica D-LUX3",
+ "Leica D-LUX4",
+ "Leica D-LUX5",
+ "Leica D-LUX6",
+ "Leica D-LUX7",
+ "Leica D-Lux (Typ 109)",
+ "Leica M8",
+ "Leica M8.2",
+ "Leica M9",
+ "Leica M10",
+ "Leica M10-D",
+ "Leica M10-P",
+ "Leica M10-R",
+ "Leica M10 Monochrom",
+ "Leica M11",
+ "Leica M (Typ 240)",
+ "Leica M (Typ 262)",
+ "Leica Monochrom (Typ 240)",
+ "Leica Monochrom (Typ 246)",
+ "Leica M-D (Typ 262)",
+ "Leica M-E",
+ "Leica M-P",
+ "Leica R8",
+ "Leica Q (Typ 116)",
+ "Leica Q-P",
+ "Leica Q2",
+ "Leica Q2 Monochrom",
+ "Leica S",
+ "Leica S2",
+ "Leica S3",
+ "Leica S (Typ 007)",
+ "Leica SL (Typ 601)",
+ "Leica SL2",
+ "Leica SL2-S",
+ "Leica T (Typ 701)",
+ "Leica TL",
+ "Leica TL2",
+ "Leica X1",
+ "Leica X (Typ 113)",
+ "Leica X2",
+ "Leica X-E (Typ 102)",
+ "Leica X-U (Typ 113)",
+ "Leica V-LUX1",
+ "Leica V-LUX2",
+ "Leica V-LUX3",
+ "Leica V-LUX4",
+ "Leica V-LUX5",
+ "Leica V-Lux (Typ 114)",
+ "Leica X VARIO (Typ 107)",
+ "LG G3",
+ "LG G4",
+ "LG G5 (H850)",
+ "LG G6",
+ "LG V20 (F800K)",
+ "LG V20 (H910)",
+ "LG VS995",
+ "Logitech Fotoman Pixtura",
+ "Mamiya ZD",
+ "Matrix 4608x3288",
+ "Meizy MX4",
+ "Micron 2010",
+ "Minolta RD175 / Agfa ActionCam",
+ "Minolta DiMAGE 5",
+ "Minolta DiMAGE 7",
+ "Minolta DiMAGE 7i",
+ "Minolta DiMAGE 7Hi",
+ "Minolta DiMAGE A1",
+ "Minolta DiMAGE A2",
+ "Minolta DiMAGE A200",
+ "Minolta DiMAGE G400",
+ "Minolta DiMAGE G500",
+ "Minolta DiMAGE G530",
+ "Minolta DiMAGE G600",
+ "Minolta DiMAGE Z2",
+ "Minolta Alpha/Dynax/Maxxum 5D",
+ "Minolta Alpha/Dynax/Maxxum 7D",
+ "Motorola PIXL",
+ "Motorola Moto G (5S)",
+ "Motorola Moto G7 Play",
+ "Nikon D1",
+ "Nikon D1H",
+ "Nikon D1X",
+ "Nikon D2H",
+ "Nikon D2Hs",
+ "Nikon D2X",
+ "Nikon D2Xs",
+ "Nikon D3",
+ "Nikon D3s",
+ "Nikon D3X",
+ "Nikon D4",
+ "Nikon D4s",
+ "Nikon D40",
+ "Nikon D40X",
+ "Nikon D5",
+ "Nikon D50",
+ "Nikon D6",
+ "Nikon D60",
+ "Nikon D70",
+ "Nikon D70s",
+ "Nikon D80",
+ "Nikon D90",
+ "Nikon D100",
+ "Nikon D200",
+ "Nikon D300",
+ "Nikon D300s",
+ "Nikon D500",
+ "Nikon D600",
+ "Nikon D610",
+ "Nikon D700",
+ "Nikon D750",
+ "Nikon D780",
+ "Nikon D800",
+ "Nikon D800E",
+ "Nikon D810",
+ "Nikon D810A",
+ "Nikon D850",
+ "Nikon D3000",
+ "Nikon D3100",
+ "Nikon D3200",
+ "Nikon D3300",
+ "Nikon D3400",
+ "Nikon D3500",
+ "Nikon D5000",
+ "Nikon D5100",
+ "Nikon D5200",
+ "Nikon D5300",
+ "Nikon D5500",
+ "Nikon D5600",
+ "Nikon D7000",
+ "Nikon D7100",
+ "Nikon D7200",
+ "Nikon D7500",
+ "Nikon Df",
+ "Nikon Z 5",
+ "Nikon Z 6",
+ "Nikon Z 6 II",
+ "Nikon Z 7",
+ "Nikon Z 7 II",
+ "Nikon Z 9 (HE/HE* formats are not supported yet)",
+ "Nikon Z 50",
+ "Nikon Z fc",
+ "Nikon 1 AW1",
+ "Nikon 1 J1",
+ "Nikon 1 J2",
+ "Nikon 1 J3",
+ "Nikon 1 J4",
+ "Nikon 1 J5",
+ "Nikon 1 S1",
+ "Nikon 1 S2",
+ "Nikon 1 V1",
+ "Nikon 1 V2",
+ "Nikon 1 V3",
+ "Nikon Coolpix 700 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 800 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 880 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 900 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 950 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 990 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 995 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 2100 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 2500 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 3200 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 3700 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 4300 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 4500 (\"DIAG RAW\" hack)",
+ "Nikon Coolpix 5000",
+ "Nikon Coolpix 5400",
+ "Nikon Coolpix 5700",
+ "Nikon Coolpix 8400",
+ "Nikon Coolpix 8700",
+ "Nikon Coolpix 8800",
+ "Nikon Coolpix A",
+ "Nikon Coolpix A1000",
+ "Nikon Coolpix B700",
+ "Nikon Coolpix P330",
+ "Nikon Coolpix P340",
+ "Nikon Coolpix P950",
+ "Nikon Coolpix P6000",
+ "Nikon Coolpix P1000",
+ "Nikon Coolpix P7000",
+ "Nikon Coolpix P7100",
+ "Nikon Coolpix P7700",
+ "Nikon Coolpix P7800",
+ "Nikon Coolpix S6 (\"DIAG RAW\" hack)",
+ "Nikon Coolscan NEF",
+ "Nokia 7 Plus",
+ "Nokia 8.3 5G",
+ "Nokia 9",
+ "Nokia N95",
+ "Nokia X2",
+ "Nokia 1200x1600",
+ "Nokia Lumia 930",
+ "Nokia Lumia 950 XL",
+ "Nokia Lumia 1020",
+ "Nokia Lumia 1520",
+ "Olympus AIR A01",
+ "Olympus C-3030Z",
+ "Olympus C-5050Z",
+ "Olympus C-5060WZ",
+ "Olympus C-7070WZ",
+ "Olympus C-70Z / C-7000Z",
+ "Olympus C-740UZ",
+ "Olympus C-770UZ",
+ "Olympus C-8080WZ",
+ "Olympus X200 / D-560Z / C-350Z",
+ "Olympus E-1",
+ "Olympus E-3",
+ "Olympus E-5",
+ "Olympus E-10",
+ "Olympus E-20 / E-20N / E-20P",
+ "Olympus E-30",
+ "Olympus E-300",
+ "Olympus E-330",
+ "Olympus E-400",
+ "Olympus E-410",
+ "Olympus E-420",
+ "Olympus E-450",
+ "Olympus E-500",
+ "Olympus E-510",
+ "Olympus E-520",
+ "Olympus E-600",
+ "Olympus E-620",
+ "Olympus E-P1",
+ "Olympus E-P2",
+ "Olympus E-P3",
+ "Olympus E-P5",
+ "Olympus E-P7",
+ "Olympus E-PL1",
+ "Olympus E-PL1s",
+ "Olympus E-PL2",
+ "Olympus E-PL3",
+ "Olympus E-PL5",
+ "Olympus E-PL6",
+ "Olympus E-PL7",
+ "Olympus E-PL8",
+ "Olympus E-PL9",
+ "Olympus E-PL10",
+ "Olympus E-PM1",
+ "Olympus E-PM2",
+ "Olympus E-M1",
+ "Olympus E-M1 Mark II",
+ "Olympus E-M1 Mark III",
+ "Olympus E-M1X",
+ "Olympus E-M10",
+ "Olympus E-M10 Mark II",
+ "Olympus E-M10 Mark III",
+ "Olympus E-M10 Mark IV",
+ "Olympus E-M5",
+ "Olympus E-M5 Mark II",
+ "Olympus E-M5 Mark III",
+ "Olympus Pen-F",
+ "Olympus SP-310",
+ "Olympus SP-320",
+ "Olympus SP-350",
+ "Olympus SP-500UZ",
+ "Olympus SP-510UZ",
+ "Olympus SP-550UZ",
+ "Olympus SP-560UZ",
+ "Olympus SP-565UZ",
+ "Olympus SP-570UZ",
+ "Olympus Stylus 1",
+ "Olympus Stylus 1s",
+ "Olympus SH-2",
+ "Olympus SH-3",
+ "Olympus TG-4",
+ "Olympus TG-5",
+ "Olympus TG-6",
+ "Olympus XZ-1",
+ "Olympus XZ-2",
+ "Olympus XZ-10",
+ "OM Digital Solutions OM-1",
+ "OmniVision 4688",
+ "OmniVision OV5647",
+ "OmniVision OV5648",
+ "OmniVision OV8850",
+ "OmniVision 13860",
+ "OnePlus 6 (A6003)",
+ "OnePlus 6T",
+ "OnePlus 7 Pro (GM1913)",
+ "OnePlus 8 Pro (IN2023)",
+ "OnePlus One",
+ "OnePlus A3303",
+ "OnePlus A5000",
+ "Panasonic DMC-CM1",
+ "Panasonic DMC-FZ8",
+ "Panasonic DMC-FZ18",
+ "Panasonic DMC-FZ28",
+ "Panasonic DMC-FZ30",
+ "Panasonic DMC-FZ35 / FZ38",
+ "Panasonic DMC-FZ40 / FZ42 / FZ45",
+ "Panasonic DMC-FZ50",
+ "Panasonic DMC-FZ70 / FZ72",
+ "Panasonic DC-FZ80 / FZ81 / FZ82 / FZ83 / FZ85",
+ "Panasonic DMC-FZ100",
+ "Panasonic DMC-FZ150",
+ "Panasonic DMC-FZ200",
+ "Panasonic DMC-FZ300 / FZ330",
+ "Panasonic DMC-FZ1000",
+ "Panasonic DC-FZ1000 II / FZ1000M2 / DC-FZ10002",
+ "Panasonic DMC-FZ2000 / FZ2500 / FZH1",
+ "Panasonic DMC-FX150 / FX180",
+ "Panasonic DMC-G1",
+ "Panasonic DMC-G10",
+ "Panasonic DMC-G2",
+ "Panasonic DMC-G3",
+ "Panasonic DMC-G5",
+ "Panasonic DMC-G6",
+ "Panasonic DMC-G7 / G70",
+ "Panasonic DMC-G8 / G80 / G81 / G85",
+ "Panasonic DC-G9",
+ "Panasonic DC-G90 / G95 / G91 / G99",
+ "Panasonic DC-G100 / G110",
+ "Panasonic DMC-GF1",
+ "Panasonic DMC-GF2",
+ "Panasonic DMC-GF3",
+ "Panasonic DMC-GF5",
+ "Panasonic DMC-GF6",
+ "Panasonic DMC-GF7",
+ "Panasonic DC-GF10 / GF90",
+ "Panasonic DMC-GH1",
+ "Panasonic DMC-GH2",
+ "Panasonic DMC-GH3",
+ "Panasonic DMC-GH4",
+ "Panasonic AG-GH4",
+ "Panasonic DC-GH5",
+ "Panasonic DC-GH5S",
+ "Panasonic DC-GH5 Mark II",
+ "Panasonic DMC-GM1",
+ "Panasonic DMC-GM1s",
+ "Panasonic DMC-GM5",
+ "Panasonic DMC-GX1",
+ "Panasonic DMC-GX7",
+ "Panasonic DMC-GX8",
+ "Panasonic DC-GX9 / GX7mkIII",
+ "Panasonic DMC-GX80 / GX85, DMC-GX7mkII",
+ "Panasonic DC-GX800 / GX850, DC-GF9",
+ "Panasonic DMC-L1",
+ "Panasonic DMC-L10",
+ "Panasonic DMC-LC1",
+ "Panasonic DMC-LF1",
+ "Panasonic DMC-LX1",
+ "Panasonic DMC-LX2",
+ "Panasonic DMC-LX3",
+ "Panasonic DMC-LX5",
+ "Panasonic DMC-LX7",
+ "Panasonic DMC-LX9 / LX10 / LX15",
+ "Panasonic DMC-LX100",
+ "Panasonic DC-LX100M2",
+ "Panasonic DC-S1",
+ "Panasonic DC-S1H",
+ "Panasonic DC-S1R",
+ "Panasonic DC-S5",
+ "Panasonic DMC-ZS40, DMC-TZ60 / TZ61",
+ "Panasonic DMC-ZS50, DMC-TZ70 / TZ71",
+ "Panasonic DMC-ZS60, DMC-TZ80 / TZ81 / TZ82 / TZ85",
+ "Panasonic DC-ZS70, DC-TZ90 / TZ91 / TZ92 / TZ93",
+ "Panasonic DC-ZS80, DC-TZ95 / TZ96 / TZ97",
+ "Panasonic DMC-ZS100 / ZS110, DMC-TZ100 / TZ101 / TZ110, DMC-TX1",
+ "Panasonic DC-ZS200 / ZS220, DC-TZ200 / TZ202 / TZ220, DC-TX2",
+ "PARROT Anafi",
+ "PARROT Bebop 2",
+ "PARROT Bebop Drone",
+ "Pentax *ist D",
+ "Pentax *ist DL",
+ "Pentax *ist DL2",
+ "Pentax *ist DS",
+ "Pentax *ist DS2",
+ "Pentax K10D",
+ "Pentax K20D",
+ "Pentax K100D",
+ "Pentax K100D Super",
+ "Pentax K110D",
+ "Pentax K200D",
+ "Pentax K2000/K-m",
+ "Pentax KP",
+ "Pentax K-x",
+ "Pentax K-r",
+ "Pentax K-01",
+ "Pentax K-1",
+ "Pentax K-1 Mark II",
+ "Pentax K-3",
+ "Pentax K-3 Mark II",
+ "Pentax K-3 Mark III",
+ "Pentax K-30",
+ "Pentax K-5",
+ "Pentax K-5 II",
+ "Pentax K-5 IIs",
+ "Pentax K-50",
+ "Pentax K-500",
+ "Pentax K-7",
+ "Pentax K-70",
+ "Pentax K-S1",
+ "Pentax K-S2",
+ "Pentax MX-1",
+ "Pentax Q",
+ "Pentax Q7",
+ "Pentax Q10",
+ "Pentax QS-1",
+ "Pentax Optio S (secret menu or hack)",
+ "Pentax Optio S4 (secret menu or hack)",
+ "Pentax Optio 33WR (secret menu or hack)",
+ "Pentax Optio 750Z (secret menu or hack)",
+ "Pentax 645D",
+ "Pentax 645Z",
+ "PhaseOne IQ140",
+ "PhaseOne IQ150",
+ "PhaseOne IQ160",
+ "PhaseOne IQ180",
+ "PhaseOne IQ180 IR",
+ "PhaseOne IQ250",
+ "PhaseOne IQ260",
+ "PhaseOne IQ260 Achromatic",
+ "PhaseOne IQ280",
+ "PhaseOne IQ3 50MP",
+ "PhaseOne IQ3 60MP",
+ "PhaseOne IQ3 80MP",
+ "PhaseOne IQ3 100MP",
+ "PhaseOne IQ3 100MP Trichromatic",
+ "PhaseOne IQ4 150MP",
+ "PhaseOne LightPhase",
+ "PhaseOne Achromatic+",
+ "PhaseOne H 10",
+ "PhaseOne H 20",
+ "PhaseOne H 25",
+ "PhaseOne P 20",
+ "PhaseOne P 20+",
+ "PhaseOne P 21",
+ "PhaseOne P 25",
+ "PhaseOne P 25+",
+ "PhaseOne P 30",
+ "PhaseOne P 30+",
+ "PhaseOne P 40+",
+ "PhaseOne P 45",
+ "PhaseOne P 45+",
+ "PhaseOne P 65",
+ "PhaseOne P 65+",
+ "Photron BC2-HD",
+ "Pixelink A782",
+#ifdef USE_X3FTOOLS
+ "Polaroid x530",
+#endif
+ "RaspberryPi Camera",
+ "RaspberryPi Camera V2",
+#ifdef USE_6BY9RPI
+ "RaspberryPi HQ Camera",
+#endif
+ "Ricoh GR",
+ "Realme 3 Pro",
+ "Ricoh GR II",
+ "Ricoh GR III",
+ "Ricoh GR IIIx",
+ "Ricoh GR Digital",
+ "Ricoh GR Digital II",
+ "Ricoh GR Digital III",
+ "Ricoh GR Digital IV",
+ "Ricoh Caplio GX100",
+ "Ricoh Caplio GX200",
+ "Ricoh GXR Mount A12",
+ "Ricoh GXR GR Lens A12 50mm F2.5 Macro",
+ "Ricoh GXR GR Lens A12 28mm F2.5",
+ "Ricoh GXR Ricoh Lens A16 24-85mm F3.5-5.5",
+ "Ricoh GXR Ricoh Lens S10 24-72mm F2.5-4.4 VC",
+ "Ricoh GXR Ricoh Lens P10 28-300 mm F3.5-5.6 VC",
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+#ifndef NO_JASPER
+ "Redcode R3D format",
+#endif
+#endif
+ "Rollei d530flex",
+ "RoverShot 3320af",
+ "Samsung EX1 / TL500",
+ "Samsung EX2F",
+ "Samsung GX-1L",
+ "Samsung GX-1S",
+ "Samsung GX10",
+ "Samsung GX20",
+ "Samsung Galaxy Nexus",
+ "Samsung Galaxy Note 9",
+ "Samsung Galaxy NX (EK-GN120)",
+ "Samsung Galaxy S3",
+ "Samsung Galaxy S6 (SM-G920F)",
+ "Samsung Galaxy S7",
+ "Samsung Galaxy S7 Edge",
+ "Samsung Galaxy S8 (SM-G950U)",
+ "Samsung Galaxy S9 (SM-G960F)",
+ "Samsung Galaxy S9+ (SM-G965U / 965F)",
+ "Samsung Galaxy S10 (SM-G973F)",
+ "Samsung Galaxy S10+ (SM-G975U)",
+ "Samsung NX1",
+ "Samsung NX5",
+ "Samsung NX10",
+ "Samsung NX11",
+ "Samsung NX100",
+ "Samsung NX1000",
+ "Samsung NX1100",
+ "Samsung NX20",
+ "Samsung NX200",
+ "Samsung NX210",
+ "Samsung NX2000",
+ "Samsung NX30",
+ "Samsung NX300",
+ "Samsung NX300M",
+ "Samsung NX3000",
+ "Samsung NX500",
+ "Samsung NX mini / NXF1",
+ "Samsung Pro815",
+ "Samsung WB550 / WB560 / HZ15W",
+ "Samsung WB2000 / TL350",
+ "Samsung WB5000 / HZ25W",
+ "Samsung S85 (hacked)",
+ "Samsung S850 (hacked)",
+ "Sarnoff 4096x5440",
+ "Seitz 6x17",
+ "Seitz Roundshot D3",
+ "Seitz Roundshot D2X",
+ "Seitz Roundshot D2Xs",
+ "Sigma fp",
+#ifdef USE_X3FTOOLS
+ "Sigma SD9 (raw decode only)",
+ "Sigma SD10 (raw decode only)",
+ "Sigma SD14 (raw decode only)",
+ "Sigma SD15 (raw decode only)",
+ "Sigma SD1",
+ "Sigma SD1 Merrill",
+ "Sigma DP1",
+ "Sigma DP1 Merrill",
+ "Sigma DP1S",
+ "Sigma DP1X",
+ "Sigma DP2",
+ "Sigma DP2 Merrill",
+ "Sigma DP2S",
+ "Sigma DP2X",
+ "Sigma DP3 Merrill",
+ "Sigma dp0 Quattro",
+ "Sigma dp1 Quattro",
+ "Sigma dp2 Quattro",
+ "Sigma dp3 Quattro",
+ "Sigma sd Quattro",
+ "Sigma sd Quattro H",
+#else
+ "Sigma dp0 Quattro (DNG only)",
+ "Sigma dp1 Quattro (DNG only)",
+ "Sigma dp2 Quattro (DNG only)",
+ "Sigma dp3 Quattro (DNG only)",
+ "Sigma sd Quattro (DNG only)",
+ "Sigma sd Quattro H (DNG only)",
+#endif
+ "Sinar eMotion 22",
+ "Sinar eMotion 54",
+ "Sinar eSpirit 65",
+ "Sinar eMotion 75",
+ "Sinar eVolution 75",
+ "Sinar 3072x2048 (Sinarback 23)",
+ "Sinar 4080x4080 (Sinarback 44)",
+ "Sinar 4080x5440",
+ "Sinar STI format",
+ "Sinar Sinarback 54",
+ "SMaL Ultra-Pocket 3",
+ "SMaL Ultra-Pocket 4",
+ "SMaL Ultra-Pocket 5",
+ "Sony ILCE-1 (A1)",
+ "Sony ILCE-7 (A7)",
+ "Sony ILCE-7M2 (A7 II)",
+ "Sony ILCE-7M3 (A7 III)",
+ "Sony ILCE-7M4 (A7 IV)",
+ "Sony ILCE-7C (A7C)",
+ "Sony ILCE-7R (A7R)",
+ "Sony ILCE-7RM2 (A7R II)",
+ "Sony ILCE-7RM3 (A7R III)",
+ "Sony ILCE-7RM3A (A7R IIIA)",
+ "Sony ILCE-7RM4 (A7R IV)",
+ "Sony ILCE-7RM4A (A7R IVA)",
+ "Sony ILCE-7S (A7S)",
+ "Sony ILCE-7SM2 (A7S II)",
+ "Sony ILCE-7SM3 (A7S III)",
+ "Sony ILCE-9 (A9)",
+ "Sony ILCE-9M2 (A9 II)",
+ "Sony ILCA-68 (A68)",
+ "Sony ILCA-77M2 (A77-II)",
+ "Sony ILCA-99M2 (A99-II)",
+ "Sony ILCE-3000 / 3500",
+ "Sony ILCE-5000",
+ "Sony ILCE-5100",
+ "Sony ILCE-6000",
+ "Sony ILCE-6100",
+ "Sony ILCE-6300",
+ "Sony ILCE-6400",
+ "Sony ILCE-6500",
+ "Sony ILCE-6600",
+ "Sony ILCE-QX1",
+ "Sony DSC-F828",
+ "Sony DSC-HX95",
+ "Sony DSC-HX99",
+ "Sony DSC-R1",
+ "Sony DSC-RX0",
+ "Sony DSC-RX0 II",
+ "Sony DSC-RX1",
+ "Sony DSC-RX1R",
+ "Sony DSC-RX1R II",
+ "Sony DSC-RX10",
+ "Sony DSC-RX10 II",
+ "Sony DSC-RX10 III",
+ "Sony DSC-RX10 IV",
+ "Sony DSC-RX100",
+ "Sony DSC-RX100 II",
+ "Sony DSC-RX100 III",
+ "Sony DSC-RX100 IV",
+ "Sony DSC-RX100 V",
+ "Sony DSC-RX100 VA",
+ "Sony DSC-RX100 VI",
+ "Sony DSC-RX100 VII",
+ "Sony DSC-V3",
+ "Sony DSLR-A100",
+ "Sony DSLR-A200",
+ "Sony DSLR-A230",
+ "Sony DSLR-A290",
+ "Sony DSLR-A300",
+ "Sony DSLR-A330",
+ "Sony DSLR-A350",
+ "Sony DSLR-A380 / A390",
+ "Sony DSLR-A450",
+ "Sony DSLR-A500",
+ "Sony DSLR-A550",
+ "Sony DSLR-A560",
+ "Sony DSLR-A580",
+ "Sony DSLR-A700",
+ "Sony DSLR-A850",
+ "Sony DSLR-A900",
+ "Sony NEX-3",
+ "Sony NEX-3N",
+ "Sony NEX-5",
+ "Sony NEX-5N",
+ "Sony NEX-5R",
+ "Sony NEX-5T",
+ "Sony NEX-6",
+ "Sony NEX-7",
+ "Sony NEX-C3",
+ "Sony NEX-F3",
+ "Sony NEX-VG20",
+ "Sony NEX-VG30",
+ "Sony NEX-VG900",
+ "Sony SLT-A33",
+ "Sony SLT-A35",
+ "Sony SLT-A37",
+ "Sony SLT-A55(V)",
+ "Sony SLT-A57",
+ "Sony SLT-A58",
+ "Sony SLT-A65(V)",
+ "Sony SLT-A77(V)",
+ "Sony SLT-A99(V)",
+ "Sony XCD-SX910CR",
+ "Sony IMX135-mipi 13mp",
+ "Sony IMX135-QCOM",
+ "Sony IMX072-mipi",
+ "Sony IMX214",
+ "Sony IMX219",
+ "Sony IMX230",
+ "Sony IMX298-mipi 16mp",
+ "Sony IMX219-mipi 8mp",
+ "Sony Xperia 5 II (XQ-AS52)",
+ "Sony Xperia L",
+ "Sony Xperia 1 III",
+ "Sony ZV-1 (DCZV1/B)",
+ "Sony ZV-E10",
+ "STV680 VGA",
+ "PtGrey GRAS-50S5C",
+ "JaiPulnix BB-500CL",
+ "JaiPulnix BB-500GE",
+ "SVS SVS625CL",
+ "Vivo X51 5G (V2006)",
+ "Yi M1",
+ "YUNEEC CGO3",
+ "YUNEEC CGO3P",
+ "YUNEEC CGO4",
+ "Xiaomi MI3",
+ "Xiaomi MI 8",
+ "Xiaomi MI 9 Lite",
+ "Xiaomi MI MAX",
+ "Xiaomi POCO M3",
+ "Xiaomi RedMi Note3 Pro",
+ "Xiaomi RedMi Note7",
+ "Xiaomi RedMi Note 8T",
+ "Xiaomi FIMI X8SE",
+ "Xiaoyi YIAC3 (YI 4k)",
+ "Zeiss ZX1",
+ "Zenit M",
+ NULL
+};
+// clang-format on
+
+const char **LibRaw::cameraList() { return static_camera_list; }
+int LibRaw::cameraCount()
+{
+ return (sizeof(static_camera_list) / sizeof(static_camera_list[0])) - 1;
+}
diff --git a/libkdcraw/libraw/src/tables/colorconst.cpp b/libkdcraw/libraw/src/tables/colorconst.cpp
new file mode 100644
index 0000000..ad5a649
--- /dev/null
+++ b/libkdcraw/libraw/src/tables/colorconst.cpp
@@ -0,0 +1,57 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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"
+
+const double LibRaw_constants::xyz_rgb[3][3] = {
+ {0.4124564, 0.3575761, 0.1804375},
+ {0.2126729, 0.7151522, 0.0721750},
+ {0.0193339, 0.1191920, 0.9503041}};
+
+const float LibRaw_constants::d65_white[3] = {0.95047f, 1.0f, 1.08883f};
+
+const double LibRaw_constants::xyzd50_srgb[3][3] = {
+ {0.436083, 0.385083, 0.143055},
+ {0.222507, 0.716888, 0.060608},
+ {0.013930, 0.097097, 0.714022}};
+const double LibRaw_constants::rgb_rgb[3][3] = {
+ {1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+const double LibRaw_constants::adobe_rgb[3][3] = {
+ {0.715146, 0.284856, 0.000000},
+ {0.000000, 1.000000, 0.000000},
+ {0.000000, 0.041166, 0.958839}};
+const double LibRaw_constants::wide_rgb[3][3] = {
+ {0.593087, 0.404710, 0.002206},
+ {0.095413, 0.843149, 0.061439},
+ {0.011621, 0.069091, 0.919288}};
+const double LibRaw_constants::prophoto_rgb[3][3] = {
+ {0.529317, 0.330092, 0.140588},
+ {0.098368, 0.873465, 0.028169},
+ {0.016879, 0.117663, 0.865457}};
+const double LibRaw_constants::aces_rgb[3][3] = {
+// Coffin's values (commented out) are not adapted from ACES "D60-like" WP to D65
+// {0.432996, 0.375380, 0.189317},
+// {0.089427, 0.816523, 0.102989},
+// {0.019165, 0.118150, 0.941914}};
+ {0.43968015, 0.38295299, 0.17736686},
+ {0.08978964, 0.81343316, 0.09677734},
+ {0.01754827, 0.11156156, 0.87089017}};
+const double LibRaw_constants::dcip3d65_rgb[3][3] = {
+ {0.822488, 0.177511, 0.000000},
+ {0.033200, 0.966800, 0.000000},
+ {0.017089, 0.072411, 0.910499}};
+const double LibRaw_constants::rec2020_rgb[3][3] = {
+ {0.627452, 0.329249, 0.043299},
+ {0.069109, 0.919531, 0.011360},
+ {0.016398, 0.088030, 0.895572}};
diff --git a/libkdcraw/libraw/src/tables/colordata.cpp b/libkdcraw/libraw/src/tables/colordata.cpp
new file mode 100644
index 0000000..fc9f100
--- /dev/null
+++ b/libkdcraw/libraw/src/tables/colordata.cpp
@@ -0,0 +1,1841 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+/*
+ All matrices are from Adobe DNG Converter unless otherwise noted.
+ */
+int LibRaw::adobe_coeff(unsigned make_idx, const char *t_model,
+ int internal_only)
+{
+ // clang-format off
+ static const struct
+ {
+ unsigned m_idx;
+ const char *prefix;
+ int t_black, t_maximum, trans[12];
+ } table[] = {
+ { LIBRAW_CAMERAMAKER_Agfa, "DC-833m", 0, 0,
+ { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Apple, "QuickTake", 0, 0,
+ { 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Broadcom, "RPi IMX219", 66, 0x3ff,
+ { 5302,1083,-728,-5320,14112,1699,-863,2371,5136 } }, /* LibRaw */
+ { LIBRAW_CAMERAMAKER_Broadcom, "RPi OV5647", 16, 0x3ff,
+ { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Broadcom, "Pi", 16, 0x3ff,
+ { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, /* DJC */
+
+#ifdef USE_6BY9RPI // this code normalizes model to LIBRAW_CAMERAMAKER_RaspberryPi
+ { LIBRAW_CAMERAMAKER_RaspberryPi, "RP_imx477", 0, 0, // Do not set black, it is set at parser to 256 or 64
+ { 5603, -1351, -600, -2872, 11180, 2132, 600, 453, 5821 } }, /* PyDNG */
+ { LIBRAW_CAMERAMAKER_RaspberryPi, "RP_imx", 66, 0x3ff,
+ { 5302,1083,-728,-5320,14112,1699,-863,2371,5136 } }, /* LibRaw */
+ { LIBRAW_CAMERAMAKER_RaspberryPi, "ov5647", 16, 0x3ff,
+ { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, /* DJC */
+#endif
+ { LIBRAW_CAMERAMAKER_Canon, "EOS D30", 0, 0,
+ { 9900,-2771,-1324,-7072,14229,3140,-2790,3344,8861 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS D60", 0, 0xfa0,
+ { 6211,-1358,-896,-8557,15766,3012,-3001,3507,8567 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 5DS", 0, 0x3c96, // same CMs: 5DS, "5DS R" */
+ { 6250,-711,-808,-5153,12794,2636,-1249,2198,5610 } }, // v.2
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 5D Mark IV", 0, 0,
+ { 6446,-366,-864,-4436,12204,2513,-952,2496,6348 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 5D Mark III", 0, 0x3c80,
+ { 6722,-635,-963,-4287,12460,2028,-908,2162,5668 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 5D Mark II", 0, 0x3cf0,
+ { 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 5D", 0, 0xe6c,
+ { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 6D Mark II", 0, 0x38de,
+ { 6875,-970,-932,-4691,12459,2501,-874,1953,5809 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 6D", 0, 0x3c82,
+ { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 77D", 0, 0,
+ { 7377,-742,-998,-4235,11981,2549,-673,1918,5538 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 7D Mark II", 0, 0x3510,
+ { 7268,-1082,-969,-4186,11839,2663,-825,2029,5839 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 7D", 0, 0x3510,
+ { 6844,-996,-856,-3876,11761,2396,-593,1772,6198 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 850D", 0, 0,
+ { 9079,-1923,-1236,-4677,12454,2492,-922,2319,5565}},
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 800D", 0, 0,
+ { 6970,-512,-968,-4425,12161,2553,-739,1982,5601 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 80D", 0, 0,
+ { 7457,-671,-937,-4849,12495,2643,-1213,2354,5492 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 10D", 0, 0xfa0,
+ { 8250,-2044,-1127,-8092,15606,2664,-2893,3453,8348 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 250D", 0, 0,
+ { 9079,-1923,-1236,-4677,12454,2492,-922,2319,5565 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 200D", 0, 0,
+ { 7377,-742,-998,-4235,11981,2549,-673,1918,5538 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 20Da", 0, 0,
+ { 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 20D", 0, 0xfff,
+ { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 30D", 0, 0,
+ { 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 40D", 0, 0x3f60,
+ { 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 50D", 0, 0x3d93,
+ { 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 60Da", 0, 0x2ff7,
+ { 17492,-7240,-2023,-1791,10323,1701,-186,1329,5406 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 60D", 0, 0x2ff7,
+ { 6719,-994,-925,-4408,12426,2211,-887,2129,6051 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 70D", 0, 0x3bc7,
+ { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 100D", 0, 0x350f,
+ { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 300D", 0, 0xfa0,
+ { 8250,-2044,-1127,-8092,15606,2664,-2893,3453,8348 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 350D", 0, 0xfff,
+ { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 3000D", 0, 0,
+ { 6939,-1016,-866,-4428,12473,2177,-1175,2178,6162 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 400D", 0, 0xe8e,
+ { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 450D", 0, 0x390d,
+ { 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 500D", 0, 0x3479,
+ { 4763,712,-646,-6821,14399,2640,-1921,3276,6561 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 550D", 0, 0x3dd7,
+ { 6941,-1164,-857,-3825,11597,2534,-416,1540,6039 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 600D", 0, 0x3510,
+ { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 650D", 0, 0x354d,
+ { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 750D", 0, 0x3c00,
+ { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 760D", 0, 0x3c00,
+ { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 700D", 0, 0x3c00,
+ { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 90D", 0, 0,
+ { 11498, -3759, -1516, -5073, 12954, 2349, -892, 1867, 6118}},
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 1000D", 0, 0xe43,
+ { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 1100D", 0, 0x3510,
+ { 6444,-904,-893,-4563,12308,2535,-903,2016,6728 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 1200D", 0, 0x37c2,
+ { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 1300D", 0, 0x37c2,
+ { 6939,-1016,-866,-4428,12473,2177,-1175,2178,6162 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS 1500D", 0, 0,
+ { 8300,-2110,-1120,-4917,12694,2482,-938,2141,5666 } }, // v.2
+
+ { LIBRAW_CAMERAMAKER_Canon, "EOS RP", 0, 0,
+ { 8608,-2097,-1178,-5425,13265,2383,-1149,2238,5680 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS R3", 0, 0,
+ { 9423,-2839,-1195,-4532,12377,2415,-483,1374,5276 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS R5", 0, 0,
+ { 9766,-2953,-1254,-4276,12116,2433,-437,1336,5131 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS R6", 0, 0,
+ { 8293,-1611,-1132,-4759,12711,2275,-1013,2415,5509 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS R7", 0, 0,
+ { 10424, -3138, -1300, -4221, 11938, 2584, -547, 1658, 6183 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS R10", 0, 0,
+ { 9269, -2012, -1107, -3990, 11762, 2527, -569, 2093, 4913 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS R", 0, 0,
+ { 8293,-1789,-1094,-5025,12925,2327,-1199,2769,6108 } }, // v.2
+
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M6 Mark II", 0, 0,
+ { 11498,-3759,-1516,-5073,12954,2349,-892,1867,6118 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M6", 0, 0,
+ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M50 Mark II", 0, 0,
+ { 10463,-2173,-1437,-4856,12635,2482,-1216,2915,7237 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M50", 0, 0,
+ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M5", 0, 0,
+ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M3", 0, 0,
+ { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M200", 0, 0,
+ { 10463,-2173,-1437,-4856,12635,2482,-1216,2915,7237 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M2", 0, 0,
+ { 6400,-480,-888,-5294,13416,2047,-1296,2203,6137 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M100", 0, 0,
+ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M10", 0, 0,
+ { 6400,-480,-888,-5294,13416,2047,-1296,2203,6137 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS M", 0, 0,
+ { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
+
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1Ds Mark III", 0, 0x3bb0,
+ { 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1Ds Mark II", 0, 0xe80,
+ { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1D Mark IV", 0, 0x3bb0,
+ { 6014,-220,-795,-4109,12014,2361,-561,1824,5787 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1D Mark III", 0, 0x3bb0,
+ { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1D Mark II N", 0, 0xe80,
+ { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1D Mark II", 0, 0xe80,
+ { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1Ds", 0, 0xe20,
+ { 3925,4060,-1739,-8973,16552,2545,-3287,3945,8243 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1D C", 0, 0x3c4e,
+ { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1D X Mark III", 0, 0,
+ { 8971, -2022, -1242, -5405, 13249, 2380, -1280, 2483, 6072}},
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1D X Mark II", 0, 0x3c4e,
+ { 7596,-978,-967,-4808,12571,2503,-1398,2567,5752 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1D X", 0, 0x3c4e,
+ { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS-1D", 0, 0xe20,
+ { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS C500", 853, 0,
+ { 17851,-10604,922,-7425,16662,763,-3660,3636,22278 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Canon, "IXUS 160", 0, 0,
+ { 11657,-3781,-1136,-3544,11262,2283,-160,1219,4700 } }, /* DJC */
+ {LIBRAW_CAMERAMAKER_Canon, "PowerShot 600", 0, 0,
+ { -3822,10019,1311,4085,-157,3386,-5341,10829,4812,-1969,10969,1126 } },
+
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A3300 IS", 0, 0,
+ { 10826,-3654,-1023,-3215,11310,1906,0,999,4960 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A460", 0, 0,
+ { 6493,-2338,-885,-1589,5934,697,-445,1368,2543 } }, // CHDK
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A470", 0, 0,
+ { 12513,-4407,-1242,-2680,10276,2405,-878,2215,4734 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A530", 0, 0,
+ { 7252,-2405,-1223,-2102,6560,523,-112,704,3007 } }, // CHDK
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A50", 0, 0,
+ { -6233,10706,1825,3260,821,3980,-6512,10745,6287,-2539,12232,262 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A5", 0, 0,
+ { -5707,10308,2002,2662,1829,4139,-6265,11063,6033,-2659,11911,593 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A610", 0, 0,
+ { 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A620", 0, 0,
+ { 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A630", 0, 0,
+ { 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A640", 0, 0,
+ { 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A650 IS", 0, 0,
+ { 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot A720 IS", 0, 0,
+ { 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot D10", 127, 0,
+ { 14052,-5229,-1156,-1325,9420,2252,-498,1957,4116 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G10", 0, 0,
+ { 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G11", 0, 0,
+ { 12177,-4817,-1069,-1612,9864,2049,-98,850,4471 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G12", 0, 0,
+ { 13244,-5501,-1248,-1508,9858,1935,-270,1083,4366 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G15", 0, 0,
+ { 7474,-2301,-567,-4056,11456,2975,-222,716,4181 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G16", 0, 0,
+ { 8020,-2687,-682,-3704,11879,2052,-965,1921,5556 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G1 X Mark III", 0, 0,
+ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G1 X Mark II", 0, 0,
+ { 7378,-1255,-1043,-4088,12251,2048,-876,1946,5805 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G1 X", 0, 0,
+ { 7378,-1255,-1043,-4088,12251,2048,-876,1946,5805 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G1", 0, 0,
+ { -5686,10300,2223,4725,-1157,4383,-6128,10783,6163,-2688,12093,604 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G2", 0, 0,
+ { 9194,-2787,-1059,-8098,15657,2608,-2610,3064,7867 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G3 X", 0, 0,
+ { 9701,-3857,-921,-3149,11537,1817,-786,1817,5147 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G3", 0, 0,
+ { 9326,-2882,-1084,-7940,15447,2677,-2620,3090,7740 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G5 X Mark II",0, 0,
+ { 11629, -5713, -914, -2706, 11090, 1842, -206, 1225, 5515 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G5 X",0, 0,
+ { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G5", 0, 0,
+ { 9869,-2972,-942,-7314,15098,2369,-1898,2536,7282 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G6", 0, 0,
+ { 9876,-3774,-871,-7613,14807,3071,-1448,1305,7485 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G7 X Mark III", 0, 0,
+ { 11629, -5713, -914, -2706, 11090, 1842, -206, 1225, 5515 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G7 X Mark II", 0, 0,
+ { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G7 X", 0, 0,
+ { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G9 X Mark II", 0, 0,
+ { 10056,-4131,-944,-2576,11143,1625,-238,1294,5179 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G9 X",0, 0,
+ { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot G9", 0, 0,
+ { 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } },
+
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S2 IS", 0, 0,
+ { 5477,-1435,-992,-1868,6639,510,-58,792,2670 } }, // CHDK
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S3 IS", 0, 0,
+ { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S30", 0, 0,
+ { 10744,-3813,-1142,-7962,15966,2075,-2492,2805,7744 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S40", 0, 0,
+ { 8606,-2573,-949,-8237,15489,2974,-2649,3076,9100 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S45", 0, 0, // +
+ { 8251,-2410,-964,-8047,15430,2823,-2380,2824,8119 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S50", 0, 0,
+ { 8979,-2658,-871,-7721,15500,2357,-1773,2366,6634 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S60", 0, 0,
+ { 8794,-2482,-797,-7804,15403,2572,-1422,1996,7083 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S70", 0, 0,
+ { 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S90", 0, 0,
+ { 12374,-5016,-1049,-1677,9902,2078,-83,852,4683 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S95", 0, 0,
+ { 13440,-5896,-1279,-1236,9598,1931,-180,1001,4651 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S120", 0, 0,
+ { 6961,-1685,-695,-4625,12945,1836,-1114,2152,5518 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S110", 0, 0,
+ { 8039,-2643,-654,-3783,11230,2930,-206,690,4194 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot S100", 0, 0,
+ { 7968,-2565,-636,-2873,10697,2513,180,667,4211 } },
+
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SD300", 0, 0,
+ { 6526,-1720,-1075,-1390,5945,602,-90,820,2380 } }, // CHDK
+
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX1 IS", 0, 0,
+ { 6578,-259,-502,-5974,13030,3309,-308,1058,4970 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX20 IS", 0, 0,
+ { 8275,-2904,-1260,-128,5305,505,51,481,2450 } }, // CHDK
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX30 IS", 0, 0,
+ { 13014,-4698,-1026,-2001,9615,2386,-164,1423,3759 } }, // CHDK
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX40 HS", 0, 0,
+ { 54480,-17404,-8039,-7505,44044,1136,-580,7158,11891 } }, // CHDK
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX50 HS", 0, 0,
+ { 12432,-4753,-1247,-2110,10691,1629,-412,1623,4926 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX60 HS", 0, 0,
+ { 13161,-5451,-1344,-1989,10654,1531,-47,1271,4955 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX70 HS", 0, 0,
+ { 18285,-8907,-1951,-1845,10688,1323,364,1101,5139 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX110 IS", 0, 0,
+ { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX120 IS", 0, 0,
+ { 7286,-2242,-1047,41,4401,457,269,684,1864 } }, // CHDK
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX220 HS", 0, 0,
+ { 13898,-5076,-1447,-1405,10109,1297,-244,1860,3687 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot SX710 HS", 0, 0,
+ { 13161,-5451,-1344,-1989,10654,1531,-47,1271,4955 } },
+
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot Pro1", 0, 0,
+ { 10062,-3522,-1000,-7643,15117,2730,-765,817,7322 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot Pro70", 34, 0,
+ { -5106,10695,1576,3820,53,4566,-6497,10736,6701,-3336,11887,1394 } },
+ { LIBRAW_CAMERAMAKER_Canon, "PowerShot Pro90", 0, 0,
+ { -5912,10768,2288,4612,-989,4333,-6153,10897,5944,-2907,12288,624 } },
+
+ { LIBRAW_CAMERAMAKER_Casio, "EX-F1", 0, 0,
+ { 9084,-2016,-848,-6711,14351,2570,-1059,1725,6135 } },
+ { LIBRAW_CAMERAMAKER_Casio, "EX-FH100", 0, 0,
+ { 12771,-4179,-1558,-2149,10938,1375,-453,1751,4494 } },
+ { LIBRAW_CAMERAMAKER_Casio, "EX-S20", 0, 0,
+ { 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Casio, "EX-Z750", 0, 0,
+ { 10819,-3873,-1099,-4903,13730,1175,-1755,3751,4632 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Casio, "EX-Z10", 128, 0xfff,
+ { 9790,-3338,-603,-2321,10222,2099,-344,1273,4799 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_CINE, "650", 0, 0,
+ { 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+ { LIBRAW_CAMERAMAKER_CINE, "660", 0, 0,
+ { 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+ { LIBRAW_CAMERAMAKER_CINE, "", 0, 0, /* empty camera name*/
+ { 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } },
+
+ { LIBRAW_CAMERAMAKER_Contax, "N Digital", 0, 0xf1e,
+ { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } },
+
+ { LIBRAW_CAMERAMAKER_DXO, "ONE", 0, 0,
+ { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } },
+
+ { LIBRAW_CAMERAMAKER_Epson, "R-D1", 0, 0, // same CMs: R-D1, R-D1s, R-D1x
+ { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "DBP for GX680", -128, 0x0fff,
+ { 12741,-4916,-1420,-8510,16791,1715,-1767,2302,7771 } }, /* temp, copy from S2Pro */
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "E550", 0, 0,
+ { 11044,-3888,-1120,-7248,15167,2208,-1531,2276,8069 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "E900", 0, 0,
+ { 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "F5", 0, 0, // F500EXR/F505EXR; F550EXR
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "F6", 0, 0, // F600EXR/F605EXR; F660EXR
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "F77", 0, 0xfe9, // F770EXR/F775EXR
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "F7", 0, 0, // same CMs: F700, F710EXR
+ { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "F810", 0, 0,
+ { 11044,-3888,-1120,-7248,15167,2208,-1531,2276,8069 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "F8", 0, 0, // F800EXR
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "F900EXR", 0, 0,
+ { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "GFX 100", 0, 0, // same CMs: "GFX 100", "GFX 100S"/"GFX100S", "GFX 100 IR"
+ { 16212,-8423,-1583,-4336,12583,1937,-195,726,6199 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "GFX 50", 0, 0, // same CMs: "GFX 50S", "GFX 50R", "GFX 50S II"
+ { 11756,-4754,-874,-3056,11045,2305,-381,1457,6006 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "HS10", 0, 0xf68,
+ { 12440,-3954,-1183,-1123,9674,1708,-83,1614,4086 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "HS2", 0, 0, // HS20EXR/HS22EXR
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "HS3", 0, 0, // HS30EXR/HS33EXR/HS35EXR
+ { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "HS50EXR", 0, 0,
+ { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "IS-1", 0, 0,
+ { 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "IS Pro", 0, 0,
+ { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S5000", 0, 0,
+ { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S5100", 0, 0,
+ { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S5200", 0, 0, // S5200/S5600
+ { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S6", 0, 0, // S6000fd/S6500fd
+ { 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S7000", 0, 0,
+ { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S9000", 0, 0, // S9000/S9500
+ { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S9100", 0, 0, // S9100/S9600
+ { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S100FS", -514, 0,
+ { 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S20Pro", 0, 0,
+ { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S20", -512, 0x3fff, // S200EXR/S205EXR
+ { 11401,-4498,-1312,-5088,12751,2613,-838,1568,5941 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "SL1000", 0, 0,
+ { 11705,-4262,-1107,-2282,10791,1709,-555,1713,4945 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S1", 0, 0,
+ { 12297,-4882,-1202,-2106,10691,1623,-88,1312,4790 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S2Pro", -128, 0,
+ { 12741,-4916,-1420,-8510,16791,1715,-1767,2302,7771 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S3Pro", 0, 0,
+ { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "S5Pro", 0, 0,
+ { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X100F", 0, 0,
+ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X100S", 0, 0,
+ { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X100T", 0, 0,
+ { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X100V", 0, 0,
+ { 13426,-6334,-1177,-4244,12136,2371,580,1303,5980 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X100", 0, 0,
+ { 12161,-4457,-1069,-5034,12874,2400,-795,1724,6904 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X10", 0, 0,
+ { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X20", 0, 0,
+ { 11768,-4971,-1133,-4904,12927,2183,-480,1723,4605 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X30", 0, 0,
+ { 12328,-5256,-1144,-4469,12927,1675,-87,1291,4351 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X70", 0, 0,
+ { 10450,-4329,-878,-3217,11105,2421,-752,1758,6519 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "XF10", 0, 0,
+ { 11673,-4760,-1041,-3988,12058,2166,-771,1417,5569 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "XF1", 0, 0,
+ { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "XQ", 0, 0, // same CMs: XQ1, XQ2
+ { 9252,-2704,-1064,-5893,14265,1717,-1101,2341,4349 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-Pro1", 0, 0,
+ { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-Pro2", 0, 0,
+ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-Pro3", 0, 0,
+ { 13426,-6334,-1177,-4244,12136,2371,580,1303,5980 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-A10", 0, 0,
+ { 11540,-4999,-991,-2949,10963,2278,-382,1049,5605} },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-A20", 0, 0,
+ { 11540,-4999,-991,-2949,10963,2278,-382,1049,5605} },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-A1", 0, 0,
+ { 11086,-4555,-839,-3512,11310,2517,-815,1341,5940 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-A2", 0, 0,
+ { 10763,-4560,-917,-3346,11311,2322,-475,1135,5843 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-A3", 0, 0,
+ { 12407,-5222,-1086,-2971,11116,2120,-294,1029,5284 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-A5", 0, 0,
+ { 11673,-4760,-1041,-3988,12058,2166,-771,1417,5569 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-A7", 0, 0,
+ { 15055,-7391,-1274,-4062,12071,2238,-610,1217,6147 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-E1", 0, 0,
+ { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-E2S", 0, 0,
+ { 11562,-5118,-961,-3022,11007,2311,-525,1569,6097 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-E2", 0, 0,
+ { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-E3", 0, 0,
+ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-E4", 0, 0,
+ { 13426, -6334, -1177, -4244, 12136, 2371, -580, 1303, 5980 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-H1", 0, 0,
+ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-H2S", 0, 0,
+ { 12836, -5909, -1032, -3087, 11132, 2236, -35, 872, 5330 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-M1", 0, 0,
+ { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-S10", 0, 0,
+ { 13426,-6334,-1177,-4244,12136,2371,-580,1303,5980 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-S1", 0, 0,
+ { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } },
+
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-T100", 0, 0,
+ { 11673,-4760,-1041,-3988,12058,2166,-771,1417,5569 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-T1", 0, 0, /* same CMs: X-T1, "X-T1IR", "X-T1 IR", X-T10 */
+ { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-T200", 0, 0,
+ { 15055,-7391,-1274,-4062,12071,2238,-610,1217,6147 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-T2", 0, 0, // same CMs: X-T2, X-T20
+ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } },
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-T3", 0, 0, // same CMs: X-T3, X-T30, "X-T30 II"
+ { 13426,-6334,-1177,-4244,12136,2371,580,1303,5980 } }, // v.2
+ { LIBRAW_CAMERAMAKER_Fujifilm, "X-T4", 0, 0,
+ { 13426,-6334,-1177,-4244,12136,2371,580,1303,5980 } },
+
+ { LIBRAW_CAMERAMAKER_GITUP, "G3DUO", 130, 62000,
+ { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
+
+ { LIBRAW_CAMERAMAKER_GITUP, "GIT2P", 4160, 0,
+ { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
+ { LIBRAW_CAMERAMAKER_GITUP, "GIT2", 3200, 0,
+ { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
+
+ { LIBRAW_CAMERAMAKER_GoPro, "HERO5 Black", 0, 0,
+ { 10344,-4210,-620,-2315,10625,1948,93,1058,5541 } },
+
+ {LIBRAW_CAMERAMAKER_Hasselblad, "L1D-20c", 0, 0,
+ { 7310, -2746, -646, -2991, 10847, 2469, 163, 585, 6324}},
+
+ { LIBRAW_CAMERAMAKER_Hasselblad, "16-Uncoated-3FR", 0, 0,
+ { 8519, -3260, -280, -5081, 13459, 1738, -1449, 2960, 7809}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "16-Uncoated-FFF", 0, 0,
+ { 8068, -2959, -108, -5788, 13608, 2389, -1002, 2237, 8162}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "16-Uncoated", 0, 0,
+ { 8519, -3260, -280, -5081, 13459, 1738, -1449, 2960, 7809}},
+
+ { LIBRAW_CAMERAMAKER_Hasselblad, "22-Uncoated-3FR", 0, 0,
+ { 8523, -3257, -280, -5078, 13458, 1743, -1449, 2961, 7809}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "22-Uncoated-FFF", 0, 0,
+ { 8068, -2959, -108, -5788, 13608, 2389, -1002, 2237, 8162}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "22-Uncoated", 0, 0,
+ { 8519, -3260, -280, -5081, 13459, 1738, -1449, 2960, 7809}},
+
+ {LIBRAW_CAMERAMAKER_Hasselblad, "31-Uncoated-FFF", 0, 0,
+ { 5155, -1201, 200, -5841, 13197, 2950, -1101, 2317, 6988}},
+ {LIBRAW_CAMERAMAKER_Hasselblad, "31-Uncoated", 0, 0,
+ { 5458, -1448, 145, -4479, 12338, 2401, -1659, 3086, 6710}},
+
+ {LIBRAW_CAMERAMAKER_Hasselblad, "39-Uncoated-3FR", 0, 0,
+ { 3904, -100, 262, -4318, 12407, 2128, -1598, 3594, 6233}},
+ {LIBRAW_CAMERAMAKER_Hasselblad, "39-Uncoated-FFF", 0, 0,
+ { 4739, -932, 295, -4829, 12220, 2952, -1027, 2341, 7083}},
+ {LIBRAW_CAMERAMAKER_Hasselblad, "39-Uncoated", 0, 0,
+ { 3894, -110, 287, -4672, 12610, 2295, -2092, 4100, 6196}},
+
+ { LIBRAW_CAMERAMAKER_Hasselblad, "39-Coated-3FR", 0, 0,
+ { 5427, -1147, 173, -3834, 12073, 1969, -1444, 3320, 5621}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "39-Coated-FFF", 0, 0,
+ { 5323, -1233, 399, -4926, 12362, 2894, -856, 2471, 5961}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "39-Coated", 0, 0,
+ { 3857, 452, -46, -6008, 14477, 1596, -2627, 4481, 5718}},
+
+ {LIBRAW_CAMERAMAKER_Hasselblad, "40-Coated5-3FR", 0, 0,
+ { 7014, -2067, -540, -4821, 13016, 1980, -1663, 3089, 6940}},
+ {LIBRAW_CAMERAMAKER_Hasselblad, "40-Coated5-FFF", 0, 0,
+ { 5963, -1357, -172, -5439, 12762, 3007, -964, 2222, 7172}},
+ {LIBRAW_CAMERAMAKER_Hasselblad, "40-Coated5", 0, 0,
+ { 6159, -1402, -177, -5439, 12762, 3007, -955, 2200, 7104}},
+
+ { LIBRAW_CAMERAMAKER_Hasselblad, "40-Coated-3FR", 0, 0,
+ { 6550, -1681, -399, -4626, 12598, 2257, -1807, 3354, 6486}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "40-Coated-FFF", 0, 0,
+ { 6041, -1375, -174, -5439, 10000, 3007, -930, 2145, 6923}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "40-Coated", 0, 0,
+ { 6159, -1402, -177, -5439, 12762, 3007, -955, 2200, 7104}},
+
+ { LIBRAW_CAMERAMAKER_Hasselblad, "50-Coated5-3FR", 0, 0,
+ { 5707, -693, -382, -4285, 12669, 1773, -1615, 3519, 5410}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "50-Coated5-FFF", 0, 0,
+ { 5263, -612, 39, -4950, 12426, 2843, -935, 2423, 5941}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "50-Coated5", 0, 0,
+ { 5656, -659, -346, -3923, 12306, 1791, -1602, 3509, 5442}},
+
+ { LIBRAW_CAMERAMAKER_Hasselblad, "50-Coated-3FR", 0, 0,
+ { 5656, -659, -346, -3923, 12305, 1790, -1602, 3509, 5442}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "50-Coated-FFF", 0, 0,
+ { 5280, -614, 39, -4950, 12426, 2843, -939, 2434, 5968}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "50-Coated", 0, 0,
+ { 5656, -659, -346, -3923, 12306, 1791, -1602, 3509, 5442}},
+
+ { LIBRAW_CAMERAMAKER_Hasselblad, "50-15-Coated5-II-3FR", 0, 0,
+ { 10887, -6152, 1034, -3564, 12412, 4224, 63, 626, 10123}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "50-15-Coated5-II-FFF", 0, 0,
+ { 4932, -835, 141, -4878, 11868, 3437, -1138, 1961, 7067}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "50-15-Coated5-II", 0, 0,
+ { 8737, -4937, 830, -2860, 9961, 3390, 51, 502, 8124}},
+
+ { LIBRAW_CAMERAMAKER_Hasselblad, "50-15-Coated5", 0, 0,
+ { 4932,-835,141,-4878,11868,3437,-1138,1961,7067 } },
+
+ { LIBRAW_CAMERAMAKER_Hasselblad, "60-Coated-3FR", 0, 0,
+ { 9296, 336, -1088, -6442, 14323, 2289, -1433, 2942, 5756}},
+ { LIBRAW_CAMERAMAKER_Hasselblad, "60-Coated", 0, 0,
+ { 9662, -684, -279, -4903, 12293, 2950, -344, 1669, 6024}},
+
+ { LIBRAW_CAMERAMAKER_Hasselblad, "100-17-Coated5", 0, 0,
+ { 5110, -1357, -308, -5573, 12835, 3077, -1279, 2025, 7010}},
+
+ { LIBRAW_CAMERAMAKER_HTC, "One A9", 64, 1023,
+ { 101,-20,-2,-11,145,41,-24,1,56 } }, /* this is FM1 transposed */
+
+ { LIBRAW_CAMERAMAKER_Imacon, "Ixpress", 0, 0,
+ { 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Kodak, "NC2000", 0, 0, // AP Nikon
+ { 13891,-6055,-803,-465,9919,642,2121,82,1291 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS315C", -8, 0,
+ { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS330C", -8, 0,
+ { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS420", 0, 0,
+ { 10868,-1852,-644,-1537,11083,484,2343,628,2216 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS46", 0, 0, // same CM as EOSDCS1 and DCS465 DB
+ { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS520C", -178, 0, // same CamID: DCS520C, "EOS D2000C"
+ { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS560C", -177, 0, // same CamID: DCS560C, "EOS D6000C"
+ { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS620C", -177, 0,
+ { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS620X", -176, 0,
+ { 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS660C", -173, 0,
+ { 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS720X", 0, 0,
+ { 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS760C", 0, 0,
+ { 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS Pro SLR", 0, 0,
+ { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS Pro 14nx", 0, 0,
+ { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "DCS Pro 14", 0, 0, // same CamID: "DCS Pro 14N", "Photo Control Camerz ZDS 14"
+ { 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "EOSDCS1", 0, 0,
+ { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "EOSDCS3", 0, 0,
+ { 9898,-2700,-940,-2478,12219,206,1985,634,1031 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "ProBack645", 0, 0,
+ { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "ProBack", 0, 0,
+ { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } },
+
+ {LIBRAW_CAMERAMAKER_Kodak, "PIXPRO AZ901", 0, 0, // dng
+ { 21875, -8006, -2558, 634, 8194, 1104, 1535, 951, 6969}},
+ { LIBRAW_CAMERAMAKER_Kodak, "P712", 0, 3963,
+ { 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "P850", 0, 3964,
+ { 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "P880", 0, 3963,
+ { 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "Z980", 0, 0,
+ { 11313,-3559,-1101,-3893,11891,2257,-1214,2398,4908 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "Z981", 0, 0,
+ { 12729,-4717,-1188,-1367,9187,2582,274,860,4411 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "Z990", 0, 0xfed,
+ { 11749,-4048,-1309,-1867,10572,1489,-138,1449,4522 } },
+ { LIBRAW_CAMERAMAKER_Kodak, "Z1015", 0, 0xef1,
+ { 11265,-4286,-992,-4694,12343,2647,-1090,1523,5447 } },
+
+ {LIBRAW_CAMERAMAKER_Leaf, "AFi 54S", 0, 0,
+ { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}},
+ {LIBRAW_CAMERAMAKER_Leaf, "AFi 65S", 0, 0,
+ { 7914, 1414, -1190, -8776, 16582, 2280, -2811, 4605, 5562}},
+ {LIBRAW_CAMERAMAKER_Leaf, "AFi 75S", 0, 0,
+ { 7914, 1414, -1190, -8776, 16582, 2280, -2811, 4605, 5562}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Aptus 17", 0, 0,
+ { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Aptus 22", 0, 0,
+ { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Aptus 54S", 0, 0,
+ { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Aptus 65S", 0, 0,
+ { 7914, 1414, -1190, -8776, 16582, 2280, -2811, 4605, 5562}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Aptus 65", 0, 0,
+ { 7914, 1414, -1190, -8776, 16582, 2280, -2811, 4605, 5562}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Aptus 75S", 0, 0,
+ { 7914, 1414, -1190, -8776, 16582, 2280, -2811, 4605, 5562}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Aptus 75", 0, 0,
+ { 7914, 1414, -1190, -8776, 16582, 2280, -2811, 4605, 5562}},
+ {LIBRAW_CAMERAMAKER_Leaf, "C-Most", 0, 0,
+ { 3952, 2188, 449, -6701, 14584, 2275, -4536, 7349, 6535}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Credo 40", 0, 0,
+ { 8035, 435, -962, -6001, 13872, 2320, -1159, 3065, 5434}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Credo 50", 0, 0, // emb
+ { 10325, 845, -604, -4113, 13385, 481, -1791, 4163, 6924}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Credo 60", 0, 0,
+ { 8035, 435, -962, -6001, 13872, 2320, -1159, 3065, 5434}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Credo 80", 0, 0,
+ { 6294, 686, -712, -5435, 13417, 2211, -1006, 2435, 5042}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Valeo 11", 0, 0,
+ { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Valeo 17", 0, 0,
+ { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Valeo 22", 0, 0,
+ { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}},
+ {LIBRAW_CAMERAMAKER_Leaf, "Valeo 6", 0, 0,
+ { 3952, 2188, 449, -6701, 14584, 2275, -4536, 7349, 6535}},
+
+// { LIBRAW_CAMERAMAKER_Leaf, "AFi-II 6", 0, 0,
+ { LIBRAW_CAMERAMAKER_Leaf, "AFi-II 7", 0, 0,
+ { 7691,-108,-339,-6185,13627,2833,-2046,3899,5952 } },
+ { LIBRAW_CAMERAMAKER_Leaf, "AFi-II 10", 0, 0,
+ { 6719,1147,-148,-6929,14061,3176,-1781,3343,5424 } },
+
+ { LIBRAW_CAMERAMAKER_Leaf, "Aptus-II 5", 0, 0,
+ { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+ { LIBRAW_CAMERAMAKER_Leaf, "Aptus-II 6", 0, 0,
+ { 7989,-113,-352,-6185,13627,2833,-2028,3866,5901 } },
+ { LIBRAW_CAMERAMAKER_Leaf, "Aptus-II 7", 0, 0,
+ { 8209,-116,-362,-6185,13627,2833,-1962,3740,5709 } },
+ { LIBRAW_CAMERAMAKER_Leaf, "Aptus-II 8", 0, 0,
+ { 7361,1257,-163,-6929,14061,3176,-1839,3454,5603 } },
+ { LIBRAW_CAMERAMAKER_Leaf, "Aptus-II 10R", 0, 0,
+ { 7167,1224,-158,-6929,14061,3176,-1826,3429,5562 } },
+ { LIBRAW_CAMERAMAKER_Leaf, "Aptus-II 10", 0, 0,
+ { 7527,1285,-166,-6929,14061,3176,-1995,3747,6077 } },
+// { LIBRAW_CAMERAMAKER_Leaf, "Aptus-II 12R", 0, 0,
+ { LIBRAW_CAMERAMAKER_Leaf, "Aptus-II 12", 0, 0,
+ { 7361,1257,-163,-6929,14061,3176,-1695,3182,5162 } },
+
+ { LIBRAW_CAMERAMAKER_Leica, "CL", 0, 0,
+ { 7743,-2896,-921,-4211,12271,2169,-697,1562,5491 } },
+
+ { LIBRAW_CAMERAMAKER_Leica, "M8", 0, 0,
+ { 7675,-2196,-305,-5860,14119,1856,-2425,4006,6578 } },
+ { LIBRAW_CAMERAMAKER_Leica, "M9", 0, 0,
+ { 6687,-1751,-291,-3556,11373,2492,-548,2204,7146 } },
+ { LIBRAW_CAMERAMAKER_Leica, "M10", 0, 0, // same CMs: M10, M10-D, M10-P
+ { 9090,-3342,-740,-4006,13456,493,-569,2266,6871 } },
+ { LIBRAW_CAMERAMAKER_Leica, "M (Typ 2", 0, 0, // same CMs: "M (Typ 240)", "M (Typ 262)", "M-D (Typ 262)"
+ { 7199,-2140,-712,-4005,13327,649,-810,2521,6673 } },
+
+ { LIBRAW_CAMERAMAKER_Leica, "Q (Typ 116)", 0, 0,
+ { 10068,-4043,-1068,-5319,14268,1044,-765,1701,6522 } },
+ { LIBRAW_CAMERAMAKER_Leica, "Q2", 0, 0,
+ { 12312,-5440,-1307,-6408,15499,824,-1075,1677,7220 } },
+
+ { LIBRAW_CAMERAMAKER_Leica, "SL (Typ 601)", 0, 0,
+ { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830 } },
+ { LIBRAW_CAMERAMAKER_Leica, "S (Typ 007)", 0, 0,
+ { 6063,-2234,-231,-5210,13787,1500,-1043,2866,6997 } },
+ { LIBRAW_CAMERAMAKER_Leica, "S2", 0, 0,
+ { 5627,-721,-447,-4423,12456,2192,-1048,2948,7379 } },
+ { LIBRAW_CAMERAMAKER_Leica, "S3", 0, 0,
+// { 5147,-1464,-318,-5374,13263,2325,-1425,2918,6450 } },
+ { 5092,-1630,-470,-6313,14297,2170,-1603,3135,5982 } },
+ {LIBRAW_CAMERAMAKER_Leica, "S", 0, 0, // same CMs: "S-E (Typ 006)", "S (Typ 006)"
+ { 5749,-1072,-382,-4274,12432,2048,-1166,3104,7105 } },
+
+ { LIBRAW_CAMERAMAKER_Leica, "TL2", 0, 0,
+ { 6375,-2062,-732,-4878,12838,2262,-877,1705,6204 } },
+ { LIBRAW_CAMERAMAKER_Leica, "T", 0, 0, // same CMs: TL, "T (Typ 701)"
+ { 6295,-1679,-475,-5586,13046,2837,-1410,1889,7075 } },
+
+ { LIBRAW_CAMERAMAKER_Leica, "X2", 0, 0,
+ { 8336,-2853,-699,-4425,11989,2760,-954,1625,6396 } },
+ { LIBRAW_CAMERAMAKER_Leica, "X1", 0, 0,
+ { 9055,-2611,-666,-4906,12652,2519,-555,1384,7417 } },
+ { LIBRAW_CAMERAMAKER_Leica, "X", 0, 0, /* same CMs: "X (Typ 113)", "X-U (Typ 113)", XV, "X Vario (Typ 107)" */
+ { 9062,-3198,-828,-4065,11772,2603,-761,1468,6458 } },
+
+ { LIBRAW_CAMERAMAKER_Mamiya,"ZD", 0, 0,
+ { 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } },
+
+ { LIBRAW_CAMERAMAKER_Micron, "2010", 110, 0,
+ { 16695,-3761,-2151,155,9682,163,3433,951,4904 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Minolta, "DiMAGE 5", 0, 0xf7d,
+ { 9117,-3063,-973,-7949,15763,2306,-2752,3136,8093 } },
+ { LIBRAW_CAMERAMAKER_Minolta, "DiMAGE 7Hi", 0, 0xf7d,
+ { 11555,-4064,-1256,-7903,15633,2409,-2811,3320,7358 } },
+ { LIBRAW_CAMERAMAKER_Minolta, "DiMAGE 7i", 0, 0xf7d,
+ { 11050,-3791,-1199,-7875,15585,2434,-2797,3359,7560 } },
+ { LIBRAW_CAMERAMAKER_Minolta, "DiMAGE 7", 0, 0xf7d,
+ { 9258,-2879,-1008,-8076,15847,2351,-2806,3280,7821 } },
+ { LIBRAW_CAMERAMAKER_Minolta, "DiMAGE A1", 0, 0xf8b,
+ { 9274,-2548,-1167,-8220,16324,1943,-2273,2721,8340 } },
+ { LIBRAW_CAMERAMAKER_Minolta, "DiMAGE A200", 0, 0,
+ { 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } },
+ { LIBRAW_CAMERAMAKER_Minolta, "DiMAGE A2", 0, 0xf8f,
+ { 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } },
+ { LIBRAW_CAMERAMAKER_Minolta, "DiMAGE Z2", 0, 0,
+ { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Minolta, "DG-5D", 0, 0xffb, // same CamID: "ALPHA 5D", "DYNAX 5D", "MAXXUM 5D", "Alpha Sweet Digital"
+ { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } },
+ { LIBRAW_CAMERAMAKER_Minolta, "DG-7D", 0, 0xffb, // same CamID: "ALPHA 7D", "DYNAX 7D", "MAXXUM 7D"
+ { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } },
+
+ { LIBRAW_CAMERAMAKER_Motorola, "PIXL", 0, 0,
+ { 8898,-989,-1033,-3292,11619,1674,-661,3178,5216 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Nikon, "1 AW1", 0, 0,
+ { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "1 J3", 0, 0,
+ { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "1 J4", 0, 0,
+ { 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "1 J5", 0, 0,
+ { 7520,-2518,-645,-3844,12102,1945,-913,2249,6835 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "1 S2", -200, 0,
+ { 6612,-1342,-618,-3338,11055,2623,-174,1792,5075 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "1 V2", 0, 0,
+ { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "1 V3", -200, 0,
+ { 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "1 ", 0, 0, /* same CMs: "1 J1", "1 J2", "1 S1", "1 V1" */
+ { 8994,-2667,-865,-4594,12324,2552,-699,1786,6260 } },
+
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 2100", 0, 0, // a.k.a. E2100
+ { 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711 } }, /* DJC, copied from Z2, new white balance */
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 2500", 0, 0, // a.k.a. E2500, possibly same CM as for E5000
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 3200", 0, 0, // a.k.a. E3200
+ { 9846,-2085,-1019,-3278,11109,2170,-774,2134,5745 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 4300", 0, 0, // a.k.a. E4300
+ { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } }, /* DJC, copied from Minolta DiMAGE Z2 */
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 4500", 0, 0, // a.k.a. E4500, possibly same CM as for E5000
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 5000", 0, 0, // a.k.a. E5000
+ { -6678,12805,2248,5725,-499,3375,-5903,10713,6034,-270,9976,134 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 5400", 0, 0, // a.k.a. E5400
+ { 9349,-2988,-1001,-7918,15766,2266,-2097,2680,6839 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 5700", 0, 0, // a.k.a. E5700
+ { -6475,12496,2428,5409,-16,3180,-5965,10912,5866,-177,9918,248 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 8400", 0, 0, // a.k.a. E8400
+ { 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 8700", 0, 0, // a.k.a. E8700
+ { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 8800", 0, 0, // a.k.a. E8800
+ { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } },
+
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 700", 0, 0x3dd, // a.k.a. E700
+ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 800", 0, 0x3dd, // a.k.a. E800
+ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 950", 0, 0x3dd, // a.k.a. E950
+ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, /* DJC */
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX 995", 0, 0, // a.k.a. E995
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, /* DJC, copied from E5000 */
+
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX A1000", 0, 0,
+ { 10601,-3487,-1127,-2931,11443,1676,-587,1740,5278 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX B700", 0, 0,
+ { 14387,-6014,-1299,-1357,9975,1616,467,1047,4744 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX A", 0, 0,
+ { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX P1000", 0, 0,
+ { 14294,-6116,-1333,-1628,10219,1637,-14,1158,5022 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX P6000", 0, 0,
+ { 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX P7000", 0, 0,
+ { 11432,-3679,-1111,-3169,11239,2202,-791,1380,4455 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX P7100", 0, 0,
+ { 11053,-4269,-1024,-1976,10182,2088,-526,1263,4469 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX P7700", -3200, 0, // same CamID: "COOLPIX P7700", "COOLPIX Deneb"
+ { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX P7800", -3200, 0, // same CamID: "COOLPIX P7800", "COOLPIX Kalon"
+ { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX P330", -200, 0,
+ { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "COOLPIX P340", -200, 0,
+ { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "Coolpix P950", 0, 0,
+ { 13307, -5641, -1290, -2048, 10581, 1689, -64, 1222, 5176}},
+
+ { LIBRAW_CAMERAMAKER_Nikon, "D3000", 0, 0,
+ { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D3100", 0, 0,
+ { 7911,-2167,-813,-5327,13150,2408,-1288,2483,7968 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D3200", 0, 0xfb9,
+ { 7013,-1408,-635,-5268,12902,2640,-1470,2801,7379 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D3300", 0, 0,
+ { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D3400", 0, 0,
+ { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D3500", 0, 0,
+ { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D5000", 0, 0xf00,
+ { 7309,-1403,-519,-8474,16008,2622,-2433,2826,8064 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D5100", 0, 0x3de6,
+ { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D5200", 0, 0,
+ { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D5300", 0, 0,
+ { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D5500", 0, 0,
+ { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D5600", 0, 0,
+ { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D7000", 0, 0,
+ { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D7100", 0, 0,
+ { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D7200", 0, 0,
+ { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D7500", 0, 0,
+ { 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 } },
+
+ { LIBRAW_CAMERAMAKER_Nikon, "D100", 0, 0,
+ { 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D200", 0, 0xfbc,
+ { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D300", 0, 0, // same CMs: D300, D300s
+ { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D500", 0, 0,
+ { 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D600", 0, 0x3e07,
+ { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D610",0, 0,
+ { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D700", 0, 0,
+ { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D750", -600, 0,
+ { 9020,-2890,-715,-4535,12436,2348,-934,1919,7086 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D780", -600, 0,
+ { 9943,-3269,-839,-5323,13269,2259,-1198,2083,7557 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D800", 0, 0, // same CMs: D800, D800E
+ { 7866,-2108,-555,-4869,12483,2681,-1176,2069,7501 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D810A", 0, 0,
+ { 11973,-5685,-888,-1965,10326,1901,-115,1123,7169 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D810", 0, 0,
+ { 9369,-3195,-791,-4488,12430,2301,-893,1796,6872 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D850", 0, 0,
+ { 10405,-3755,-1270,-5461,13787,1793,-1040,2015,6785 } },
+
+ { LIBRAW_CAMERAMAKER_Nikon, "D40X", 0, 0,
+ { 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D40", 0, 0,
+ { 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D50", 0, 0,
+ { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D60", 0, 0,
+ { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D70", 0, 0, // same CMs: D70, D70s
+ { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D80", 0, 0,
+ { 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D90", 0, 0xf00,
+ { 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } },
+
+ { LIBRAW_CAMERAMAKER_Nikon, "D1H", 0, 0,
+ { 7659,-2238,-935,-8942,16969,2004,-2701,3051,8690 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D1X", 0, 0,
+ { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D1", 0, 0,
+// { 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } }, /* multiplied by 2.218750, 1.0, 1.148438 */
+ { 7637,-2199,-974,-9109,17099,2043,-2822,3306,8372 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D2H", 0, 0, // same CMs: D2H, D2Hs
+ { 5733,-911,-629,-7967,15987,2055,-3050,4013,7048 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D2X", 0, 0, // same CMs: D2X, D2Xs
+ { 10231,-2768,-1254,-8302,15900,2551,-797,681,7148 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D3S", 0, 0,
+ { 8828,-2406,-694,-4874,12603,2541,-660,1509,7587 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D3X", 0, 0,
+ { 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D3", 0, 0,
+ { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D4", 0, 0, // same CMs: D4, D4S (and Df)
+ { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D5", 0, 0,
+ { 9200,-3522,-992,-5755,13803,2117,-753,1486,6338 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "D6", 0, 0,
+ { 9028,-3423,-1035,-6321,14265,2217,-1013,1683,6928 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "Df", 0, 0,
+ { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } },
+
+ { LIBRAW_CAMERAMAKER_Nikon, "Z 50", 0, 0,
+ { 11640,-4829,-1079,-5107,13006,2325,-972,1711,7380 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "Z 5", 0, 0,
+ { 8695,-2558,-648,-5015,12711,2575,-1279,2215,7514 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "Z 6", 0, 0,
+ { 9943,-3269,-839,-5323,13269,2259,-1198,2083,7557 } }, // 'Z 6'(v.2), 'Z 6_2'
+ { LIBRAW_CAMERAMAKER_Nikon, "Z 7", 0, 0,
+ { 13705,-6004,-1400,-5464,13568,2062,-940,1706,7618 } }, // 'Z 7'(v.2), 'Z 7_2'
+ { LIBRAW_CAMERAMAKER_Nikon, "Z 9", 0, 0,
+ { 13389,-6049,-1441,-4544,12757,1969,229,498,7390 } },
+ { LIBRAW_CAMERAMAKER_Nikon, "Z fc", 0, 0,
+ { 11640,-4829,-1079,-5107,13006,2325,-972,1711,7380 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "AIR A01", 0, 0xfe1,
+ { 8992,-3093,-639,-2563,10721,2122,-437,1270,5473 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "C-5050Z", 0, 0,
+ { 10633,-3234,-1285,-7460,15570,1967,-1917,2510,6299 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "C-5060WZ", 0, 0,
+ { 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "C-7070WZ", 0, 0,
+ { 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "C-7000Z", 0, 0,
+ { 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "C-8080WZ", 0, 0,
+ { 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "E-300", 0, 0,
+ { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-330", 0, 0,
+ { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-400", 0, 0,
+ { 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-410", 0, 0xf6a,
+ { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-420", 0, 0xfd7,
+ { 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-450", 0, 0xfd2,
+ { 8745,-2425,-1095,-7594,15613,2073,-1780,2309,7416 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-500", 0, 0,
+ { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-510", 0, 0xf6a,
+ { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-520", 0, 0xfd2,
+ { 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-600", 0, 0xfaf,
+ { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-620", 0, 0xfaf,
+ { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "E-10", 0, 0x3ff,
+ { 12970,-4703,-1433,-7466,15843,1644,-2191,2451,6668 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-20", 0, 0x3ff, // model is "E-20,E-20N,E-20P"
+ { 13414,-4950,-1517,-7166,15293,1960,-2325,2664,7212 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-30", 0, 0xfbc,
+ { 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "E-1", 0, 0,
+ { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-3", 0, 0xf99,
+ { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-5", 0, 0xeec,
+ { 11200,-3783,-1325,-4576,12593,2206,-695,1742,7504 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "E-P1", 0, 0xffd,
+ { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-P2", 0, 0xffd,
+ { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-P3", 0, 0,
+ { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-P5", 0, 0,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-P7", 0, 0,
+ { 9476,-3182,-765,-2613,10958,1893,-449,1315,5268 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PL10", 0, 0,
+ { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PL1s", 0, 0,
+ { 11409,-3872,-1393,-4572,12757,2003,-709,1810,7415 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PL1", 0, 0,
+ { 11408,-4289,-1215,-4286,12385,2118,-387,1467,7787 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PL2", 0, 0xcf3,
+ { 15030,-5552,-1806,-3987,12387,1767,-592,1670,7023 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PL3", 0, 0,
+ { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PL5", 0, 0xfcb,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PL6", 0, 0,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PL7", 0, 0,
+ { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PL8", 0, 0,
+ { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PL9", 0, 0,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PM1", 0, 0,
+ { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-PM2", 0, 0,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "E-M10 Mark IV", 0, 0,
+ { 9476,-3182,-765,-2613,10958,1893,-449,1315,5268 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-M10", 0, 0, // Same CMs: E-M10, E-M10 Mark II, E-M10 Mark III; "CLAUSS piX 5oo"
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-M1X", 0, 0,
+ { 11896,-5110,-1076,-3181,11378,2048,-519,1224,5166 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "E-M1 Mark III", 0, 0,
+ { 11896,-5110,-1076,-3181,11378,2048,-519,1224,5166 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-M1 Mark II", 0, 0,
+ { 9383,-3170,-763,-2457,10702,2020,-384,1236,5552 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-M1", 0, 0,
+ { 7687,-1984,-606,-4327,11928,2721,-1381,2339,6452 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "E-M5 Mark III", 0, 0,
+ { 11896,-5110,-1076,-3181,11378,2048,-519,1224,5166 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-M5 Mark II", 0, 0,
+ { 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "E-M5", 0, 0xfe1,
+ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "PEN-F",0, 0,
+ { 9476,-3182,-765,-2613,10958,1893,-449,1315,5268 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "SH-2", 0, 0, // same CamID: SH-2, SH-3
+ { 10156,-3425,-1077,-2611,11177,1624,-385,1592,5080 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "SP-350", 0, 0,
+ { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "SP-3", 0, 0, // Same CMs: SP310, SP320
+ { 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "SP-500UZ", 0, 0xfff,
+ { 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "SP-510UZ", 0, 0xffe,
+ { 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "SP-550UZ", 0, 0xffe,
+ { 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "SP-560UZ", 0, 0xff9,
+ { 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "SP-565UZ", 0, 0,
+ { 11856,-4469,-1159,-4814,12368,2756,-993,1779,5589 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "SP-570UZ", 0, 0,
+ { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "STYLUS 1",0, 0, // Olympus "STYLUS 1 and STYLUS 1s have the same CamID, cameras are slightly different
+ { 8360,-2420,-880,-3928,12353,1739,-1381,2416,5173 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "TG-4", 0, 0,
+ { 11426,-4159,-1126,-2066,10678,1593,-120,1327,4998 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "TG-", 0, 0, // same CMs: TG-5, TG-6
+ { 10899,-3833,-1082,-2112,10736,1575,-267,1452,5269 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "XZ-10", 0, 0,
+ { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "XZ-1", 0, 0,
+ { 10901,-4095,-1074,-1141,9208,2293,-62,1417,5158 } },
+ { LIBRAW_CAMERAMAKER_Olympus, "XZ-2", 0, 0,
+ { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } },
+
+ { LIBRAW_CAMERAMAKER_Olympus, "OM-1", 0, 0,
+ { 9488, -3984, -714, -2887, 10945, 2229, -137, 960, 5786 } },
+
+ { LIBRAW_CAMERAMAKER_OmniVison, "", 16, 0x3ff,
+ { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Pentax, "*istDL2", 0, 0,
+ { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "*istDL", 0, 0,
+ { 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "*istDS2", 0, 0,
+ { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "*istDS", 0, 0,
+ { 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "*istD", 0, 0,
+ { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } },
+
+ { LIBRAW_CAMERAMAKER_Pentax, "K-01", 0, 0,
+ { 8134,-2728,-645,-4365,11987,2694,-838,1509,6498 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K10D", 0, 0,
+ { 9679,-2965,-811,-8622,16514,2182,-975,883,9793 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K1", 0, 0, // same CMs: K100D, "K100D Super", K110D
+ { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K20D", 0, 0,
+ { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K200D", 0, 0,
+ { 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-m", 0, 0,
+ { 9730,-2989,-970,-8527,16258,2381,-1060,970,8362 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "KP", 0, 0,
+ { 7825,-2160,-1403,-4841,13555,1349,-1559,2449,5814 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-x", 0, 0,
+ { 8843,-2837,-625,-5025,12644,2668,-411,1234,7410 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-r", 0, 0,
+ { 9895,-3077,-850,-5304,13035,2521,-883,1768,6936 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-1", 0, 0, // same CMs: K-1, "K-1 Mark II"
+ { 8596,-2981,-639,-4202,12046,2431,-685,1424,6122 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-30", 0, 0,
+ { 8134,-2728,-645,-4365,11987,2694,-838,1509,6498 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-3 Mark III", 0, 0,
+ { 9251, -3817, -1069, -4627, 12667, 2175, -798, 1660, 5633 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-3", 0, 0, // same CMs: K-3, "K-3 II"
+ { 7415,-2052,-721,-5186,12788,2682,-1446,2157,6773 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-500", 0, 0,
+ { 8109,-2740,-608,-4593,12175,2731,-1006,1515,6545 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-50", 0, 0,
+ { 8109,-2740,-608,-4593,12175,2731,-1006,1515,6545 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-5 II", 0, 0, // same CMs: "K-5 II" and "K-5 IIs"
+ { 8170,-2725,-639,-4440,12017,2744,-771,1465,6599 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-5", 0, 0,
+ { 8713,-2833,-743,-4342,11900,2772,-722,1543,6247 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-70", 0, 0,
+ { 8766,-3149,-747,-3976,11943,2292,-517,1259,5552 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-7", 0, 0,
+ { 9142,-2947,-678,-8648,16967,1663,-2224,2898,8615 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "KP", 0, 0,
+ { 8617,-3228,-1034,-4674,12821,2044,-803,1577,5728 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-S1", 0, 0,
+ { 8512,-3211,-787,-4167,11966,2487,-638,1288,6054 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "K-S2", 0, 0,
+ { 8662,-3280,-798,-3928,11771,2444,-586,1232,6054 } },
+
+ { LIBRAW_CAMERAMAKER_Pentax, "Q-S1", 0, 0,
+ { 12995,-5593,-1107,-1879,10139,2027,-64,1233,4919 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "Q7", 0, 0,
+ { 10901,-3938,-1025,-2743,11210,1738,-823,1805,5344 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "Q10", 0, 0,
+ { 11562,-4183,-1172,-2357,10919,1641,-582,1726,5112 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "Q", 0, 0,
+ { 11731,-4169,-1267,-2015,10727,1473,-217,1492,4870 } },
+
+ { LIBRAW_CAMERAMAKER_Pentax, "MX-1", 0, 0,
+ { 9296,-3146,-888,-2860,11287,1783,-618,1698,5151 } },
+
+ { LIBRAW_CAMERAMAKER_Pentax, "645D", 0, 0x3e00,
+ { 10646,-3593,-1158,-3329,11699,1831,-667,2874,6287 } },
+ { LIBRAW_CAMERAMAKER_Pentax, "645Z", 0, 0,
+ { 9519,-3591,-664,-4074,11725,2671,-624,1501,6653 } },
+
+
+ {LIBRAW_CAMERAMAKER_Panasonic, "DC-S1R", 0, 0,
+ { 11822,-5321,-1249,-5958,15114,766,-614,1264,7043 } },
+ {LIBRAW_CAMERAMAKER_Panasonic, "DC-S1H", 0, 0,
+ { 9397,-3719,-805,-5425,13326,2309,-972,1715,6034 } },
+ {LIBRAW_CAMERAMAKER_Panasonic, "DC-S1", 0, 0,
+ { 9744,-3905,-779,-4899,12807,2324,-798,1630,5827 } },
+ {LIBRAW_CAMERAMAKER_Panasonic, "DC-S5", 0, 0,
+ { 9744,-3905,-779,-4899,12807,2324,-798,1630,5827 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-CM1", -15, 0, // same CMs: DMC-CM1, DMC-CM10
+ { 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-FZ1000M2", -15, 0,
+ { 9803,-4185,-992,-4066,12578,1628,-838,1824,5288 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ1000", -15, 0,
+ { 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ2500", -15, 0,
+ { 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ100", -15, 0xfff,
+ { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ150", -15, 0xfff,
+ { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ200", -15, 0xfff,
+ { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ300", -15, 0xfff,
+ { 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ18", 0, 0,
+ { 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ28", -15, 0xf96,
+ { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ30", 0, 0xf94,
+ { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ35", -15, 0,
+ { 9938,-2780,-890,-4604,12393,2480,-1117,2304,4620 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ40", -15, 0,
+ { 13639,-5535,-1371,-1698,9633,2430,316,1152,4108 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ50", 0, 0,
+ { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ70", -15, 0,
+ { 11532,-4324,-1066,-2375,10847,1749,-564,1699,4351 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-FZ80", -15, 0,
+ { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FZ8", 0, 0xf7f,
+ { 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } },
+
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-L10", -15, 0xf96,
+ { 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-L1", 0, 0xf7f,
+ { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-LC1", 0, 0,
+ { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-LF1", -15, 0,
+ { 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-LX100M2", -15, 0,
+ { 8585,-3127,-833,-4005,12250,1953,-650,1494,4862 } }, // v.2
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-LX100", -15, 0,
+ { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-LX1", 0, 0xf7f,
+ { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-LX2", 0, 0,
+ { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-LX3", -15, 0,
+ { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-LX5", -15, 0,
+ { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-LX7", -15, 0,
+ { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-LX9", -15, 0,
+ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-FX150", -15, 0xfff,
+ { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-G99", -15, 0,
+ { 9657,-3963,-748,-3361,11378,2258,-568,1415,5158 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-G100", -15, 0,
+ { 8370,-2869,-710,-3389,11372,2298,-640,1599,4887 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-G10", 0, 0,
+ { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-G1", -15, 0xf94,
+ { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-G2", -15, 0xf3c,
+ { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-G3", -15, 0xfff,
+ { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-G5", -15, 0xfff,
+ { 7798,-2562,-740,-3879,11584,2613,-1055,2248,5434 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-G6", -15, 0xfff,
+ { 8294,-2891,-651,-3869,11590,2595,-1183,2267,5352 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-G7", -15, 0xfff,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-G8", -15, 0xfff,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-G9", -15, 0,
+ { 7685,-2375,-634,-3687,11700,2249,-748,1546,5111 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GH1", -15, 0xf92,
+ { 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GH2", -15, 0xf95,
+ { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GH3", -15, 0,
+ { 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GH4", -15, 0,
+ { 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-GH5s", -15, 0,
+ { 6929,-2355,-708,-4192,12534,1828,-1097,1989,5195 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-GH5M2", 0, 0,
+ { 9300, -3659, -755, -2981, 10988, 2287, -190, 1077, 5016 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-GH5", -15, 0,
+ { 7641,-2336,-605,-3218,11299,2187,-485,1338,5121 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GM1", -15, 0,
+ { 6770,-1895,-744,-5232,13145,2303,-1664,2691,5703 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GM5", -15, 0,
+ { 8238,-3244,-679,-3921,11814,2384,-836,2022,5852 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-GF10", -15, 0,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GF1", -15, 0xf92,
+ { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GF2", -15, 0xfff,
+ { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GF3", -15, 0xfff,
+ { 9051,-2468,-1204,-5212,13276,2121,-1197,2510,6890 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GF5", -15, 0xfff,
+ { 8228,-2945,-660,-3938,11792,2430,-1094,2278,5793 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GF6", -15, 0,
+ { 8130,-2801,-946,-3520,11289,2552,-1314,2511,5791 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GF7", -15, 0,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GF8", -15, 0,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-GF9", -15, 0,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GX85", -15, 0,
+ { 7771,-3020,-629,-4029,11950,2345,-821,1977,6119 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GX1", -15, 0,
+ { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GX7", -15,0,
+ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-GX8", -15,0,
+ { 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-GX9", -15, 0,
+ { 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-ZS100", -15, 0,
+ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-ZS200", -15, 0,
+ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } },
+
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-ZS40", -15, 0,
+ { 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-ZS50", -15, 0,
+ { 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DMC-ZS60", -15, 0,
+ { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-ZS70", -15, 0,
+ { 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 } },
+ { LIBRAW_CAMERAMAKER_Panasonic, "DC-ZS80", -15, 0,
+ { 12194,-5340,-1329,-3035,11394,1858,-50,1418,5219 } },
+
+ { LIBRAW_CAMERAMAKER_PhaseOne, "H20", 0, 0,
+ { 3906,1422,-467,-9953,18472,1365,-3307,4496,6406 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "H25", 0, 0,
+ { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ4 150MP", 0, 0,
+ { 6644, -2257, -804, -6459, 14562, 2019, -1221, 1876, 6411}},
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ140", 0, 0,
+ { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ150", 0, 0,
+ {10325,845,-604,-4113,13385,481,-1791,4163,6924}}, /* temp */ /* emb */
+// { 3984,0,0,0,10000,0,0,0,7666 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ160", 0, 0,
+ { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ180", 0, 0,
+ { 6294,686,-712,-5435,13417,2211,-1006,2435,5042 } },
+
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ250",0, 0,
+// {3984,0,0,0,10000,0,0,0,7666}},
+ {10325,845,-604,-4113,13385,481,-1791,4163,6924}}, /* emb */
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ260", 0, 0,
+ { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ280", 0, 0,
+ { 6294,686,-712,-5435,13417,2211,-1006,2435,5042 } },
+
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ3 100MP", 0, 0,
+// {2423,0,0,0,9901,0,0,0,7989}},
+ { 10999,354,-742,-4590,13342,937,-1060,2166,8120} }, /* emb */
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ3 50MP", 0, 0,
+// { 3984,0,0,0,10000,0,0,0,7666 } },
+ {10058,1079,-587,-4135,12903,944,-916,2726,7480}}, /* emb */
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ3 60MP", 0, 0,
+ { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "IQ3 80MP", 0, 0,
+ { 6294,686,-712,-5435,13417,2211,-1006,2435,5042 } },
+
+ { LIBRAW_CAMERAMAKER_PhaseOne, "P21", 0, 0,
+ { 6516,-2050,-507,-8217,16703,1479,-3492,4741,8489 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "P30", 0, 0,
+ { 4516,-244,-36,-7020,14976,2174,-3206,4670,7087 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "P40", 0, 0,
+ { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "P45", 0, 0,
+ { 5053,-24,-117,-5685,14077,1703,-2619,4491,5850 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "P65", 0, 0,
+ { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } },
+ { LIBRAW_CAMERAMAKER_PhaseOne, "P2", 0, 0,
+ { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
+
+ { LIBRAW_CAMERAMAKER_Photron, "BC2-HD", 0, 0,
+ { 14603,-4122,-528,-1810,9794,2017,-297,2763,5936 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Polaroid, "x530", 0, 0,
+ { 13458,-2556,-510,-5444,15081,205,0,0,12120 } },
+
+ { LIBRAW_CAMERAMAKER_RED, "One", 704, 0xffff,
+ { 21014,-7891,-2613,-3056,12201,856,-2203,5125,8042 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Ricoh, "S10 24-72mm F2.5-4.4 VC", 0, 0,
+ { 10531,-4043,-878,-2038,10270,2052,-107,895,4577 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GR A12 50mm F2.5 MACRO", 0, 0,
+ { 8849,-2560,-689,-5092,12831,2520,-507,1280,7104 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GR DIGITAL 2", 0, 0,
+ { 8846,-2704,-729,-5265,12708,2871,-1471,1955,6218 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GR DIGITAL 3", 0, 0,
+ { 8170,-2496,-655,-5147,13056,2312,-1367,1859,5265 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GR DIGITAL 4", 0, 0,
+ { 8771,-3151,-837,-3097,11015,2389,-703,1343,4924 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GR III", 0, 0,
+ { 6127,-1777,-585,-5913,13699,2428,-1088,1780,6017 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GR II", 0, 0,
+ { 5329,-1459,-390,-5407,12930,2768,-1119,1772,6046 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GR", 0, 0,
+ { 5329,-1459,-390,-5407,12930,2768,-1119,1772,6046 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GX200", 0, 0,
+ { 8040,-2368,-626,-4659,12543,2363,-1125,1581,5660 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GXR Mount A12", 0, 0,
+ { 7834,-2182,-739,-5453,13409,2241,-952,2005,6620 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GXR A12 50mm", 0, 0,
+ { 8849,-2560,-689,-5092,12831,2520,-507,1280,7104 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GXR A12 28mm", 0, 0,
+ { 10228,-3159,-933,-5304,13158,2371,-943,1873,6685 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GXR A16", 0, 0,
+ { 7837,-2538,-730,-4370,12184,2461,-868,1648,5830 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GXR P10", 0, 0,
+ { 13168,-5128,-1663,-3006,11569,1611,-373,1244,4907 } },
+ { LIBRAW_CAMERAMAKER_Ricoh, "GXR S10", 0, 0,
+ { 8963,-2926,-754,-4881,12921,2164,-1464,1944,4901 } },
+
+ { LIBRAW_CAMERAMAKER_Samsung, "EX1", 0, 0x3e00,
+ { 8898,-2498,-994,-3144,11328,2066,-760,1381,4576 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "EX2F", 0, 0x7ff,
+ { 10648,-3897,-1055,-2022,10573,1668,-492,1611,4742 } },
+// { LIBRAW_CAMERAMAKER_Samsung, "GX20", 0, 0,
+// { 23213,-14575,-4840,-7077,16564,316,385,-1656,9398 } }, // Adobe DNG
+// { 27717,-17403,-5779,-8450,19778,377,459,1978,11221 } }, // Samsung DNG
+// { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } }, // Adobe DCP
+
+// { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S6 Edge Rear Camera", 0, 0,
+// { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S6 Rear Camera", 0, 0,
+ { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S6", 0, 0, // same CMs: "Galaxy S6", "Galaxy S6 Edge"
+ { 13699,-5767,-1384,-4449,13879,499,-467,1691,5892 } },
+
+// { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S7 Edge Rear Camera", 0, 0,
+// { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S7 Rear Camera", 0, 0,
+ { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S7", 0, 0, // same CMs: "Galaxy S7", "Galaxy S7 Edge"
+ { 9927,-3704,-1024,-3935,12758,1257,-389,1512,4993 } },
+
+// { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S8+ Rear Camera", 0, 0,
+// { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S8 Rear Camera", 0, 0,
+ { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S8", 0, 0, // same CMs: "Galaxy S8", "Galaxy S8+"
+ { 9927,-3704,-1024,-3935,12758,1257,-389,1512,4993 } },
+
+// { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S9+ Rear Camera", 0, 0,
+// { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S9 Rear Camera", 0, 0,
+ { LIBRAW_CAMERAMAKER_Samsung, "Galaxy S9", 0, 0, // same CMs: "Galaxy S9", "Galaxy S9+"
+ { 13292,-6142,-1268,-4095,12890,1283,-557,1930,5163 } },
+// { LIBRAW_CAMERAMAKER_Samsung, "Galaxy Note 9 Rear Telephoto Camera", 0, 0,
+ { LIBRAW_CAMERAMAKER_Samsung, "Galaxy Note 9 Rear Camera", 0, 0,
+ { 13292,-6142,-1268,-4095,12890,1283,-557,1930,5163 } },
+
+ { LIBRAW_CAMERAMAKER_Samsung, "NX U", 0, 0,
+ { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX3300", 0, 0,
+ { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX3000", 0, 0,
+ { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX30", 0, 0, // same CMs: NX30, NX300, NX300M
+ { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX2000", 0, 0,
+ { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX2", 0, 0xfff, // same CMs: NX20, NX200, NX210
+ { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX1000", 0, 0,
+ { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX1100", 0, 0,
+ { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX11", 0, 0,
+ { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX10", 0, 0, // same CMs: NX10, NX100
+ { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX500", 0, 0,
+ { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX5", 0, 0,
+ { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX1", 0, 0,
+ { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "NX mini", 0, 0,
+ { 5222,-1196,-550,-6540,14649,2009,-1666,2819,5657 } },
+
+ { LIBRAW_CAMERAMAKER_Samsung, "WB2000", 0, 0xfff,
+ { 12093,-3557,-1155,-1000,9534,1733,-22,1787,4576 } },
+ { LIBRAW_CAMERAMAKER_Samsung, "WB5000", 0, 0,
+ { 7675, -2195, -305, -5860, 14118, 1857, -2425, 4007, 6578}},
+ { LIBRAW_CAMERAMAKER_Samsung, "S85", 0, 0,
+ { 11885,-3968,-1473,-4214,12299,1916,-835,1655,5549 } }, /* DJC */
+
+// Foveon: LibRaw color data
+ { LIBRAW_CAMERAMAKER_Sigma, "dp0 Quattro", 2047, 0,
+ { 13801,-3390,-1016,5535,3802,877,1848,4245,3730 } },
+ { LIBRAW_CAMERAMAKER_Sigma, "dp1 Quattro", 2047, 0,
+ { 13801,-3390,-1016,5535,3802,877,1848,4245,3730 } },
+ { LIBRAW_CAMERAMAKER_Sigma, "dp2 Quattro", 2047, 0,
+ { 13801,-3390,-1016,5535,3802,877,1848,4245,3730 } },
+ { LIBRAW_CAMERAMAKER_Sigma, "dp3 Quattro", 2047, 0,
+ { 13801,-3390,-1016,5535,3802,877,1848,4245,3730 } },
+ { LIBRAW_CAMERAMAKER_Sigma, "sd Quattro H", 256, 0,
+ { 1295,108,-311,256,828,-65,-28,750,254 } }, /* temp */
+ { LIBRAW_CAMERAMAKER_Sigma, "sd Quattro", 2047, 0,
+ { 1295,108,-311,256,828,-65,-28,750,254 } }, /* temp */
+ { LIBRAW_CAMERAMAKER_Sigma, "SD9", 15, 4095,
+ { 13564,-2537,-751,-5465,15154,194,-67,116,10425 } },
+ { LIBRAW_CAMERAMAKER_Sigma, "SD10", 15, 16383,
+ { 6787,-1682,575,-3091,8357,160,217,-369,12314 } },
+ { LIBRAW_CAMERAMAKER_Sigma, "SD14", 15, 16383,
+ { 13589,-2509,-739,-5440,15104,193,-61,105,10554 } },
+ { LIBRAW_CAMERAMAKER_Sigma, "SD15", 15, 4095,
+ { 13556,-2537,-730,-5462,15144,195,-61,106,10577 } },
+// Merrills + SD1
+ { LIBRAW_CAMERAMAKER_Sigma, "SD1", 31, 4095,
+ { 5133,-1895,-353,4978,744,144,3837,3069,2777 } }, /* LibRaw */
+ { LIBRAW_CAMERAMAKER_Sigma, "DP1 Merrill", 31, 4095,
+ { 5133,-1895,-353,4978,744,144,3837,3069,2777 } }, /* LibRaw */
+ { LIBRAW_CAMERAMAKER_Sigma, "DP2 Merrill", 31, 4095,
+ { 5133,-1895,-353,4978,744,144,3837,3069,2777 } }, /* LibRaw */
+ { LIBRAW_CAMERAMAKER_Sigma, "DP3 Merrill", 31, 4095,
+ { 5133,-1895,-353,4978,744,144,3837,3069,2777 } }, /* LibRaw */
+// Sigma DP (non-Merrill Versions)
+ { LIBRAW_CAMERAMAKER_Sigma, "DP1X", 0, 4095,
+ { 13704,-2452,-857,-5413,15073,186,-89,151,9820 } },
+ { LIBRAW_CAMERAMAKER_Sigma, "DP1", 0, 4095,
+ { 12774,-2591,-394,-5333,14676,207,15,-21,12127 } },
+ { LIBRAW_CAMERAMAKER_Sigma, "DP", 0, 4095,
+ // { 7401,-1169,-567,2059,3769,1510,664,3367,5328 } },
+ { 13100,-3638,-847,6855,2369,580,2723,3218,3251 } }, /* LibRaw */
+
+ { LIBRAW_CAMERAMAKER_Sinar, "", 0, 0,
+ { 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } }, /* DJC */
+
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-F828", 0, 0,
+ { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-R1", 0, 0,
+ { 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-V3", 0, 0,
+ { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-HX9", -800, 0, // same CMs: DSC-HX95, DSC-HX99
+ { 13076,-5686,-1481,-4027,12851,1251,-167,725,4937 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "ZV-1", -800, 0,
+ { 8280,-2987,-703,-3531,11645,2133,-550,1542,5312 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ZV-E10", 0, 0,
+ { 6355,-2067,-490,-3653,11542,2400,-406,1258,5506 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX100M7", -800, 0,
+ {10315, -4390, -937, -4859, 12734, 2365, -734, 1537, 5997 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX100M6", -800, 0,
+ { 7325,-2321,-596,-3494,11674,2055,-668,1562,5031 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX100M5A", -800, 0,
+ { 11176,-4700,-965,-4004,12184,2032,-763,1726,5876 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX100M", -800, 0, // same CMs: DSC-RX100M2, DSC-RX100M3, DSC-RX100M4, DSC-RX100M5
+ { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX100", 0, 0,
+ { 8651,-2754,-1057,-3464,12207,1373,-568,1398,4434 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX10M4", -800, 0,
+ { 7699,-2566,-629,-2967,11270,1928,-378,1286,4807 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX10",0, 0, // same CMs: DSC-RX10, DSC-RX10M2, DSC-RX10M3
+ { 6679,-1825,-745,-5047,13256,1953,-1580,2422,5183 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX1RM2", 0, 0,
+ { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX1R", 0, 0,
+ { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX1", 0, 0,
+ { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "DSC-RX0", -800, 0, // same CMs: DSC-RX0, DSC-RX0M2
+ { 9396,-3507,-843,-2497,11111,1572,-343,1355,5089 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A100", 0, 0xfeb,
+ { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A290", 0, 0,
+ { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A2", 0, 0, // same CMs: DSLR-A200, DSLR-A230
+ { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A300", 0, 0,
+ { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A330", 0, 0,
+ { 9847,-3091,-929,-8485,16346,2225,-714,595,7103 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A3", 0, 0, // same CMs: DSLR-A350, DSLR-A380, DSLR-A390
+ { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A450", 0, 0, // close to 16596 if arw is 14-bit
+ { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A580", 0, 16596,
+ { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A500", 0, 16596,
+ { 6046,-1127,-278,-5574,13076,2786,-691,1419,7625 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A5", 0, 16596, // same CMs: DSLR-A550, DSLR-A560
+ { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A700", 0, 0,
+ { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A850", 0, 0,
+ { 5413,-1162,-365,-5665,13098,2866,-608,1179,8440 } },
+ { LIBRAW_CAMERAMAKER_Sony, "DSLR-A900", 0, 0,
+ { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "ILCA-68", 0, 0,
+ { 6435,-1903,-536,-4722,12449,2550,-663,1363,6517 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCA-77M2", 0, 0,
+ { 5991,-1732,-443,-4100,11989,2381,-704,1467,5992 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCA-99M2", 0, 0,
+ { 6660,-1918,-471,-4613,12398,2485,-649,1433,6447 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-1", 0, 0,
+ { 8161, -2947, -739, -4811, 12668, 2389, -437, 1229, 6524}},
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7RM4", 0, 0, // same CMs: ILCE-7RM4, ILCE-7RM4A
+ { 7662, -2686,-660,-5240, 12965,2530, -796, 1508, 6167 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7RM3", 0, 0, // same CMs: ILCE-7RM3, ILCE-7RM3A
+ { 6640,-1847,-503,-5238,13010,2474,-993,1673,6527 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7RM2", 0, 0,
+ { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7R", 0, 0,
+ { 4913,-541,-202,-6130,13513,2906,-1564,2151,7183 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7SM3", 0, 0,
+ { 6912,-2127,-469,-4470,12175,2587,-398,1478,6492 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7S", 0, 0, // same CMs: ILCE-7S, ILCE-7SM2
+ { 5838,-1430,-246,-3497,11477,2297,-748,1885,5778 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7C", 0, 0,
+ { 7374,-2389,-551,-5435,13162,2519,-1006,1795,6552 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7M4", 0, 0,
+ { 7460,-2365,-588,-5687,13442,2474,-624,1156,6584 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7M3", 0, 0,
+ { 7374,-2389,-551,-5435,13162,2519,-1006,1795,6552 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7", 0, 0, // same CMs: ILCE-7, ILCE-7M2
+ { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-9", 0, 0, // same CMs: ILCE-9, ILCE-9M2
+ { 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-6100", 0, 0,
+ { 7657,-2847,-607,-4083,11966,2389,-684,1418,5844 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-6300", 0, 0,
+ { 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-6400", 0, 0,
+ { 7657,-2847,-607,-4083,11966,2389,-684,1418,5844 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-6500", 0, 0,
+ { 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-6600", 0, 0,
+ { 7657,-2847,-607,-4083,11966,2389,-684,1418,5844 } },
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE", 0, 0, // same CMs: ILCE-3000, ILCE-5000, ILCE-5100, ILCE-6000, ILCE-QX1
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "ILME-FX3", 0, 0,
+ { 6912, -2127, -469, -4470, 12175, 2587, -398, 1478, 6492 } },
+
+ { LIBRAW_CAMERAMAKER_Sony, "NEX-5N", 0, 0,
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+ { LIBRAW_CAMERAMAKER_Sony, "NEX-5R", 0, 0,
+ { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
+ { LIBRAW_CAMERAMAKER_Sony, "NEX-5T", 0, 0,
+ { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
+ { LIBRAW_CAMERAMAKER_Sony, "NEX-5", 0, 0,
+ { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } },
+ { LIBRAW_CAMERAMAKER_Sony, "NEX-3N", 0, 0,
+ { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
+ { LIBRAW_CAMERAMAKER_Sony, "NEX-3", 0, 0,
+ { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } },
+ { LIBRAW_CAMERAMAKER_Sony, "NEX-6", 0, 0,
+ { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
+ { LIBRAW_CAMERAMAKER_Sony, "NEX-7", 0, 0,
+ { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } },
+ { LIBRAW_CAMERAMAKER_Sony, "NEX-VG30", 0, 0,
+ { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
+ { LIBRAW_CAMERAMAKER_Sony, "NEX-VG900", 0, 0,
+ { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } },
+ { LIBRAW_CAMERAMAKER_Sony, "NEX", 0, 0, // same CMs: NEX-C3, NEX-F3, NEX-VG20
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+ { LIBRAW_CAMERAMAKER_Sony, "SLT-A33", 0, 0,
+ { 6069,-1221,-366,-5221,12779,2734,-1024,2066,6834 } },
+ { LIBRAW_CAMERAMAKER_Sony, "SLT-A35", 0, 0,
+ { 5986,-1618,-415,-4557,11820,3120,-681,1404,6971 } },
+ { LIBRAW_CAMERAMAKER_Sony, "SLT-A37", 0, 0,
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+ { LIBRAW_CAMERAMAKER_Sony, "SLT-A55", 0, 0,
+ { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } },
+ { LIBRAW_CAMERAMAKER_Sony, "SLT-A5", 0, 0, // same CMs: SLT-A57, SLT-A58
+ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
+ { LIBRAW_CAMERAMAKER_Sony, "SLT-A65", 0, 0,
+ { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } },
+ { LIBRAW_CAMERAMAKER_Sony, "SLT-A77", 0, 0,
+ { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } },
+ { LIBRAW_CAMERAMAKER_Sony, "SLT-A99", 0, 0,
+ { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } },
+ { LIBRAW_CAMERAMAKER_Sony, "MODEL-NAME", 0, 0,
+ { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } },
+
+ { LIBRAW_CAMERAMAKER_YI, "M1", 0, 0,
+ { 7712,-2059,-653,-3882,11494,2726,-710,1332,5958 } },
+ };
+ // clang-format on
+
+ double cam_xyz[4][3];
+ //char name[130];
+ int i, j;
+
+ if (colors > 4 || colors < 1)
+ return 1;
+
+ int bl4 = (cblack[0] + cblack[1] + cblack[2] + cblack[3]) / 4, bl64 = 0;
+ if (cblack[4] * cblack[5] > 0)
+ {
+ for (unsigned c = 0; c < 4096 && c < cblack[4] * cblack[5]; c++)
+ bl64 += cblack[c + 6];
+ bl64 /= cblack[4] * cblack[5];
+ }
+ int rblack = black + bl4 + bl64;
+
+ for (i = 0; i < int(sizeof table / sizeof *table); i++)
+ {
+ if (table[i].m_idx == make_idx)
+ {
+ size_t l = strlen(table[i].prefix);
+ if (!l || !strncasecmp(t_model, table[i].prefix, l))
+ {
+ if (!dng_version)
+ {
+ if (table[i].t_black > 0)
+ {
+ black = (ushort)table[i].t_black;
+ memset(cblack, 0, sizeof(cblack));
+ }
+ else if (table[i].t_black < 0 && rblack == 0)
+ {
+ black = (ushort)(-table[i].t_black);
+ memset(cblack, 0, sizeof(cblack));
+ }
+ if (table[i].t_maximum)
+ maximum = (ushort)table[i].t_maximum;
+ }
+ if (table[i].trans[0])
+ {
+ for (raw_color = j = 0; j < 12; j++)
+ if (internal_only)
+ imgdata.color.cam_xyz[j / 3][j % 3] = table[i].trans[j] / 10000.f;
+ else
+ ((double *)cam_xyz)[j] = imgdata.color.cam_xyz[j / 3][j % 3] = table[i].trans[j] / 10000.f;
+ if (!internal_only)
+ cam_xyz_coeff(rgb_cam, cam_xyz);
+ }
+ return 1; // CM found
+ }
+ }
+ }
+ return 0; // CM not found
+}
+void LibRaw::simple_coeff(int index)
+{
+ static const float table[][12] = {
+ /* index 0 -- all Foveon cameras */
+ {1.4032f, -0.2231f, -0.1016f, -0.5263f, 1.4816f, 0.017f, -0.0112f, 0.0183f,
+ 0.9113f},
+ /* index 1 -- Kodak DC20 and DC25 */
+ {2.25f, 0.75f, -1.75f, -0.25f, -0.25f, 0.75f, 0.75f, -0.25f, -0.25f, -1.75f, 0.75f,
+ 2.25f},
+ /* index 2 -- Logitech Fotoman Pixtura */
+ {1.893f, -0.418f, -0.476f, -0.495f, 1.773f, -0.278f, -1.017f, -0.655f, 2.672f},
+ /* index 3 -- Nikon E880, E900, and E990 */
+ {-1.936280f, 1.800443f, -1.448486f, 2.584324f, 1.405365f, -0.524955f, -0.289090f,
+ 0.408680f, -1.204965f, 1.082304f, 2.941367f, -1.818705f}};
+ int i, c;
+
+ for (raw_color = i = 0; i < 3; i++)
+ FORCC rgb_cam[i][c] = table[index][i * MIN(colors,4) + c];
+}
diff --git a/libkdcraw/libraw/src/tables/wblists.cpp b/libkdcraw/libraw/src/tables/wblists.cpp
new file mode 100644
index 0000000..f377cd3
--- /dev/null
+++ b/libkdcraw/libraw/src/tables/wblists.cpp
@@ -0,0 +1,217 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+
+#define _ARR_SZ(a) (sizeof(a)/sizeof(a[0]))
+
+static const int _tagtype_dataunit_bytes [19] = {
+ 1, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4, 2, 8, 8, 8, 8
+};
+
+libraw_static_table_t LibRaw::tagtype_dataunit_bytes(_tagtype_dataunit_bytes, _ARR_SZ(_tagtype_dataunit_bytes));
+
+int libraw_tagtype_dataunit_bytes(int tagtype)
+{
+ return _tagtype_dataunit_bytes[((unsigned)tagtype <= _ARR_SZ(_tagtype_dataunit_bytes)) ? tagtype : 0];
+}
+
+
+static const int _Canon_wbi2std[] = { // Canon WB index to standard indexes
+// std. number wbi - Canon number
+ LIBRAW_WBI_Auto, // 0
+ LIBRAW_WBI_Daylight, // 1
+ LIBRAW_WBI_Cloudy, // 2
+ LIBRAW_WBI_Tungsten, // 3
+ LIBRAW_WBI_Fluorescent, // 4
+ LIBRAW_WBI_Flash, // 5
+ LIBRAW_WBI_Custom, // 6
+ LIBRAW_WBI_BW, // 7
+ LIBRAW_WBI_Shade, // 8
+ LIBRAW_WBI_Kelvin, // 9
+ LIBRAW_WBI_PC_Set1, // 10
+ LIBRAW_WBI_PC_Set2, // 11
+ LIBRAW_WBI_PC_Set3, // 12
+ LIBRAW_WBI_Unknown, // 13, unlucky number "13", not used
+ LIBRAW_WBI_FluorescentHigh, // 14
+ LIBRAW_WBI_Custom1, // 15
+ LIBRAW_WBI_Custom2, // 16
+ LIBRAW_WBI_Underwater, // 17, last one for older PowerShot models
+ LIBRAW_WBI_Custom3, // 18
+ LIBRAW_WBI_Custom4, // 19
+ LIBRAW_WBI_PC_Set4, // 20
+ LIBRAW_WBI_PC_Set5, // 21
+ LIBRAW_WBI_Unknown, // 22
+ LIBRAW_WBI_Auto1 // 23
+};
+
+libraw_static_table_t LibRaw::Canon_wbi2std(_Canon_wbi2std, _ARR_SZ(_Canon_wbi2std));
+
+static const int _Canon_KeyIsZero_Len2048_linenums_2_StdWBi[] = { // Appendix A: G2, S30, S40; G3, G5, S45, S50
+ LIBRAW_WBI_Custom1,
+ LIBRAW_WBI_Custom2,
+ LIBRAW_WBI_Daylight,
+ LIBRAW_WBI_Cloudy,
+ LIBRAW_WBI_Tungsten,
+ LIBRAW_WBI_Fluorescent,
+ LIBRAW_WBI_Unknown, // ? FluorescentHigh, Shade, Custom, Kelvin
+ LIBRAW_WBI_Flash
+};
+
+libraw_static_table_t LibRaw::Canon_KeyIsZero_Len2048_linenums_2_StdWBi(_Canon_KeyIsZero_Len2048_linenums_2_StdWBi,
+ _ARR_SZ(_Canon_KeyIsZero_Len2048_linenums_2_StdWBi));
+
+static const int _Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi[] = { // G6, S60, S70; offset +16
+ LIBRAW_WBI_Custom1,
+ LIBRAW_WBI_Custom2,
+ LIBRAW_WBI_Daylight,
+ LIBRAW_WBI_Cloudy,
+ LIBRAW_WBI_Tungsten,
+ LIBRAW_WBI_Fluorescent,
+ LIBRAW_WBI_FluorescentHigh, // LIBRAW_WBI_Unknown, // ? FluorescentHigh, Shade, Custom, Kelvin
+ LIBRAW_WBI_Unknown,
+ LIBRAW_WBI_Underwater, // LIBRAW_WBI_Unknown,
+ LIBRAW_WBI_Unknown,
+ LIBRAW_WBI_Flash
+};
+
+libraw_static_table_t LibRaw::Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi(_Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi,
+ _ARR_SZ(_Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi));
+
+static const int _Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi[] = { // Pro1; offset +8
+ LIBRAW_WBI_Custom1,
+ LIBRAW_WBI_Custom2,
+ LIBRAW_WBI_Daylight,
+ LIBRAW_WBI_Cloudy,
+ LIBRAW_WBI_Tungsten,
+ LIBRAW_WBI_Fluorescent,
+ LIBRAW_WBI_Unknown,
+ LIBRAW_WBI_Flash, // LIBRAW_WBI_Unknown,
+ LIBRAW_WBI_Unknown,
+ LIBRAW_WBI_Unknown,
+ LIBRAW_WBI_Unknown // LIBRAW_WBI_Flash
+};
+
+libraw_static_table_t LibRaw::Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi(_Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi,
+ _ARR_SZ(_Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi));
+
+static const int _Canon_G9_linenums_2_StdWBi[] = {
+ LIBRAW_WBI_Auto,
+ LIBRAW_WBI_Daylight,
+ LIBRAW_WBI_Cloudy,
+ LIBRAW_WBI_Tungsten,
+ LIBRAW_WBI_Fluorescent,
+ LIBRAW_WBI_FluorescentHigh,
+ LIBRAW_WBI_Flash,
+ LIBRAW_WBI_Underwater,
+ LIBRAW_WBI_Custom1,
+ LIBRAW_WBI_Custom2
+};
+libraw_static_table_t LibRaw::Canon_G9_linenums_2_StdWBi(_Canon_G9_linenums_2_StdWBi, _ARR_SZ(_Canon_G9_linenums_2_StdWBi));
+
+static const int _Canon_D30_linenums_2_StdWBi[] = {
+ LIBRAW_WBI_Daylight,
+ LIBRAW_WBI_Cloudy,
+ LIBRAW_WBI_Tungsten,
+ LIBRAW_WBI_Fluorescent,
+ LIBRAW_WBI_Flash,
+ LIBRAW_WBI_Custom
+};
+libraw_static_table_t LibRaw::Canon_D30_linenums_2_StdWBi(_Canon_D30_linenums_2_StdWBi, _ARR_SZ(_Canon_D30_linenums_2_StdWBi));
+
+static const int _Fuji_wb_list1[] = {
+ LIBRAW_WBI_FineWeather, LIBRAW_WBI_Shade, LIBRAW_WBI_FL_D,
+ LIBRAW_WBI_FL_N, LIBRAW_WBI_FL_W, LIBRAW_WBI_Tungsten
+
+};
+libraw_static_table_t LibRaw::Fuji_wb_list1(_Fuji_wb_list1, _ARR_SZ(_Fuji_wb_list1));
+
+static const int _FujiCCT_K[31] = {
+ 2500, 2550, 2650, 2700, 2800, 2850, 2950, 3000, 3100, 3200, 3300,
+ 3400, 3600, 3700, 3800, 4000, 4200, 4300, 4500, 4800, 5000, 5300,
+ 5600, 5900, 6300, 6700, 7100, 7700, 8300, 9100, 10000
+};
+libraw_static_table_t LibRaw::FujiCCT_K(_FujiCCT_K, _ARR_SZ(_FujiCCT_K));
+
+static const int _Fuji_wb_list2[] = {
+ LIBRAW_WBI_Auto, 0, LIBRAW_WBI_Custom, 6, LIBRAW_WBI_FineWeather, 1,
+ LIBRAW_WBI_Shade, 8, LIBRAW_WBI_FL_D, 10, LIBRAW_WBI_FL_N, 11,
+ LIBRAW_WBI_FL_W, 12, LIBRAW_WBI_Tungsten, 2, LIBRAW_WBI_Underwater, 35,
+ LIBRAW_WBI_Ill_A, 82, LIBRAW_WBI_D65, 83
+};
+libraw_static_table_t LibRaw::Fuji_wb_list2(_Fuji_wb_list2, _ARR_SZ(_Fuji_wb_list2));
+
+static const int _Pentax_wb_list1[] = {
+ LIBRAW_WBI_Daylight, LIBRAW_WBI_Shade,
+ LIBRAW_WBI_Cloudy, LIBRAW_WBI_Tungsten,
+ LIBRAW_WBI_FL_D, LIBRAW_WBI_FL_N,
+ LIBRAW_WBI_FL_W, LIBRAW_WBI_Flash
+};
+libraw_static_table_t LibRaw::Pentax_wb_list1(_Pentax_wb_list1, _ARR_SZ(_Pentax_wb_list1));
+
+static const int _Pentax_wb_list2[] = {
+ LIBRAW_WBI_Daylight, LIBRAW_WBI_Shade, LIBRAW_WBI_Cloudy,
+ LIBRAW_WBI_Tungsten, LIBRAW_WBI_FL_D, LIBRAW_WBI_FL_N,
+ LIBRAW_WBI_FL_W, LIBRAW_WBI_Flash, LIBRAW_WBI_FL_L
+};
+libraw_static_table_t LibRaw::Pentax_wb_list2(_Pentax_wb_list2, _ARR_SZ(_Pentax_wb_list2));
+
+
+static const int _Oly_wb_list1[] = {
+ LIBRAW_WBI_Shade, LIBRAW_WBI_Cloudy, LIBRAW_WBI_FineWeather,
+ LIBRAW_WBI_Tungsten, LIBRAW_WBI_Sunset, LIBRAW_WBI_FL_D,
+ LIBRAW_WBI_FL_N, LIBRAW_WBI_FL_W, LIBRAW_WBI_FL_WW
+};
+libraw_static_table_t LibRaw::Oly_wb_list1(_Oly_wb_list1, _ARR_SZ(_Oly_wb_list1));
+
+static const int _Oly_wb_list2[] = {
+ LIBRAW_WBI_Auto, 0,
+ LIBRAW_WBI_Tungsten, 3000,
+ 0x100, 3300,
+ 0x100, 3600,
+ 0x100, 3900,
+ LIBRAW_WBI_FL_W, 4000,
+ 0x100, 4300,
+ LIBRAW_WBI_FL_D, 4500,
+ 0x100, 4800,
+ LIBRAW_WBI_FineWeather, 5300,
+ LIBRAW_WBI_Cloudy, 6000,
+ LIBRAW_WBI_FL_N, 6600,
+ LIBRAW_WBI_Shade, 7500,
+ LIBRAW_WBI_Custom1, 0,
+ LIBRAW_WBI_Custom2, 0,
+ LIBRAW_WBI_Custom3, 0,
+ LIBRAW_WBI_Custom4, 0
+};
+libraw_static_table_t LibRaw::Oly_wb_list2(_Oly_wb_list2, _ARR_SZ(_Oly_wb_list2));
+
+static const int _Sony_SRF_wb_list[] = {
+ LIBRAW_WBI_Daylight, LIBRAW_WBI_Cloudy, LIBRAW_WBI_Fluorescent,
+ LIBRAW_WBI_Tungsten, LIBRAW_WBI_Flash
+};
+libraw_static_table_t LibRaw::Sony_SRF_wb_list(_Sony_SRF_wb_list, _ARR_SZ(_Sony_SRF_wb_list));
+
+static const int _Sony_SR2_wb_list[] = {
+ LIBRAW_WBI_Daylight, LIBRAW_WBI_Cloudy, LIBRAW_WBI_Tungsten, LIBRAW_WBI_Flash,
+ 4500, LIBRAW_WBI_Unknown, LIBRAW_WBI_Fluorescent
+};
+libraw_static_table_t LibRaw::Sony_SR2_wb_list(_Sony_SR2_wb_list, _ARR_SZ(_Sony_SR2_wb_list));
+
+static const int _Sony_SR2_wb_list1[] = {
+ LIBRAW_WBI_Daylight, LIBRAW_WBI_Cloudy, LIBRAW_WBI_Tungsten, LIBRAW_WBI_Flash,
+ 4500, LIBRAW_WBI_Shade, LIBRAW_WBI_FL_W, LIBRAW_WBI_FL_N, LIBRAW_WBI_FL_D,
+ LIBRAW_WBI_FL_L, 8500, 6000, 3200, 2500
+};
+libraw_static_table_t LibRaw::Sony_SR2_wb_list1(_Sony_SR2_wb_list1, _ARR_SZ(_Sony_SR2_wb_list1));
diff --git a/libkdcraw/libraw/src/utils/curves.cpp b/libkdcraw/libraw/src/utils/curves.cpp
new file mode 100644
index 0000000..03b1253
--- /dev/null
+++ b/libkdcraw/libraw/src/utils/curves.cpp
@@ -0,0 +1,151 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+void LibRaw::cubic_spline(const int *x_, const int *y_, const int len)
+{
+ float **A, *b, *c, *d, *x, *y;
+ int i, j;
+
+ A = (float **)calloc(((2 * len + 4) * sizeof **A + sizeof *A), 2 * len);
+ if (!A)
+ return;
+ A[0] = (float *)(A + 2 * len);
+ for (i = 1; i < 2 * len; i++)
+ A[i] = A[0] + 2 * len * i;
+ y = len + (x = i + (d = i + (c = i + (b = A[0] + i * i))));
+ for (i = 0; i < len; i++)
+ {
+ x[i] = x_[i] / 65535.0;
+ y[i] = y_[i] / 65535.0;
+ }
+ for (i = len - 1; i > 0; i--)
+ {
+ b[i] = (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
+ d[i - 1] = x[i] - x[i - 1];
+ }
+ for (i = 1; i < len - 1; i++)
+ {
+ A[i][i] = 2 * (d[i - 1] + d[i]);
+ if (i > 1)
+ {
+ A[i][i - 1] = d[i - 1];
+ A[i - 1][i] = d[i - 1];
+ }
+ A[i][len - 1] = 6 * (b[i + 1] - b[i]);
+ }
+ for (i = 1; i < len - 2; i++)
+ {
+ float v = A[i + 1][i] / A[i][i];
+ for (j = 1; j <= len - 1; j++)
+ A[i + 1][j] -= v * A[i][j];
+ }
+ for (i = len - 2; i > 0; i--)
+ {
+ float acc = 0;
+ for (j = i; j <= len - 2; j++)
+ acc += A[i][j] * c[j];
+ c[i] = (A[i][len - 1] - acc) / A[i][i];
+ }
+ for (i = 0; i < 0x10000; i++)
+ {
+ float x_out = (float)(i / 65535.0);
+ float y_out = 0;
+ for (j = 0; j < len - 1; j++)
+ {
+ if (x[j] <= x_out && x_out <= x[j + 1])
+ {
+ float v = x_out - x[j];
+ y_out = y[j] +
+ ((y[j + 1] - y[j]) / d[j] -
+ (2 * d[j] * c[j] + c[j + 1] * d[j]) / 6) *
+ v +
+ (c[j] * 0.5) * v * v +
+ ((c[j + 1] - c[j]) / (6 * d[j])) * v * v * v;
+ }
+ }
+ curve[i] = y_out < 0.0
+ ? 0
+ : (y_out >= 1.0 ? 65535 : (ushort)(y_out * 65535.0 + 0.5));
+ }
+ free(A);
+}
+void LibRaw::gamma_curve(double pwr, double ts, int mode, int imax)
+{
+ int i;
+ double g[6], bnd[2] = {0, 0}, r;
+
+ g[0] = pwr;
+ g[1] = ts;
+ g[2] = g[3] = g[4] = 0;
+ bnd[g[1] >= 1] = 1;
+ if (g[1] && (g[1] - 1) * (g[0] - 1) <= 0)
+ {
+ for (i = 0; i < 48; i++)
+ {
+ g[2] = (bnd[0] + bnd[1]) / 2;
+ if (g[0])
+ bnd[(pow(g[2] / g[1], -g[0]) - 1) / g[0] - 1 / g[2] > -1] = g[2];
+ else
+ bnd[g[2] / exp(1 - 1 / g[2]) < g[1]] = g[2];
+ }
+ g[3] = g[2] / g[1];
+ if (g[0])
+ g[4] = g[2] * (1 / g[0] - 1);
+ }
+ if (g[0])
+ g[5] = 1 / (g[1] * SQR(g[3]) / 2 - g[4] * (1 - g[3]) +
+ (1 - pow(g[3], 1 + g[0])) * (1 + g[4]) / (1 + g[0])) -
+ 1;
+ else
+ g[5] = 1 / (g[1] * SQR(g[3]) / 2 + 1 - g[2] - g[3] -
+ g[2] * g[3] * (log(g[3]) - 1)) -
+ 1;
+ if (!mode--)
+ {
+ memcpy(gamm, g, sizeof gamm);
+ return;
+ }
+ for (i = 0; i < 0x10000; i++)
+ {
+ curve[i] = 0xffff;
+ if ((r = (double)i / imax) < 1)
+ curve[i] =
+ 0x10000 *
+ (mode ? (r < g[3] ? r * g[1]
+ : (g[0] ? pow(r, g[0]) * (1 + g[4]) - g[4]
+ : log(r) * g[2] + 1))
+ : (r < g[2] ? r / g[1]
+ : (g[0] ? pow((r + g[4]) / (1 + g[4]), 1 / g[0])
+ : exp((r - 1) / g[2]))));
+ }
+}
+
+void LibRaw::linear_table(unsigned len)
+{
+ int i;
+ if (len > 0x10000)
+ len = 0x10000;
+ else if (len < 1)
+ return;
+ read_shorts(curve, len);
+ for (i = len; i < 0x10000; i++)
+ curve[i] = curve[i - 1];
+ maximum = curve[len < 0x1000 ? 0xfff : len - 1];
+}
diff --git a/libkdcraw/libraw/src/utils/decoder_info.cpp b/libkdcraw/libraw/src/utils/decoder_info.cpp
new file mode 100644
index 0000000..cc440db
--- /dev/null
+++ b/libkdcraw/libraw/src/utils/decoder_info.cpp
@@ -0,0 +1,413 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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"
+
+const char *LibRaw::unpack_function_name()
+{
+ libraw_decoder_info_t decoder_info;
+ get_decoder_info(&decoder_info);
+ return decoder_info.decoder_name;
+}
+
+int LibRaw::get_decoder_info(libraw_decoder_info_t *d_info)
+{
+ if (!d_info)
+ return LIBRAW_UNSPECIFIED_ERROR;
+ d_info->decoder_name = 0;
+ d_info->decoder_flags = 0;
+ if (!load_raw)
+ return LIBRAW_OUT_OF_ORDER_CALL;
+
+ // dcraw.c names order
+ if (load_raw == &LibRaw::android_tight_load_raw)
+ {
+ d_info->decoder_name = "android_tight_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::android_loose_load_raw)
+ {
+ d_info->decoder_name = "android_loose_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::vc5_dng_load_raw_placeholder)
+ {
+ d_info->decoder_name = "vc5_dng_load_raw_placeholder()";
+#ifndef USE_GPRSDK
+ d_info->decoder_flags = LIBRAW_DECODER_UNSUPPORTED_FORMAT;
+#endif
+ }
+ else if (load_raw == &LibRaw::canon_600_load_raw)
+ {
+ d_info->decoder_name = "canon_600_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::fuji_compressed_load_raw)
+ {
+ d_info->decoder_name = "fuji_compressed_load_raw()";
+ }
+ else if (load_raw == &LibRaw::fuji_14bit_load_raw)
+ {
+ d_info->decoder_name = "fuji_14bit_load_raw()";
+ }
+ else if (load_raw == &LibRaw::canon_load_raw)
+ {
+ d_info->decoder_name = "canon_load_raw()";
+ }
+ else if (load_raw == &LibRaw::lossless_jpeg_load_raw)
+ {
+ d_info->decoder_name = "lossless_jpeg_load_raw()";
+ d_info->decoder_flags =
+ LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED3;
+ }
+ else if (load_raw == &LibRaw::canon_sraw_load_raw)
+ {
+ d_info->decoder_name = "canon_sraw_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED3;
+ }
+ else if (load_raw == &LibRaw::crxLoadRaw)
+ {
+ d_info->decoder_name = "crxLoadRaw()";
+ }
+ else if (load_raw == &LibRaw::lossless_dng_load_raw)
+ {
+ d_info->decoder_name = "lossless_dng_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE |
+ LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED3 |
+ LIBRAW_DECODER_ADOBECOPYPIXEL;
+ }
+ else if (load_raw == &LibRaw::packed_dng_load_raw)
+ {
+ d_info->decoder_name = "packed_dng_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE |
+ LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED3 |
+ LIBRAW_DECODER_ADOBECOPYPIXEL;
+ }
+ else if (load_raw == &LibRaw::pentax_load_raw)
+ {
+ d_info->decoder_name = "pentax_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED3;
+ }
+ else if (load_raw == &LibRaw::nikon_load_raw)
+ {
+ d_info->decoder_name = "nikon_load_raw()";
+ d_info->decoder_flags =
+ LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_TRYRAWSPEED3;
+ }
+ else if (load_raw == &LibRaw::nikon_coolscan_load_raw)
+ {
+ d_info->decoder_name = "nikon_coolscan_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::nikon_he_load_raw_placeholder)
+ {
+ d_info->decoder_name = "nikon_he_load_raw_placeholder()";
+ d_info->decoder_flags = LIBRAW_DECODER_UNSUPPORTED_FORMAT;
+ }
+ else if (load_raw == &LibRaw::nikon_load_sraw)
+ {
+ d_info->decoder_name = "nikon_load_sraw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::nikon_yuv_load_raw)
+ {
+ d_info->decoder_name = "nikon_load_yuv_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::rollei_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "rollei_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::phase_one_load_raw)
+ {
+ d_info->decoder_name = "phase_one_load_raw()";
+ }
+ else if (load_raw == &LibRaw::phase_one_load_raw_c)
+ {
+ d_info->decoder_name = "phase_one_load_raw_c()";
+ d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED3; /* FIXME: need to make sure correction not applied*/
+ }
+ else if (load_raw == &LibRaw::phase_one_load_raw_s)
+ {
+ d_info->decoder_name = "phase_one_load_raw_s()";
+ }
+ else if (load_raw == &LibRaw::hasselblad_load_raw)
+ {
+ d_info->decoder_name = "hasselblad_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED3; /* FIXME: need to make sure correction not applied*/
+ }
+ else if (load_raw == &LibRaw::leaf_hdr_load_raw)
+ {
+ d_info->decoder_name = "leaf_hdr_load_raw()";
+ }
+ else if (load_raw == &LibRaw::unpacked_load_raw)
+ {
+ d_info->decoder_name = "unpacked_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FLATDATA;
+ }
+ else if (load_raw == &LibRaw::unpacked_load_raw_reversed)
+ {
+ d_info->decoder_name = "unpacked_load_raw_reversed()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::sinar_4shot_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "sinar_4shot_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_SINAR4SHOT;
+ }
+ else if (load_raw == &LibRaw::imacon_full_load_raw)
+ {
+ d_info->decoder_name = "imacon_full_load_raw()";
+ }
+ else if (load_raw == &LibRaw::hasselblad_full_load_raw)
+ {
+ d_info->decoder_name = "hasselblad_full_load_raw()";
+ }
+ else if (load_raw == &LibRaw::packed_load_raw)
+ {
+ d_info->decoder_name = "packed_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED3;
+ }
+ else if (load_raw == &LibRaw::broadcom_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "broadcom_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::nokia_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "nokia_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ else if (load_raw == &LibRaw::canon_rmf_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "canon_rmf_load_raw()";
+ }
+#endif
+ else if (load_raw == &LibRaw::panasonic_load_raw)
+ {
+ d_info->decoder_name = "panasonic_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED;
+ }
+ else if (load_raw == &LibRaw::panasonicC6_load_raw)
+ {
+ d_info->decoder_name = "panasonicC6_load_raw()";
+ /* FIXME: No rawspeed3: not sure it handles 12-bit data too */
+ }
+ else if (load_raw == &LibRaw::panasonicC7_load_raw)
+ {
+ d_info->decoder_name = "panasonicC7_load_raw()";
+ }
+ else if (load_raw == &LibRaw::olympus_load_raw)
+ {
+ d_info->decoder_name = "olympus_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED3;;
+ }
+ else if (load_raw == &LibRaw::minolta_rd175_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "minolta_rd175_load_raw()";
+ }
+ else if (load_raw == &LibRaw::quicktake_100_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "quicktake_100_load_raw()";
+ }
+ else if (load_raw == &LibRaw::kodak_radc_load_raw)
+ {
+ d_info->decoder_name = "kodak_radc_load_raw()";
+ }
+ else if (load_raw == &LibRaw::kodak_jpeg_load_raw)
+ {
+ // UNTESTED + RBAYER
+ d_info->decoder_name = "kodak_jpeg_load_raw()";
+ }
+ else if (load_raw == &LibRaw::lossy_dng_load_raw)
+ {
+ // Check rbayer
+ d_info->decoder_name = "lossy_dng_load_raw()";
+ d_info->decoder_flags =
+ LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_HASCURVE;
+ }
+ else if (load_raw == &LibRaw::kodak_dc120_load_raw)
+ {
+ d_info->decoder_name = "kodak_dc120_load_raw()";
+ }
+ else if (load_raw == &LibRaw::eight_bit_load_raw)
+ {
+ d_info->decoder_name = "eight_bit_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::kodak_c330_load_raw)
+ {
+ d_info->decoder_name = "kodak_yrgb_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::kodak_c603_load_raw)
+ {
+ d_info->decoder_name = "kodak_yrgb_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::kodak_262_load_raw)
+ {
+ d_info->decoder_name = "kodak_262_load_raw()"; // UNTESTED!
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::kodak_65000_load_raw)
+ {
+ d_info->decoder_name = "kodak_65000_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE;
+ }
+ else if (load_raw == &LibRaw::kodak_ycbcr_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "kodak_ycbcr_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::kodak_rgb_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "kodak_rgb_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::sony_load_raw)
+ {
+ d_info->decoder_name = "sony_load_raw()";
+ }
+ else if (load_raw == &LibRaw::sony_ljpeg_load_raw)
+ {
+ d_info->decoder_name = "sony_ljpeg_load_raw()";
+ }
+ else if (load_raw == &LibRaw::sony_arw_load_raw)
+ {
+ d_info->decoder_name = "sony_arw_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED3;
+ }
+ else if (load_raw == &LibRaw::sony_arw2_load_raw)
+ {
+ d_info->decoder_name = "sony_arw2_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE |
+ LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED3 |
+ LIBRAW_DECODER_SONYARW2;
+ }
+ else if (load_raw == &LibRaw::sony_arq_load_raw)
+ {
+ d_info->decoder_name = "sony_arq_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_LEGACY_WITH_MARGINS | LIBRAW_DECODER_FLATDATA | LIBRAW_DECODER_FLAT_BG2_SWAPPED;
+ }
+ else if (load_raw == &LibRaw::samsung_load_raw)
+ {
+ d_info->decoder_name = "samsung_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED3;
+ }
+ else if (load_raw == &LibRaw::samsung2_load_raw)
+ {
+ d_info->decoder_name = "samsung2_load_raw()";
+ }
+ else if (load_raw == &LibRaw::samsung3_load_raw)
+ {
+ d_info->decoder_name = "samsung3_load_raw()";
+ }
+ else if (load_raw == &LibRaw::smal_v6_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "smal_v6_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+ else if (load_raw == &LibRaw::smal_v9_load_raw)
+ {
+ // UNTESTED
+ d_info->decoder_name = "smal_v9_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC;
+ }
+#ifdef LIBRAW_OLD_VIDEO_SUPPORT
+ else if (load_raw == &LibRaw::redcine_load_raw)
+ {
+ d_info->decoder_name = "redcine_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE;
+ }
+#endif
+ else if (load_raw == &LibRaw::x3f_load_raw)
+ {
+ d_info->decoder_name = "x3f_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_OWNALLOC | LIBRAW_DECODER_FIXEDMAXC |
+ LIBRAW_DECODER_LEGACY_WITH_MARGINS;
+ }
+ else if (load_raw == &LibRaw::pentax_4shot_load_raw)
+ {
+ d_info->decoder_name = "pentax_4shot_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_OWNALLOC;
+ }
+ else if (load_raw == &LibRaw::deflate_dng_load_raw)
+ {
+ d_info->decoder_name = "deflate_dng_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_OWNALLOC;
+ }
+ else if (load_raw == &LibRaw::uncompressed_fp_dng_load_raw)
+ {
+ d_info->decoder_name = "uncompressed_fp_dng_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_OWNALLOC;
+ }
+ else if (load_raw == &LibRaw::nikon_load_striped_packed_raw)
+ {
+ d_info->decoder_name = "nikon_load_striped_packed_raw()";
+ }
+ else if (load_raw == &LibRaw::nikon_load_padded_packed_raw)
+ {
+ d_info->decoder_name = "nikon_load_padded_packed_raw()";
+ }
+ else if (load_raw == &LibRaw::nikon_14bit_load_raw)
+ {
+ d_info->decoder_name = "nikon_14bit_load_raw()";
+ }
+ /* -- added 07/02/18 -- */
+ else if (load_raw == &LibRaw::unpacked_load_raw_fuji_f700s20)
+ {
+ d_info->decoder_name = "unpacked_load_raw_fuji_f700s20()";
+ }
+ else if (load_raw == &LibRaw::unpacked_load_raw_FujiDBP)
+ {
+ d_info->decoder_name = "unpacked_load_raw_FujiDBP()";
+ }
+#ifdef USE_6BY9RPI
+ else if (load_raw == &LibRaw::rpi_load_raw8)
+ {
+ d_info->decoder_name = "rpi_load_raw8";
+ }
+ else if (load_raw == &LibRaw::rpi_load_raw12)
+ {
+ d_info->decoder_name = "rpi_load_raw12";
+ }
+ else if (load_raw == &LibRaw::rpi_load_raw14)
+ {
+ d_info->decoder_name = "rpi_load_raw14";
+ }
+ else if (load_raw == &LibRaw::rpi_load_raw16)
+ {
+ d_info->decoder_name = "rpi_load_raw16";
+ }
+#endif
+ else
+ {
+ d_info->decoder_name = "Unknown unpack function";
+ d_info->decoder_flags = LIBRAW_DECODER_NOTSET;
+ }
+ return LIBRAW_SUCCESS;
+}
diff --git a/libkdcraw/libraw/src/utils/init_close_utils.cpp b/libkdcraw/libraw/src/utils/init_close_utils.cpp
new file mode 100644
index 0000000..26478d8
--- /dev/null
+++ b/libkdcraw/libraw/src/utils/init_close_utils.cpp
@@ -0,0 +1,340 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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"
+#ifdef USE_RAWSPEED3
+#include "rawspeed3_capi.h"
+#endif
+
+static void cleargps(libraw_gps_info_t *q)
+{
+ for (int i = 0; i < 3; i++)
+ q->latitude[i] = q->longitude[i] = q->gpstimestamp[i] = 0.f;
+ q->altitude = 0.f;
+ q->altref = q->latref = q->longref = q->gpsstatus = q->gpsparsed = 0;
+}
+
+LibRaw::LibRaw(unsigned int flags) : memmgr(1024)
+{
+ double aber[4] = {1, 1, 1, 1};
+ double gamm[6] = {0.45, 4.5, 0, 0, 0, 0};
+ unsigned greybox[4] = {0, 0, UINT_MAX, UINT_MAX};
+ unsigned cropbox[4] = {0, 0, UINT_MAX, UINT_MAX};
+ ZERO(imgdata);
+
+ cleargps(&imgdata.other.parsed_gps);
+ ZERO(libraw_internal_data);
+ ZERO(callbacks);
+
+ _rawspeed_camerameta = _rawspeed_decoder = NULL;
+ _rawspeed3_handle = NULL;
+ dnghost = NULL;
+ dngnegative = NULL;
+ dngimage = NULL;
+ _x3f_data = NULL;
+
+#ifdef USE_RAWSPEED
+ CameraMetaDataLR *camerameta =
+ make_camera_metadata(); // May be NULL in case of exception in
+ // make_camera_metadata()
+ _rawspeed_camerameta = static_cast<void *>(camerameta);
+#endif
+ callbacks.data_cb = (flags & LIBRAW_OPTIONS_NO_DATAERR_CALLBACK)
+ ? NULL
+ : &default_data_callback;
+ callbacks.exif_cb = NULL; // no default callback
+ callbacks.pre_identify_cb = NULL;
+ callbacks.post_identify_cb = NULL;
+ callbacks.pre_subtractblack_cb = callbacks.pre_scalecolors_cb =
+ callbacks.pre_preinterpolate_cb = callbacks.pre_interpolate_cb =
+ callbacks.interpolate_bayer_cb = callbacks.interpolate_xtrans_cb =
+ callbacks.post_interpolate_cb = callbacks.pre_converttorgb_cb =
+ callbacks.post_converttorgb_cb = NULL;
+
+ memmove(&imgdata.params.aber, &aber, sizeof(aber));
+ memmove(&imgdata.params.gamm, &gamm, sizeof(gamm));
+ memmove(&imgdata.params.greybox, &greybox, sizeof(greybox));
+ memmove(&imgdata.params.cropbox, &cropbox, sizeof(cropbox));
+
+ imgdata.params.bright = 1;
+ imgdata.params.use_camera_matrix = 1;
+ imgdata.params.user_flip = -1;
+ imgdata.params.user_black = -1;
+ imgdata.params.user_cblack[0] = imgdata.params.user_cblack[1] =
+ imgdata.params.user_cblack[2] = imgdata.params.user_cblack[3] = -1000001;
+ imgdata.params.user_sat = -1;
+ imgdata.params.user_qual = -1;
+ imgdata.params.output_color = 1;
+ imgdata.params.output_bps = 8;
+ imgdata.params.use_fuji_rotate = 1;
+ imgdata.params.exp_shift = 1.0;
+ imgdata.params.auto_bright_thr = LIBRAW_DEFAULT_AUTO_BRIGHTNESS_THRESHOLD;
+ imgdata.params.adjust_maximum_thr = LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD;
+ imgdata.rawparams.use_rawspeed = 1;
+ imgdata.rawparams.use_dngsdk = LIBRAW_DNG_DEFAULT;
+ imgdata.params.no_auto_scale = 0;
+ imgdata.params.no_interpolation = 0;
+ imgdata.rawparams.specials = 0; /* was inverted : LIBRAW_PROCESSING_DP2Q_INTERPOLATERG | LIBRAW_PROCESSING_DP2Q_INTERPOLATEAF; */
+ imgdata.rawparams.options = LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT;
+ imgdata.rawparams.sony_arw2_posterization_thr = 0;
+ imgdata.rawparams.max_raw_memory_mb = LIBRAW_MAX_ALLOC_MB_DEFAULT;
+ imgdata.params.green_matching = 0;
+ imgdata.rawparams.custom_camera_strings = 0;
+ imgdata.rawparams.coolscan_nef_gamma = 1.0f;
+ imgdata.parent_class = this;
+ imgdata.progress_flags = 0;
+ imgdata.color.dng_levels.baseline_exposure = -999.f;
+ imgdata.color.dng_levels.LinearResponseLimit = 1.0f;
+ MN.hasselblad.nIFD_CM[0] =
+ MN.hasselblad.nIFD_CM[1] = -1;
+ MN.kodak.ISOCalibrationGain = 1.0f;
+ _exitflag = 0;
+ tls = new LibRaw_TLS;
+ tls->init();
+}
+
+LibRaw::~LibRaw()
+{
+ recycle();
+ delete tls;
+#ifdef USE_RAWSPEED3
+ if (_rawspeed3_handle)
+ rawspeed3_close(_rawspeed3_handle);
+ _rawspeed3_handle = NULL;
+#endif
+
+#ifdef USE_RAWSPEED
+ if (_rawspeed_camerameta)
+ {
+ CameraMetaDataLR *cmeta =
+ static_cast<CameraMetaDataLR *>(_rawspeed_camerameta);
+ delete cmeta;
+ _rawspeed_camerameta = NULL;
+ }
+#endif
+}
+
+void x3f_clear(void *);
+
+void LibRaw::recycle()
+{
+ recycle_datastream();
+#define FREE(a) \
+ do \
+ { \
+ if (a) \
+ { \
+ free(a); \
+ a = NULL; \
+ } \
+ } while (0)
+
+ FREE(imgdata.image);
+
+ // explicit cleanup of afdata allocations; entire array is zeroed below
+ for (int i = 0; i < LIBRAW_AFDATA_MAXCOUNT; i++)
+ FREE(MN.common.afdata[i].AFInfoData);
+
+ FREE(imgdata.thumbnail.thumb);
+ FREE(libraw_internal_data.internal_data.meta_data);
+ FREE(libraw_internal_data.output_data.histogram);
+ FREE(libraw_internal_data.output_data.oprof);
+ FREE(imgdata.color.profile);
+ FREE(imgdata.rawdata.ph1_cblack);
+ FREE(imgdata.rawdata.ph1_rblack);
+ FREE(imgdata.rawdata.raw_alloc);
+ FREE(imgdata.idata.xmpdata);
+
+ parseCR3_Free();
+
+#undef FREE
+
+ ZERO(imgdata.sizes);
+ imgdata.sizes.raw_inset_crops[0].cleft = imgdata.sizes.raw_inset_crops[1].cleft = 0xffff;
+ imgdata.sizes.raw_inset_crops[0].ctop = imgdata.sizes.raw_inset_crops[1].ctop = 0xffff;
+
+ ZERO(imgdata.idata);
+ ZERO(imgdata.color);
+ ZERO(imgdata.lens);
+ ZERO(imgdata.other);
+ ZERO(imgdata.rawdata);
+ ZERO(imgdata.shootinginfo);
+ ZERO(imgdata.thumbnail);
+ ZERO(imgdata.thumbs_list);
+ ZERO(MN);
+ cleargps(&imgdata.other.parsed_gps);
+ ZERO(libraw_internal_data);
+
+ imgdata.lens.makernotes.FocalUnits = 1;
+ imgdata.lens.makernotes.LensID = LIBRAW_LENS_NOT_SET;
+ imgdata.shootinginfo.DriveMode = -1;
+ imgdata.shootinginfo.FocusMode = -1;
+ imgdata.shootinginfo.MeteringMode = -1;
+ imgdata.shootinginfo.AFPoint = -1;
+ imgdata.shootinginfo.ExposureMode = -1;
+ imgdata.shootinginfo.ExposureProgram = -1;
+ imgdata.shootinginfo.ImageStabilization = -1;
+
+ imgdata.color.dng_levels.baseline_exposure = -999.f;
+ imgdata.color.dng_levels.LinearResponseLimit = 1.f;
+ imgdata.color.dng_color[0].illuminant =
+ imgdata.color.dng_color[1].illuminant = LIBRAW_WBI_None;
+ for (int i = 0; i < 4; i++) imgdata.color.dng_levels.analogbalance[i] = 1.0f;
+
+ MN.canon.DefaultCropAbsolute.l = -1;
+ MN.canon.DefaultCropAbsolute.t = -1;
+ MN.canon.AutoLightingOptimizer = 3; // 'off' value
+
+ MN.fuji.WB_Preset = 0xffff;
+ MN.fuji.ExpoMidPointShift = -999.f;
+ MN.fuji.DynamicRange = 0xffff;
+ MN.fuji.FilmMode = 0xffff;
+ MN.fuji.DynamicRangeSetting = 0xffff;
+ MN.fuji.DevelopmentDynamicRange = 0xffff;
+ MN.fuji.AutoDynamicRange = 0xffff;
+ MN.fuji.DRangePriority = 0xffff;
+ MN.fuji.FocusMode = 0xffff;
+ MN.fuji.AFMode = 0xffff;
+ MN.fuji.FocusPixel[0] = MN.fuji.FocusPixel[1] = 0xffff;
+ MN.fuji.FocusSettings = 0xffffffff;
+ MN.fuji.AF_C_Settings = 0xffffffff;
+ MN.fuji.FocusWarning = 0xffff;
+ for (int i = 0; i < 3; i++) MN.fuji.ImageStabilization[i] = 0xffff;
+ MN.fuji.DriveMode = -1;
+ MN.fuji.ImageCount = -1;
+ MN.fuji.AutoBracketing = -1;
+ MN.fuji.SequenceNumber = -1;
+ MN.fuji.SeriesLength = -1;
+ MN.fuji.PixelShiftOffset[0] = MN.fuji.PixelShiftOffset[1] = -999.f;
+
+ MN.hasselblad.nIFD_CM[0] = MN.hasselblad.nIFD_CM[1] = -1;
+
+ MN.kodak.BlackLevelTop = 0xffff;
+ MN.kodak.BlackLevelBottom = 0xffff;
+ MN.kodak.ISOCalibrationGain = 1.0f;
+
+ MN.nikon.SensorHighSpeedCrop.cleft = 0xffff;
+ MN.nikon.SensorHighSpeedCrop.ctop = 0xffff;
+
+ MN.olympus.FocusMode[0] = 0xffff;
+ MN.olympus.AutoFocus = 0xffff;
+ MN.olympus.AFPoint = 0xffff;
+ MN.olympus.AFResult = 0xffff;
+ MN.olympus.AFFineTune = 0xff;
+ for (int i = 0; i < 3; i++) {
+ MN.olympus.AFFineTuneAdj[i] = -32768;
+ MN.olympus.SpecialMode[i] = 0xffffffff;
+ }
+ MN.olympus.ZoomStepCount = 0xffff;
+ MN.olympus.FocusStepCount = 0xffff;
+ MN.olympus.FocusStepInfinity = 0xffff;
+ MN.olympus.FocusStepNear = 0xffff;
+ MN.olympus.FocusDistance = -999.0;
+ for (int i = 0; i < 4; i++) MN.olympus.AspectFrame[i] = 0xffff;
+ MN.olympus.StackedImage[0] = 0xffffffff;
+
+ MN.panasonic.LensManufacturer = 0xffffffff;
+
+ MN.pentax.FocusMode[0] =
+ MN.pentax.FocusMode[1] = 0xffff;
+ MN.pentax.AFPointSelected[1] = 0xffff;
+ MN.pentax.AFPointSelected_Area = 0xffff;
+ MN.pentax.AFPointsInFocus = 0xffffffff;
+ MN.pentax.AFPointMode = 0xff;
+
+ MN.ricoh.AFStatus = 0xffff;
+ MN.ricoh.AFAreaMode = 0xffff;
+ MN.ricoh.WideAdapter = 0xffff;
+ MN.ricoh.CropMode = 0xffff;
+ MN.ricoh.NDFilter = 0xffff;
+ MN.ricoh.AutoBracketing = 0xffff;
+ MN.ricoh.MacroMode = 0xffff;
+ MN.ricoh.FlashMode = 0xffff;
+ MN.ricoh.FlashExposureComp = -999.0;
+ MN.ricoh.ManualFlashOutput = -999.0;
+
+ MN.samsung.ColorSpace[0] = MN.samsung.ColorSpace[1] = -1;
+
+ MN.sony.CameraType = LIBRAW_SONY_CameraType_UNKNOWN;
+ MN.sony.group2010 = 0;
+ MN.sony.real_iso_offset = 0xffff;
+ MN.sony.ImageCount3_offset = 0xffff;
+ MN.sony.MeteringMode_offset = 0xffff;
+ MN.sony.ExposureProgram_offset = 0xffff;
+ MN.sony.ReleaseMode2_offset = 0xffff;
+ MN.sony.ElectronicFrontCurtainShutter = 0xffffffff;
+ MN.sony.MinoltaCamID = 0xffffffff;
+ MN.sony.RAWFileType = 0xffff;
+ MN.sony.AFAreaModeSetting = 0xff;
+ MN.sony.AFAreaMode = 0xffff;
+ MN.sony.FlexibleSpotPosition[0] =
+ MN.sony.FlexibleSpotPosition[1] = 0xffff;
+ MN.sony.AFPointSelected = MN.sony.AFPointSelected_0x201e = 0xff;
+ MN.sony.AFTracking = 0xff;
+ MN.sony.FocusPosition = 0xffff;
+ MN.sony.LongExposureNoiseReduction = 0xffffffff;
+ MN.sony.Quality = 0xffffffff;
+ MN.sony.HighISONoiseReduction = 0xffff;
+ MN.sony.SonyRawFileType = 0xffff;
+ MN.sony.RawSizeType = 0xffff;
+ MN.sony.AFMicroAdjValue = 0x7f;
+ MN.sony.AFMicroAdjOn = -1;
+ MN.sony.AFMicroAdjRegisteredLenses = 0xff;
+
+ _exitflag = 0;
+#ifdef USE_RAWSPEED
+ if (_rawspeed_decoder)
+ {
+ RawSpeed::RawDecoder *d =
+ static_cast<RawSpeed::RawDecoder *>(_rawspeed_decoder);
+ delete d;
+ }
+ _rawspeed_decoder = 0;
+#endif
+#ifdef USE_RAWSPEED3
+ if (_rawspeed3_handle)
+ rawspeed3_release(_rawspeed3_handle);
+#endif
+#ifdef USE_DNGSDK
+ if (dngnegative)
+ {
+ dng_negative *ng = (dng_negative *)dngnegative;
+ delete ng;
+ dngnegative = 0;
+ }
+ if(dngimage)
+ {
+ dng_image *dimage = (dng_image*)dngimage;
+ delete dimage;
+ dngimage = 0;
+ }
+#endif
+#ifdef USE_X3FTOOLS
+ if (_x3f_data)
+ {
+ x3f_clear(_x3f_data);
+ _x3f_data = 0;
+ }
+#endif
+ memmgr.cleanup();
+
+ imgdata.thumbnail.tformat = LIBRAW_THUMBNAIL_UNKNOWN;
+ libraw_internal_data.unpacker_data.thumb_format = LIBRAW_INTERNAL_THUMBNAIL_UNKNOWN;
+ imgdata.progress_flags = 0;
+
+ load_raw = 0;
+
+ tls->init();
+}
diff --git a/libkdcraw/libraw/src/utils/open.cpp b/libkdcraw/libraw/src/utils/open.cpp
new file mode 100644
index 0000000..2adca43
--- /dev/null
+++ b/libkdcraw/libraw/src/utils/open.cpp
@@ -0,0 +1,1259 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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"
+#include "../../internal/libraw_cameraids.h"
+
+#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
+int LibRaw::open_file(const char *fname, INT64 max_buf_size)
+{
+ int big = 0;
+ if (max_buf_size == LIBRAW_OPEN_BIGFILE)
+ big = 1;
+ else if (max_buf_size == LIBRAW_OPEN_FILE)
+ big = 0;
+ else
+ {
+#ifndef LIBRAW_WIN32_CALLS
+ struct stat st;
+ if (stat(fname, &st))
+ return LIBRAW_IO_ERROR;
+ big = (st.st_size > max_buf_size) ? 1 : 0;
+#else
+ struct _stati64 st;
+ if (_stati64(fname, &st))
+ return LIBRAW_IO_ERROR;
+ big = (st.st_size > max_buf_size) ? 1 : 0;
+#endif
+ }
+
+ LibRaw_abstract_datastream *stream;
+ try
+ {
+ if (big)
+ stream = new LibRaw_bigfile_datastream(fname);
+ else
+ stream = new LibRaw_file_datastream(fname);
+ }
+
+ catch (const std::bad_alloc& )
+ {
+ recycle();
+ return LIBRAW_UNSUFFICIENT_MEMORY;
+ }
+ if (!stream->valid())
+ {
+ delete stream;
+ return LIBRAW_IO_ERROR;
+ }
+ ID.input_internal = 0; // preserve from deletion on error
+ int ret = open_datastream(stream);
+ if (ret == LIBRAW_SUCCESS)
+ {
+ ID.input_internal = 1; // flag to delete datastream on recycle
+ }
+ else
+ {
+ delete stream;
+ ID.input_internal = 0;
+ }
+ return ret;
+}
+
+#if defined(WIN32) || defined(_WIN32)
+#ifndef LIBRAW_WIN32_UNICODEPATHS
+int LibRaw::open_file(const wchar_t *, INT64)
+{
+ return LIBRAW_NOT_IMPLEMENTED;
+}
+#else
+int LibRaw::open_file(const wchar_t *fname, INT64 max_buf_size)
+{
+ int big = 0;
+ if (max_buf_size == LIBRAW_OPEN_BIGFILE)
+ big = 1;
+ else if (max_buf_size == LIBRAW_OPEN_FILE)
+ big = 0;
+ else
+ {
+ struct _stati64 st;
+ if (_wstati64(fname, &st))
+ return LIBRAW_IO_ERROR;
+ big = (st.st_size > max_buf_size) ? 1 : 0;
+ }
+
+ LibRaw_abstract_datastream *stream;
+ try
+ {
+ if (big)
+ stream = new LibRaw_bigfile_datastream(fname);
+ else
+ stream = new LibRaw_file_datastream(fname);
+ }
+
+ catch (const std::bad_alloc&)
+ {
+ recycle();
+ return LIBRAW_UNSUFFICIENT_MEMORY;
+ }
+ if (!stream->valid())
+ {
+ delete stream;
+ return LIBRAW_IO_ERROR;
+ }
+ ID.input_internal = 0; // preserve from deletion on error
+ int ret = open_datastream(stream);
+ if (ret == LIBRAW_SUCCESS)
+ {
+ ID.input_internal = 1; // flag to delete datastream on recycle
+ }
+ else
+ {
+ delete stream;
+ ID.input_internal = 0;
+ }
+ return ret;
+}
+#endif
+#endif
+
+#else /* LIBRAW_NO_IOSTREAMS_DATASTREAM*/
+
+int LibRaw::libraw_openfile_tail(LibRaw_abstract_datastream *stream)
+{
+ if (!stream->valid())
+ {
+ delete stream;
+ return LIBRAW_IO_ERROR;
+ }
+ ID.input_internal = 0; // preserve from deletion on error
+ int ret = open_datastream(stream);
+ if (ret == LIBRAW_SUCCESS)
+ {
+ ID.input_internal = 1; // flag to delete datastream on recycle
+ }
+ else
+ {
+ delete stream;
+ ID.input_internal = 0;
+ }
+ return ret;
+}
+
+int LibRaw::open_file(const char *fname)
+{
+ LibRaw_abstract_datastream *stream;
+ try
+ {
+#ifdef LIBRAW_WIN32_CALLS
+ stream = new LibRaw_bigfile_buffered_datastream(fname);
+#else
+ stream = new LibRaw_bigfile_datastream(fname);
+#endif
+ }
+ catch (const std::bad_alloc&)
+ {
+ recycle();
+ return LIBRAW_UNSUFFICIENT_MEMORY;
+ }
+ if ((stream->size() > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE) && (stream->size() > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE))
+ {
+ delete stream;
+ return LIBRAW_TOO_BIG;
+ }
+ return libraw_openfile_tail(stream);
+}
+
+#if defined(WIN32) || defined(_WIN32)
+#ifndef LIBRAW_WIN32_UNICODEPATHS
+int LibRaw::open_file(const wchar_t *)
+{
+ return LIBRAW_NOT_IMPLEMENTED;
+}
+#else
+int LibRaw::open_file(const wchar_t *fname)
+{
+ LibRaw_abstract_datastream *stream;
+ try
+ {
+#ifdef LIBRAW_WIN32_CALLS
+ stream = new LibRaw_bigfile_buffered_datastream(fname);
+#else
+ stream = new LibRaw_bigfile_datastream(fname);
+#endif
+ }
+ catch (const std::bad_alloc&)
+ {
+ recycle();
+ return LIBRAW_UNSUFFICIENT_MEMORY;
+ }
+ if ((stream->size() > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE) && (stream->size() > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE))
+ {
+ delete stream;
+ return LIBRAW_TOO_BIG;
+ }
+
+ return libraw_openfile_tail(stream);
+}
+#endif
+#endif
+
+#endif
+
+int LibRaw::open_buffer(const void *buffer, size_t size)
+{
+ // this stream will close on recycle()
+ if (!buffer || buffer == (const void *)-1)
+ return LIBRAW_IO_ERROR;
+
+ if ((size > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE) && (size > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE))
+ return LIBRAW_TOO_BIG;
+
+ LibRaw_buffer_datastream *stream;
+ try
+ {
+ stream = new LibRaw_buffer_datastream(buffer, size);
+ }
+ catch (const std::bad_alloc& )
+ {
+ recycle();
+ return LIBRAW_UNSUFFICIENT_MEMORY;
+ }
+ if (!stream->valid())
+ {
+ delete stream;
+ return LIBRAW_IO_ERROR;
+ }
+ ID.input_internal = 0; // preserve from deletion on error
+ int ret = open_datastream(stream);
+ if (ret == LIBRAW_SUCCESS)
+ {
+ ID.input_internal = 1; // flag to delete datastream on recycle
+ }
+ else
+ {
+ delete stream;
+ ID.input_internal = 0;
+ }
+ return ret;
+}
+
+int LibRaw::open_bayer(const unsigned char *buffer, unsigned datalen,
+ ushort _raw_width, ushort _raw_height,
+ ushort _left_margin, ushort _top_margin,
+ ushort _right_margin, ushort _bottom_margin,
+ unsigned char procflags, unsigned char bayer_pattern,
+ unsigned unused_bits, unsigned otherflags,
+ unsigned black_level)
+{
+ // this stream will close on recycle()
+ if (!buffer || buffer == (const void *)-1)
+ return LIBRAW_IO_ERROR;
+
+ LibRaw_buffer_datastream *stream;
+ try
+ {
+ stream = new LibRaw_buffer_datastream(buffer, datalen);
+ }
+ catch (const std::bad_alloc& )
+ {
+ recycle();
+ return LIBRAW_UNSUFFICIENT_MEMORY;
+ }
+ if (!stream->valid())
+ {
+ delete stream;
+ return LIBRAW_IO_ERROR;
+ }
+ ID.input = stream;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);
+ // From identify
+ initdata();
+ strcpy(imgdata.idata.make, "BayerDump");
+ snprintf(imgdata.idata.model, sizeof(imgdata.idata.model) - 1,
+ "%u x %u pixels", _raw_width, _raw_height);
+ S.flip = procflags >> 2;
+ libraw_internal_data.internal_output_params.zero_is_bad = procflags & 2;
+ libraw_internal_data.unpacker_data.data_offset = 0;
+ S.raw_width = _raw_width;
+ S.raw_height = _raw_height;
+ S.left_margin = _left_margin;
+ S.top_margin = _top_margin;
+ S.width = S.raw_width - S.left_margin - _right_margin;
+ S.height = S.raw_height - S.top_margin - _bottom_margin;
+
+ imgdata.idata.filters = 0x1010101 * bayer_pattern;
+ imgdata.idata.colors =
+ 4 - !((imgdata.idata.filters & imgdata.idata.filters >> 1) & 0x5555);
+ libraw_internal_data.unpacker_data.load_flags = otherflags;
+ switch (libraw_internal_data.unpacker_data.tiff_bps =
+ (datalen)*8 / (S.raw_width * S.raw_height))
+ {
+ case 8:
+ load_raw = &LibRaw::eight_bit_load_raw;
+ break;
+ case 10:
+ if ((datalen) / S.raw_height * 3u >= S.raw_width * 4u)
+ {
+ load_raw = &LibRaw::android_loose_load_raw;
+ break;
+ }
+ else if (libraw_internal_data.unpacker_data.load_flags & 1)
+ {
+ load_raw = &LibRaw::android_tight_load_raw;
+ break;
+ }
+ case 12:
+ libraw_internal_data.unpacker_data.load_flags |= 128;
+ load_raw = &LibRaw::packed_load_raw;
+ break;
+ case 16:
+ libraw_internal_data.unpacker_data.order =
+ 0x4949 | 0x404 * (libraw_internal_data.unpacker_data.load_flags & 1);
+ libraw_internal_data.unpacker_data.tiff_bps -=
+ libraw_internal_data.unpacker_data.load_flags >> 4;
+ libraw_internal_data.unpacker_data.tiff_bps -=
+ libraw_internal_data.unpacker_data.load_flags =
+ libraw_internal_data.unpacker_data.load_flags >> 1 & 7;
+ load_raw = &LibRaw::unpacked_load_raw;
+ }
+ C.maximum =
+ (1 << libraw_internal_data.unpacker_data.tiff_bps) - (1 << unused_bits);
+ C.black = black_level;
+ S.iwidth = S.width;
+ S.iheight = S.height;
+ imgdata.idata.colors = 3;
+ imgdata.idata.filters |= ((imgdata.idata.filters >> 2 & 0x22222222) |
+ (imgdata.idata.filters << 2 & 0x88888888)) &
+ imgdata.idata.filters << 1;
+
+ imgdata.idata.raw_count = 1;
+ for (int i = 0; i < 4; i++)
+ imgdata.color.pre_mul[i] = 1.0;
+
+ strcpy(imgdata.idata.cdesc, "RGBG");
+
+ ID.input_internal = 1;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
+ return LIBRAW_SUCCESS;
+}
+
+struct foveon_data_t
+{
+ const char *make;
+ const char *model;
+ const int raw_width, raw_height;
+ const int white;
+ const int left_margin, top_margin;
+ const int width, height;
+} foveon_data[] = {
+ {"Sigma", "SD9", 2304, 1531, 12000, 20, 8, 2266, 1510},
+ {"Sigma", "SD9", 1152, 763, 12000, 10, 2, 1132, 755},
+ {"Sigma", "SD10", 2304, 1531, 12000, 20, 8, 2266, 1510},
+ {"Sigma", "SD10", 1152, 763, 12000, 10, 2, 1132, 755},
+ {"Sigma", "SD14", 2688, 1792, 14000, 18, 12, 2651, 1767},
+ {"Sigma", "SD14", 2688, 896, 14000, 18, 6, 2651, 883}, // 2/3
+ {"Sigma", "SD14", 1344, 896, 14000, 9, 6, 1326, 883}, // 1/2
+ {"Sigma", "SD15", 2688, 1792, 2900, 18, 12, 2651, 1767},
+ {"Sigma", "SD15", 2688, 896, 2900, 18, 6, 2651, 883}, // 2/3 ?
+ {"Sigma", "SD15", 1344, 896, 2900, 9, 6, 1326, 883}, // 1/2 ?
+ {"Sigma", "DP1", 2688, 1792, 2100, 18, 12, 2651, 1767},
+ {"Sigma", "DP1", 2688, 896, 2100, 18, 6, 2651, 883}, // 2/3 ?
+ {"Sigma", "DP1", 1344, 896, 2100, 9, 6, 1326, 883}, // 1/2 ?
+ {"Sigma", "DP1S", 2688, 1792, 2200, 18, 12, 2651, 1767},
+ {"Sigma", "DP1S", 2688, 896, 2200, 18, 6, 2651, 883}, // 2/3
+ {"Sigma", "DP1S", 1344, 896, 2200, 9, 6, 1326, 883}, // 1/2
+ {"Sigma", "DP1X", 2688, 1792, 3560, 18, 12, 2651, 1767},
+ {"Sigma", "DP1X", 2688, 896, 3560, 18, 6, 2651, 883}, // 2/3
+ {"Sigma", "DP1X", 1344, 896, 3560, 9, 6, 1326, 883}, // 1/2
+ {"Sigma", "DP2", 2688, 1792, 2326, 13, 16, 2651, 1767},
+ {"Sigma", "DP2", 2688, 896, 2326, 13, 8, 2651, 883}, // 2/3 ??
+ {"Sigma", "DP2", 1344, 896, 2326, 7, 8, 1325, 883}, // 1/2 ??
+ {"Sigma", "DP2S", 2688, 1792, 2300, 18, 12, 2651, 1767},
+ {"Sigma", "DP2S", 2688, 896, 2300, 18, 6, 2651, 883}, // 2/3
+ {"Sigma", "DP2S", 1344, 896, 2300, 9, 6, 1326, 883}, // 1/2
+ {"Sigma", "DP2X", 2688, 1792, 2300, 18, 12, 2651, 1767},
+ {"Sigma", "DP2X", 2688, 896, 2300, 18, 6, 2651, 883}, // 2/3
+ {"Sigma", "DP2X", 1344, 896, 2300, 9, 6, 1325, 883}, // 1/2
+ {"Sigma", "SD1", 4928, 3264, 3900, 12, 52, 4807, 3205}, // Full size
+ {"Sigma", "SD1", 4928, 1632, 3900, 12, 26, 4807, 1603}, // 2/3 size
+ {"Sigma", "SD1", 2464, 1632, 3900, 6, 26, 2403, 1603}, // 1/2 size
+ {"Sigma", "SD1 Merrill", 4928, 3264, 3900, 12, 52, 4807, 3205}, // Full size
+ {"Sigma", "SD1 Merrill", 4928, 1632, 3900, 12, 26, 4807, 1603}, // 2/3 size
+ {"Sigma", "SD1 Merrill", 2464, 1632, 3900, 6, 26, 2403, 1603}, // 1/2 size
+ {"Sigma", "DP1 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205},
+ {"Sigma", "DP1 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size
+ {"Sigma", "DP1 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size
+ {"Sigma", "DP2 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205},
+ {"Sigma", "DP2 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size
+ {"Sigma", "DP2 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size
+ {"Sigma", "DP3 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205},
+ {"Sigma", "DP3 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size
+ {"Sigma", "DP3 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size
+ {"Polaroid", "x530", 1440, 1088, 2700, 10, 13, 1419, 1059},
+ // dp2 Q
+ {"Sigma", "dp3 Quattro", 5888, 3776, 16383, 204, 76, 5446,
+ 3624}, // full size, new fw ??
+ {"Sigma", "dp3 Quattro", 5888, 3672, 16383, 204, 24, 5446,
+ 3624}, // full size
+ {"Sigma", "dp3 Quattro", 2944, 1836, 16383, 102, 12, 2723,
+ 1812}, // half size
+ {"Sigma", "dp3 Quattro", 2944, 1888, 16383, 102, 38, 2723,
+ 1812}, // half size, new fw??
+
+ {"Sigma", "dp2 Quattro", 5888, 3776, 16383, 204, 76, 5446,
+ 3624}, // full size, new fw
+ {"Sigma", "dp2 Quattro", 5888, 3672, 16383, 204, 24, 5446,
+ 3624}, // full size
+ {"Sigma", "dp2 Quattro", 2944, 1836, 16383, 102, 12, 2723,
+ 1812}, // half size
+ {"Sigma", "dp2 Quattro", 2944, 1888, 16383, 102, 38, 2723,
+ 1812}, // half size, new fw
+
+ {"Sigma", "dp1 Quattro", 5888, 3776, 16383, 204, 76, 5446,
+ 3624}, // full size, new fw??
+ {"Sigma", "dp1 Quattro", 5888, 3672, 16383, 204, 24, 5446,
+ 3624}, // full size
+ {"Sigma", "dp1 Quattro", 2944, 1836, 16383, 102, 12, 2723,
+ 1812}, // half size
+ {"Sigma", "dp1 Quattro", 2944, 1888, 16383, 102, 38, 2723,
+ 1812}, // half size, new fw
+
+ {"Sigma", "dp0 Quattro", 5888, 3776, 16383, 204, 76, 5446,
+ 3624}, // full size, new fw??
+ {"Sigma", "dp0 Quattro", 5888, 3672, 16383, 204, 24, 5446,
+ 3624}, // full size
+ {"Sigma", "dp0 Quattro", 2944, 1836, 16383, 102, 12, 2723,
+ 1812}, // half size
+ {"Sigma", "dp0 Quattro", 2944, 1888, 16383, 102, 38, 2723,
+ 1812}, // half size, new fw
+ // Sigma sd Quattro
+ {"Sigma", "sd Quattro", 5888, 3776, 16383, 204, 76, 5446,
+ 3624}, // full size
+ {"Sigma", "sd Quattro", 2944, 1888, 16383, 102, 38, 2723,
+ 1812}, // half size
+ // Sd Quattro H
+ {"Sigma", "sd Quattro H", 6656, 4480, 4000, 224, 160, 6208,
+ 4160}, // full size
+ {"Sigma", "sd Quattro H", 3328, 2240, 4000, 112, 80, 3104,
+ 2080}, // half size
+ {"Sigma", "sd Quattro H", 5504, 3680, 4000, 0, 4, 5496, 3668}, // full size
+ {"Sigma", "sd Quattro H", 2752, 1840, 4000, 0, 2, 2748, 1834}, // half size
+};
+const int foveon_count = sizeof(foveon_data) / sizeof(foveon_data[0]);
+
+int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
+{
+
+ if (!stream)
+ return ENOENT;
+ if (!stream->valid())
+ return LIBRAW_IO_ERROR;
+ if ((stream->size() > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE) && (stream->size() > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE))
+ return LIBRAW_TOO_BIG;
+
+ recycle();
+ if (callbacks.pre_identify_cb)
+ {
+ int r = (callbacks.pre_identify_cb)(this);
+ if (r == 1)
+ goto final;
+ }
+
+ try
+ {
+ ID.input = stream;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);
+
+ identify();
+
+ // Fuji layout files: either DNG or unpacked_load_raw should be used
+ if (libraw_internal_data.internal_output_params.fuji_width || libraw_internal_data.unpacker_data.fuji_layout)
+ {
+ if (!imgdata.idata.dng_version && load_raw != &LibRaw::unpacked_load_raw)
+ return LIBRAW_FILE_UNSUPPORTED;
+ }
+
+ // promote the old single thumbnail to the thumbs_list if not present already
+ if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT)
+ {
+ bool already = false;
+ if(imgdata.thumbnail.tlength || libraw_internal_data.internal_data.toffset)
+ for(int i = 0; i < imgdata.thumbs_list.thumbcount; i++)
+ if (imgdata.thumbs_list.thumblist[i].toffset == libraw_internal_data.internal_data.toffset
+ && imgdata.thumbs_list.thumblist[i].tlength == imgdata.thumbnail.tlength)
+ {
+ already = true;
+ break;
+ }
+ if (!already)
+ {
+ int idx = imgdata.thumbs_list.thumbcount;
+ imgdata.thumbs_list.thumblist[idx].toffset = libraw_internal_data.internal_data.toffset;
+ imgdata.thumbs_list.thumblist[idx].tlength = imgdata.thumbnail.tlength;
+ imgdata.thumbs_list.thumblist[idx].tflip = 0xffff;
+ imgdata.thumbs_list.thumblist[idx].tformat = libraw_internal_data.unpacker_data.thumb_format;
+ imgdata.thumbs_list.thumblist[idx].tmisc = libraw_internal_data.unpacker_data.thumb_misc;
+ // promote if set
+ imgdata.thumbs_list.thumblist[idx].twidth = imgdata.thumbnail.twidth;
+ imgdata.thumbs_list.thumblist[idx].theight = imgdata.thumbnail.theight;
+ imgdata.thumbs_list.thumbcount++;
+ }
+ }
+
+
+ imgdata.lens.Lens[sizeof(imgdata.lens.Lens) - 1] = 0; // make sure lens is 0-terminated
+
+ if (callbacks.post_identify_cb)
+ (callbacks.post_identify_cb)(this);
+
+#define isRIC imgdata.sizes.raw_inset_crops[0]
+
+ if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Fujifilm)
+ && (!strcmp(imgdata.idata.normalized_model, "S3Pro")
+ || !strcmp(imgdata.idata.normalized_model, "S5Pro")
+ || !strcmp(imgdata.idata.normalized_model, "S2Pro")))
+ {
+ isRIC.cleft = isRIC.ctop = 0xffff;
+ isRIC.cwidth = isRIC.cheight = 0;
+ }
+ // Wipe out canon incorrect in-camera crop
+ if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Canon)
+ && isRIC.cleft == 0 && isRIC.ctop == 0 // non symmetric!
+ && isRIC.cwidth < (imgdata.sizes.raw_width * 4 / 5)) // less than 80% of sensor width
+ {
+ isRIC.cleft = isRIC.ctop = 0xffff;
+ isRIC.cwidth = isRIC.cheight = 0;
+ }
+
+ // Wipe out non-standard WB
+ if (!imgdata.idata.dng_version &&
+ (makeIs(LIBRAW_CAMERAMAKER_Sony) && !strcmp(imgdata.idata.normalized_model, "DSC-F828"))
+ && !(imgdata.rawparams.options & LIBRAW_RAWOPTIONS_PROVIDE_NONSTANDARD_WB))
+ {
+ for (int i = 0; i < 4; i++) imgdata.color.cam_mul[i] = (i == 1);
+ memset(imgdata.color.WB_Coeffs, 0, sizeof(imgdata.color.WB_Coeffs));
+ memset(imgdata.color.WBCT_Coeffs, 0, sizeof(imgdata.color.WBCT_Coeffs));
+ }
+
+ if (load_raw == &LibRaw::nikon_load_raw)
+ nikon_read_curve();
+
+ if (load_raw == &LibRaw::lossless_jpeg_load_raw &&
+ MN.canon.RecordMode && makeIs(LIBRAW_CAMERAMAKER_Kodak) &&
+ /* Not normalized models here, it is intentional */
+ (!strncasecmp(imgdata.idata.model, "EOS D2000", 9) || // if we want something different for B&W cameras,
+ !strncasecmp(imgdata.idata.model, "EOS D6000", 9))) // it's better to compare with CamIDs
+ {
+ imgdata.color.black = 0;
+ imgdata.color.maximum = 4501;
+ memset(imgdata.color.cblack, 0, sizeof(imgdata.color.cblack));
+ memset(imgdata.sizes.mask, 0, sizeof(imgdata.sizes.mask));
+ imgdata.sizes.mask[0][3] = 1; // to skip mask re-calc
+ libraw_internal_data.unpacker_data.load_flags |= 512;
+ }
+
+ if (load_raw == &LibRaw::panasonic_load_raw)
+ {
+ if (libraw_internal_data.unpacker_data.pana_encoding == 6 ||
+ libraw_internal_data.unpacker_data.pana_encoding == 7)
+ {
+ for (int i = 0; i < 3; i++)
+ imgdata.color.cblack[i] =
+ libraw_internal_data.internal_data.pana_black[i];
+ imgdata.color.cblack[3] = imgdata.color.cblack[1];
+ imgdata.color.cblack[4] = imgdata.color.cblack[5] = 0;
+ imgdata.color.black = 0;
+ imgdata.color.maximum =
+ MAX(imgdata.color.linear_max[0],
+ MAX(imgdata.color.linear_max[1], imgdata.color.linear_max[2]));
+ }
+
+ if (libraw_internal_data.unpacker_data.pana_encoding == 6)
+ {
+ int rowbytes11 = imgdata.sizes.raw_width / 11 * 16;
+ int rowbytes14 = imgdata.sizes.raw_width / 14 * 16;
+ INT64 ds = INT64(libraw_internal_data.unpacker_data.data_size);
+ if (!ds)
+ ds = libraw_internal_data.internal_data.input->size() - libraw_internal_data.unpacker_data.data_offset;
+ if ((imgdata.sizes.raw_width % 11) == 0 &&
+ (INT64(imgdata.sizes.raw_height) * rowbytes11 == ds))
+ load_raw = &LibRaw::panasonicC6_load_raw;
+ else if ((imgdata.sizes.raw_width % 14) == 0 &&
+ (INT64(imgdata.sizes.raw_height) * rowbytes14 == ds))
+ load_raw = &LibRaw::panasonicC6_load_raw;
+ else
+ imgdata.idata.raw_count = 0; // incorrect size
+ }
+ else if (libraw_internal_data.unpacker_data.pana_encoding == 7)
+ {
+ int pixperblock =
+ libraw_internal_data.unpacker_data.pana_bpp == 14 ? 9 : 10;
+ int rowbytes = imgdata.sizes.raw_width / pixperblock * 16;
+ if ((imgdata.sizes.raw_width % pixperblock) == 0 &&
+ (INT64(imgdata.sizes.raw_height) * rowbytes ==
+ INT64(libraw_internal_data.unpacker_data.data_size)))
+ load_raw = &LibRaw::panasonicC7_load_raw;
+ else
+ imgdata.idata.raw_count = 0; // incorrect size
+ }
+ }
+
+#define NIKON_14BIT_SIZE(rw, rh) \
+ (((unsigned)(ceilf((float)(rw * 7 / 4) / 16.0)) * 16) * rh)
+
+ // Ugly hack, replace with proper data/line size for different
+ // cameras/format when available
+ if (makeIs(LIBRAW_CAMERAMAKER_Nikon)
+ && (!strncasecmp(imgdata.idata.model, "Z", 1) || !strcasecmp(imgdata.idata.model,"D6"))
+ && NIKON_14BIT_SIZE(imgdata.sizes.raw_width, imgdata.sizes.raw_height) ==
+ libraw_internal_data.unpacker_data.data_size)
+ {
+ load_raw = &LibRaw::nikon_14bit_load_raw;
+ }
+#undef NIKON_14BIT_SIZE
+
+ // Linear max from 14-bit camera, but on 12-bit data?
+ if (makeIs(LIBRAW_CAMERAMAKER_Sony) &&
+ imgdata.color.maximum > 0 &&
+ imgdata.color.linear_max[0] > (long)imgdata.color.maximum &&
+ imgdata.color.linear_max[0] <= (long)imgdata.color.maximum * 4)
+ for (int c = 0; c < 4; c++)
+ imgdata.color.linear_max[c] /= 4;
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Canon))
+ {
+ if (MN.canon.DefaultCropAbsolute.l != -1) // tag 0x00e0 SensorInfo was parsed
+ {
+ if (imgdata.sizes.raw_aspect != LIBRAW_IMAGE_ASPECT_UNKNOWN)
+ { // tag 0x009a AspectInfo was parsed
+ isRIC.cleft += MN.canon.DefaultCropAbsolute.l;
+ isRIC.ctop += MN.canon.DefaultCropAbsolute.t;
+ }
+ else
+ {
+ isRIC.cleft = MN.canon.DefaultCropAbsolute.l;
+ isRIC.ctop = MN.canon.DefaultCropAbsolute.t;
+ isRIC.cwidth = MN.canon.DefaultCropAbsolute.r - MN.canon.DefaultCropAbsolute.l + 1;
+ isRIC.cheight = MN.canon.DefaultCropAbsolute.b - MN.canon.DefaultCropAbsolute.t + 1;
+ }
+ }
+ else
+ {
+ if (imgdata.sizes.raw_aspect != LIBRAW_IMAGE_ASPECT_UNKNOWN)
+ {
+ }
+ else
+ { // Canon PowerShot S2 IS
+ }
+ }
+#undef isRIC
+ if (imgdata.color.raw_bps < 14 && !imgdata.idata.dng_version && load_raw != &LibRaw::canon_sraw_load_raw)
+ {
+ int xmax = (1 << imgdata.color.raw_bps) - 1;
+ if (MN.canon.SpecularWhiteLevel > xmax) // Adjust 14-bit metadata to real bps
+ {
+ int div = 1 << (14 - imgdata.color.raw_bps);
+ for (int c = 0; c < 4; c++) imgdata.color.linear_max[c] /= div;
+ for (int c = 0; c < 4; c++) MN.canon.ChannelBlackLevel[c] /= div;
+ MN.canon.AverageBlackLevel /= div;
+ MN.canon.SpecularWhiteLevel /= div;
+ MN.canon.NormalWhiteLevel /= div;
+ }
+ }
+ }
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Canon) &&
+ (load_raw == &LibRaw::canon_sraw_load_raw) &&
+ imgdata.sizes.raw_width > 0)
+ {
+ float ratio =
+ float(imgdata.sizes.raw_height) / float(imgdata.sizes.raw_width);
+ if ((ratio < 0.57 || ratio > 0.75) &&
+ MN.canon.SensorHeight > 1 &&
+ MN.canon.SensorWidth > 1)
+ {
+ imgdata.sizes.raw_width = MN.canon.SensorWidth;
+ imgdata.sizes.left_margin = MN.canon.DefaultCropAbsolute.l;
+ imgdata.sizes.iwidth = imgdata.sizes.width =
+ MN.canon.DefaultCropAbsolute.r - MN.canon.DefaultCropAbsolute.l + 1;
+ imgdata.sizes.raw_height = MN.canon.SensorHeight;
+ imgdata.sizes.top_margin = MN.canon.DefaultCropAbsolute.t;
+ imgdata.sizes.iheight = imgdata.sizes.height =
+ MN.canon.DefaultCropAbsolute.b - MN.canon.DefaultCropAbsolute.t + 1;
+ libraw_internal_data.unpacker_data.load_flags |=
+ 256; // reset width/height in canon_sraw_load_raw()
+ imgdata.sizes.raw_pitch = 8 * imgdata.sizes.raw_width;
+ }
+ else if (imgdata.sizes.raw_width == 4032 &&
+ imgdata.sizes.raw_height == 3402 &&
+ !strcasecmp(imgdata.idata.model, "EOS 80D")) // 80D hardcoded
+ {
+ imgdata.sizes.raw_width = 4536;
+ imgdata.sizes.left_margin = 28;
+ imgdata.sizes.iwidth = imgdata.sizes.width =
+ imgdata.sizes.raw_width - imgdata.sizes.left_margin;
+ imgdata.sizes.raw_height = 3024;
+ imgdata.sizes.top_margin = 8;
+ imgdata.sizes.iheight = imgdata.sizes.height =
+ imgdata.sizes.raw_height - imgdata.sizes.top_margin;
+ libraw_internal_data.unpacker_data.load_flags |= 256;
+ imgdata.sizes.raw_pitch = 8 * imgdata.sizes.raw_width;
+ }
+ }
+
+#ifdef USE_DNGSDK
+ if (imgdata.idata.dng_version
+ &&libraw_internal_data.unpacker_data.tiff_compress == 34892
+ && libraw_internal_data.unpacker_data.tiff_bps == 8
+ && libraw_internal_data.unpacker_data.tiff_samples == 3
+ && load_raw == &LibRaw::lossy_dng_load_raw)
+ {
+ // Data should be linearized by DNG SDK
+ C.black = 0;
+ memset(C.cblack, 0, sizeof(C.cblack));
+ }
+#endif
+
+ // XTrans Compressed?
+ if (!imgdata.idata.dng_version &&
+ makeIs(LIBRAW_CAMERAMAKER_Fujifilm) &&
+ (load_raw == &LibRaw::unpacked_load_raw))
+ {
+ if (imgdata.sizes.raw_width * (imgdata.sizes.raw_height * 2ul) !=
+ libraw_internal_data.unpacker_data.data_size)
+ {
+ if ((imgdata.sizes.raw_width * (imgdata.sizes.raw_height * 7ul)) / 4 ==
+ libraw_internal_data.unpacker_data.data_size)
+ load_raw = &LibRaw::fuji_14bit_load_raw;
+ else
+ parse_fuji_compressed_header();
+ }
+ else if (!strcmp(imgdata.idata.normalized_model, "X-H2S")
+ && libraw_internal_data.internal_data.input->size()
+ < (libraw_internal_data.unpacker_data.data_size + libraw_internal_data.unpacker_data.data_offset))
+ {
+ parse_fuji_compressed_header(); // try to use compressed header: X-H2S may record wrong data size
+ }
+ }
+ // set raw_inset_crops[1] via raw_aspect
+ if (imgdata.sizes.raw_aspect >= LIBRAW_IMAGE_ASPECT_MINIMAL_REAL_ASPECT_VALUE
+ && imgdata.sizes.raw_aspect <= LIBRAW_IMAGE_ASPECT_MAXIMAL_REAL_ASPECT_VALUE
+ /* crops[0] is valid*/
+ && (imgdata.sizes.raw_inset_crops[0].cleft < 0xffff)
+ && (imgdata.sizes.raw_inset_crops[0].cleft + imgdata.sizes.raw_inset_crops[0].cwidth <= imgdata.sizes.raw_width)
+ && (imgdata.sizes.raw_inset_crops[0].ctop < 0xffff)
+ && (imgdata.sizes.raw_inset_crops[0].ctop + imgdata.sizes.raw_inset_crops[0].cheight <= imgdata.sizes.raw_height)
+ && imgdata.sizes.raw_inset_crops[0].cwidth > 0 && imgdata.sizes.raw_inset_crops[0].cheight >0
+ /* crops[1] is not set*/
+ && (imgdata.sizes.raw_inset_crops[1].cleft == 0xffff)
+ && (imgdata.sizes.raw_inset_crops[1].ctop == 0xffff)
+ )
+ {
+ float c0_ratio = float(imgdata.sizes.raw_inset_crops[0].cwidth) / float(imgdata.sizes.raw_inset_crops[0].cheight);
+ float c1_ratio = float(imgdata.sizes.raw_aspect) / 1000.f;
+ if (c0_ratio / c1_ratio < 0.98 || c0_ratio / c1_ratio > 1.02) // set crops[1]
+ {
+ if (c1_ratio > c0_ratio) // requested image is wider, cut from top/bottom
+ {
+ int newheight = int(imgdata.sizes.raw_inset_crops[0].cwidth / c1_ratio);
+ int dtop = (imgdata.sizes.raw_inset_crops[0].cheight - newheight) / 2;
+ imgdata.sizes.raw_inset_crops[1].ctop = imgdata.sizes.raw_inset_crops[0].ctop + dtop;
+ imgdata.sizes.raw_inset_crops[1].cheight = newheight;
+ imgdata.sizes.raw_inset_crops[1].cleft = imgdata.sizes.raw_inset_crops[0].cleft;
+ imgdata.sizes.raw_inset_crops[1].cwidth = imgdata.sizes.raw_inset_crops[0].cwidth;
+ }
+ else
+ {
+ int newwidth = int(imgdata.sizes.raw_inset_crops[0].cheight * c1_ratio);
+ int dleft = (imgdata.sizes.raw_inset_crops[0].cwidth - newwidth) / 2;
+ imgdata.sizes.raw_inset_crops[1].cleft = imgdata.sizes.raw_inset_crops[0].cleft + dleft;
+ imgdata.sizes.raw_inset_crops[1].cwidth = newwidth;
+ imgdata.sizes.raw_inset_crops[1].ctop = imgdata.sizes.raw_inset_crops[0].ctop;
+ imgdata.sizes.raw_inset_crops[1].cheight = imgdata.sizes.raw_inset_crops[0].cheight;
+ }
+ }
+ }
+
+ int adjust_margins = 0;
+ if (makeIs(LIBRAW_CAMERAMAKER_Fujifilm) && (imgdata.idata.filters == 9))
+ {
+ // Adjust top/left margins for X-Trans
+ int newtm = imgdata.sizes.top_margin % 6
+ ? (imgdata.sizes.top_margin / 6 + 1) * 6
+ : imgdata.sizes.top_margin;
+ int newlm = imgdata.sizes.left_margin % 6
+ ? (imgdata.sizes.left_margin / 6 + 1) * 6
+ : imgdata.sizes.left_margin;
+ if (newtm != imgdata.sizes.top_margin ||
+ newlm != imgdata.sizes.left_margin)
+ {
+ imgdata.sizes.height -= (newtm - imgdata.sizes.top_margin);
+ imgdata.sizes.top_margin = newtm;
+ imgdata.sizes.width -= (newlm - imgdata.sizes.left_margin);
+ imgdata.sizes.left_margin = newlm;
+ for (int c1 = 0; c1 < 6; c1++)
+ for (int c2 = 0; c2 < 6; c2++)
+ imgdata.idata.xtrans[c1][c2] = imgdata.idata.xtrans_abs[c1][c2];
+ }
+ adjust_margins = 6;
+ }
+ else if (!libraw_internal_data.internal_output_params.fuji_width
+ && imgdata.idata.filters >= 1000)
+ {
+ if ((imgdata.sizes.top_margin % 2) || (imgdata.sizes.left_margin % 2))
+ {
+ int crop[2] = { 0,0 };
+ unsigned filt;
+ int c;
+ if (imgdata.sizes.top_margin % 2)
+ {
+ imgdata.sizes.top_margin += 1;
+ imgdata.sizes.height -= 1;
+ crop[1] = 1;
+ }
+ if (imgdata.sizes.left_margin % 2)
+ {
+ imgdata.sizes.left_margin += 1;
+ imgdata.sizes.width -= 1;
+ crop[0] = 1;
+ }
+ for (filt = c = 0; c < 16; c++)
+ filt |= FC((c >> 1) + (crop[1]), (c & 1) + (crop[0])) << c * 2;
+ imgdata.idata.filters = filt;
+ }
+ adjust_margins = 2;
+ }
+
+ if(adjust_margins) // adjust crop_inset margins
+ for (int i = 0; i < 2; i++)
+ {
+ if (imgdata.sizes.raw_inset_crops[i].cleft && imgdata.sizes.raw_inset_crops[i].cleft < 0xffff
+ && imgdata.sizes.raw_inset_crops[i].cwidth && imgdata.sizes.raw_inset_crops[i].cwidth < 0xffff
+ && (imgdata.sizes.raw_inset_crops[i].cleft%adjust_margins)
+ && (imgdata.sizes.raw_inset_crops[i].cwidth > adjust_margins))
+ {
+ int newleft = ((imgdata.sizes.raw_inset_crops[i].cleft / adjust_margins) + 1) * adjust_margins;
+ int diff = newleft - imgdata.sizes.raw_inset_crops[i].cleft;
+ if (diff > 0)
+ {
+ imgdata.sizes.raw_inset_crops[i].cleft += diff;
+ imgdata.sizes.raw_inset_crops[i].cwidth -= diff;
+ }
+ }
+ if (imgdata.sizes.raw_inset_crops[i].ctop && imgdata.sizes.raw_inset_crops[i].ctop < 0xffff
+ && imgdata.sizes.raw_inset_crops[i].cheight && imgdata.sizes.raw_inset_crops[i].cheight < 0xffff
+ && (imgdata.sizes.raw_inset_crops[i].ctop%adjust_margins)
+ && (imgdata.sizes.raw_inset_crops[i].cheight > adjust_margins))
+ {
+ int newtop = ((imgdata.sizes.raw_inset_crops[i].ctop / adjust_margins) + 1) * adjust_margins;
+ int diff = newtop - imgdata.sizes.raw_inset_crops[i].ctop;
+ if (diff > 0)
+ {
+ imgdata.sizes.raw_inset_crops[i].ctop += diff;
+ imgdata.sizes.raw_inset_crops[i].cheight -= diff;
+ }
+ }
+ }
+
+
+#ifdef USE_DNGSDK
+ if (
+ imgdata.rawparams.use_dngsdk &&
+ !(imgdata.rawparams.options & (LIBRAW_RAWOPTIONS_DNG_STAGE2 | LIBRAW_RAWOPTIONS_DNG_STAGE3 | LIBRAW_RAWOPTIONS_DNG_DISABLEWBADJUST)))
+#endif
+ {
+ // Fix DNG white balance if needed: observed only for Kalpanika X3F tools produced DNGs
+ if (imgdata.idata.dng_version && (imgdata.idata.filters == 0) &&
+ imgdata.idata.colors > 1 && imgdata.idata.colors < 5)
+ {
+ float delta[4] = { 0.f, 0.f, 0.f, 0.f };
+ int black[4];
+ for (int c = 0; c < 4; c++)
+ black[c] = imgdata.color.dng_levels.dng_black +
+ imgdata.color.dng_levels.dng_cblack[c];
+ for (int c = 0; c < imgdata.idata.colors; c++)
+ delta[c] = imgdata.color.dng_levels.dng_whitelevel[c] - black[c];
+ float mindelta = delta[0], maxdelta = delta[0];
+ for (int c = 1; c < imgdata.idata.colors; c++)
+ {
+ if (mindelta > delta[c])
+ mindelta = delta[c];
+ if (maxdelta < delta[c])
+ maxdelta = delta[c];
+ }
+ if (mindelta > 1 && maxdelta < (mindelta * 20)) // safety
+ {
+ for (int c = 0; c < imgdata.idata.colors; c++)
+ {
+ imgdata.color.cam_mul[c] /= (delta[c] / maxdelta);
+ imgdata.color.pre_mul[c] /= (delta[c] / maxdelta);
+ }
+ imgdata.color.maximum = imgdata.color.cblack[0] + maxdelta;
+ }
+ }
+ }
+
+ if (imgdata.idata.dng_version &&
+ makeIs(LIBRAW_CAMERAMAKER_Panasonic)
+ && !strcasecmp(imgdata.idata.normalized_model, "DMC-LX100"))
+ imgdata.sizes.width = 4288;
+
+ if (imgdata.idata.dng_version
+ && makeIs(LIBRAW_CAMERAMAKER_Leica)
+ && !strcasecmp(imgdata.idata.normalized_model, "SL2"))
+ imgdata.sizes.height -= 16;
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Sony) &&
+ imgdata.idata.dng_version)
+ {
+ if (S.raw_width == 3984)
+ S.width = 3925;
+ else if (S.raw_width == 4288)
+ S.width = S.raw_width - 32;
+ else if (S.raw_width == 4928 && S.height < 3280)
+ S.width = S.raw_width - 8;
+ else if (S.raw_width == 5504)
+ S.width = S.raw_width - (S.height > 3664 ? 8 : 32);
+ }
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Sony) &&
+ !imgdata.idata.dng_version)
+ {
+ if(load_raw ==&LibRaw::sony_arq_load_raw)
+ {
+ if(S.raw_width > 12000) // A7RM4 16x, both APS-C and APS
+ S.width = S.raw_width - 64;
+ else // A7RM3/M4 4x merge
+ S.width = S.raw_width - 32;
+ }
+
+ if (((!strncasecmp(imgdata.idata.model, "ILCE-7RM", 8) ||
+ !strcasecmp(imgdata.idata.model, "ILCA-99M2")) &&
+ (S.raw_width == 5216 || S.raw_width == 6304)) // A7RM2/M3/A99M2 in APS mode; A7RM4 in APS-C
+ ||
+ (!strcasecmp(imgdata.idata.model, "ILCE-7R") && S.raw_width >= 4580 &&
+ S.raw_width < 5020) // A7R in crop mode, no samples, so size est.
+ || (!strcasecmp(imgdata.idata.model, "ILCE-7") &&
+ S.raw_width == 3968) // A7 in crop mode
+ ||
+ ((!strncasecmp(imgdata.idata.model, "ILCE-7M", 7) ||
+ !strcasecmp(imgdata.idata.model, "ILCE-9") ||
+#if 0
+ !strcasecmp(imgdata.idata.model,
+ "SLT-A99V")) // Does SLT-A99 also have APS-C mode??
+#endif
+ (mnCamID == SonyID_SLT_A99)) // 2 reasons: some cameras are SLT-A99, no 'V'; some are Hasselblad HV
+ && S.raw_width > 3750 &&
+ S.raw_width < 4120) // A7M2, A7M3, AA9, most likely APS-C raw_width
+ // is 3968 (same w/ A7), but no samples, so guess
+ || (!strncasecmp(imgdata.idata.model, "ILCE-7S", 7) &&
+ S.raw_width == 2816) // A7S2=> exact, hope it works for A7S-I too
+ )
+ S.width = S.raw_width - 32;
+ }
+
+
+ // FIXME: it is possible that DNG contains 4x main frames + some previews; in this case imgdata.idata.raw_count will be greater than 4
+ if (makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
+ /*!strcasecmp(imgdata.idata.model,"K-3 II") &&*/
+ imgdata.idata.raw_count == 4 &&
+ (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_PENTAX_PS_ALLFRAMES))
+ {
+ imgdata.idata.raw_count = 1;
+ imgdata.idata.filters = 0;
+ imgdata.idata.colors = 4;
+ imgdata.sizes.top_margin+=2;
+ imgdata.sizes.left_margin+=2;
+ imgdata.sizes.width-=4;
+ imgdata.sizes.height-=4;
+ IO.mix_green = 1;
+ pentax_component_load_raw = load_raw;
+ load_raw = &LibRaw::pentax_4shot_load_raw;
+ }
+
+ if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Leaf) &&
+ !strcmp(imgdata.idata.model, "Credo 50"))
+ {
+ imgdata.color.pre_mul[0] = 1.f / 0.3984f;
+ imgdata.color.pre_mul[2] = 1.f / 0.7666f;
+ imgdata.color.pre_mul[1] = imgdata.color.pre_mul[3] = 1.0;
+ }
+
+ if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Fujifilm) &&
+ (!strncmp(imgdata.idata.model, "S20Pro", 6) ||
+ !strncmp(imgdata.idata.model, "F700", 4)))
+ {
+ imgdata.sizes.raw_width /= 2;
+ load_raw = &LibRaw::unpacked_load_raw_fuji_f700s20;
+ }
+
+ if (load_raw == &LibRaw::packed_load_raw &&
+ makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
+ !libraw_internal_data.unpacker_data.load_flags &&
+ (!strncasecmp(imgdata.idata.model, "D810", 4) ||
+ !strcasecmp(imgdata.idata.model, "D4S")) &&
+ libraw_internal_data.unpacker_data.data_size * 2u ==
+ imgdata.sizes.raw_height * imgdata.sizes.raw_width * 3u)
+ {
+ libraw_internal_data.unpacker_data.load_flags = 80;
+ }
+ // Adjust BL for Sony A900/A850
+ if (load_raw == &LibRaw::packed_load_raw &&
+ makeIs(LIBRAW_CAMERAMAKER_Sony)) // 12 bit sony, but metadata may be for 14-bit range
+ {
+ if (C.maximum > 4095)
+ C.maximum = 4095;
+ if (C.black > 256 || C.cblack[0] > 256)
+ {
+ C.black /= 4;
+ for (int c = 0; c < 4; c++)
+ C.cblack[c] /= 4;
+ for (unsigned c = 0; c < C.cblack[4] * C.cblack[5]; c++)
+ C.cblack[6 + c] /= 4;
+ }
+ }
+
+ if (load_raw == &LibRaw::nikon_yuv_load_raw) // Is it Nikon sRAW?
+ {
+ load_raw = &LibRaw::nikon_load_sraw;
+ C.black = 0;
+ memset(C.cblack, 0, sizeof(C.cblack));
+ imgdata.idata.filters = 0;
+ libraw_internal_data.unpacker_data.tiff_samples = 3;
+ imgdata.idata.colors = 3;
+ double beta_1 = -5.79342238397656E-02;
+ double beta_2 = 3.28163551282665;
+ double beta_3 = -8.43136004842678;
+ double beta_4 = 1.03533181861023E+01;
+ for (int i = 0; i <= 3072; i++)
+ {
+ double x = (double)i / 3072.;
+ double y = (1. - exp(-beta_1 * x - beta_2 * x * x - beta_3 * x * x * x -
+ beta_4 * x * x * x * x));
+ if (y < 0.)
+ y = 0.;
+ imgdata.color.curve[i] = (y * 16383.);
+ }
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 4; j++)
+ imgdata.color.rgb_cam[i][j] = float(i == j);
+ }
+ // Adjust BL for Nikon 12bit
+ if ((load_raw == &LibRaw::nikon_load_raw ||
+ load_raw == &LibRaw::packed_load_raw ||
+ load_raw == &LibRaw::nikon_load_padded_packed_raw) &&
+ makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
+ strncmp(imgdata.idata.model, "COOLPIX", 7) &&
+ libraw_internal_data.unpacker_data.tiff_bps == 12)
+ {
+ C.maximum = 4095;
+ C.black /= 4;
+ for (int c = 0; c < 4; c++)
+ C.cblack[c] /= 4;
+ for (unsigned c = 0; c < C.cblack[4] * C.cblack[5]; c++)
+ C.cblack[6 + c] /= 4;
+ }
+
+ // Adjust wb_already_applied
+ if (load_raw == &LibRaw::nikon_load_sraw)
+ imgdata.color.as_shot_wb_applied =
+ LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_NIKON_SRAW;
+ else if (makeIs(LIBRAW_CAMERAMAKER_Canon) &&
+ MN.canon.multishot[0] >= 8 &&
+ MN.canon.multishot[1] > 0)
+ imgdata.color.as_shot_wb_applied =
+ LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_CANON;
+ else if (makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
+ MN.nikon.ExposureMode == 1)
+ imgdata.color.as_shot_wb_applied =
+ LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_NIKON;
+ else if (makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
+ ((MN.pentax.MultiExposure & 0x01) == 1))
+ imgdata.color.as_shot_wb_applied =
+ LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_PENTAX;
+ else
+ imgdata.color.as_shot_wb_applied = 0;
+
+ // Adjust Highlight Linearity limit
+ if (C.linear_max[0] < 0)
+ {
+ if (imgdata.idata.dng_version)
+ {
+ for (int c = 0; c < 4; c++)
+ C.linear_max[c] = -1 * C.linear_max[c] + imgdata.color.cblack[c + 6];
+ }
+ else
+ {
+ for (int c = 0; c < 4; c++)
+ C.linear_max[c] = -1 * C.linear_max[c] + imgdata.color.cblack[c];
+ }
+ }
+
+ if (makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
+ (!C.linear_max[0]) && (C.maximum > 1024) && (load_raw != &LibRaw::nikon_load_sraw))
+ {
+ C.linear_max[0] = C.linear_max[1] = C.linear_max[2] = C.linear_max[3] =
+ (long)((float)(C.maximum) / 1.07f);
+ }
+
+ // Correct WB for Samsung GX20
+ if (
+#if 0
+ /* GX20 should be corrected, but K20 is not */
+ makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
+ !strcasecmp(imgdata.idata.normalized_model, "K20D")
+#endif
+#if 0
+ !strcasecmp(imgdata.idata.make, "Samsung") &&
+ !strcasecmp(imgdata.idata.model, "GX20")
+#endif
+ makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
+ (mnCamID == PentaxID_GX20) // Samsung rebranding
+ )
+ {
+ for (int cnt = LIBRAW_WBI_Unknown; cnt <= LIBRAW_WBI_StudioTungsten; cnt++) {
+ if (C.WB_Coeffs[cnt][1]) {
+ C.WB_Coeffs[cnt][0] = (int)((float)(C.WB_Coeffs[cnt][0]) * 1.0503f);
+ C.WB_Coeffs[cnt][2] = (int)((float)(C.WB_Coeffs[cnt][2]) * 2.2867f);
+ }
+ }
+ for (int cnt = 0; cnt < 64; cnt++) {
+ if (C.WBCT_Coeffs[cnt][0] > 0.0f) {
+ C.WBCT_Coeffs[cnt][1] *= 1.0503f;
+ C.WBCT_Coeffs[cnt][3] *= 2.2867f;
+ }
+ }
+ for(int cnt = 0; cnt < 4; cnt++)
+ imgdata.color.pre_mul[cnt] =
+ C.WB_Coeffs[LIBRAW_WBI_Daylight][cnt];
+ }
+
+ // Adjust BL for Panasonic
+ if (load_raw == &LibRaw::panasonic_load_raw &&
+ makeIs(LIBRAW_CAMERAMAKER_Panasonic) &&
+ ID.pana_black[0] && ID.pana_black[1] && ID.pana_black[2])
+ {
+ if (libraw_internal_data.unpacker_data.pana_encoding == 5)
+ libraw_internal_data.internal_output_params.zero_is_bad = 0;
+ C.black = 0;
+ int add = libraw_internal_data.unpacker_data.pana_encoding == 4 ? 15 : 0;
+ C.cblack[0] = ID.pana_black[0] + add;
+ C.cblack[1] = C.cblack[3] = ID.pana_black[1] + add;
+ C.cblack[2] = ID.pana_black[2] + add;
+ unsigned i = C.cblack[3];
+ for (int c = 0; c < 3; c++)
+ if (i > C.cblack[c])
+ i = C.cblack[c];
+ for (int c = 0; c < 4; c++)
+ C.cblack[c] -= i;
+ C.black = i;
+ }
+
+ // Adjust sizes for X3F processing
+#ifdef USE_X3FTOOLS
+ if (load_raw == &LibRaw::x3f_load_raw)
+ {
+ for (int i = 0; i < foveon_count; i++)
+ if (!strcasecmp(imgdata.idata.make, foveon_data[i].make) &&
+ !strcasecmp(imgdata.idata.model, foveon_data[i].model) &&
+ imgdata.sizes.raw_width == foveon_data[i].raw_width &&
+ imgdata.sizes.raw_height == foveon_data[i].raw_height)
+ {
+ imgdata.sizes.top_margin = foveon_data[i].top_margin;
+ imgdata.sizes.left_margin = foveon_data[i].left_margin;
+ imgdata.sizes.width = imgdata.sizes.iwidth = foveon_data[i].width;
+ imgdata.sizes.height = imgdata.sizes.iheight = foveon_data[i].height;
+ C.maximum = foveon_data[i].white;
+ break;
+ }
+ }
+#endif
+#if 0
+ size_t bytes = ID.input->size()-libraw_internal_data.unpacker_data.data_offset;
+ float bpp = float(bytes)/float(S.raw_width)/float(S.raw_height);
+ float bpp2 = float(bytes)/float(S.width)/float(S.height);
+ if(!strcasecmp(imgdata.idata.make,"Hasselblad") && bpp == 6.0f)
+ {
+ load_raw = &LibRaw::hasselblad_full_load_raw;
+ S.width = S.raw_width;
+ S.height = S.raw_height;
+ P1.filters = 0;
+ P1.colors=3;
+ P1.raw_count=1;
+ C.maximum=0xffff;
+ }
+#endif
+ if (C.profile_length)
+ {
+ if (C.profile)
+ free(C.profile);
+ C.profile = malloc(C.profile_length);
+ ID.input->seek(ID.profile_offset, SEEK_SET);
+ ID.input->read(C.profile, C.profile_length, 1);
+ }
+
+ SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
+ }
+ catch (const std::bad_alloc&)
+ {
+ EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC);
+ }
+ catch (const LibRaw_exceptions& err)
+ {
+ EXCEPTION_HANDLER(err);
+ }
+ catch (const std::exception& )
+ {
+ EXCEPTION_HANDLER(LIBRAW_EXCEPTION_IO_CORRUPT);
+ }
+
+final:;
+
+ if (P1.raw_count < 1)
+ return LIBRAW_FILE_UNSUPPORTED;
+
+ write_fun = &LibRaw::write_ppm_tiff;
+
+ if (load_raw == &LibRaw::kodak_ycbcr_load_raw)
+ {
+ S.height += S.height & 1;
+ S.width += S.width & 1;
+ }
+
+ IO.shrink =
+ P1.filters &&
+ (O.half_size || ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1)));
+ if (IO.shrink && P1.filters >= 1000)
+ {
+ S.width &= 65534;
+ S.height &= 65534;
+ }
+
+ S.iheight = (S.height + IO.shrink) >> IO.shrink;
+ S.iwidth = (S.width + IO.shrink) >> IO.shrink;
+
+ // Save color,sizes and internal data into raw_image fields
+ memmove(&imgdata.rawdata.color, &imgdata.color, sizeof(imgdata.color));
+ memmove(&imgdata.rawdata.sizes, &imgdata.sizes, sizeof(imgdata.sizes));
+ memmove(&imgdata.rawdata.iparams, &imgdata.idata, sizeof(imgdata.idata));
+ memmove(&imgdata.rawdata.ioparams,
+ &libraw_internal_data.internal_output_params,
+ sizeof(libraw_internal_data.internal_output_params));
+
+ SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST);
+
+ return LIBRAW_SUCCESS;
+}
diff --git a/libkdcraw/libraw/src/utils/phaseone_processing.cpp b/libkdcraw/libraw/src/utils/phaseone_processing.cpp
new file mode 100644
index 0000000..b82988b
--- /dev/null
+++ b/libkdcraw/libraw/src/utils/phaseone_processing.cpp
@@ -0,0 +1,101 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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/libraw_cxx_defs.h"
+
+void LibRaw::phase_one_allocate_tempbuffer()
+{
+ // Allocate temp raw_image buffer
+ imgdata.rawdata.raw_image = (ushort *)malloc(S.raw_pitch * S.raw_height);
+}
+void LibRaw::phase_one_free_tempbuffer()
+{
+ free(imgdata.rawdata.raw_image);
+ imgdata.rawdata.raw_image = (ushort *)imgdata.rawdata.raw_alloc;
+}
+
+int LibRaw::phase_one_subtract_black(ushort *src, ushort *dest)
+{
+
+ try
+ {
+ if (O.user_black < 0 && O.user_cblack[0] <= -1000000 &&
+ O.user_cblack[1] <= -1000000 && O.user_cblack[2] <= -1000000 &&
+ O.user_cblack[3] <= -1000000)
+ {
+ if (!imgdata.rawdata.ph1_cblack || !imgdata.rawdata.ph1_rblack)
+ {
+ int bl = imgdata.color.phase_one_data.t_black;
+ for (int row = 0; row < S.raw_height; row++)
+ {
+ checkCancel();
+ for (int col = 0; col < S.raw_width; col++)
+ {
+ int idx = row * S.raw_width + col;
+ int val = int(src[idx]) - bl;
+ dest[idx] = val > 0 ? val : 0;
+ }
+ }
+ }
+ else
+ {
+ int bl = imgdata.color.phase_one_data.t_black;
+ for (int row = 0; row < S.raw_height; row++)
+ {
+ checkCancel();
+ for (int col = 0; col < S.raw_width; col++)
+ {
+ int idx = row * S.raw_width + col;
+ int val =
+ int(src[idx]) - bl +
+ imgdata.rawdata
+ .ph1_cblack[row][col >= imgdata.rawdata.color.phase_one_data
+ .split_col] +
+ imgdata.rawdata
+ .ph1_rblack[col][row >= imgdata.rawdata.color.phase_one_data
+ .split_row];
+ dest[idx] = val > 0 ? val : 0;
+ }
+ }
+ }
+ }
+ else // black set by user interaction
+ {
+ // Black level in cblack!
+ for (int row = 0; row < S.raw_height; row++)
+ {
+ checkCancel();
+ unsigned short cblk[16];
+ for (int cc = 0; cc < 16; cc++)
+ cblk[cc] = C.cblack[fcol(row, cc)];
+ for (int col = 0; col < S.raw_width; col++)
+ {
+ int idx = row * S.raw_width + col;
+ ushort val = src[idx];
+ ushort bl = cblk[col & 0xf];
+ dest[idx] = val > bl ? val - bl : 0;
+ }
+ }
+ }
+ return 0;
+ }
+ catch (const LibRaw_exceptions& )
+ {
+ return LIBRAW_CANCELLED_BY_CALLBACK;
+ }
+}
diff --git a/libkdcraw/libraw/src/utils/read_utils.cpp b/libkdcraw/libraw/src/utils/read_utils.cpp
new file mode 100644
index 0000000..974ffc0
--- /dev/null
+++ b/libkdcraw/libraw/src/utils/read_utils.cpp
@@ -0,0 +1,176 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+ushort LibRaw::sget2Rev(uchar *s) // specific to some Canon Makernotes fields,
+ // where they have endian in reverse
+{
+ if (order == 0x4d4d) /* "II" means little-endian, and we reverse to "MM" - big
+ endian */
+ return s[0] | s[1] << 8;
+ else /* "MM" means big-endian... */
+ return s[0] << 8 | s[1];
+}
+
+ushort libraw_sget2_static(short _order, uchar *s)
+{
+ if (_order == 0x4949) /* "II" means little-endian */
+ return s[0] | s[1] << 8;
+ else /* "MM" means big-endian */
+ return s[0] << 8 | s[1];
+}
+
+ushort LibRaw::sget2(uchar *s)
+{
+ return libraw_sget2_static(order, s);
+}
+
+
+ushort LibRaw::get2()
+{
+ uchar str[2] = {0xff, 0xff};
+ fread(str, 1, 2, ifp);
+ return sget2(str);
+}
+
+unsigned LibRaw::sget4(uchar *s)
+{
+ return libraw_sget4_static(order, s);
+}
+
+
+unsigned libraw_sget4_static(short _order, uchar *s)
+{
+ if (_order == 0x4949)
+ return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+ else
+ return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
+}
+
+unsigned LibRaw::get4()
+{
+ uchar str[4] = {0xff, 0xff, 0xff, 0xff};
+ fread(str, 1, 4, ifp);
+ return sget4(str);
+}
+
+unsigned LibRaw::getint(int type) { return tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) ? get2() : get4(); }
+
+float libraw_int_to_float(int i)
+{
+ union {
+ int i;
+ float f;
+ } u;
+ u.i = i;
+ return u.f;
+}
+
+float LibRaw::int_to_float(int i) { return libraw_int_to_float(i); }
+
+double LibRaw::getreal(int type)
+{
+ union {
+ char c[8];
+ double d;
+ } u, v;
+ int i, rev;
+
+ switch (type)
+ {
+ case LIBRAW_EXIFTAG_TYPE_SHORT:
+ return (unsigned short)get2();
+ case LIBRAW_EXIFTAG_TYPE_LONG:
+ return (unsigned int)get4();
+ case LIBRAW_EXIFTAG_TYPE_RATIONAL: // (unsigned, unsigned)
+ u.d = (unsigned int)get4();
+ v.d = (unsigned int)get4();
+ return u.d / (v.d ? v.d : 1);
+ case LIBRAW_EXIFTAG_TYPE_SSHORT:
+ return (signed short)get2();
+ case LIBRAW_EXIFTAG_TYPE_SLONG:
+ return (signed int)get4();
+ case LIBRAW_EXIFTAG_TYPE_SRATIONAL: // (int, int)
+ u.d = (signed int)get4();
+ v.d = (signed int)get4();
+ return u.d / (v.d ? v.d : 1);
+ case LIBRAW_EXIFTAG_TYPE_FLOAT:
+ return int_to_float(get4());
+ case LIBRAW_EXIFTAG_TYPE_DOUBLE:
+ rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234));
+ for (i = 0; i < 8; i++)
+ u.c[i ^ rev] = fgetc(ifp);
+ return u.d;
+ default:
+ return fgetc(ifp);
+ }
+}
+
+double LibRaw::sgetreal(int type, uchar *s)
+{
+ return libraw_sgetreal_static(order, type, s);
+}
+
+
+double libraw_sgetreal_static(short _order, int type, uchar *s)
+{
+ union {
+ char c[8];
+ double d;
+ } u, v;
+ int i, rev;
+
+ switch (type)
+ {
+ case LIBRAW_EXIFTAG_TYPE_SHORT:
+ return (unsigned short) libraw_sget2_static(_order,s);
+ case LIBRAW_EXIFTAG_TYPE_LONG:
+ return (unsigned int)libraw_sget4_static(_order, s);
+ case LIBRAW_EXIFTAG_TYPE_RATIONAL: // (unsigned, unsigned)
+ u.d = (unsigned int)libraw_sget4_static(_order,s);
+ v.d = (unsigned int)libraw_sget4_static(_order,s+4);
+ return u.d / (v.d ? v.d : 1);
+ case LIBRAW_EXIFTAG_TYPE_SSHORT:
+ return (signed short)libraw_sget2_static(_order,s);
+ case LIBRAW_EXIFTAG_TYPE_SLONG:
+ return (signed int) libraw_sget4_static(_order,s);
+ case LIBRAW_EXIFTAG_TYPE_SRATIONAL: // (int, int)
+ u.d = (signed int)libraw_sget4_static(_order,s);
+ v.d = (signed int)libraw_sget4_static(_order,s+4);
+ return u.d / (v.d ? v.d : 1);
+ case LIBRAW_EXIFTAG_TYPE_FLOAT:
+ return libraw_int_to_float(libraw_sget4_static(_order,s));
+ case LIBRAW_EXIFTAG_TYPE_DOUBLE:
+ rev = 7 * ((_order == 0x4949) == (ntohs(0x1234) == 0x1234));
+ for (i = 0; i < 8; i++)
+ u.c[i ^ rev] = *(s+1);
+ return u.d;
+ default:
+ return *(s+1);
+ }
+}
+
+
+void LibRaw::read_shorts(ushort *pixel, unsigned count)
+{
+ if ((unsigned)fread(pixel, 2, count, ifp) < count)
+ derror();
+ if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
+ libraw_swab(pixel, count * 2);
+}
diff --git a/libkdcraw/libraw/src/utils/thumb_utils.cpp b/libkdcraw/libraw/src/utils/thumb_utils.cpp
new file mode 100644
index 0000000..ffdb802
--- /dev/null
+++ b/libkdcraw/libraw/src/utils/thumb_utils.cpp
@@ -0,0 +1,328 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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::kodak_thumb_loader()
+{
+ INT64 est_datasize =
+ T.theight * T.twidth / 3; // is 0.3 bytes per pixel good estimate?
+ if (ID.toffset < 0)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ if (ID.toffset + est_datasize > ID.input->size() + THUMB_READ_BEYOND)
+ throw LIBRAW_EXCEPTION_IO_EOF;
+
+ if(INT64(T.theight) * INT64(T.twidth) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ if (INT64(T.theight) * INT64(T.twidth) < 64ULL)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ if(T.twidth < 16 || T.twidth > 8192 || T.theight < 16 || T.theight > 8192)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ // some kodak cameras
+ ushort s_height = S.height, s_width = S.width, s_iwidth = S.iwidth,
+ s_iheight = S.iheight;
+ ushort s_flags = libraw_internal_data.unpacker_data.load_flags;
+ libraw_internal_data.unpacker_data.load_flags = 12;
+ int s_colors = P1.colors;
+ unsigned s_filters = P1.filters;
+ ushort(*s_image)[4] = imgdata.image;
+
+ S.height = T.theight;
+ S.width = T.twidth;
+ P1.filters = 0;
+
+#define Tformat libraw_internal_data.unpacker_data.thumb_format
+
+
+ if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_YCBCR)
+ {
+ S.height += S.height & 1;
+ S.width += S.width & 1;
+ }
+
+ S.iheight = S.height;
+ S.iwidth = S.width;
+
+ imgdata.image =
+ (ushort(*)[4])calloc(S.iheight * S.iwidth, sizeof(*imgdata.image));
+
+ ID.input->seek(ID.toffset, SEEK_SET);
+ // read kodak thumbnail into T.image[]
+ try
+ {
+ if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_YCBCR)
+ kodak_ycbcr_load_raw();
+ else if(Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_RGB)
+ kodak_rgb_load_raw();
+ else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_THUMB)
+ kodak_thumb_load_raw();
+ }
+ catch (...)
+ {
+ free(imgdata.image);
+ imgdata.image = s_image;
+
+ T.twidth = 0;
+ S.width = s_width;
+
+ S.iwidth = s_iwidth;
+ S.iheight = s_iheight;
+
+ T.theight = 0;
+ S.height = s_height;
+
+ T.tcolors = 0;
+ P1.colors = s_colors;
+
+ P1.filters = s_filters;
+ T.tlength = 0;
+ libraw_internal_data.unpacker_data.load_flags = s_flags;
+ return;
+ }
+
+ // from scale_colors
+ {
+ double dmax;
+ float scale_mul[4];
+ int c, val;
+ for (dmax = DBL_MAX, c = 0; c < 3; c++)
+ if (dmax > C.pre_mul[c])
+ dmax = C.pre_mul[c];
+
+ for (c = 0; c < 3; c++)
+ scale_mul[c] = (C.pre_mul[c] / dmax) * 65535.0 / C.maximum;
+ scale_mul[3] = scale_mul[1];
+
+ size_t size = S.height * S.width;
+ for (unsigned i = 0; i < size * 4; i++)
+ {
+ val = imgdata.image[0][i];
+ if (!val)
+ continue;
+ val *= scale_mul[i & 3];
+ imgdata.image[0][i] = CLIP(val);
+ }
+ }
+
+ // from convert_to_rgb
+ ushort *img;
+ int row, col;
+
+ int(*t_hist)[LIBRAW_HISTOGRAM_SIZE] =
+ (int(*)[LIBRAW_HISTOGRAM_SIZE])calloc(sizeof(*t_hist), 4);
+
+ float out[3], out_cam[3][4] = {{2.81761312f, -1.98369181f, 0.166078627f, 0},
+ {-0.111855984f, 1.73688626f, -0.625030339f, 0},
+ {-0.0379119813f, -0.891268849f, 1.92918086f, 0}};
+
+ for (img = imgdata.image[0], row = 0; row < S.height; row++)
+ for (col = 0; col < S.width; col++, img += 4)
+ {
+ out[0] = out[1] = out[2] = 0;
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ out[0] += out_cam[0][c] * img[c];
+ out[1] += out_cam[1][c] * img[c];
+ out[2] += out_cam[2][c] * img[c];
+ }
+ for (c = 0; c < 3; c++)
+ img[c] = CLIP((int)out[c]);
+ for (c = 0; c < P1.colors; c++)
+ t_hist[c][img[c] >> 3]++;
+ }
+
+ // from gamma_lut
+ int(*save_hist)[LIBRAW_HISTOGRAM_SIZE] =
+ libraw_internal_data.output_data.histogram;
+ libraw_internal_data.output_data.histogram = t_hist;
+
+ // make curve output curve!
+ ushort *t_curve = (ushort *)calloc(sizeof(C.curve), 1);
+ memmove(t_curve, C.curve, sizeof(C.curve));
+ memset(C.curve, 0, sizeof(C.curve));
+ {
+ int perc, val, total, t_white = 0x2000, c;
+
+ perc = S.width * S.height * 0.01; /* 99th percentile white level */
+ if (IO.fuji_width)
+ perc /= 2;
+ if (!((O.highlight & ~2) || O.no_auto_bright))
+ for (t_white = c = 0; c < P1.colors; c++)
+ {
+ for (val = 0x2000, total = 0; --val > 32;)
+ if ((total += libraw_internal_data.output_data.histogram[c][val]) >
+ perc)
+ break;
+ if (t_white < val)
+ t_white = val;
+ }
+ gamma_curve(O.gamm[0], O.gamm[1], 2, (t_white << 3) / O.bright);
+ }
+
+ libraw_internal_data.output_data.histogram = save_hist;
+ free(t_hist);
+
+ // from write_ppm_tiff - copy pixels into bitmap
+
+ int s_flip = imgdata.sizes.flip;
+ if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_NO_ROTATE_FOR_KODAK_THUMBNAILS)
+ imgdata.sizes.flip = 0;
+
+ S.iheight = S.height;
+ S.iwidth = S.width;
+ if (S.flip & 4)
+ SWAP(S.height, S.width);
+
+ if (T.thumb)
+ free(T.thumb);
+ T.thumb = (char *)calloc(S.width * S.height, P1.colors);
+ T.tlength = S.width * S.height * P1.colors;
+
+ // from write_tiff_ppm
+ {
+ int soff = flip_index(0, 0);
+ int cstep = flip_index(0, 1) - soff;
+ int rstep = flip_index(1, 0) - flip_index(0, S.width);
+
+ for (int rr = 0; rr < S.height; rr++, soff += rstep)
+ {
+ char *ppm = T.thumb + rr * S.width * P1.colors;
+ for (int cc = 0; cc < S.width; cc++, soff += cstep)
+ for (int c = 0; c < P1.colors; c++)
+ ppm[cc * P1.colors + c] =
+ imgdata.color.curve[imgdata.image[soff][c]] >> 8;
+ }
+ }
+
+ memmove(C.curve, t_curve, sizeof(C.curve));
+ free(t_curve);
+
+ // restore variables
+ free(imgdata.image);
+ imgdata.image = s_image;
+
+ if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_NO_ROTATE_FOR_KODAK_THUMBNAILS)
+ imgdata.sizes.flip = s_flip;
+
+ T.twidth = S.width;
+ S.width = s_width;
+
+ S.iwidth = s_iwidth;
+ S.iheight = s_iheight;
+
+ T.theight = S.height;
+ S.height = s_height;
+
+ T.tcolors = P1.colors;
+ P1.colors = s_colors;
+
+ P1.filters = s_filters;
+ libraw_internal_data.unpacker_data.load_flags = s_flags;
+}
+
+// ������� thumbnail �� �����, ������ thumb_format � ������������ � ��������
+
+int LibRaw::thumbOK(INT64 maxsz)
+{
+ if (!ID.input)
+ return 0;
+ if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 &&
+ load_raw == &LibRaw::broadcom_load_raw) // RPi
+#ifdef USE_6BY9RPI
+ && !(imgdata.thumbnail.tlength > 0 && libraw_internal_data.unpacker_data.load_flags & 0x4000 &&
+ (load_raw == &LibRaw::rpi_load_raw8 || load_raw == &LibRaw::nokia_load_raw ||
+ load_raw == &LibRaw::rpi_load_raw12 || load_raw == &LibRaw::rpi_load_raw14))
+#endif
+ )
+ return 0;
+ INT64 fsize = ID.input->size();
+ if (fsize > 0xffffffffU)
+ return 0; // No thumb for raw > 4Gb-1
+ int tsize = 0;
+ int tcol = (T.tcolors > 0 && T.tcolors < 4) ? T.tcolors : 3;
+ if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_JPEG)
+ tsize = T.tlength;
+ else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_PPM)
+ tsize = tcol * T.twidth * T.theight;
+ else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_PPM16)
+ tsize = tcol * T.twidth * T.theight *
+ ((imgdata.rawparams.options & LIBRAW_RAWOPTIONS_USE_PPM16_THUMBS) ? 2 : 1);
+#ifdef USE_X3FTOOLS
+ else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_X3F)
+ {
+ tsize = x3f_thumb_size();
+ }
+#endif
+ else // Kodak => no check
+ tsize = 1;
+ if (tsize < 0)
+ return 0;
+ if (maxsz > 0 && tsize > maxsz)
+ return 0;
+ return (tsize + ID.toffset <= fsize) ? 1 : 0;
+}
+
+int LibRaw::dcraw_thumb_writer(const char *fname)
+{
+ // CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD);
+
+ if (!fname)
+ return ENOENT;
+
+ FILE *tfp = fopen(fname, "wb");
+
+ if (!tfp)
+ return errno;
+
+ if (!T.thumb)
+ {
+ fclose(tfp);
+ return LIBRAW_OUT_OF_ORDER_CALL;
+ }
+
+ try
+ {
+ switch (T.tformat)
+ {
+ case LIBRAW_THUMBNAIL_JPEG:
+ jpeg_thumb_writer(tfp, T.thumb, T.tlength);
+ break;
+ case LIBRAW_THUMBNAIL_BITMAP:
+ fprintf(tfp, "P%d\n%d %d\n255\n", T.tcolors == 1 ? 5 : 6, T.twidth, T.theight);
+ fwrite(T.thumb, 1, T.tlength, tfp);
+ break;
+ default:
+ fclose(tfp);
+ return LIBRAW_UNSUPPORTED_THUMBNAIL;
+ }
+ fclose(tfp);
+ return 0;
+ }
+ catch (const std::bad_alloc&)
+ {
+ fclose(tfp);
+ EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC);
+ }
+ catch (const LibRaw_exceptions& err)
+ {
+ fclose(tfp);
+ EXCEPTION_HANDLER(err);
+ }
+}
diff --git a/libkdcraw/libraw/src/utils/utils_dcraw.cpp b/libkdcraw/libraw/src/utils/utils_dcraw.cpp
new file mode 100644
index 0000000..97d1455
--- /dev/null
+++ b/libkdcraw/libraw/src/utils/utils_dcraw.cpp
@@ -0,0 +1,330 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+
+int LibRaw::fcol(int row, int col)
+{
+ static const char filter[16][16] = {
+ {2, 1, 1, 3, 2, 3, 2, 0, 3, 2, 3, 0, 1, 2, 1, 0},
+ {0, 3, 0, 2, 0, 1, 3, 1, 0, 1, 1, 2, 0, 3, 3, 2},
+ {2, 3, 3, 2, 3, 1, 1, 3, 3, 1, 2, 1, 2, 0, 0, 3},
+ {0, 1, 0, 1, 0, 2, 0, 2, 2, 0, 3, 0, 1, 3, 2, 1},
+ {3, 1, 1, 2, 0, 1, 0, 2, 1, 3, 1, 3, 0, 1, 3, 0},
+ {2, 0, 0, 3, 3, 2, 3, 1, 2, 0, 2, 0, 3, 2, 2, 1},
+ {2, 3, 3, 1, 2, 1, 2, 1, 2, 1, 1, 2, 3, 0, 0, 1},
+ {1, 0, 0, 2, 3, 0, 0, 3, 0, 3, 0, 3, 2, 1, 2, 3},
+ {2, 3, 3, 1, 1, 2, 1, 0, 3, 2, 3, 0, 2, 3, 1, 3},
+ {1, 0, 2, 0, 3, 0, 3, 2, 0, 1, 1, 2, 0, 1, 0, 2},
+ {0, 1, 1, 3, 3, 2, 2, 1, 1, 3, 3, 0, 2, 1, 3, 2},
+ {2, 3, 2, 0, 0, 1, 3, 0, 2, 0, 1, 2, 3, 0, 1, 0},
+ {1, 3, 1, 2, 3, 2, 3, 2, 0, 2, 0, 1, 1, 0, 3, 0},
+ {0, 2, 0, 3, 1, 0, 0, 1, 1, 3, 3, 2, 3, 2, 2, 1},
+ {2, 1, 3, 2, 3, 1, 2, 1, 0, 3, 0, 2, 0, 2, 0, 2},
+ {0, 3, 1, 0, 0, 2, 0, 3, 2, 1, 3, 1, 1, 3, 1, 3}};
+
+ if (filters == 1)
+ return filter[(row + top_margin) & 15][(col + left_margin) & 15];
+ if (filters == 9)
+ return xtrans[(row + 6) % 6][(col + 6) % 6];
+ return FC(row, col);
+}
+
+size_t LibRaw::strnlen(const char *s, size_t n)
+{
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__)
+ const char *p = (const char *)memchr(s, 0, n);
+ return (p ? p - s : n);
+#else
+ return ::strnlen(s, n);
+#endif
+}
+
+void *LibRaw::memmem(char *haystack, size_t haystacklen, char *needle,
+ size_t needlelen)
+{
+#if !defined(__GLIBC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
+ char *c;
+ for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
+ if (!memcmp(c, needle, needlelen))
+ return c;
+ return 0;
+#else
+ return ::memmem(haystack, haystacklen, needle, needlelen);
+#endif
+}
+
+char *LibRaw::strcasestr(char *haystack, const char *needle)
+{
+ char *c;
+ for (c = haystack; *c; c++)
+ if (!strncasecmp(c, needle, strlen(needle)))
+ return c;
+ return 0;
+}
+
+void LibRaw::initdata()
+{
+ tiff_flip = flip = filters = UINT_MAX; /* unknown */
+ raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
+ maximum = height = width = top_margin = left_margin = 0;
+ cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
+ iso_speed = shutter = aperture = focal_len = 0;
+ unique_id = 0ULL;
+ tiff_nifds = 0;
+ memset(tiff_ifd, 0, sizeof tiff_ifd);
+ for (int i = 0; i < LIBRAW_IFD_MAXCOUNT; i++)
+ {
+ tiff_ifd[i].dng_color[0].illuminant = tiff_ifd[i].dng_color[1].illuminant =
+ 0xffff;
+ for (int c = 0; c < 4; c++)
+ tiff_ifd[i].dng_levels.analogbalance[c] = 1.0f;
+ }
+ for (int i = 0; i < 0x10000; i++)
+ curve[i] = i;
+ memset(gpsdata, 0, sizeof gpsdata);
+ memset(cblack, 0, sizeof cblack);
+ memset(white, 0, sizeof white);
+ memset(mask, 0, sizeof mask);
+ thumb_offset = thumb_length = thumb_width = thumb_height = 0;
+ load_raw = 0;
+ thumb_format = LIBRAW_INTERNAL_THUMBNAIL_JPEG; // default to JPEG
+ data_offset = meta_offset = meta_length = tiff_bps = tiff_compress = 0;
+ kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
+ timestamp = shot_order = tiff_samples = black = is_foveon = 0;
+ mix_green = profile_length = data_error = zero_is_bad = 0;
+ pixel_aspect = is_raw = raw_color = 1;
+ tile_width = tile_length = 0;
+ metadata_blocks = 0;
+ is_NikonTransfer = 0;
+ is_Olympus = 0;
+ OlympusDNG_SubDirOffsetValid = 0;
+ is_Sony = 0;
+ is_pana_raw = 0;
+ maker_index = LIBRAW_CAMERAMAKER_Unknown;
+ FujiCropMode = 0;
+ is_PentaxRicohMakernotes = 0;
+ normalized_model[0] = 0;
+ normalized_make[0] = 0;
+ CM_found = 0;
+}
+
+void LibRaw::aRGB_coeff(double aRGB_cam[3][3])
+{
+ static const double rgb_aRGB[3][3] = {
+ {1.39828313770000, -0.3982830047, 9.64980900741708E-8},
+ {6.09219200572997E-8, 0.9999999809, 1.33230799934103E-8},
+ {2.17237099975343E-8, -0.0429383201, 1.04293828050000}};
+
+ double cmatrix_tmp[3][3] = {
+ {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
+ int i, j, k;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ {
+ for (k = 0; k < 3; k++)
+ cmatrix_tmp[i][j] += rgb_aRGB[i][k] * aRGB_cam[k][j];
+ cmatrix[i][j] = (float)cmatrix_tmp[i][j];
+ }
+}
+
+void LibRaw::romm_coeff(float romm_cam[3][3])
+{
+ static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */
+ {{2.034193f, -0.727420f, -0.306766f},
+ {-0.228811f, 1.231729f, -0.002922f},
+ {-0.008565f, -0.153273f, 1.161839f}};
+ int i, j, k;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ for (cmatrix[i][j] = k = 0; k < 3; k++)
+ cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j];
+}
+
+void LibRaw::remove_zeroes()
+{
+ unsigned row, col, tot, n;
+ int r, c;
+
+ RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES, 0, 2);
+
+ for (row = 0; row < height; row++)
+ for (col = 0; col < width; col++)
+ if (BAYER(row, col) == 0)
+ {
+ tot = n = 0;
+ for (r = (int)row - 2; r <= (int)row + 2; r++)
+ for (c = (int)col - 2; c <= (int)col + 2; c++)
+ if (r >= 0 && r < height && c >= 0 && c < width &&
+ FC(r, c) == FC(row, col) && BAYER(r, c))
+ tot += (n++, BAYER(r, c));
+ if (n)
+ BAYER(row, col) = tot / n;
+ }
+ RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES, 1, 2);
+}
+void LibRaw::crop_masked_pixels()
+{
+ int row, col;
+ unsigned c, m, zero, val;
+#define mblack imgdata.color.black_stat
+
+ if (mask[0][3] > 0)
+ goto mask_set;
+ if (load_raw == &LibRaw::canon_load_raw ||
+ load_raw == &LibRaw::lossless_jpeg_load_raw ||
+ load_raw == &LibRaw::crxLoadRaw)
+ {
+ mask[0][1] = mask[1][1] += 2;
+ mask[0][3] -= 2;
+ goto sides;
+ }
+ if (load_raw == &LibRaw::canon_600_load_raw ||
+ load_raw == &LibRaw::sony_load_raw ||
+ (load_raw == &LibRaw::eight_bit_load_raw && strncmp(model, "DC2", 3)) ||
+ load_raw == &LibRaw::kodak_262_load_raw ||
+ (load_raw == &LibRaw::packed_load_raw && (load_flags & 32)))
+ {
+ sides:
+ mask[0][0] = mask[1][0] = top_margin;
+ mask[0][2] = mask[1][2] = top_margin + height;
+ mask[0][3] += left_margin;
+ mask[1][1] += left_margin + width;
+ mask[1][3] += raw_width;
+ }
+ if (load_raw == &LibRaw::nokia_load_raw)
+ {
+ mask[0][2] = top_margin;
+ mask[0][3] = width;
+ }
+ if (load_raw == &LibRaw::broadcom_load_raw)
+ {
+ mask[0][2] = top_margin;
+ mask[0][3] = width;
+ }
+mask_set:
+ memset(mblack, 0, sizeof mblack);
+ for (zero = m = 0; m < 8; m++)
+ for (row = MAX(mask[m][0], 0); row < MIN(mask[m][2], raw_height); row++)
+ for (col = MAX(mask[m][1], 0); col < MIN(mask[m][3], raw_width); col++)
+ {
+ /* No need to subtract margins because full area and active area filters are the same */
+ c = FC(row, col);
+ mblack[c] += val = raw_image[(row)*raw_pitch / 2 + (col)];
+ mblack[4 + c]++;
+ zero += !val;
+ }
+ if (load_raw == &LibRaw::canon_600_load_raw && width < raw_width)
+ {
+ black = (mblack[0] + mblack[1] + mblack[2] + mblack[3]) /
+ MAX(1, (mblack[4] + mblack[5] + mblack[6] + mblack[7])) -
+ 4;
+ }
+ else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7])
+ {
+ FORC4 cblack[c] = mblack[c] / MAX(1, mblack[4 + c]);
+ black = cblack[4] = cblack[5] = cblack[6] = 0;
+ }
+}
+#undef mblack
+
+void LibRaw::pseudoinverse(double (*in)[3], double (*out)[3], int size)
+{
+ double work[3][6], num;
+ int i, j, k;
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 6; j++)
+ work[i][j] = j == i + 3;
+ for (j = 0; j < 3; j++)
+ for (k = 0; k < size && k < 4; k++)
+ work[i][j] += in[k][i] * in[k][j];
+ }
+ for (i = 0; i < 3; i++)
+ {
+ num = work[i][i];
+ for (j = 0; j < 6; j++)
+ if (fabs(num) > 0.00001f)
+ work[i][j] /= num;
+ for (k = 0; k < 3; k++)
+ {
+ if (k == i)
+ continue;
+ num = work[k][i];
+ for (j = 0; j < 6; j++)
+ work[k][j] -= work[i][j] * num;
+ }
+ }
+ for (i = 0; i < size && i < 4; i++)
+ for (j = 0; j < 3; j++)
+ for (out[i][j] = k = 0; k < 3; k++)
+ out[i][j] += work[j][k + 3] * in[i][k];
+}
+
+void LibRaw::cam_xyz_coeff(float _rgb_cam[3][4], double cam_xyz[4][3])
+{
+ double cam_rgb[4][3], inverse[4][3], num;
+ int i, j, k;
+
+ for (i = 0; i < colors && i < 4; i++) /* Multiply out XYZ colorspace */
+ for (j = 0; j < 3; j++)
+ for (cam_rgb[i][j] = k = 0; k < 3; k++)
+ cam_rgb[i][j] += cam_xyz[i][k] * LibRaw_constants::xyz_rgb[k][j];
+
+ for (i = 0; i < colors && i < 4; i++)
+ { /* Normalize cam_rgb so that */
+ for (num = j = 0; j < 3; j++) /* cam_rgb * (1,1,1) is (1,1,1,1) */
+ num += cam_rgb[i][j];
+ if (num > 0.00001)
+ {
+ for (j = 0; j < 3; j++)
+ cam_rgb[i][j] /= num;
+ pre_mul[i] = 1 / num;
+ }
+ else
+ {
+ for (j = 0; j < 3; j++)
+ cam_rgb[i][j] = 0.0;
+ pre_mul[i] = 1.0;
+ }
+ }
+ pseudoinverse(cam_rgb, inverse, colors);
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < colors && j < 4; j++)
+ _rgb_cam[i][j] = inverse[j][i];
+}
+
+void LibRaw::tiff_get(unsigned base, unsigned *tag, unsigned *type,
+ unsigned *len, unsigned *save)
+{
+#ifdef LIBRAW_IOSPACE_CHECK
+ INT64 pos = ftell(ifp);
+ INT64 fsize = ifp->size();
+ if (fsize < 12 || (fsize - pos) < 12)
+ throw LIBRAW_EXCEPTION_IO_EOF;
+#endif
+ *tag = get2();
+ *type = get2();
+ *len = get4();
+ *save = ftell(ifp) + 4;
+ if (*len * tagtype_dataunit_bytes[(*type <= LIBRAW_EXIFTAG_TYPE_IFD8) ? *type : 0] > 4)
+ fseek(ifp, get4() + base, SEEK_SET);
+}
diff --git a/libkdcraw/libraw/src/utils/utils_libraw.cpp b/libkdcraw/libraw/src/utils/utils_libraw.cpp
new file mode 100644
index 0000000..15a7b65
--- /dev/null
+++ b/libkdcraw/libraw/src/utils/utils_libraw.cpp
@@ -0,0 +1,673 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void default_data_callback(void *, const char *file, const int offset)
+ {
+ if (offset < 0)
+ fprintf(stderr, "%s: Unexpected end of file\n",
+ file ? file : "unknown file");
+ else
+ fprintf(stderr, "%s: data corrupted at %d\n",
+ file ? file : "unknown file", offset);
+ }
+ const char *libraw_strerror(int e)
+ {
+ enum LibRaw_errors errorcode = (LibRaw_errors)e;
+ switch (errorcode)
+ {
+ case LIBRAW_SUCCESS:
+ return "No error";
+ case LIBRAW_UNSPECIFIED_ERROR:
+ return "Unspecified error";
+ case LIBRAW_FILE_UNSUPPORTED:
+ return "Unsupported file format or not RAW file";
+ case LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE:
+ return "Request for nonexisting image number";
+ case LIBRAW_OUT_OF_ORDER_CALL:
+ return "Out of order call of libraw function";
+ case LIBRAW_NO_THUMBNAIL:
+ return "No thumbnail in file";
+ case LIBRAW_UNSUPPORTED_THUMBNAIL:
+ return "Unsupported thumbnail format";
+ case LIBRAW_INPUT_CLOSED:
+ return "No input stream, or input stream closed";
+ case LIBRAW_NOT_IMPLEMENTED:
+ return "Decoder not implemented for this data format";
+ case LIBRAW_REQUEST_FOR_NONEXISTENT_THUMBNAIL:
+ return "Request for nonexisting thumbnail number";
+ case LIBRAW_MEMPOOL_OVERFLOW:
+ return "Libraw internal mempool overflowed";
+ case LIBRAW_UNSUFFICIENT_MEMORY:
+ return "Unsufficient memory";
+ case LIBRAW_DATA_ERROR:
+ return "Corrupted data or unexpected EOF";
+ case LIBRAW_IO_ERROR:
+ return "Input/output error";
+ case LIBRAW_CANCELLED_BY_CALLBACK:
+ return "Cancelled by user callback";
+ case LIBRAW_BAD_CROP:
+ return "Bad crop box";
+ case LIBRAW_TOO_BIG:
+ return "Image too big for processing";
+ default:
+ return "Unknown error code";
+ }
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+unsigned LibRaw::parse_custom_cameras(unsigned limit,
+ libraw_custom_camera_t table[],
+ char **list)
+{
+ if (!list)
+ return 0;
+ unsigned index = 0;
+ for (unsigned i = 0; i < limit; i++)
+ {
+ if (!list[i])
+ break;
+ if (strlen(list[i]) < 10)
+ continue;
+ char *string = (char *)malloc(strlen(list[i]) + 1);
+ strcpy(string, list[i]);
+ char *start = string;
+ memset(&table[index], 0, sizeof(table[0]));
+ for (int j = 0; start && j < 14; j++)
+ {
+ char *end = strchr(start, ',');
+ if (end)
+ {
+ *end = 0;
+ end++;
+ } // move to next char
+ while (isspace(*start) && *start)
+ start++; // skip leading spaces?
+ unsigned val = strtol(start, 0, 10);
+ switch (j)
+ {
+ case 0:
+ table[index].fsize = val;
+ break;
+ case 1:
+ table[index].rw = val;
+ break;
+ case 2:
+ table[index].rh = val;
+ break;
+ case 3:
+ table[index].lm = val;
+ break;
+ case 4:
+ table[index].tm = val;
+ break;
+ case 5:
+ table[index].rm = val;
+ break;
+ case 6:
+ table[index].bm = val;
+ break;
+ case 7:
+ table[index].lf = val;
+ break;
+ case 8:
+ table[index].cf = val;
+ break;
+ case 9:
+ table[index].max = val;
+ break;
+ case 10:
+ table[index].flags = val;
+ break;
+ case 11:
+ strncpy(table[index].t_make, start, sizeof(table[index].t_make) - 1);
+ break;
+ case 12:
+ strncpy(table[index].t_model, start, sizeof(table[index].t_model) - 1);
+ break;
+ case 13:
+ table[index].offset = val;
+ break;
+ default:
+ break;
+ }
+ start = end;
+ }
+ free(string);
+ if (table[index].t_make[0])
+ index++;
+ }
+ return index;
+}
+
+void LibRaw::derror()
+{
+ if (!libraw_internal_data.unpacker_data.data_error &&
+ libraw_internal_data.internal_data.input)
+ {
+ if (libraw_internal_data.internal_data.input->eof())
+ {
+ if (callbacks.data_cb)
+ (*callbacks.data_cb)(callbacks.datacb_data,
+ libraw_internal_data.internal_data.input->fname(),
+ -1);
+ throw LIBRAW_EXCEPTION_IO_EOF;
+ }
+ else
+ {
+ if (callbacks.data_cb)
+ (*callbacks.data_cb)(callbacks.datacb_data,
+ libraw_internal_data.internal_data.input->fname(),
+ libraw_internal_data.internal_data.input->tell());
+ // throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+ }
+ libraw_internal_data.unpacker_data.data_error++;
+}
+
+const char *LibRaw::version() { return LIBRAW_VERSION_STR; }
+int LibRaw::versionNumber() { return LIBRAW_VERSION; }
+const char *LibRaw::strerror(int p) { return libraw_strerror(p); }
+
+unsigned LibRaw::capabilities()
+{
+ unsigned ret = 0;
+#ifdef USE_RAWSPEED
+ ret |= LIBRAW_CAPS_RAWSPEED;
+#endif
+#ifdef USE_RAWSPEED3
+ ret |= LIBRAW_CAPS_RAWSPEED3;
+#endif
+#ifdef USE_RAWSPEED_BITS
+ ret |= LIBRAW_CAPS_RAWSPEED_BITS;
+#endif
+#ifdef USE_DNGSDK
+ ret |= LIBRAW_CAPS_DNGSDK;
+#ifdef USE_GPRSDK
+ ret |= LIBRAW_CAPS_GPRSDK;
+#endif
+#ifdef LIBRAW_WIN32_UNICODEPATHS
+ ret |= LIBRAW_CAPS_UNICODEPATHS;
+#endif
+#endif
+#ifdef USE_X3FTOOLS
+ ret |= LIBRAW_CAPS_X3FTOOLS;
+#endif
+#ifdef USE_6BY9RPI
+ ret |= LIBRAW_CAPS_RPI6BY9;
+#endif
+#ifdef USE_ZLIB
+ ret |= LIBRAW_CAPS_ZLIB;
+#endif
+#ifdef USE_JPEG
+ ret |= LIBRAW_CAPS_JPEG;
+#endif
+ return ret;
+}
+
+int LibRaw::is_sraw()
+{
+ return load_raw == &LibRaw::canon_sraw_load_raw ||
+ load_raw == &LibRaw::nikon_load_sraw;
+}
+int LibRaw::is_coolscan_nef()
+{
+ return load_raw == &LibRaw::nikon_coolscan_load_raw;
+}
+int LibRaw::is_jpeg_thumb()
+{
+ return libraw_internal_data.unpacker_data.thumb_format == LIBRAW_INTERNAL_THUMBNAIL_JPEG;
+}
+
+int LibRaw::is_nikon_sraw() { return load_raw == &LibRaw::nikon_load_sraw; }
+int LibRaw::sraw_midpoint()
+{
+ if (load_raw == &LibRaw::canon_sraw_load_raw)
+ return 8192;
+ else if (load_raw == &LibRaw::nikon_load_sraw)
+ return 2048;
+ else
+ return 0;
+}
+
+void *LibRaw::malloc(size_t t)
+{
+ void *p = memmgr.malloc(t);
+ if (!p)
+ throw LIBRAW_EXCEPTION_ALLOC;
+ return p;
+}
+void *LibRaw::realloc(void *q, size_t t)
+{
+ void *p = memmgr.realloc(q, t);
+ if (!p)
+ throw LIBRAW_EXCEPTION_ALLOC;
+ return p;
+}
+
+void *LibRaw::calloc(size_t n, size_t t)
+{
+ void *p = memmgr.calloc(n, t);
+ if (!p)
+ throw LIBRAW_EXCEPTION_ALLOC;
+ return p;
+}
+void LibRaw::free(void *p) { memmgr.free(p); }
+
+void LibRaw::recycle_datastream()
+{
+ if (libraw_internal_data.internal_data.input &&
+ libraw_internal_data.internal_data.input_internal)
+ {
+ delete libraw_internal_data.internal_data.input;
+ libraw_internal_data.internal_data.input = NULL;
+ }
+ libraw_internal_data.internal_data.input_internal = 0;
+}
+
+void LibRaw::clearCancelFlag()
+{
+#ifdef _MSC_VER
+ InterlockedExchange(&_exitflag, 0);
+#else
+ __sync_fetch_and_and(&_exitflag, 0);
+#endif
+#ifdef RAWSPEED_FASTEXIT
+ if (_rawspeed_decoder)
+ {
+ RawSpeed::RawDecoder *d =
+ static_cast<RawSpeed::RawDecoder *>(_rawspeed_decoder);
+ d->resumeProcessing();
+ }
+#endif
+}
+
+void LibRaw::setCancelFlag()
+{
+#ifdef _MSC_VER
+ InterlockedExchange(&_exitflag, 1);
+#else
+ __sync_fetch_and_add(&_exitflag, 1);
+#endif
+#ifdef RAWSPEED_FASTEXIT
+ if (_rawspeed_decoder)
+ {
+ RawSpeed::RawDecoder *d =
+ static_cast<RawSpeed::RawDecoder *>(_rawspeed_decoder);
+ d->cancelProcessing();
+ }
+#endif
+}
+
+void LibRaw::checkCancel()
+{
+#ifdef _MSC_VER
+ if (InterlockedExchange(&_exitflag, 0))
+ throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK;
+#else
+ if (__sync_fetch_and_and(&_exitflag, 0))
+ throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK;
+#endif
+}
+
+int LibRaw::is_curve_linear()
+{
+ for (int i = 0; i < 0x10000; i++)
+ if (imgdata.color.curve[i] != i)
+ return 0;
+ return 1;
+}
+
+void LibRaw::free_image(void)
+{
+ if (imgdata.image)
+ {
+ free(imgdata.image);
+ imgdata.image = 0;
+ imgdata.progress_flags = LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN |
+ LIBRAW_PROGRESS_IDENTIFY |
+ LIBRAW_PROGRESS_SIZE_ADJUST |
+ LIBRAW_PROGRESS_LOAD_RAW;
+ }
+}
+
+int LibRaw::is_phaseone_compressed()
+{
+ return (load_raw == &LibRaw::phase_one_load_raw_c ||
+ load_raw == &LibRaw::phase_one_load_raw_s ||
+ load_raw == &LibRaw::phase_one_load_raw);
+}
+
+int LibRaw::is_canon_600() { return load_raw == &LibRaw::canon_600_load_raw; }
+const char *LibRaw::strprogress(enum LibRaw_progress p)
+{
+ switch (p)
+ {
+ case LIBRAW_PROGRESS_START:
+ return "Starting";
+ case LIBRAW_PROGRESS_OPEN:
+ return "Opening file";
+ case LIBRAW_PROGRESS_IDENTIFY:
+ return "Reading metadata";
+ case LIBRAW_PROGRESS_SIZE_ADJUST:
+ return "Adjusting size";
+ case LIBRAW_PROGRESS_LOAD_RAW:
+ return "Reading RAW data";
+ case LIBRAW_PROGRESS_REMOVE_ZEROES:
+ return "Clearing zero values";
+ case LIBRAW_PROGRESS_BAD_PIXELS:
+ return "Removing dead pixels";
+ case LIBRAW_PROGRESS_DARK_FRAME:
+ return "Subtracting dark frame data";
+ case LIBRAW_PROGRESS_FOVEON_INTERPOLATE:
+ return "Interpolating Foveon sensor data";
+ case LIBRAW_PROGRESS_SCALE_COLORS:
+ return "Scaling colors";
+ case LIBRAW_PROGRESS_PRE_INTERPOLATE:
+ return "Pre-interpolating";
+ case LIBRAW_PROGRESS_INTERPOLATE:
+ return "Interpolating";
+ case LIBRAW_PROGRESS_MIX_GREEN:
+ return "Mixing green channels";
+ case LIBRAW_PROGRESS_MEDIAN_FILTER:
+ return "Median filter";
+ case LIBRAW_PROGRESS_HIGHLIGHTS:
+ return "Highlight recovery";
+ case LIBRAW_PROGRESS_FUJI_ROTATE:
+ return "Rotating Fuji diagonal data";
+ case LIBRAW_PROGRESS_FLIP:
+ return "Flipping image";
+ case LIBRAW_PROGRESS_APPLY_PROFILE:
+ return "ICC conversion";
+ case LIBRAW_PROGRESS_CONVERT_RGB:
+ return "Converting to RGB";
+ case LIBRAW_PROGRESS_STRETCH:
+ return "Stretching image";
+ case LIBRAW_PROGRESS_THUMB_LOAD:
+ return "Loading thumbnail";
+ default:
+ return "Some strange things";
+ }
+}
+int LibRaw::adjust_sizes_info_only(void)
+{
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+
+ raw2image_start();
+ if (O.use_fuji_rotate)
+ {
+ if (IO.fuji_width)
+ {
+ IO.fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink;
+ S.iwidth = (ushort)(IO.fuji_width / sqrt(0.5));
+ S.iheight = (ushort)((S.iheight - IO.fuji_width) / sqrt(0.5));
+ }
+ else
+ {
+ if (S.pixel_aspect < 0.995)
+ S.iheight = (ushort)(S.iheight / S.pixel_aspect + 0.5);
+ if (S.pixel_aspect > 1.005)
+ S.iwidth = (ushort)(S.iwidth * S.pixel_aspect + 0.5);
+ }
+ }
+ SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+ if (S.flip & 4)
+ {
+ unsigned short t = S.iheight;
+ S.iheight = S.iwidth;
+ S.iwidth = t;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP);
+ }
+ return 0;
+}
+int LibRaw::adjust_maximum()
+{
+ ushort real_max;
+ float auto_threshold;
+
+ if (O.adjust_maximum_thr < 0.00001)
+ return LIBRAW_SUCCESS;
+ else if (O.adjust_maximum_thr > 0.99999)
+ auto_threshold = LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD;
+ else
+ auto_threshold = O.adjust_maximum_thr;
+
+ real_max = C.data_maximum;
+ if (real_max > 0 && real_max < C.maximum &&
+ real_max > C.maximum * auto_threshold)
+ {
+ C.maximum = real_max;
+ }
+ return LIBRAW_SUCCESS;
+}
+void LibRaw::adjust_bl()
+{
+ int clear_repeat = 0;
+ if (O.user_black >= 0)
+ {
+ C.black = O.user_black;
+ clear_repeat = 1;
+ }
+ for (int i = 0; i < 4; i++)
+ if (O.user_cblack[i] > -1000000)
+ {
+ C.cblack[i] = O.user_cblack[i];
+ clear_repeat = 1;
+ }
+
+ if (clear_repeat)
+ C.cblack[4] = C.cblack[5] = 0;
+
+ // Add common part to cblack[] early
+ if (imgdata.idata.filters > 1000 && (C.cblack[4] + 1) / 2 == 1 &&
+ (C.cblack[5] + 1) / 2 == 1)
+ {
+ int clrs[4];
+ int lastg = -1, gcnt = 0;
+ for (int c = 0; c < 4; c++)
+ {
+ clrs[c] = FC(c / 2, c % 2);
+ if (clrs[c] == 1)
+ {
+ gcnt++;
+ lastg = c;
+ }
+ }
+ if (gcnt > 1 && lastg >= 0)
+ clrs[lastg] = 3;
+ for (int c = 0; c < 4; c++)
+ C.cblack[clrs[c]] +=
+ C.cblack[6 + c / 2 % C.cblack[4] * C.cblack[5] + c % 2 % C.cblack[5]];
+ C.cblack[4] = C.cblack[5] = 0;
+ // imgdata.idata.filters = sfilters;
+ }
+ else if (imgdata.idata.filters <= 1000 && C.cblack[4] == 1 &&
+ C.cblack[5] == 1) // Fuji RAF dng
+ {
+ for (int c = 0; c < 4; c++)
+ C.cblack[c] += C.cblack[6];
+ C.cblack[4] = C.cblack[5] = 0;
+ }
+ // remove common part from C.cblack[]
+ int i = C.cblack[3];
+ int c;
+ for (c = 0; c < 3; c++)
+ if (i > (int)C.cblack[c])
+ i = C.cblack[c];
+
+ for (c = 0; c < 4; c++)
+ C.cblack[c] -= i; // remove common part
+ C.black += i;
+
+ // Now calculate common part for cblack[6+] part and move it to C.black
+
+ if (C.cblack[4] && C.cblack[5])
+ {
+ i = C.cblack[6];
+ for (c = 1; c < int(C.cblack[4] * C.cblack[5]); c++)
+ if (i > int(C.cblack[6 + c]))
+ i = C.cblack[6 + c];
+ // Remove i from cblack[6+]
+ int nonz = 0;
+ for (c = 0; c < int(C.cblack[4] * C.cblack[5]); c++)
+ {
+ C.cblack[6 + c] -= i;
+ if (C.cblack[6 + c])
+ nonz++;
+ }
+ C.black += i;
+ if (!nonz)
+ C.cblack[4] = C.cblack[5] = 0;
+ }
+ for (c = 0; c < 4; c++)
+ C.cblack[c] += C.black;
+}
+int LibRaw::getwords(char *line, char *words[], int maxwords, int maxlen)
+{
+ line[maxlen - 1] = 0;
+ unsigned char *p = (unsigned char*)line;
+ int nwords = 0;
+
+ while (1)
+ {
+ while (isspace(*p))
+ p++;
+ if (*p == '\0')
+ return nwords;
+ words[nwords++] = (char*)p;
+ while (!isspace(*p) && *p != '\0')
+ p++;
+ if (*p == '\0')
+ return nwords;
+ *p++ = '\0';
+ if (nwords >= maxwords)
+ return nwords;
+ }
+}
+int LibRaw::stread(char *buf, size_t len, LibRaw_abstract_datastream *fp)
+{
+ if (len > 0)
+ {
+ int r = fp->read(buf, len, 1);
+ buf[len - 1] = 0;
+ return r;
+ }
+ else
+ return 0;
+}
+
+int LibRaw::find_ifd_by_offset(int o)
+{
+ for(unsigned i = 0; i < libraw_internal_data.identify_data.tiff_nifds && i < LIBRAW_IFD_MAXCOUNT; i++)
+ if(tiff_ifd[i].offset == o)
+ return i;
+ return -1;
+}
+
+short LibRaw::tiff_sget (unsigned save, uchar *buf, unsigned buf_len, INT64 *tag_offset,
+ unsigned *tag_id, unsigned *tag_type, INT64 *tag_dataoffset,
+ unsigned *tag_datalen, int *tag_dataunitlen) {
+ uchar *pos = buf + *tag_offset;
+ if ((((*tag_offset) + 12) > buf_len) || (*tag_offset < 0)) { // abnormal, tag buffer overrun
+ return -1;
+ }
+ *tag_id = sget2(pos); pos += 2;
+ *tag_type = sget2(pos); pos += 2;
+ *tag_datalen = sget4(pos); pos += 4;
+ *tag_dataunitlen = tagtype_dataunit_bytes[(*tag_type <= LIBRAW_EXIFTAG_TYPE_IFD8) ? *tag_type : 0];
+ if ((*tag_datalen * (*tag_dataunitlen)) > 4) {
+ *tag_dataoffset = sget4(pos) - save;
+ if ((*tag_dataoffset + *tag_datalen) > buf_len) { // abnormal, tag data buffer overrun
+ return -2;
+ }
+ } else *tag_dataoffset = *tag_offset + 8;
+ *tag_offset += 12;
+ return 0;
+}
+
+#define rICC imgdata.sizes.raw_inset_crops
+#define S imgdata.sizes
+#define RS imgdata.rawdata.sizes
+int LibRaw::adjust_to_raw_inset_crop(unsigned mask, float maxcrop)
+
+{
+ int adjindex = -1;
+ int limwidth = S.width * maxcrop;
+ int limheight = S.height * maxcrop;
+
+ for(int i = 1; i >= 0; i--)
+ if (mask & (1<<i))
+ if (rICC[i].ctop < 0xffff && rICC[i].cleft < 0xffff
+ && rICC[i].cleft + rICC[i].cwidth <= S.raw_width
+ && rICC[i].ctop + rICC[i].cheight <= S.raw_height
+ && rICC[i].cwidth >= limwidth && rICC[i].cheight >= limheight)
+ {
+ adjindex = i;
+ break;
+ }
+
+ if (adjindex >= 0)
+ {
+ RS.left_margin = S.left_margin = rICC[adjindex].cleft;
+ RS.top_margin = S.top_margin = rICC[adjindex].ctop;
+ RS.width = S.width = MIN(rICC[adjindex].cwidth, int(S.raw_width) - int(S.left_margin));
+ RS.height = S.height = MIN(rICC[adjindex].cheight, int(S.raw_height) - int(S.top_margin));
+ }
+ return adjindex + 1;
+}
+
+char** LibRaw::malloc_omp_buffers(int buffer_count, size_t buffer_size)
+{
+ char** buffers = (char**)calloc(sizeof(char*), buffer_count);
+
+ for (int i = 0; i < buffer_count; i++)
+ {
+ buffers[i] = (char*)malloc(buffer_size);
+ }
+ return buffers;
+}
+
+void LibRaw::free_omp_buffers(char** buffers, int buffer_count)
+{
+ for (int i = 0; i < buffer_count; i++)
+ if(buffers[i])
+ free(buffers[i]);
+ free(buffers);
+}
+
+void LibRaw::libraw_swab(void *arr, size_t len)
+{
+#ifdef LIBRAW_OWN_SWAB
+ uint16_t *array = (uint16_t*)arr;
+ size_t bytes = len/2;
+ for(; bytes; --bytes)
+ {
+ *array = ((*array << 8) & 0xff00) | ((*array >> 8) & 0xff);
+ array++;
+ }
+#else
+ swab((char*)arr,(char*)arr,len);
+#endif
+
+}
diff --git a/libkdcraw/libraw/src/write/apply_profile.cpp b/libkdcraw/libraw/src/write/apply_profile.cpp
new file mode 100644
index 0000000..0bcb16d
--- /dev/null
+++ b/libkdcraw/libraw/src/write/apply_profile.cpp
@@ -0,0 +1,76 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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"
+
+#ifndef NO_LCMS
+void LibRaw::apply_profile(const char *input, const char *output)
+{
+ char *prof;
+ cmsHPROFILE hInProfile = 0, hOutProfile = 0;
+ cmsHTRANSFORM hTransform;
+ FILE *fp;
+ unsigned size;
+
+ if (strcmp(input, "embed"))
+ hInProfile = cmsOpenProfileFromFile(input, "r");
+ else if (profile_length)
+ {
+ hInProfile = cmsOpenProfileFromMem(imgdata.color.profile, profile_length);
+ }
+ else
+ {
+ imgdata.process_warnings |= LIBRAW_WARN_NO_EMBEDDED_PROFILE;
+ }
+ if (!hInProfile)
+ {
+ imgdata.process_warnings |= LIBRAW_WARN_NO_INPUT_PROFILE;
+ return;
+ }
+ if (!output)
+ hOutProfile = cmsCreate_sRGBProfile();
+ else if ((fp = fopen(output, "rb")))
+ {
+ fread(&size, 4, 1, fp);
+ fseek(fp, 0, SEEK_SET);
+ oprof = (unsigned *)malloc(size = ntohl(size));
+ fread(oprof, 1, size, fp);
+ fclose(fp);
+ if (!(hOutProfile = cmsOpenProfileFromMem(oprof, size)))
+ {
+ free(oprof);
+ oprof = 0;
+ }
+ }
+ if (!hOutProfile)
+ {
+ imgdata.process_warnings |= LIBRAW_WARN_BAD_OUTPUT_PROFILE;
+ goto quit;
+ }
+ RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE, 0, 2);
+ hTransform = cmsCreateTransform(hInProfile, TYPE_RGBA_16, hOutProfile,
+ TYPE_RGBA_16, INTENT_PERCEPTUAL, 0);
+ cmsDoTransform(hTransform, image, image, width * height);
+ raw_color = 1; /* Don't use rgb_cam with a profile */
+ cmsDeleteTransform(hTransform);
+ cmsCloseProfile(hOutProfile);
+quit:
+ cmsCloseProfile(hInProfile);
+ RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE, 1, 2);
+}
+#endif
diff --git a/libkdcraw/libraw/src/write/file_write.cpp b/libkdcraw/libraw/src/write/file_write.cpp
new file mode 100644
index 0000000..bf17ea2
--- /dev/null
+++ b/libkdcraw/libraw/src/write/file_write.cpp
@@ -0,0 +1,338 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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_defs.h"
+#include <vector>
+
+int LibRaw::flip_index(int row, int col)
+{
+ if (flip & 4)
+ SWAP(row, col);
+ if (flip & 2)
+ row = iheight - 1 - row;
+ if (flip & 1)
+ col = iwidth - 1 - col;
+ return row * iwidth + col;
+}
+
+void LibRaw::tiff_set(struct tiff_hdr *th, ushort *ntag, ushort tag,
+ ushort type, int count, int val)
+{
+ struct libraw_tiff_tag *tt;
+ int c;
+
+ tt = (struct libraw_tiff_tag *)(ntag + 1) + (*ntag)++;
+ tt->val.i = val;
+ if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_BYTE) && count <= 4)
+ FORC(4) tt->val.c[c] = val >> (c << 3);
+ else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII))
+ {
+ count = int(strnlen((char *)th + val, count - 1)) + 1;
+ if (count <= 4)
+ FORC(4) tt->val.c[c] = ((char *)th)[val + c];
+ }
+ else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) && count <= 2)
+ FORC(2) tt->val.s[c] = val >> (c << 4);
+ tt->count = count;
+ tt->type = type;
+ tt->tag = tag;
+}
+
+#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
+
+void LibRaw::tiff_head(struct tiff_hdr *th, int full)
+{
+ int c, psize = 0;
+ struct tm *t;
+
+ memset(th, 0, sizeof *th);
+ th->t_order = htonl(0x4d4d4949) >> 16;
+ th->magic = 42;
+ th->ifd = 10;
+ th->rat[0] = th->rat[2] = 300;
+ th->rat[1] = th->rat[3] = 1;
+ FORC(6) th->rat[4 + c] = 1000000;
+ th->rat[4] *= shutter;
+ th->rat[6] *= aperture;
+ th->rat[8] *= focal_len;
+ strncpy(th->t_desc, desc, 512);
+ strncpy(th->t_make, make, 64);
+ strncpy(th->t_model, model, 64);
+ strcpy(th->soft, "dcraw v" DCRAW_VERSION);
+ t = localtime(&timestamp);
+ sprintf(th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year + 1900,
+ t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
+ strncpy(th->t_artist, artist, 64);
+ if (full)
+ {
+ tiff_set(th, &th->ntag, 254, 4, 1, 0);
+ tiff_set(th, &th->ntag, 256, 4, 1, width);
+ tiff_set(th, &th->ntag, 257, 4, 1, height);
+ tiff_set(th, &th->ntag, 258, 3, colors, output_bps);
+ if (colors > 2)
+ th->tag[th->ntag - 1].val.i = TOFF(th->bps);
+ FORC4 th->bps[c] = output_bps;
+ tiff_set(th, &th->ntag, 259, 3, 1, 1);
+ tiff_set(th, &th->ntag, 262, 3, 1, 1 + (colors > 1));
+ }
+ tiff_set(th, &th->ntag, 270, 2, 512, TOFF(th->t_desc));
+ tiff_set(th, &th->ntag, 271, 2, 64, TOFF(th->t_make));
+ tiff_set(th, &th->ntag, 272, 2, 64, TOFF(th->t_model));
+ if (full)
+ {
+ if (oprof)
+ psize = ntohl(oprof[0]);
+ tiff_set(th, &th->ntag, 273, 4, 1, sizeof *th + psize);
+ tiff_set(th, &th->ntag, 277, 3, 1, colors);
+ tiff_set(th, &th->ntag, 278, 4, 1, height);
+ tiff_set(th, &th->ntag, 279, 4, 1,
+ height * width * colors * output_bps / 8);
+ }
+ else
+ tiff_set(th, &th->ntag, 274, 3, 1, "12435867"[flip] - '0');
+ tiff_set(th, &th->ntag, 282, 5, 1, TOFF(th->rat[0]));
+ tiff_set(th, &th->ntag, 283, 5, 1, TOFF(th->rat[2]));
+ tiff_set(th, &th->ntag, 284, 3, 1, 1);
+ tiff_set(th, &th->ntag, 296, 3, 1, 2);
+ tiff_set(th, &th->ntag, 305, 2, 32, TOFF(th->soft));
+ tiff_set(th, &th->ntag, 306, 2, 20, TOFF(th->date));
+ tiff_set(th, &th->ntag, 315, 2, 64, TOFF(th->t_artist));
+ tiff_set(th, &th->ntag, 34665, 4, 1, TOFF(th->nexif));
+ if (psize)
+ tiff_set(th, &th->ntag, 34675, 7, psize, sizeof *th);
+ tiff_set(th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
+ tiff_set(th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
+ tiff_set(th, &th->nexif, 34855, 3, 1, iso_speed);
+ tiff_set(th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
+ if (gpsdata[1])
+ {
+ uchar latref[4] = { (uchar)(gpsdata[29]),0,0,0 },
+ lonref[4] = { (uchar)(gpsdata[30]),0,0,0 };
+ tiff_set(th, &th->ntag, 34853, 4, 1, TOFF(th->ngps));
+ tiff_set(th, &th->ngps, 0, 1, 4, 0x202);
+ tiff_set(th, &th->ngps, 1, 2, 2, TOFF(latref));
+ tiff_set(th, &th->ngps, 2, 5, 3, TOFF(th->gps[0]));
+ tiff_set(th, &th->ngps, 3, 2, 2, TOFF(lonref));
+ tiff_set(th, &th->ngps, 4, 5, 3, TOFF(th->gps[6]));
+ tiff_set(th, &th->ngps, 5, 1, 1, gpsdata[31]);
+ tiff_set(th, &th->ngps, 6, 5, 1, TOFF(th->gps[18]));
+ tiff_set(th, &th->ngps, 7, 5, 3, TOFF(th->gps[12]));
+ tiff_set(th, &th->ngps, 18, 2, 12, TOFF(th->gps[20]));
+ tiff_set(th, &th->ngps, 29, 2, 12, TOFF(th->gps[23]));
+ memcpy(th->gps, gpsdata, sizeof th->gps);
+ }
+}
+
+void LibRaw::jpeg_thumb_writer(FILE *tfp, char *t_humb, int t_humb_length)
+{
+ ushort exif[5];
+ struct tiff_hdr th;
+ fputc(0xff, tfp);
+ fputc(0xd8, tfp);
+ if (strcmp(t_humb + 6, "Exif"))
+ {
+ memcpy(exif, "\xff\xe1 Exif\0\0", 10);
+ exif[1] = htons(8 + sizeof th);
+ fwrite(exif, 1, sizeof exif, tfp);
+ tiff_head(&th, 0);
+ fwrite(&th, 1, sizeof th, tfp);
+ }
+ fwrite(t_humb + 2, 1, t_humb_length - 2, tfp);
+}
+void LibRaw::write_ppm_tiff()
+{
+ try
+ {
+ struct tiff_hdr th;
+ ushort *ppm2;
+ int c, row, col, soff, rstep, cstep;
+ int perc, val, total, t_white = 0x2000;
+
+ perc = width * height * auto_bright_thr;
+
+ if (fuji_width)
+ perc /= 2;
+ if (!((highlight & ~2) || no_auto_bright))
+ for (t_white = c = 0; c < colors; c++)
+ {
+ for (val = 0x2000, total = 0; --val > 32;)
+ if ((total += histogram[c][val]) > perc)
+ break;
+ if (t_white < val)
+ t_white = val;
+ }
+ gamma_curve(gamm[0], gamm[1], 2, (t_white << 3) / bright);
+ iheight = height;
+ iwidth = width;
+ if (flip & 4)
+ SWAP(height, width);
+
+ std::vector<uchar> ppm(width * colors * output_bps / 8);
+ ppm2 = (ushort *)ppm.data();
+ if (output_tiff)
+ {
+ tiff_head(&th, 1);
+ fwrite(&th, sizeof th, 1, ofp);
+ if (oprof)
+ fwrite(oprof, ntohl(oprof[0]), 1, ofp);
+ }
+ else if (colors > 3)
+ {
+ if(imgdata.params.output_flags & LIBRAW_OUTPUT_FLAGS_PPMMETA)
+ fprintf(ofp,
+ "P7\n# EXPTIME=%0.5f\n# TIMESTAMP=%d\n# ISOSPEED=%d\n"
+ "# APERTURE=%0.1f\n# FOCALLEN=%0.1f\n# MAKE=%s\n# MODEL=%s\n"
+ "WIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
+ shutter, (int)timestamp, (int)iso_speed,aperture,
+ focal_len, make, model,
+ width, height, colors, (1 << output_bps) - 1, cdesc);
+ else
+ fprintf(
+ ofp,
+ "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
+ width, height, colors, (1 << output_bps) - 1, cdesc);
+ }
+ else
+ {
+ if(imgdata.params.output_flags & LIBRAW_OUTPUT_FLAGS_PPMMETA)
+ fprintf(ofp, "P%d\n# EXPTIME=%0.5f\n# TIMESTAMP=%d\n"
+ "# ISOSPEED=%d\n# APERTURE=%0.1f\n# FOCALLEN=%0.1f\n"
+ "# MAKE=%s\n# MODEL=%s\n%d %d\n%d\n",
+ colors/2+5,
+ shutter, (int)timestamp, (int)iso_speed,aperture,focal_len,
+ make,model,
+ width, height, (1 << output_bps)-1);
+ else
+ fprintf(ofp, "P%d\n%d %d\n%d\n", colors / 2 + 5, width, height,
+ (1 << output_bps) - 1);
+ }
+ soff = flip_index(0, 0);
+ cstep = flip_index(0, 1) - soff;
+ rstep = flip_index(1, 0) - flip_index(0, width);
+ for (row = 0; row < height; row++, soff += rstep)
+ {
+ for (col = 0; col < width; col++, soff += cstep)
+ if (output_bps == 8)
+ FORCC ppm[col * colors + c] = curve[image[soff][c]] >> 8;
+ else
+ FORCC ppm2[col * colors + c] = curve[image[soff][c]];
+ if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
+ libraw_swab(ppm2, width * colors * 2);
+ fwrite(ppm.data(), colors * output_bps / 8, width, ofp);
+ }
+ }
+ catch (...)
+ {
+ throw LIBRAW_EXCEPTION_ALLOC; // rethrow
+ }
+}
+#if 0
+void LibRaw::ppm_thumb()
+{
+ try
+ {
+ thumb_length = thumb_width * thumb_height * 3;
+ std::vector<char> thumb(thumb_length);
+ fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ fread(thumb.data(), 1, thumb_length, ifp);
+ fwrite(thumb.data(), 1, thumb_length, ofp);
+ }
+ catch (...)
+ {
+ throw LIBRAW_EXCEPTION_ALLOC; // rethrow
+ }
+}
+
+void LibRaw::ppm16_thumb()
+{
+ try
+ {
+ unsigned i;
+ thumb_length = thumb_width * thumb_height * 3;
+ std::vector<char> thumb(thumb_length * 2, 0);
+ read_shorts((ushort *)thumb.data(), thumb_length);
+ for (i = 0; i < thumb_length; i++)
+ thumb[i] = ((ushort *)thumb.data())[i] >> 8;
+ fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ fwrite(thumb.data(), 1, thumb_length, ofp);
+ }
+ catch (...)
+ {
+ throw LIBRAW_EXCEPTION_ALLOC; // rethrow
+ }
+}
+
+void LibRaw::layer_thumb()
+{
+ try
+ {
+ unsigned int i;
+ int c;
+ char map[][4] = { "012", "102" };
+
+ colors = thumb_misc >> 5 & 7;
+ thumb_length = thumb_width * thumb_height;
+ std::vector<char> thumb(colors * thumb_length, 0);
+ fprintf(ofp, "P%d\n%d %d\n255\n", 5 + (colors >> 1), thumb_width,
+ thumb_height);
+ fread(thumb.data(), thumb_length, colors, ifp);
+ for (i = 0; i < thumb_length; i++)
+ FORCC putc(thumb[i + thumb_length * (map[thumb_misc >> 8][c] - '0')], ofp);
+ }
+ catch (...)
+ {
+ throw LIBRAW_EXCEPTION_ALLOC; // rethrow
+ }
+}
+
+void LibRaw::rollei_thumb()
+{
+ try
+ {
+ unsigned i;
+ thumb_length = thumb_width * thumb_height;
+ std::vector<ushort> thumb(thumb_length, 0);
+ fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ read_shorts(thumb.data(), thumb_length);
+ for (i = 0; i < thumb_length; i++)
+ {
+ putc(thumb[i] << 3, ofp);
+ putc(thumb[i] >> 5 << 2, ofp);
+ putc(thumb[i] >> 11 << 3, ofp);
+ }
+ }
+ catch (...)
+ {
+ throw LIBRAW_EXCEPTION_ALLOC; // rethrow
+ }
+}
+
+void LibRaw::jpeg_thumb()
+{
+ try
+ {
+ std::vector<char> thumb(thumb_length);
+ fread(thumb.data(), 1, thumb_length, ifp);
+ jpeg_thumb_writer(ofp, thumb.data(), thumb_length);
+ }
+ catch (...)
+ {
+ throw LIBRAW_EXCEPTION_ALLOC; // rethrow
+ }
+}
+#endif
diff --git a/libkdcraw/libraw/src/write/tiff_writer.cpp b/libkdcraw/libraw/src/write/tiff_writer.cpp
new file mode 100644
index 0000000..895b18e
--- /dev/null
+++ b/libkdcraw/libraw/src/write/tiff_writer.cpp
@@ -0,0 +1,73 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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/libraw_cxx_defs.h"
+
+int LibRaw::dcraw_ppm_tiff_writer(const char *filename)
+{
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+
+ if (!imgdata.image)
+ return LIBRAW_OUT_OF_ORDER_CALL;
+
+ if (!filename)
+ return ENOENT;
+ FILE *f = NULL;
+ if (!strcmp(filename, "-"))
+ {
+#ifdef LIBRAW_WIN32_CALLS
+ _setmode(_fileno(stdout), _O_BINARY);
+#endif
+ f = stdout;
+ }
+ else
+ f = fopen(filename, "wb");
+
+ if (!f)
+ return errno;
+
+ try
+ {
+ if (!libraw_internal_data.output_data.histogram)
+ {
+ libraw_internal_data.output_data.histogram =
+ (int(*)[LIBRAW_HISTOGRAM_SIZE])malloc(
+ sizeof(*libraw_internal_data.output_data.histogram) * 4);
+ }
+ libraw_internal_data.internal_data.output = f;
+ write_ppm_tiff();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP);
+ libraw_internal_data.internal_data.output = NULL;
+ if (strcmp(filename, "-"))
+ fclose(f);
+ return 0;
+ }
+ catch (const LibRaw_exceptions& err)
+ {
+ if (strcmp(filename, "-"))
+ fclose(f);
+ EXCEPTION_HANDLER(err);
+ }
+ catch (const std::bad_alloc&)
+ {
+ if (strcmp(filename, "-"))
+ fclose(f);
+ EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC);
+ }
+
+}
diff --git a/libkdcraw/libraw/src/write/write_ph.cpp b/libkdcraw/libraw/src/write/write_ph.cpp
new file mode 100644
index 0000000..8151f10
--- /dev/null
+++ b/libkdcraw/libraw/src/write/write_ph.cpp
@@ -0,0 +1,39 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+ 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/dcraw_defs.h"
+int LibRaw::flip_index(int row, int col)
+{
+ if (flip & 4)
+ SWAP(row, col);
+ if (flip & 2)
+ row = iheight - 1 - row;
+ if (flip & 1)
+ col = iwidth - 1 - col;
+ return row * iwidth + col;
+}
+
+void LibRaw::write_ppm_tiff(){}
+void LibRaw::jpeg_thumb_writer(FILE *tfp, char *t_humb, int t_humb_length){}
+#if 0
+void LibRaw::ppm_thumb(){}
+void LibRaw::jpeg_thumb(){}
+void LibRaw::rollei_thumb(){}
+void LibRaw::ppm16_thumb(){}
+void LibRaw::layer_thumb(){}
+#endif \ No newline at end of file
diff --git a/libkdcraw/libraw/src/x3f/x3f_parse_process.cpp b/libkdcraw/libraw/src/x3f/x3f_parse_process.cpp
new file mode 100644
index 0000000..354e467
--- /dev/null
+++ b/libkdcraw/libraw/src/x3f/x3f_parse_process.cpp
@@ -0,0 +1,708 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC ([email protected])
+ *
+
+ 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).
+ */
+
+/* Library for accessing X3F Files
+----------------------------------------------------------------
+BSD-style License
+----------------------------------------------------------------
+
+* Copyright (c) 2010, Roland Karlsson ([email protected])
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of the organization nor the
+* names of its contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY ROLAND KARLSSON ''AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ROLAND KARLSSON BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifdef USE_X3FTOOLS
+
+#include "../../internal/libraw_cxx_defs.h"
+
+#if defined __sun && defined DS
+#undef DS
+#endif
+#ifdef ID
+#undef ID /* used in x3f utils */
+#endif
+
+#include "../../internal/x3f_tools.h"
+
+#define Sigma_X3F 22
+
+void x3f_clear(void *p) { x3f_delete((x3f_t *)p); }
+
+static void utf2char(utf16_t *str, char *buffer, unsigned bufsz)
+{
+ if (bufsz < 1)
+ return;
+ buffer[bufsz - 1] = 0;
+ char *b = buffer;
+
+ while (*str != 0x00 && --bufsz > 0)
+ {
+ char *chr = (char *)str;
+ *b++ = *chr;
+ str++;
+ }
+ *b = 0;
+}
+
+static void *lr_memmem(const void *l, size_t l_len, const void *s, size_t s_len)
+{
+ char *cur, *last;
+ const char *cl = (const char *)l;
+ const char *cs = (const char *)s;
+
+ /* we need something to compare */
+ if (l_len == 0 || s_len == 0)
+ return NULL;
+
+ /* "s" must be smaller or equal to "l" */
+ if (l_len < s_len)
+ return NULL;
+
+ /* special case where s_len == 1 */
+ if (s_len == 1)
+ return (void *)memchr(l, (int)*cs, l_len);
+
+ /* the last position where its possible to find "s" in "l" */
+ last = (char *)cl + l_len - s_len;
+
+ for (cur = (char *)cl; cur <= last; cur++)
+ if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
+ return cur;
+ return NULL;
+}
+
+void LibRaw::parse_x3f()
+{
+ x3f_t *x3f = x3f_new_from_file(libraw_internal_data.internal_data.input);
+ if (!x3f)
+ return;
+ _x3f_data = x3f;
+
+ x3f_header_t *H = NULL;
+
+ H = &x3f->header;
+ // Parse RAW size from RAW section
+ x3f_directory_entry_t *DE = x3f_get_raw(x3f);
+ if (!DE)
+ return;
+ imgdata.sizes.flip = H->rotation;
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ imgdata.sizes.raw_width = ID->columns;
+ imgdata.sizes.raw_height = ID->rows;
+ // Parse other params from property section
+
+ DE = x3f_get_prop(x3f);
+ if ((x3f_load_data(x3f, DE) == X3F_OK))
+ {
+ // Parse property list
+ DEH = &DE->header;
+ x3f_property_list_t *PL = &DEH->data_subsection.property_list;
+ utf16_t *datap = (utf16_t *)PL->data;
+ uint32_t maxitems = PL->data_size / sizeof(utf16_t);
+ if (PL->property_table.size != 0)
+ {
+ int i;
+ x3f_property_t *P = PL->property_table.element;
+ for (i = 0; i < (int)PL->num_properties; i++)
+ {
+ char name[100], value[100];
+ int noffset = (P[i].name - datap);
+ int voffset = (P[i].value - datap);
+ if (noffset < 0 || noffset > (int)maxitems || voffset < 0 ||
+ voffset > (int)maxitems)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ int maxnsize = maxitems - (P[i].name - datap);
+ int maxvsize = maxitems - (P[i].value - datap);
+ utf2char(P[i].name, name, MIN(maxnsize, ((int)sizeof(name))));
+ utf2char(P[i].value, value, MIN(maxvsize, ((int)sizeof(value))));
+ if (!strcmp(name, "ISO"))
+ imgdata.other.iso_speed = atoi(value);
+ if (!strcmp(name, "CAMMANUF"))
+ strcpy(imgdata.idata.make, value);
+ if (!strcmp(name, "CAMMODEL"))
+ strcpy(imgdata.idata.model, value);
+ if (!strcmp(name, "CAMSERIAL"))
+ strcpy(imgdata.shootinginfo.BodySerial, value);
+ if (!strcmp(name, "WB_DESC"))
+ strcpy(imgdata.color.model2, value);
+ if (!strcmp(name, "TIME"))
+ imgdata.other.timestamp = atoi(value);
+ if (!strcmp(name, "SHUTTER"))
+ imgdata.other.shutter = atof(value);
+ if (!strcmp(name, "APERTURE"))
+ imgdata.other.aperture = atof(value);
+ if (!strcmp(name, "FLENGTH"))
+ imgdata.other.focal_len = atof(value);
+ if (!strcmp(name, "FLEQ35MM"))
+ imgdata.lens.makernotes.FocalLengthIn35mmFormat = atof(value);
+ if (!strcmp(name, "IMAGERTEMP"))
+ MN.common.SensorTemperature = atof(value);
+ if (!strcmp(name, "LENSARANGE"))
+ {
+ char *sp;
+ imgdata.lens.makernotes.MaxAp4CurFocal =
+ imgdata.lens.makernotes.MinAp4CurFocal = atof(value);
+ sp = strrchr(value, ' ');
+ if (sp)
+ {
+ imgdata.lens.makernotes.MinAp4CurFocal = atof(sp);
+ if (imgdata.lens.makernotes.MaxAp4CurFocal >
+ imgdata.lens.makernotes.MinAp4CurFocal)
+ my_swap(float, imgdata.lens.makernotes.MaxAp4CurFocal,
+ imgdata.lens.makernotes.MinAp4CurFocal);
+ }
+ }
+ if (!strcmp(name, "LENSFRANGE"))
+ {
+ char *sp;
+ imgdata.lens.makernotes.MinFocal = imgdata.lens.makernotes.MaxFocal =
+ atof(value);
+ sp = strrchr(value, ' ');
+ if (sp)
+ {
+ imgdata.lens.makernotes.MaxFocal = atof(sp);
+ if ((imgdata.lens.makernotes.MaxFocal + 0.17f) <
+ imgdata.lens.makernotes.MinFocal)
+ my_swap(float, imgdata.lens.makernotes.MaxFocal,
+ imgdata.lens.makernotes.MinFocal);
+ }
+ }
+ if (!strcmp(name, "LENSMODEL"))
+ {
+ char *sp;
+ imgdata.lens.makernotes.LensID =
+ strtol(value, &sp, 16); // atoi(value);
+ if (imgdata.lens.makernotes.LensID)
+ imgdata.lens.makernotes.LensMount = Sigma_X3F;
+ }
+ }
+ imgdata.idata.raw_count = 1;
+ load_raw = &LibRaw::x3f_load_raw;
+ imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 6;
+ imgdata.idata.is_foveon = 1;
+ libraw_internal_data.internal_output_params.raw_color =
+ 1; // Force adobe coeff
+ imgdata.color.maximum = 0x3fff; // To be reset by color table
+ libraw_internal_data.unpacker_data.order = 0x4949;
+ }
+ }
+ else
+ {
+ // No property list
+ if (imgdata.sizes.raw_width == 5888 || imgdata.sizes.raw_width == 2944 ||
+ imgdata.sizes.raw_width == 6656 || imgdata.sizes.raw_width == 3328 ||
+ imgdata.sizes.raw_width == 5504 ||
+ imgdata.sizes.raw_width == 2752) // Quattro
+ {
+ imgdata.idata.raw_count = 1;
+ load_raw = &LibRaw::x3f_load_raw;
+ imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 6;
+ imgdata.idata.is_foveon = 1;
+ libraw_internal_data.internal_output_params.raw_color =
+ 1; // Force adobe coeff
+ libraw_internal_data.unpacker_data.order = 0x4949;
+ strcpy(imgdata.idata.make, "SIGMA");
+#if 1
+ // Try to find model number in first 2048 bytes;
+ int pos = libraw_internal_data.internal_data.input->tell();
+ libraw_internal_data.internal_data.input->seek(0, SEEK_SET);
+ unsigned char buf[2048];
+ libraw_internal_data.internal_data.input->read(buf, 2048, 1);
+ libraw_internal_data.internal_data.input->seek(pos, SEEK_SET);
+ unsigned char *fnd = (unsigned char *)lr_memmem(buf, 2048, "SIGMA dp", 8);
+ unsigned char *fndsd =
+ (unsigned char *)lr_memmem(buf, 2048, "sd Quatt", 8);
+ if (fnd)
+ {
+ unsigned char *nm = fnd + 8;
+ snprintf(imgdata.idata.model, 64, "dp%c Quattro",
+ *nm <= '9' && *nm >= '0' ? *nm : '2');
+ }
+ else if (fndsd)
+ {
+ snprintf(imgdata.idata.model, 64, "%s", fndsd);
+ }
+ else
+#endif
+ if (imgdata.sizes.raw_width == 6656 ||
+ imgdata.sizes.raw_width == 3328)
+ strcpy(imgdata.idata.model, "sd Quattro H");
+ else
+ strcpy(imgdata.idata.model, "dp2 Quattro");
+ }
+ // else
+ }
+ // Try to get thumbnail data
+ LibRaw_thumbnail_formats format = LIBRAW_THUMBNAIL_UNKNOWN;
+ if ((DE = x3f_get_thumb_jpeg(x3f)))
+ {
+ format = LIBRAW_THUMBNAIL_JPEG;
+ }
+ else if ((DE = x3f_get_thumb_plain(x3f)))
+ {
+ format = LIBRAW_THUMBNAIL_BITMAP;
+ }
+ if (DE)
+ {
+ x3f_directory_entry_header_t *_DEH = &DE->header;
+ x3f_image_data_t *_ID = &_DEH->data_subsection.image_data;
+ imgdata.thumbnail.twidth = _ID->columns;
+ imgdata.thumbnail.theight = _ID->rows;
+ imgdata.thumbnail.tcolors = 3;
+ imgdata.thumbnail.tformat = format;
+ libraw_internal_data.internal_data.toffset = DE->input.offset;
+ libraw_internal_data.unpacker_data.thumb_format = LIBRAW_INTERNAL_THUMBNAIL_X3F;
+ }
+ DE = x3f_get_camf(x3f);
+ if (DE && DE->input.size > 28)
+ {
+ libraw_internal_data.unpacker_data.meta_offset = DE->input.offset + 8;
+ libraw_internal_data.unpacker_data.meta_length = DE->input.size - 28;
+ }
+}
+
+INT64 LibRaw::x3f_thumb_size()
+{
+ try
+ {
+ x3f_t *x3f = (x3f_t *)_x3f_data;
+ if (!x3f)
+ return -1; // No data pointer set
+ x3f_directory_entry_t *DE = x3f_get_thumb_jpeg(x3f);
+ if (!DE)
+ DE = x3f_get_thumb_plain(x3f);
+ if (!DE)
+ return -1;
+ int64_t p = x3f_load_data_size(x3f, DE);
+ if (p < 0 || p > 0xffffffff)
+ return -1;
+ return p;
+ }
+ catch (...)
+ {
+ return -1;
+ }
+}
+
+void LibRaw::x3f_thumb_loader()
+{
+ try
+ {
+ x3f_t *x3f = (x3f_t *)_x3f_data;
+ if (!x3f)
+ return; // No data pointer set
+ x3f_directory_entry_t *DE = x3f_get_thumb_jpeg(x3f);
+ if (!DE)
+ DE = x3f_get_thumb_plain(x3f);
+ if (!DE)
+ return;
+ if (X3F_OK != x3f_load_data(x3f, DE))
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ imgdata.thumbnail.twidth = ID->columns;
+ imgdata.thumbnail.theight = ID->rows;
+ imgdata.thumbnail.tcolors = 3;
+ if (imgdata.thumbnail.tformat == LIBRAW_THUMBNAIL_JPEG)
+ {
+ imgdata.thumbnail.thumb = (char *)malloc(ID->data_size);
+ memmove(imgdata.thumbnail.thumb, ID->data, ID->data_size);
+ imgdata.thumbnail.tlength = ID->data_size;
+ }
+ else if (imgdata.thumbnail.tformat == LIBRAW_THUMBNAIL_BITMAP)
+ {
+ imgdata.thumbnail.tlength = ID->columns * ID->rows * 3;
+ imgdata.thumbnail.thumb = (char *)malloc(ID->columns * ID->rows * 3);
+ char *src0 = (char *)ID->data;
+ for (int row = 0; row < (int)ID->rows; row++)
+ {
+ int offset = row * ID->row_stride;
+ if (offset + ID->columns * 3 > ID->data_size)
+ break;
+ char *dest = &imgdata.thumbnail.thumb[row * ID->columns * 3];
+ char *src = &src0[offset];
+ memmove(dest, src, ID->columns * 3);
+ }
+ }
+ }
+ catch (...)
+ {
+ // do nothing
+ }
+}
+
+void LibRaw::x3f_dpq_interpolate_rg()
+{
+ int w = imgdata.sizes.raw_width / 2;
+ int h = imgdata.sizes.raw_height / 2;
+ unsigned short *image = (ushort *)imgdata.rawdata.color3_image;
+
+ for (int color = 0; color < 2; color++)
+ {
+ for (int y = 2; y < (h - 2); y++)
+ {
+ uint16_t *row0 =
+ &image[imgdata.sizes.raw_width * 3 * (y * 2) + color]; // dst[1]
+ uint16_t *row1 =
+ &image[imgdata.sizes.raw_width * 3 * (y * 2 + 1) + color]; // dst1[1]
+ for (int x = 2; x < (w - 2); x++)
+ {
+ row1[0] = row1[3] = row0[3] = row0[0];
+ row0 += 6;
+ row1 += 6;
+ }
+ }
+ }
+}
+
+#ifdef _ABS
+#undef _ABS
+#endif
+#define _ABS(a) ((a) < 0 ? -(a) : (a))
+
+#undef CLIP
+#define CLIP(value, high) ((value) > (high) ? (high) : (value))
+
+void LibRaw::x3f_dpq_interpolate_af(int xstep, int ystep, int scale)
+{
+ unsigned short *image = (ushort *)imgdata.rawdata.color3_image;
+ for (int y = 0;
+ y < imgdata.rawdata.sizes.height + imgdata.rawdata.sizes.top_margin;
+ y += ystep)
+ {
+ if (y < imgdata.rawdata.sizes.top_margin)
+ continue;
+ if (y < scale)
+ continue;
+ if (y > imgdata.rawdata.sizes.raw_height - scale)
+ break;
+ uint16_t *row0 = &image[imgdata.sizes.raw_width * 3 * y]; // Наша строка
+ uint16_t *row_minus =
+ &image[imgdata.sizes.raw_width * 3 * (y - scale)]; // Строка выше
+ uint16_t *row_plus =
+ &image[imgdata.sizes.raw_width * 3 * (y + scale)]; // Строка ниже
+ for (int x = 0;
+ x < imgdata.rawdata.sizes.width + imgdata.rawdata.sizes.left_margin;
+ x += xstep)
+ {
+ if (x < imgdata.rawdata.sizes.left_margin)
+ continue;
+ if (x < scale)
+ continue;
+ if (x > imgdata.rawdata.sizes.raw_width - scale)
+ break;
+ uint16_t *pixel0 = &row0[x * 3];
+ uint16_t *pixel_top = &row_minus[x * 3];
+ uint16_t *pixel_bottom = &row_plus[x * 3];
+ uint16_t *pixel_left = &row0[(x - scale) * 3];
+ uint16_t *pixel_right = &row0[(x + scale) * 3];
+ uint16_t *pixf = pixel_top;
+ if (_ABS(pixf[2] - pixel0[2]) > _ABS(pixel_bottom[2] - pixel0[2]))
+ pixf = pixel_bottom;
+ if (_ABS(pixf[2] - pixel0[2]) > _ABS(pixel_left[2] - pixel0[2]))
+ pixf = pixel_left;
+ if (_ABS(pixf[2] - pixel0[2]) > _ABS(pixel_right[2] - pixel0[2]))
+ pixf = pixel_right;
+ int blocal = pixel0[2], bnear = pixf[2];
+ if (blocal < (int)imgdata.color.black + 16 || bnear < (int)imgdata.color.black + 16)
+ {
+ if (pixel0[0] < imgdata.color.black)
+ pixel0[0] = imgdata.color.black;
+ if (pixel0[1] < imgdata.color.black)
+ pixel0[1] = imgdata.color.black;
+ pixel0[0] = CLIP(
+ (pixel0[0] - imgdata.color.black) * 4 + imgdata.color.black, 16383);
+ pixel0[1] = CLIP(
+ (pixel0[1] - imgdata.color.black) * 4 + imgdata.color.black, 16383);
+ }
+ else
+ {
+ float multip = float(bnear - imgdata.color.black) /
+ float(blocal - imgdata.color.black);
+ if (pixel0[0] < imgdata.color.black)
+ pixel0[0] = imgdata.color.black;
+ if (pixel0[1] < imgdata.color.black)
+ pixel0[1] = imgdata.color.black;
+ float pixf0 = pixf[0];
+ if (pixf0 < imgdata.color.black)
+ pixf0 = imgdata.color.black;
+ float pixf1 = pixf[1];
+ if (pixf1 < imgdata.color.black)
+ pixf1 = imgdata.color.black;
+
+ pixel0[0] = CLIP(
+ ((float(pixf0 - imgdata.color.black) * multip +
+ imgdata.color.black) +
+ ((pixel0[0] - imgdata.color.black) * 3.75 + imgdata.color.black)) /
+ 2,
+ 16383);
+ pixel0[1] = CLIP(
+ ((float(pixf1 - imgdata.color.black) * multip +
+ imgdata.color.black) +
+ ((pixel0[1] - imgdata.color.black) * 3.75 + imgdata.color.black)) /
+ 2,
+ 16383);
+ // pixel0[1] = float(pixf[1]-imgdata.color.black)*multip +
+ // imgdata.color.black;
+ }
+ }
+ }
+}
+
+void LibRaw::x3f_dpq_interpolate_af_sd(int xstart, int ystart, int xend,
+ int yend, int xstep, int ystep,
+ int scale)
+{
+ unsigned short *image = (ushort *)imgdata.rawdata.color3_image;
+ for (int y = ystart; y <= yend && y < imgdata.rawdata.sizes.height +
+ imgdata.rawdata.sizes.top_margin;
+ y += ystep)
+ {
+ uint16_t *row0 = &image[imgdata.sizes.raw_width * 3 * y]; // Наша строка
+ uint16_t *row1 =
+ &image[imgdata.sizes.raw_width * 3 * (y + 1)]; // Следующая строка
+ uint16_t *row_minus =
+ &image[imgdata.sizes.raw_width * 3 * (y - scale)]; // Строка выше
+ uint16_t *row_plus =
+ &image[imgdata.sizes.raw_width * 3 *
+ (y + scale)]; // Строка ниже AF-point (scale=2 -> ниже row1
+ uint16_t *row_minus1 = &image[imgdata.sizes.raw_width * 3 * (y - 1)];
+ for (int x = xstart; x < xend && x < imgdata.rawdata.sizes.width +
+ imgdata.rawdata.sizes.left_margin;
+ x += xstep)
+ {
+ uint16_t *pixel00 = &row0[x * 3]; // Current pixel
+ float sumR = 0.f, sumG = 0.f;
+ float cnt = 0.f;
+ for (int xx = -scale; xx <= scale; xx += scale)
+ {
+ sumR += row_minus[(x + xx) * 3];
+ sumR += row_plus[(x + xx) * 3];
+ sumG += row_minus[(x + xx) * 3 + 1];
+ sumG += row_plus[(x + xx) * 3 + 1];
+ cnt += 1.f;
+ if (xx)
+ {
+ cnt += 1.f;
+ sumR += row0[(x + xx) * 3];
+ sumG += row0[(x + xx) * 3 + 1];
+ }
+ }
+ pixel00[0] = sumR / 8.f;
+ pixel00[1] = sumG / 8.f;
+
+ if (scale == 2)
+ {
+ uint16_t *pixel0B = &row0[x * 3 + 3]; // right pixel
+ uint16_t *pixel1B = &row1[x * 3 + 3]; // right pixel
+ float sumG0 = 0, sumG1 = 0.f;
+ float _cnt = 0.f;
+ for (int xx = -scale; xx <= scale; xx += scale)
+ {
+ sumG0 += row_minus1[(x + xx) * 3 + 2];
+ sumG1 += row_plus[(x + xx) * 3 + 2];
+ _cnt += 1.f;
+ if (xx)
+ {
+ sumG0 += row0[(x + xx) * 3 + 2];
+ sumG1 += row1[(x + xx) * 3 + 2];
+ _cnt += 1.f;
+ }
+ }
+ if (_cnt > 1.0)
+ {
+ pixel0B[2] = sumG0 / _cnt;
+ pixel1B[2] = sumG1 / _cnt;
+ }
+ }
+
+ // uint16_t* pixel10 = &row1[x*3]; // Pixel below current
+ // uint16_t* pixel_bottom = &row_plus[x*3];
+ }
+ }
+}
+
+void LibRaw::x3f_load_raw()
+{
+ // already in try/catch
+ int raise_error = 0;
+ x3f_t *x3f = (x3f_t *)_x3f_data;
+ if (!x3f)
+ return; // No data pointer set
+ if (X3F_OK == x3f_load_data(x3f, x3f_get_raw(x3f)))
+ {
+ x3f_directory_entry_t *DE = x3f_get_raw(x3f);
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ if (!ID)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ x3f_quattro_t *Q = ID->quattro;
+ x3f_huffman_t *HUF = ID->huffman;
+ x3f_true_t *TRU = ID->tru;
+ uint16_t *data = NULL;
+ if (ID->rows != S.raw_height || ID->columns != S.raw_width)
+ {
+ raise_error = 1;
+ goto end;
+ }
+ if (HUF != NULL)
+ data = HUF->x3rgb16.data;
+ if (TRU != NULL)
+ data = TRU->x3rgb16.data;
+ if (data == NULL)
+ {
+ raise_error = 1;
+ goto end;
+ }
+
+ size_t datasize = S.raw_height * S.raw_width * 3 * sizeof(unsigned short);
+ S.raw_pitch = S.raw_width * 3 * sizeof(unsigned short);
+ if (!(imgdata.rawdata.raw_alloc = malloc(datasize)))
+ throw LIBRAW_EXCEPTION_ALLOC;
+
+ imgdata.rawdata.color3_image = (ushort(*)[3])imgdata.rawdata.raw_alloc;
+ // swap R/B channels for known old cameras
+ if (!strcasecmp(P1.make, "Polaroid") && !strcasecmp(P1.model, "x530"))
+ {
+ ushort(*src)[3] = (ushort(*)[3])data;
+ for (int p = 0; p < S.raw_height * S.raw_width; p++)
+ {
+ imgdata.rawdata.color3_image[p][0] = src[p][2];
+ imgdata.rawdata.color3_image[p][1] = src[p][1];
+ imgdata.rawdata.color3_image[p][2] = src[p][0];
+ }
+ }
+ else if (HUF)
+ memmove(imgdata.rawdata.raw_alloc, data, datasize);
+ else if (TRU && (!Q || !Q->quattro_layout))
+ memmove(imgdata.rawdata.raw_alloc, data, datasize);
+ else if (TRU && Q)
+ {
+ // Move quattro data in place
+ // R/B plane
+ for (int prow = 0; prow < (int)TRU->x3rgb16.rows && prow < S.raw_height / 2;
+ prow++)
+ {
+ ushort(*destrow)[3] =
+ (unsigned short(*)[3]) &
+ imgdata.rawdata
+ .color3_image[prow * 2 * S.raw_pitch / 3 / sizeof(ushort)][0];
+ ushort(*srcrow)[3] =
+ (unsigned short(*)[3]) & data[prow * TRU->x3rgb16.row_stride];
+ for (int pcol = 0;
+ pcol < (int)TRU->x3rgb16.columns && pcol < S.raw_width / 2; pcol++)
+ {
+ destrow[pcol * 2][0] = srcrow[pcol][0];
+ destrow[pcol * 2][1] = srcrow[pcol][1];
+ }
+ }
+ for (int row = 0; row < (int)Q->top16.rows && row < S.raw_height; row++)
+ {
+ ushort(*destrow)[3] =
+ (unsigned short(*)[3]) &
+ imgdata.rawdata
+ .color3_image[row * S.raw_pitch / 3 / sizeof(ushort)][0];
+ ushort *srcrow =
+ (unsigned short *)&Q->top16.data[row * Q->top16.columns];
+ for (int col = 0; col < (int)Q->top16.columns && col < S.raw_width; col++)
+ destrow[col][2] = srcrow[col];
+ }
+ }
+
+#if 1
+ if (TRU && Q &&
+ !(imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_NODP2Q_INTERPOLATEAF))
+ {
+ if (imgdata.sizes.raw_width == 5888 &&
+ imgdata.sizes.raw_height == 3672) // dpN Quattro normal
+ {
+ x3f_dpq_interpolate_af(32, 8, 2);
+ }
+ else if (imgdata.sizes.raw_width == 5888 &&
+ imgdata.sizes.raw_height == 3776) // sd Quattro normal raw
+ {
+ x3f_dpq_interpolate_af_sd(216, 464, imgdata.sizes.raw_width - 1, 3312,
+ 16, 32, 2);
+ }
+ else if (imgdata.sizes.raw_width == 6656 &&
+ imgdata.sizes.raw_height == 4480) // sd Quattro H normal raw
+ {
+ x3f_dpq_interpolate_af_sd(232, 592, imgdata.sizes.raw_width - 1, 3920,
+ 16, 32, 2);
+ }
+ else if (imgdata.sizes.raw_width == 3328 &&
+ imgdata.sizes.raw_height == 2240) // sd Quattro H half size
+ {
+ x3f_dpq_interpolate_af_sd(116, 296, imgdata.sizes.raw_width - 1, 2200,
+ 8, 16, 1);
+ }
+ else if (imgdata.sizes.raw_width == 5504 &&
+ imgdata.sizes.raw_height == 3680) // sd Quattro H APS-C raw
+ {
+ x3f_dpq_interpolate_af_sd(8, 192, imgdata.sizes.raw_width - 1, 3185, 16,
+ 32, 2);
+ }
+ else if (imgdata.sizes.raw_width == 2752 &&
+ imgdata.sizes.raw_height == 1840) // sd Quattro H APS-C half size
+ {
+ x3f_dpq_interpolate_af_sd(4, 96, imgdata.sizes.raw_width - 1, 1800, 8,
+ 16, 1);
+ }
+ else if (imgdata.sizes.raw_width == 2944 &&
+ imgdata.sizes.raw_height == 1836) // dpN Quattro small raw
+ {
+ x3f_dpq_interpolate_af(16, 4, 1);
+ }
+ else if (imgdata.sizes.raw_width == 2944 &&
+ imgdata.sizes.raw_height == 1888) // sd Quattro small
+ {
+ x3f_dpq_interpolate_af_sd(108, 232, imgdata.sizes.raw_width - 1, 1656,
+ 8, 16, 1);
+ }
+ }
+#endif
+ if (TRU && Q && Q->quattro_layout &&
+ !(imgdata.rawparams.specials & LIBRAW_RAWSPECIAL_NODP2Q_INTERPOLATERG))
+ x3f_dpq_interpolate_rg();
+ }
+ else
+ raise_error = 1;
+end:
+ if (raise_error)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+}
+#endif
diff --git a/libkdcraw/libraw/src/x3f/x3f_utils_patched.cpp b/libkdcraw/libraw/src/x3f/x3f_utils_patched.cpp
new file mode 100644
index 0000000..6b20b90
--- /dev/null
+++ b/libkdcraw/libraw/src/x3f/x3f_utils_patched.cpp
@@ -0,0 +1,2119 @@
+#ifdef USE_X3FTOOLS
+
+/* Library for accessing X3F Files
+----------------------------------------------------------------
+BSD-style License
+----------------------------------------------------------------
+
+* Copyright (c) 2010, Roland Karlsson ([email protected])
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of the organization nor the
+* names of its contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY ROLAND KARLSSON ''AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ROLAND KARLSSON BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "../../internal/libraw_cxx_defs.h"
+
+#if defined __sun && defined DS
+#undef DS
+#endif
+#ifdef ID
+#undef ID /* used in x3f utils */
+#endif
+
+#include "../../internal/x3f_tools.h"
+
+/* extern */ int legacy_offset = 0;
+/* extern */ bool_t auto_legacy_offset = 1;
+
+/* --------------------------------------------------------------------- */
+/* Reading and writing - assuming little endian in the file */
+/* --------------------------------------------------------------------- */
+
+static int x3f_get1(LibRaw_abstract_datastream *f)
+{
+ /* Little endian file */
+ return f->get_char();
+}
+
+static int x3f_sget2(uchar *s) { return s[0] | s[1] << 8; }
+
+static int x3f_get2(LibRaw_abstract_datastream *f)
+{
+ uchar str[2] = {0xff, 0xff};
+ f->read(str, 1, 2);
+ return x3f_sget2(str);
+}
+
+unsigned x3f_sget4(uchar *s)
+{
+ return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+}
+
+unsigned x3f_get4(LibRaw_abstract_datastream *f)
+{
+ uchar str[4] = {0xff, 0xff, 0xff, 0xff};
+ f->read(str, 1, 4);
+ return x3f_sget4(str);
+}
+
+#define FREE(P) \
+ do \
+ { \
+ free(P); \
+ (P) = NULL; \
+ } while (0)
+
+#define PUT_GET_N(_buffer, _size, _file, _func) \
+ do \
+ { \
+ int _left = _size; \
+ while (_left != 0) \
+ { \
+ int _cur = _file->_func(_buffer, 1, _left); \
+ if (_cur == 0) \
+ { \
+ throw LIBRAW_EXCEPTION_IO_CORRUPT; \
+ } \
+ _left -= _cur; \
+ } \
+ } while (0)
+
+#define GET1(_v) \
+ do \
+ { \
+ (_v) = x3f_get1(I->input.file); \
+ } while (0)
+#define GET2(_v) \
+ do \
+ { \
+ (_v) = x3f_get2(I->input.file); \
+ } while (0)
+#define GET4(_v) \
+ do \
+ { \
+ (_v) = x3f_get4(I->input.file); \
+ } while (0)
+
+#define GET4F(_v) \
+ do \
+ { \
+ union { \
+ int32_t i; \
+ float f; \
+ } _tmp; \
+ _tmp.i = x3f_get4(I->input.file); \
+ (_v) = _tmp.f; \
+ } while (0)
+
+#define GETN(_v, _s) PUT_GET_N(_v, _s, I->input.file, read)
+
+#define GET_TABLE(_T, _GETX, _NUM, _TYPE) \
+ do \
+ { \
+ int _i; \
+ (_T).size = (_NUM); \
+ (_T).element = \
+ (_TYPE *)realloc((_T).element, (_NUM) * sizeof((_T).element[0])); \
+ for (_i = 0; _i < (int)(_T).size; _i++) \
+ _GETX((_T).element[_i]); \
+ } while (0)
+
+#define GET_PROPERTY_TABLE(_T, _NUM) \
+ do \
+ { \
+ int _i; \
+ (_T).size = (_NUM); \
+ (_T).element = (x3f_property_t *)realloc( \
+ (_T).element, (_NUM) * sizeof((_T).element[0])); \
+ for (_i = 0; _i < (int)(_T).size; _i++) \
+ { \
+ GET4((_T).element[_i].name_offset); \
+ GET4((_T).element[_i].value_offset); \
+ } \
+ } while (0)
+
+#define GET_TRUE_HUFF_TABLE(_T) \
+ do \
+ { \
+ int _i; \
+ (_T).element = NULL; \
+ for (_i = 0;; _i++) \
+ { \
+ (_T).size = _i + 1; \
+ (_T).element = (x3f_true_huffman_element_t *)realloc( \
+ (_T).element, (_i + 1) * sizeof((_T).element[0])); \
+ GET1((_T).element[_i].code_size); \
+ GET1((_T).element[_i].code); \
+ if ((_T).element[_i].code_size == 0) \
+ break; \
+ } \
+ } while (0)
+
+/* --------------------------------------------------------------------- */
+/* Allocating Huffman tree help data */
+/* --------------------------------------------------------------------- */
+
+static void cleanup_huffman_tree(x3f_hufftree_t *HTP) { free(HTP->nodes); }
+
+static void new_huffman_tree(x3f_hufftree_t *HTP, int bits)
+{
+ int leaves = 1 << bits;
+
+ HTP->free_node_index = 0;
+ HTP->total_node_index = HUF_TREE_MAX_NODES(leaves);
+ HTP->nodes = (x3f_huffnode_t *)calloc(1, HUF_TREE_MAX_NODES(leaves) *
+ sizeof(x3f_huffnode_t));
+}
+
+/* --------------------------------------------------------------------- */
+/* Allocating TRUE engine RAW help data */
+/* --------------------------------------------------------------------- */
+
+static void cleanup_true(x3f_true_t **TRUP)
+{
+ x3f_true_t *TRU = *TRUP;
+
+ if (TRU == NULL)
+ return;
+
+ FREE(TRU->table.element);
+ FREE(TRU->plane_size.element);
+ cleanup_huffman_tree(&TRU->tree);
+ FREE(TRU->x3rgb16.buf);
+
+ FREE(TRU);
+
+ *TRUP = NULL;
+}
+
+static x3f_true_t *new_true(x3f_true_t **TRUP)
+{
+ x3f_true_t *TRU = (x3f_true_t *)calloc(1, sizeof(x3f_true_t));
+
+ cleanup_true(TRUP);
+
+ TRU->table.size = 0;
+ TRU->table.element = NULL;
+ TRU->plane_size.size = 0;
+ TRU->plane_size.element = NULL;
+ TRU->tree.nodes = NULL;
+ TRU->x3rgb16.data = NULL;
+ TRU->x3rgb16.buf = NULL;
+
+ *TRUP = TRU;
+
+ return TRU;
+}
+
+static void cleanup_quattro(x3f_quattro_t **QP)
+{
+ x3f_quattro_t *Q = *QP;
+
+ if (Q == NULL)
+ return;
+
+ FREE(Q->top16.buf);
+ FREE(Q);
+
+ *QP = NULL;
+}
+
+static x3f_quattro_t *new_quattro(x3f_quattro_t **QP)
+{
+ x3f_quattro_t *Q = (x3f_quattro_t *)calloc(1, sizeof(x3f_quattro_t));
+ int i;
+
+ cleanup_quattro(QP);
+
+ for (i = 0; i < TRUE_PLANES; i++)
+ {
+ Q->plane[i].columns = 0;
+ Q->plane[i].rows = 0;
+ }
+
+ Q->unknown = 0;
+
+ Q->top16.data = NULL;
+ Q->top16.buf = NULL;
+
+ *QP = Q;
+
+ return Q;
+}
+
+/* --------------------------------------------------------------------- */
+/* Allocating Huffman engine help data */
+/* --------------------------------------------------------------------- */
+
+static void cleanup_huffman(x3f_huffman_t **HUFP)
+{
+ x3f_huffman_t *HUF = *HUFP;
+
+ if (HUF == NULL)
+ return;
+
+ FREE(HUF->mapping.element);
+ FREE(HUF->table.element);
+ cleanup_huffman_tree(&HUF->tree);
+ FREE(HUF->row_offsets.element);
+ FREE(HUF->rgb8.buf);
+ FREE(HUF->x3rgb16.buf);
+ FREE(HUF);
+
+ *HUFP = NULL;
+}
+
+static x3f_huffman_t *new_huffman(x3f_huffman_t **HUFP)
+{
+ x3f_huffman_t *HUF = (x3f_huffman_t *)calloc(1, sizeof(x3f_huffman_t));
+
+ cleanup_huffman(HUFP);
+
+ /* Set all not read data block pointers to NULL */
+ HUF->mapping.size = 0;
+ HUF->mapping.element = NULL;
+ HUF->table.size = 0;
+ HUF->table.element = NULL;
+ HUF->tree.nodes = NULL;
+ HUF->row_offsets.size = 0;
+ HUF->row_offsets.element = NULL;
+ HUF->rgb8.data = NULL;
+ HUF->rgb8.buf = NULL;
+ HUF->x3rgb16.data = NULL;
+ HUF->x3rgb16.buf = NULL;
+
+ *HUFP = HUF;
+
+ return HUF;
+}
+
+/* --------------------------------------------------------------------- */
+/* Creating a new x3f structure from file */
+/* --------------------------------------------------------------------- */
+
+/* extern */ x3f_t *x3f_new_from_file(LibRaw_abstract_datastream *infile)
+{
+ if (!infile)
+ return NULL;
+ INT64 fsize = infile->size();
+ x3f_t *x3f = (x3f_t *)calloc(1, sizeof(x3f_t));
+ if (!x3f)
+ throw LIBRAW_EXCEPTION_ALLOC;
+ try
+ {
+ x3f_info_t *I = NULL;
+ x3f_header_t *H = NULL;
+ x3f_directory_section_t *DS = NULL;
+ int i, d;
+
+ I = &x3f->info;
+ I->error = NULL;
+ I->input.file = infile;
+ I->output.file = NULL;
+
+ /* Read file header */
+ H = &x3f->header;
+ infile->seek(0, SEEK_SET);
+ GET4(H->identifier);
+
+ if (H->identifier != X3F_FOVb)
+ {
+ free(x3f);
+ return NULL;
+ }
+
+ GET4(H->version);
+ GETN(H->unique_identifier, SIZE_UNIQUE_IDENTIFIER);
+ /* TODO: the meaning of the rest of the header for version >= 4.0 (Quattro)
+ * is unknown */
+ if (H->version < X3F_VERSION_4_0)
+ {
+ GET4(H->mark_bits);
+ GET4(H->columns);
+ GET4(H->rows);
+ GET4(H->rotation);
+ if (H->version >= X3F_VERSION_2_1)
+ {
+ int num_ext_data =
+ H->version >= X3F_VERSION_3_0 ? NUM_EXT_DATA_3_0 : NUM_EXT_DATA_2_1;
+
+ GETN(H->white_balance, SIZE_WHITE_BALANCE);
+ if (H->version >= X3F_VERSION_2_3)
+ GETN(H->color_mode, SIZE_COLOR_MODE);
+ GETN(H->extended_types, num_ext_data);
+ for (i = 0; i < num_ext_data; i++)
+ GET4F(H->extended_data[i]);
+ }
+ }
+
+ /* Go to the beginning of the directory */
+ infile->seek(-4, SEEK_END);
+ infile->seek(x3f_get4(infile), SEEK_SET);
+
+ /* Read the directory header */
+ DS = &x3f->directory_section;
+ GET4(DS->identifier);
+ GET4(DS->version);
+ GET4(DS->num_directory_entries);
+
+ if (DS->num_directory_entries > 50)
+ goto _err; // too much direntries, most likely broken file
+
+ if (DS->num_directory_entries > 0)
+ {
+ size_t size = DS->num_directory_entries * sizeof(x3f_directory_entry_t);
+ DS->directory_entry = (x3f_directory_entry_t *)calloc(1, size);
+ }
+
+ /* Traverse the directory */
+ for (d = 0; d < (int)DS->num_directory_entries; d++)
+ {
+ x3f_directory_entry_t *DE = &DS->directory_entry[d];
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ uint32_t save_dir_pos;
+
+ /* Read the directory entry info */
+ GET4(DE->input.offset);
+ GET4(DE->input.size);
+ if (DE->input.offset + DE->input.size > fsize * 2)
+ goto _err;
+
+ DE->output.offset = 0;
+ DE->output.size = 0;
+
+ GET4(DE->type);
+
+ /* Save current pos and go to the entry */
+ save_dir_pos = infile->tell();
+ infile->seek(DE->input.offset, SEEK_SET);
+
+ /* Read the type independent part of the entry header */
+ DEH = &DE->header;
+ GET4(DEH->identifier);
+ GET4(DEH->version);
+
+ /* NOTE - the tests below could be made on DE->type instead */
+
+ if (DEH->identifier == X3F_SECp)
+ {
+ x3f_property_list_t *PL = &DEH->data_subsection.property_list;
+ if (!PL)
+ goto _err;
+ /* Read the property part of the header */
+ GET4(PL->num_properties);
+ GET4(PL->character_format);
+ GET4(PL->reserved);
+ GET4(PL->total_length);
+
+ /* Set all not read data block pointers to NULL */
+ PL->data = NULL;
+ PL->data_size = 0;
+ }
+
+ if (DEH->identifier == X3F_SECi)
+ {
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ if (!ID)
+ goto _err;
+ /* Read the image part of the header */
+ GET4(ID->type);
+ GET4(ID->format);
+ ID->type_format = (ID->type << 16) + (ID->format);
+ GET4(ID->columns);
+ GET4(ID->rows);
+ GET4(ID->row_stride);
+
+ /* Set all not read data block pointers to NULL */
+ ID->huffman = NULL;
+
+ ID->data = NULL;
+ ID->data_size = 0;
+ }
+
+ if (DEH->identifier == X3F_SECc)
+ {
+ x3f_camf_t *CAMF = &DEH->data_subsection.camf;
+ if (!CAMF)
+ goto _err;
+ /* Read the CAMF part of the header */
+ GET4(CAMF->type);
+ GET4(CAMF->tN.val0);
+ GET4(CAMF->tN.val1);
+ GET4(CAMF->tN.val2);
+ GET4(CAMF->tN.val3);
+
+ /* Set all not read data block pointers to NULL */
+ CAMF->data = NULL;
+ CAMF->data_size = 0;
+
+ /* Set all not allocated help pointers to NULL */
+ CAMF->table.element = NULL;
+ CAMF->table.size = 0;
+ CAMF->tree.nodes = NULL;
+ CAMF->decoded_data = NULL;
+ CAMF->decoded_data_size = 0;
+ CAMF->entry_table.element = NULL;
+ CAMF->entry_table.size = 0;
+ }
+
+ /* Reset the file pointer back to the directory */
+ infile->seek(save_dir_pos, SEEK_SET);
+ }
+
+ return x3f;
+ _err:
+ if (x3f)
+ {
+ DS = &x3f->directory_section;
+ if (DS && DS->directory_entry)
+ free(DS->directory_entry);
+ free(x3f);
+ }
+ return NULL;
+ }
+ catch (...)
+ {
+ x3f_directory_section_t *DS = &x3f->directory_section;
+ if (DS && DS->directory_entry)
+ free(DS->directory_entry);
+ free(x3f);
+ return NULL;
+ }
+}
+
+/* --------------------------------------------------------------------- */
+/* Clean up an x3f structure */
+/* --------------------------------------------------------------------- */
+
+static void free_camf_entry(camf_entry_t *entry)
+{
+ FREE(entry->property_name);
+ FREE(entry->property_value);
+ FREE(entry->matrix_decoded);
+ FREE(entry->matrix_dim_entry);
+}
+
+/* extern */ x3f_return_t x3f_delete(x3f_t *x3f)
+{
+ x3f_directory_section_t *DS;
+ int d;
+
+ if (x3f == NULL)
+ return X3F_ARGUMENT_ERROR;
+
+ DS = &x3f->directory_section;
+ if (DS->num_directory_entries > 50)
+ return X3F_ARGUMENT_ERROR;
+
+ for (d = 0; d < (int)DS->num_directory_entries; d++)
+ {
+ x3f_directory_entry_t *DE = &DS->directory_entry[d];
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ if (DEH->identifier == X3F_SECp)
+ {
+ x3f_property_list_t *PL = &DEH->data_subsection.property_list;
+ FREE(PL->property_table.element);
+ FREE(PL->data);
+ }
+
+ if (DEH->identifier == X3F_SECi)
+ {
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+
+ if (ID)
+ {
+ cleanup_huffman(&ID->huffman);
+ cleanup_true(&ID->tru);
+ cleanup_quattro(&ID->quattro);
+ FREE(ID->data);
+ }
+ }
+
+ if (DEH->identifier == X3F_SECc)
+ {
+ x3f_camf_t *CAMF = &DEH->data_subsection.camf;
+ int i;
+ if (CAMF)
+ {
+ FREE(CAMF->data);
+ FREE(CAMF->table.element);
+ cleanup_huffman_tree(&CAMF->tree);
+ FREE(CAMF->decoded_data);
+ for (i = 0; i < (int)CAMF->entry_table.size; i++)
+ {
+ free_camf_entry(&CAMF->entry_table.element[i]);
+ }
+ }
+ FREE(CAMF->entry_table.element);
+ }
+ }
+
+ FREE(DS->directory_entry);
+ FREE(x3f);
+
+ return X3F_OK;
+}
+
+/* --------------------------------------------------------------------- */
+/* Getting a reference to a directory entry */
+/* --------------------------------------------------------------------- */
+
+/* TODO: all those only get the first instance */
+
+static x3f_directory_entry_t *x3f_get(x3f_t *x3f, uint32_t type,
+ uint32_t image_type)
+{
+ x3f_directory_section_t *DS;
+ int d;
+
+ if (x3f == NULL)
+ return NULL;
+
+ DS = &x3f->directory_section;
+
+ for (d = 0; d < (int)DS->num_directory_entries; d++)
+ {
+ x3f_directory_entry_t *DE = &DS->directory_entry[d];
+ x3f_directory_entry_header_t *DEH = &DE->header;
+
+ if (DEH->identifier == type)
+ {
+ switch (DEH->identifier)
+ {
+ case X3F_SECi:
+ {
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+
+ if (ID->type_format == image_type)
+ return DE;
+ }
+ break;
+ default:
+ return DE;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/* extern */ x3f_directory_entry_t *x3f_get_raw(x3f_t *x3f)
+{
+ x3f_directory_entry_t *DE;
+
+ if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_HUFFMAN_X530)) != NULL)
+ return DE;
+
+ if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_HUFFMAN_10BIT)) != NULL)
+ return DE;
+
+ if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_TRUE)) != NULL)
+ return DE;
+
+ if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_MERRILL)) != NULL)
+ return DE;
+
+ if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_QUATTRO)) != NULL)
+ return DE;
+
+ if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_SDQ)) != NULL)
+ return DE;
+
+ if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_SDQH)) != NULL)
+ return DE;
+ if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_SDQH2)) != NULL)
+ return DE;
+
+ return NULL;
+}
+
+/* extern */ x3f_directory_entry_t *x3f_get_thumb_plain(x3f_t *x3f)
+{
+ return x3f_get(x3f, X3F_SECi, X3F_IMAGE_THUMB_PLAIN);
+}
+
+/* extern */ x3f_directory_entry_t *x3f_get_thumb_huffman(x3f_t *x3f)
+{
+ return x3f_get(x3f, X3F_SECi, X3F_IMAGE_THUMB_HUFFMAN);
+}
+
+/* extern */ x3f_directory_entry_t *x3f_get_thumb_jpeg(x3f_t *x3f)
+{
+ return x3f_get(x3f, X3F_SECi, X3F_IMAGE_THUMB_JPEG);
+}
+
+/* extern */ x3f_directory_entry_t *x3f_get_camf(x3f_t *x3f)
+{
+ return x3f_get(x3f, X3F_SECc, 0);
+}
+
+/* extern */ x3f_directory_entry_t *x3f_get_prop(x3f_t *x3f)
+{
+ return x3f_get(x3f, X3F_SECp, 0);
+}
+
+/* For some obscure reason, the bit numbering is weird. It is
+ generally some kind of "big endian" style - e.g. the bit 7 is the
+ first in a byte and bit 31 first in a 4 byte int. For patterns in
+ the huffman pattern table, bit 27 is the first bit and bit 26 the
+ next one. */
+
+#define PATTERN_BIT_POS(_len, _bit) ((_len) - (_bit)-1)
+#define MEMORY_BIT_POS(_bit) PATTERN_BIT_POS(8, _bit)
+
+/* --------------------------------------------------------------------- */
+/* Huffman Decode */
+/* --------------------------------------------------------------------- */
+
+/* Make the huffman tree */
+
+#ifdef DBG_PRNT
+static char *display_code(int length, uint32_t code, char *buffer)
+{
+ int i;
+
+ for (i = 0; i < length; i++)
+ {
+ int pos = PATTERN_BIT_POS(length, i);
+ buffer[i] = ((code >> pos) & 1) == 0 ? '0' : '1';
+ }
+
+ buffer[i] = 0;
+
+ return buffer;
+}
+#endif
+
+static x3f_huffnode_t *new_node(x3f_hufftree_t *tree)
+{
+ if (tree->free_node_index >= tree->total_node_index)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ x3f_huffnode_t *t = &tree->nodes[tree->free_node_index];
+
+ t->branch[0] = NULL;
+ t->branch[1] = NULL;
+ t->leaf = UNDEFINED_LEAF;
+
+ tree->free_node_index++;
+
+ return t;
+}
+
+static void add_code_to_tree(x3f_hufftree_t *tree, int length, uint32_t code,
+ uint32_t value)
+{
+ int i;
+
+ x3f_huffnode_t *t = tree->nodes;
+
+ for (i = 0; i < length; i++)
+ {
+ int pos = PATTERN_BIT_POS(length, i);
+ int bit = (code >> pos) & 1;
+ x3f_huffnode_t *t_next = t->branch[bit];
+
+ if (t_next == NULL)
+ t_next = t->branch[bit] = new_node(tree);
+
+ t = t_next;
+ }
+
+ t->leaf = value;
+}
+
+static void populate_true_huffman_tree(x3f_hufftree_t *tree,
+ x3f_true_huffman_t *table)
+{
+ int i;
+
+ new_node(tree);
+
+ for (i = 0; i < (int)table->size; i++)
+ {
+ x3f_true_huffman_element_t *element = &table->element[i];
+ uint32_t length = element->code_size;
+
+ if (length != 0)
+ {
+ /* add_code_to_tree wants the code right adjusted */
+ uint32_t code = ((element->code) >> (8 - length)) & 0xff;
+ uint32_t value = i;
+
+ add_code_to_tree(tree, length, code, value);
+
+#ifdef DBG_PRNT
+ {
+ char buffer[100];
+
+ x3f_printf(DEBUG, "H %5d : %5x : %5d : %02x %08x (%08x) (%s)\n", i, i,
+ value, length, code, value,
+ display_code(length, code, buffer));
+ }
+#endif
+ }
+ }
+}
+
+static void populate_huffman_tree(x3f_hufftree_t *tree, x3f_table32_t *table,
+ x3f_table16_t *mapping)
+{
+ int i;
+
+ new_node(tree);
+
+ for (i = 0; i < (int)table->size; i++)
+ {
+ uint32_t element = table->element[i];
+
+ if (element != 0)
+ {
+ uint32_t length = HUF_TREE_GET_LENGTH(element);
+ uint32_t code = HUF_TREE_GET_CODE(element);
+ uint32_t value;
+
+ /* If we have a valid mapping table - then the value from the
+ mapping table shall be used. Otherwise we use the current
+ index in the table as value. */
+ if (table->size == mapping->size)
+ value = mapping->element[i];
+ else
+ value = i;
+
+ add_code_to_tree(tree, length, code, value);
+
+#ifdef DBG_PRNT
+ {
+ char buffer[100];
+
+ x3f_printf(DEBUG, "H %5d : %5x : %5d : %02x %08x (%08x) (%s)\n", i, i,
+ value, length, code, element,
+ display_code(length, code, buffer));
+ }
+#endif
+ }
+ }
+}
+
+#ifdef DBG_PRNT
+static void print_huffman_tree(x3f_huffnode_t *t, int length, uint32_t code)
+{
+ char buf1[100];
+ char buf2[100];
+
+ x3f_printf(DEBUG, "%*s (%s,%s) %s (%s)\n", length,
+ length < 1 ? "-" : (code & 1) ? "1" : "0",
+ t->branch[0] == NULL ? "-" : "0", t->branch[1] == NULL ? "-" : "1",
+ t->leaf == UNDEFINED_LEAF ? "-"
+ : (sprintf(buf1, "%x", t->leaf), buf1),
+ display_code(length, code, buf2));
+
+ code = code << 1;
+ if (t->branch[0])
+ print_huffman_tree(t->branch[0], length + 1, code + 0);
+ if (t->branch[1])
+ print_huffman_tree(t->branch[1], length + 1, code + 1);
+}
+#endif
+
+/* Help machinery for reading bits in a memory */
+
+typedef struct bit_state_s
+{
+ uint8_t *next_address;
+ uint8_t bit_offset;
+ uint8_t bits[8];
+} bit_state_t;
+
+static void set_bit_state(bit_state_t *BS, uint8_t *address)
+{
+ BS->next_address = address;
+ BS->bit_offset = 8;
+}
+
+static uint8_t get_bit(bit_state_t *BS)
+{
+ if (BS->bit_offset == 8)
+ {
+ uint8_t byte = *BS->next_address;
+ int i;
+
+ for (i = 7; i >= 0; i--)
+ {
+ BS->bits[i] = byte & 1;
+ byte = byte >> 1;
+ }
+ BS->next_address++;
+ BS->bit_offset = 0;
+ }
+
+ return BS->bits[BS->bit_offset++];
+}
+
+/* Decode use the TRUE algorithm */
+
+static int32_t get_true_diff(bit_state_t *BS, x3f_hufftree_t *HTP)
+{
+ int32_t diff;
+ x3f_huffnode_t *node = &HTP->nodes[0];
+ uint8_t bits;
+
+ while (node->branch[0] != NULL || node->branch[1] != NULL)
+ {
+ uint8_t bit = get_bit(BS);
+ x3f_huffnode_t *new_node = node->branch[bit];
+
+ node = new_node;
+ if (node == NULL)
+ {
+ /* TODO: Shouldn't this be treated as a fatal error? */
+ return 0;
+ }
+ }
+
+ bits = node->leaf;
+
+ if (bits == 0)
+ diff = 0;
+ else
+ {
+ uint8_t first_bit = get_bit(BS);
+ int i;
+
+ diff = first_bit;
+
+ for (i = 1; i < bits; i++)
+ diff = (diff << 1) + get_bit(BS);
+
+ if (first_bit == 0)
+ diff -= (1 << bits) - 1;
+ }
+
+ return diff;
+}
+
+/* This code (that decodes one of the X3F color planes, really is a
+ decoding of a compression algorithm suited for Bayer CFA data. In
+ Bayer CFA the data is divided into 2x2 squares that represents
+ (R,G1,G2,B) data. Those four positions are (in this compression)
+ treated as one data stream each, where you store the differences to
+ previous data in the stream. The reason for this is, of course,
+ that the date is more often than not near to the next data in a
+ stream that represents the same color. */
+
+/* TODO: write more about the compression */
+
+static void true_decode_one_color(x3f_image_data_t *ID, int color)
+{
+ x3f_true_t *TRU = ID->tru;
+ x3f_quattro_t *Q = ID->quattro;
+ uint32_t seed = TRU->seed[color]; /* TODO : Is this correct ? */
+ int row;
+
+ x3f_hufftree_t *tree = &TRU->tree;
+ bit_state_t BS;
+
+ int32_t row_start_acc[2][2];
+ uint32_t rows = ID->rows;
+ uint32_t cols = ID->columns;
+ x3f_area16_t *area = &TRU->x3rgb16;
+ uint16_t *dst = area->data + color;
+
+ set_bit_state(&BS, TRU->plane_address[color]);
+
+ row_start_acc[0][0] = seed;
+ row_start_acc[0][1] = seed;
+ row_start_acc[1][0] = seed;
+ row_start_acc[1][1] = seed;
+
+ if (ID->type_format == X3F_IMAGE_RAW_QUATTRO ||
+ ID->type_format == X3F_IMAGE_RAW_SDQ ||
+ ID->type_format == X3F_IMAGE_RAW_SDQH ||
+ ID->type_format == X3F_IMAGE_RAW_SDQH2)
+ {
+ rows = Q->plane[color].rows;
+ cols = Q->plane[color].columns;
+
+ if (Q->quattro_layout && color == 2)
+ {
+ area = &Q->top16;
+ dst = area->data;
+ }
+ }
+ else
+ {
+ }
+
+ if (rows != area->rows || cols < area->columns)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ for (row = 0; row < (int)rows; row++)
+ {
+ int col;
+ bool_t odd_row = row & 1;
+ int32_t acc[2];
+
+ for (col = 0; col < (int)cols; col++)
+ {
+ bool_t odd_col = col & 1;
+ int32_t diff = get_true_diff(&BS, tree);
+ int32_t prev = col < 2 ? row_start_acc[odd_row][odd_col] : acc[odd_col];
+ int32_t value = prev + diff;
+
+ acc[odd_col] = value;
+ if (col < 2)
+ row_start_acc[odd_row][odd_col] = value;
+
+ /* Discard additional data at the right for binned Quattro plane 2 */
+ if (col >= (int)area->columns)
+ continue;
+
+ *dst = value;
+ dst += area->channels;
+ }
+ }
+}
+
+static void true_decode(x3f_info_t * /*I*/, x3f_directory_entry_t *DE)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ int color;
+
+ for (color = 0; color < 3; color++)
+ {
+ true_decode_one_color(ID, color);
+ }
+}
+
+/* Decode use the huffman tree */
+
+static int32_t get_huffman_diff(bit_state_t *BS, x3f_hufftree_t *HTP)
+{
+ int32_t diff;
+ x3f_huffnode_t *node = &HTP->nodes[0];
+
+ while (node->branch[0] != NULL || node->branch[1] != NULL)
+ {
+ uint8_t bit = get_bit(BS);
+ x3f_huffnode_t *new_node = node->branch[bit];
+
+ node = new_node;
+ if (node == NULL)
+ {
+ /* TODO: Shouldn't this be treated as a fatal error? */
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ return 0; /* unreachable code */
+ }
+ }
+
+ diff = node->leaf;
+
+ return diff;
+}
+
+static void huffman_decode_row(x3f_info_t * /*I*/, x3f_directory_entry_t *DE,
+ int /*bits*/, int row, int offset, int *minimum)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ x3f_huffman_t *HUF = ID->huffman;
+
+ int16_t c[3] = {(int16_t)offset, (int16_t)offset, (int16_t)offset};
+ int col;
+ bit_state_t BS;
+
+ if (HUF->row_offsets.element[row] > ID->data_size - 1)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ set_bit_state(&BS, (uint8_t *)ID->data + HUF->row_offsets.element[row]);
+
+ for (col = 0; col < (int)ID->columns; col++)
+ {
+ int color;
+
+ for (color = 0; color < 3; color++)
+ {
+ uint16_t c_fix;
+
+ c[color] += get_huffman_diff(&BS, &HUF->tree);
+ if (c[color] < 0)
+ {
+ c_fix = 0;
+ if (c[color] < *minimum)
+ *minimum = c[color];
+ }
+ else
+ {
+ c_fix = c[color];
+ }
+
+ switch (ID->type_format)
+ {
+ case X3F_IMAGE_RAW_HUFFMAN_X530:
+ case X3F_IMAGE_RAW_HUFFMAN_10BIT:
+ HUF->x3rgb16.data[3 * (row * ID->columns + col) + color] =
+ (uint16_t)c_fix;
+ break;
+ case X3F_IMAGE_THUMB_HUFFMAN:
+ HUF->rgb8.data[3 * (row * ID->columns + col) + color] = (uint8_t)c_fix;
+ break;
+ default:
+ /* TODO: Shouldn't this be treated as a fatal error? */
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+ }
+ }
+}
+
+static void huffman_decode(x3f_info_t *I, x3f_directory_entry_t *DE, int bits)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+
+ int row;
+ int minimum = 0;
+ int offset = legacy_offset;
+
+ for (row = 0; row < (int)ID->rows; row++)
+ huffman_decode_row(I, DE, bits, row, offset, &minimum);
+
+ if (auto_legacy_offset && minimum < 0)
+ {
+ offset = -minimum;
+ for (row = 0; row < (int)ID->rows; row++)
+ huffman_decode_row(I, DE, bits, row, offset, &minimum);
+ }
+}
+
+static int32_t get_simple_diff(x3f_huffman_t *HUF, uint16_t index)
+{
+ if (HUF->mapping.size == 0)
+ return index;
+ else
+ return HUF->mapping.element[index];
+}
+
+static void simple_decode_row(x3f_info_t * /*I*/, x3f_directory_entry_t *DE,
+ int bits, int row, int row_stride)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ x3f_huffman_t *HUF = ID->huffman;
+
+ if (row*row_stride > (int)(ID->data_size - (ID->columns*sizeof(uint32_t))))
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ uint32_t *data = (uint32_t *)((unsigned char *)ID->data + row * row_stride);
+
+ uint16_t c[3] = {0, 0, 0};
+ int col;
+
+ uint32_t mask = 0;
+
+ switch (bits)
+ {
+ case 8:
+ mask = 0x0ff;
+ break;
+ case 9:
+ mask = 0x1ff;
+ break;
+ case 10:
+ mask = 0x3ff;
+ break;
+ case 11:
+ mask = 0x7ff;
+ break;
+ case 12:
+ mask = 0xfff;
+ break;
+ default:
+ mask = 0;
+ /* TODO: Shouldn't this be treated as a fatal error? */
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ break;
+ }
+
+ for (col = 0; col < (int)ID->columns; col++)
+ {
+ int color;
+ uint32_t val = data[col];
+
+ for (color = 0; color < 3; color++)
+ {
+ uint16_t c_fix;
+ c[color] += get_simple_diff(HUF, (val >> (color * bits)) & mask);
+
+ switch (ID->type_format)
+ {
+ case X3F_IMAGE_RAW_HUFFMAN_X530:
+ case X3F_IMAGE_RAW_HUFFMAN_10BIT:
+ c_fix = (int16_t)c[color] > 0 ? c[color] : 0;
+
+ HUF->x3rgb16.data[3 * (row * ID->columns + col) + color] = c_fix;
+ break;
+ case X3F_IMAGE_THUMB_HUFFMAN:
+ c_fix = (int8_t)c[color] > 0 ? c[color] : 0;
+
+ HUF->rgb8.data[3 * (row * ID->columns + col) + color] = c_fix;
+ break;
+ default:
+ /* TODO: Shouldn't this be treated as a fatal error? */
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+ }
+ }
+}
+
+static void simple_decode(x3f_info_t *I, x3f_directory_entry_t *DE, int bits,
+ int row_stride)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+
+ int row;
+
+ for (row = 0; row < (int)ID->rows; row++)
+ simple_decode_row(I, DE, bits, row, row_stride);
+}
+
+/* --------------------------------------------------------------------- */
+/* Loading the data in a directory entry */
+/* --------------------------------------------------------------------- */
+
+/* First you set the offset to where to start reading the data ... */
+
+static void read_data_set_offset(x3f_info_t *I, x3f_directory_entry_t *DE,
+ uint32_t header_size)
+{
+ uint32_t i_off = DE->input.offset + header_size;
+
+ I->input.file->seek(i_off, SEEK_SET);
+}
+
+/* ... then you read the data, block for block */
+
+static uint32_t read_data_block(void **data, x3f_info_t *I,
+ x3f_directory_entry_t *DE, uint32_t footer)
+{
+ INT64 fpos = I->input.file->tell();
+ uint32_t size = DE->input.size + DE->input.offset - fpos - footer;
+
+ if (fpos + size > I->input.file->size())
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ *data = (void *)malloc(size);
+
+ GETN(*data, size);
+
+ return size;
+}
+
+static uint32_t data_block_size(void ** /*data*/, x3f_info_t *I,
+ x3f_directory_entry_t *DE, uint32_t footer)
+{
+ uint32_t size =
+ DE->input.size + DE->input.offset - I->input.file->tell() - footer;
+ return size;
+}
+
+static void x3f_load_image_verbatim(x3f_info_t *I, x3f_directory_entry_t *DE)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ if (!ID->data_size)
+ ID->data_size = read_data_block(&ID->data, I, DE, 0);
+}
+
+static int32_t x3f_load_image_verbatim_size(x3f_info_t *I,
+ x3f_directory_entry_t *DE)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ return data_block_size(&ID->data, I, DE, 0);
+}
+
+static void x3f_load_property_list(x3f_info_t *I, x3f_directory_entry_t *DE)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_property_list_t *PL = &DEH->data_subsection.property_list;
+ int i;
+
+ read_data_set_offset(I, DE, X3F_PROPERTY_LIST_HEADER_SIZE);
+
+ GET_PROPERTY_TABLE(PL->property_table, PL->num_properties);
+
+ if (!PL->data_size)
+ PL->data_size = read_data_block(&PL->data, I, DE, 0);
+ uint32_t maxoffset = PL->data_size / sizeof(utf16_t) -
+ 2; // at least 2 chars, value + terminating 0x0000
+
+ for (i = 0; i < (int)PL->num_properties; i++)
+ {
+ x3f_property_t *P = &PL->property_table.element[i];
+ if (P->name_offset > maxoffset || P->value_offset > maxoffset)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ P->name = ((utf16_t *)PL->data + P->name_offset);
+ P->value = ((utf16_t *)PL->data + P->value_offset);
+ }
+}
+
+static void x3f_load_true(x3f_info_t *I, x3f_directory_entry_t *DE)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ x3f_true_t *TRU = new_true(&ID->tru);
+ x3f_quattro_t *Q = NULL;
+ int i;
+
+ if (ID->type_format == X3F_IMAGE_RAW_QUATTRO ||
+ ID->type_format == X3F_IMAGE_RAW_SDQ ||
+ ID->type_format == X3F_IMAGE_RAW_SDQH ||
+ ID->type_format == X3F_IMAGE_RAW_SDQH2)
+ {
+ Q = new_quattro(&ID->quattro);
+
+ for (i = 0; i < TRUE_PLANES; i++)
+ {
+ GET2(Q->plane[i].columns);
+ GET2(Q->plane[i].rows);
+ }
+
+ if (Q->plane[0].rows == ID->rows / 2)
+ {
+ Q->quattro_layout = 1;
+ }
+ else if (Q->plane[0].rows == ID->rows)
+ {
+ Q->quattro_layout = 0;
+ }
+ else
+ {
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+ }
+
+ /* Read TRUE header data */
+ GET2(TRU->seed[0]);
+ GET2(TRU->seed[1]);
+ GET2(TRU->seed[2]);
+ GET2(TRU->unknown);
+ GET_TRUE_HUFF_TABLE(TRU->table);
+
+ if (ID->type_format == X3F_IMAGE_RAW_QUATTRO ||
+ ID->type_format == X3F_IMAGE_RAW_SDQ ||
+ ID->type_format == X3F_IMAGE_RAW_SDQH ||
+ ID->type_format == X3F_IMAGE_RAW_SDQH2)
+ {
+ GET4(Q->unknown);
+ }
+
+ GET_TABLE(TRU->plane_size, GET4, TRUE_PLANES, uint32_t);
+
+ /* Read image data */
+ if (!ID->data_size)
+ ID->data_size = read_data_block(&ID->data, I, DE, 0);
+
+ /* TODO: can it be fewer than 8 bits? Maybe taken from TRU->table? */
+ new_huffman_tree(&TRU->tree, 8);
+
+ populate_true_huffman_tree(&TRU->tree, &TRU->table);
+
+#ifdef DBG_PRNT
+ print_huffman_tree(TRU->tree.nodes, 0, 0);
+#endif
+
+ TRU->plane_address[0] = (uint8_t *)ID->data;
+ for (i = 1; i < TRUE_PLANES; i++)
+ TRU->plane_address[i] = TRU->plane_address[i - 1] +
+ (((TRU->plane_size.element[i - 1] + 15) / 16) * 16);
+
+ if ((ID->type_format == X3F_IMAGE_RAW_QUATTRO ||
+ ID->type_format == X3F_IMAGE_RAW_SDQ ||
+ ID->type_format == X3F_IMAGE_RAW_SDQH ||
+ ID->type_format == X3F_IMAGE_RAW_SDQH2) &&
+ Q->quattro_layout)
+ {
+ uint32_t columns = Q->plane[0].columns;
+ uint32_t rows = Q->plane[0].rows;
+ uint32_t channels = 3;
+ uint32_t size = columns * rows * channels;
+
+ TRU->x3rgb16.columns = columns;
+ TRU->x3rgb16.rows = rows;
+ TRU->x3rgb16.channels = channels;
+ TRU->x3rgb16.row_stride = columns * channels;
+ TRU->x3rgb16.buf = malloc(sizeof(uint16_t) * size);
+ TRU->x3rgb16.data = (uint16_t *)TRU->x3rgb16.buf;
+
+ columns = Q->plane[2].columns;
+ rows = Q->plane[2].rows;
+ channels = 1;
+ size = columns * rows * channels;
+
+ Q->top16.columns = columns;
+ Q->top16.rows = rows;
+ Q->top16.channels = channels;
+ Q->top16.row_stride = columns * channels;
+ Q->top16.buf = malloc(sizeof(uint16_t) * size);
+ Q->top16.data = (uint16_t *)Q->top16.buf;
+ }
+ else
+ {
+ uint32_t size = ID->columns * ID->rows * 3;
+
+ TRU->x3rgb16.columns = ID->columns;
+ TRU->x3rgb16.rows = ID->rows;
+ TRU->x3rgb16.channels = 3;
+ TRU->x3rgb16.row_stride = ID->columns * 3;
+ TRU->x3rgb16.buf = malloc(sizeof(uint16_t) * size);
+ TRU->x3rgb16.data = (uint16_t *)TRU->x3rgb16.buf;
+ }
+
+ true_decode(I, DE);
+}
+
+static void x3f_load_huffman_compressed(x3f_info_t *I,
+ x3f_directory_entry_t *DE, int bits,
+ int /*use_map_table*/)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ x3f_huffman_t *HUF = ID->huffman;
+ int table_size = 1 << bits;
+ int row_offsets_size = ID->rows * sizeof(HUF->row_offsets.element[0]);
+
+ GET_TABLE(HUF->table, GET4, table_size, uint32_t);
+
+ if (!ID->data_size)
+ ID->data_size = read_data_block(&ID->data, I, DE, row_offsets_size);
+
+ GET_TABLE(HUF->row_offsets, GET4, ID->rows, uint32_t);
+
+ new_huffman_tree(&HUF->tree, bits);
+ populate_huffman_tree(&HUF->tree, &HUF->table, &HUF->mapping);
+
+ huffman_decode(I, DE, bits);
+}
+
+static void x3f_load_huffman_not_compressed(x3f_info_t *I,
+ x3f_directory_entry_t *DE, int bits,
+ int /*use_map_table*/, int row_stride)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+
+ if (!ID->data_size)
+ ID->data_size = read_data_block(&ID->data, I, DE, 0);
+
+ simple_decode(I, DE, bits, row_stride);
+}
+
+static void x3f_load_huffman(x3f_info_t *I, x3f_directory_entry_t *DE, int bits,
+ int use_map_table, int row_stride)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+ x3f_huffman_t *HUF = new_huffman(&ID->huffman);
+ uint32_t size;
+
+ if (use_map_table)
+ {
+ int table_size = 1 << bits;
+
+ GET_TABLE(HUF->mapping, GET2, table_size, uint16_t);
+ }
+
+ switch (ID->type_format)
+ {
+ case X3F_IMAGE_RAW_HUFFMAN_X530:
+ case X3F_IMAGE_RAW_HUFFMAN_10BIT:
+ size = ID->columns * ID->rows * 3;
+ HUF->x3rgb16.columns = ID->columns;
+ HUF->x3rgb16.rows = ID->rows;
+ HUF->x3rgb16.channels = 3;
+ HUF->x3rgb16.row_stride = ID->columns * 3;
+ HUF->x3rgb16.buf = malloc(sizeof(uint16_t) * size);
+ HUF->x3rgb16.data = (uint16_t *)HUF->x3rgb16.buf;
+ break;
+ case X3F_IMAGE_THUMB_HUFFMAN:
+ size = ID->columns * ID->rows * 3;
+ HUF->rgb8.columns = ID->columns;
+ HUF->rgb8.rows = ID->rows;
+ HUF->rgb8.channels = 3;
+ HUF->rgb8.row_stride = ID->columns * 3;
+ HUF->rgb8.buf = malloc(sizeof(uint8_t) * size);
+ HUF->rgb8.data = (uint8_t *)HUF->rgb8.buf;
+ break;
+ default:
+ /* TODO: Shouldn't this be treated as a fatal error? */
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+
+ if (row_stride == 0)
+ return x3f_load_huffman_compressed(I, DE, bits, use_map_table);
+ else
+ return x3f_load_huffman_not_compressed(I, DE, bits, use_map_table,
+ row_stride);
+}
+
+static void x3f_load_pixmap(x3f_info_t *I, x3f_directory_entry_t *DE)
+{
+ x3f_load_image_verbatim(I, DE);
+}
+
+static uint32_t x3f_load_pixmap_size(x3f_info_t *I, x3f_directory_entry_t *DE)
+{
+ return x3f_load_image_verbatim_size(I, DE);
+}
+
+static void x3f_load_jpeg(x3f_info_t *I, x3f_directory_entry_t *DE)
+{
+ x3f_load_image_verbatim(I, DE);
+}
+
+static uint32_t x3f_load_jpeg_size(x3f_info_t *I, x3f_directory_entry_t *DE)
+{
+ return x3f_load_image_verbatim_size(I, DE);
+}
+
+static void x3f_load_image(x3f_info_t *I, x3f_directory_entry_t *DE)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+
+ if (ID->rows > 65535 || ID->columns > 65535)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ read_data_set_offset(I, DE, X3F_IMAGE_HEADER_SIZE);
+
+ switch (ID->type_format)
+ {
+ case X3F_IMAGE_RAW_TRUE:
+ case X3F_IMAGE_RAW_MERRILL:
+ case X3F_IMAGE_RAW_QUATTRO:
+ case X3F_IMAGE_RAW_SDQ:
+ case X3F_IMAGE_RAW_SDQH:
+ case X3F_IMAGE_RAW_SDQH2:
+ x3f_load_true(I, DE);
+ break;
+ case X3F_IMAGE_RAW_HUFFMAN_X530:
+ case X3F_IMAGE_RAW_HUFFMAN_10BIT:
+ x3f_load_huffman(I, DE, 10, 1, ID->row_stride);
+ break;
+ case X3F_IMAGE_THUMB_PLAIN:
+ x3f_load_pixmap(I, DE);
+ break;
+ case X3F_IMAGE_THUMB_HUFFMAN:
+ x3f_load_huffman(I, DE, 8, 0, ID->row_stride);
+ break;
+ case X3F_IMAGE_THUMB_JPEG:
+ x3f_load_jpeg(I, DE);
+ break;
+ default:
+ /* TODO: Shouldn't this be treated as a fatal error? */
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+}
+
+// Used only for thumbnail size estimation
+static uint32_t x3f_load_image_size(x3f_info_t *I, x3f_directory_entry_t *DE)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_image_data_t *ID = &DEH->data_subsection.image_data;
+
+ read_data_set_offset(I, DE, X3F_IMAGE_HEADER_SIZE);
+
+ switch (ID->type_format)
+ {
+ case X3F_IMAGE_THUMB_PLAIN:
+ return x3f_load_pixmap_size(I, DE);
+ case X3F_IMAGE_THUMB_JPEG:
+ return x3f_load_jpeg_size(I, DE);
+ break;
+ default:
+ return 0;
+ }
+}
+
+static void x3f_load_camf_decode_type2(x3f_camf_t *CAMF)
+{
+ uint32_t key = CAMF->t2.crypt_key;
+ int i;
+
+ CAMF->decoded_data_size = CAMF->data_size;
+ CAMF->decoded_data = malloc(CAMF->decoded_data_size);
+
+ for (i = 0; i < (int)CAMF->data_size; i++)
+ {
+ uint8_t old, _new;
+ uint32_t tmp;
+
+ old = ((uint8_t *)CAMF->data)[i];
+ key = (key * 1597 + 51749) % 244944;
+ tmp = (uint32_t)(key * ((int64_t)301593171) >> 24);
+ _new = (uint8_t)(old ^ (uint8_t)(((((key << 8) - tmp) >> 1) + tmp) >> 17));
+ ((uint8_t *)CAMF->decoded_data)[i] = _new;
+ }
+}
+
+/* NOTE: the unpacking in this code is in big respects identical to
+ true_decode_one_color(). The difference is in the output you
+ build. It might be possible to make some parts shared. NOTE ALSO:
+ This means that the meta data is obfuscated using an image
+ compression algorithm. */
+
+static void camf_decode_type4(x3f_camf_t *CAMF)
+{
+ uint32_t seed = CAMF->t4.decode_bias;
+ int row;
+
+ uint8_t *dst;
+ uint32_t dst_size = CAMF->t4.decoded_data_size;
+ uint8_t *dst_end;
+
+ bool_t odd_dst = 0;
+
+ x3f_hufftree_t *tree = &CAMF->tree;
+ bit_state_t BS;
+
+ int32_t row_start_acc[2][2];
+ uint32_t rows = CAMF->t4.block_count;
+ uint32_t cols = CAMF->t4.block_size;
+
+ CAMF->decoded_data_size = dst_size;
+
+ CAMF->decoded_data = malloc(CAMF->decoded_data_size);
+ memset(CAMF->decoded_data, 0, CAMF->decoded_data_size);
+
+ dst = (uint8_t *)CAMF->decoded_data;
+ dst_end = dst + dst_size;
+
+ set_bit_state(&BS, CAMF->decoding_start);
+
+ row_start_acc[0][0] = seed;
+ row_start_acc[0][1] = seed;
+ row_start_acc[1][0] = seed;
+ row_start_acc[1][1] = seed;
+
+ for (row = 0; row < (int)rows; row++)
+ {
+ int col;
+ bool_t odd_row = row & 1;
+ int32_t acc[2];
+
+ /* We loop through all the columns and the rows. But the actual
+ data is smaller than that, so we break the loop when reaching
+ the end. */
+ for (col = 0; col < (int)cols; col++)
+ {
+ bool_t odd_col = col & 1;
+ int32_t diff = get_true_diff(&BS, tree);
+ int32_t prev = col < 2 ? row_start_acc[odd_row][odd_col] : acc[odd_col];
+ int32_t value = prev + diff;
+
+ acc[odd_col] = value;
+ if (col < 2)
+ row_start_acc[odd_row][odd_col] = value;
+
+ switch (odd_dst)
+ {
+ case 0:
+ *dst++ = (uint8_t)((value >> 4) & 0xff);
+
+ if (dst >= dst_end)
+ {
+ goto ready;
+ }
+
+ *dst = (uint8_t)((value << 4) & 0xf0);
+ break;
+ case 1:
+ *dst++ |= (uint8_t)((value >> 8) & 0x0f);
+
+ if (dst >= dst_end)
+ {
+ goto ready;
+ }
+
+ *dst++ = (uint8_t)((value << 0) & 0xff);
+
+ if (dst >= dst_end)
+ {
+ goto ready;
+ }
+
+ break;
+ }
+
+ odd_dst = !odd_dst;
+ } /* end col */
+ } /* end row */
+
+ready:;
+}
+
+static void x3f_load_camf_decode_type4(x3f_camf_t *CAMF)
+{
+ int i;
+ uint8_t *p;
+ x3f_true_huffman_element_t *element = NULL;
+
+ for (i = 0, p = (uint8_t *)CAMF->data; *p != 0; i++)
+ {
+ /* TODO: Is this too expensive ??*/
+ element = (x3f_true_huffman_element_t *)realloc(element,
+ (i + 1) * sizeof(*element));
+
+ element[i].code_size = *p++;
+ element[i].code = *p++;
+ }
+
+ CAMF->table.size = i;
+ CAMF->table.element = element;
+
+ /* TODO: where does the values 28 and 32 come from? */
+#define CAMF_T4_DATA_SIZE_OFFSET 28
+#define CAMF_T4_DATA_OFFSET 32
+ CAMF->decoding_size =
+ *(uint32_t *)((unsigned char *)CAMF->data + CAMF_T4_DATA_SIZE_OFFSET);
+ CAMF->decoding_start = (uint8_t *)CAMF->data + CAMF_T4_DATA_OFFSET;
+
+ /* TODO: can it be fewer than 8 bits? Maybe taken from TRU->table? */
+ new_huffman_tree(&CAMF->tree, 8);
+
+ populate_true_huffman_tree(&CAMF->tree, &CAMF->table);
+
+#ifdef DBG_PRNT
+ print_huffman_tree(CAMF->tree.nodes, 0, 0);
+#endif
+
+ camf_decode_type4(CAMF);
+}
+
+static void camf_decode_type5(x3f_camf_t *CAMF)
+{
+ int32_t acc = CAMF->t5.decode_bias;
+
+ uint8_t *dst;
+
+ x3f_hufftree_t *tree = &CAMF->tree;
+ bit_state_t BS;
+
+ int32_t i;
+
+ CAMF->decoded_data_size = CAMF->t5.decoded_data_size;
+ CAMF->decoded_data = malloc(CAMF->decoded_data_size);
+
+ dst = (uint8_t *)CAMF->decoded_data;
+
+ set_bit_state(&BS, CAMF->decoding_start);
+
+ for (i = 0; i < (int)CAMF->decoded_data_size; i++)
+ {
+ int32_t diff = get_true_diff(&BS, tree);
+
+ acc = acc + diff;
+ *dst++ = (uint8_t)(acc & 0xff);
+ }
+}
+
+static void x3f_load_camf_decode_type5(x3f_camf_t *CAMF)
+{
+ int i;
+ uint8_t *p;
+ x3f_true_huffman_element_t *element = NULL;
+
+ for (i = 0, p = (uint8_t *)CAMF->data; *p != 0; i++)
+ {
+ /* TODO: Is this too expensive ??*/
+ element = (x3f_true_huffman_element_t *)realloc(element,
+ (i + 1) * sizeof(*element));
+
+ element[i].code_size = *p++;
+ element[i].code = *p++;
+ }
+
+ CAMF->table.size = i;
+ CAMF->table.element = element;
+
+ /* TODO: where does the values 28 and 32 come from? */
+#define CAMF_T5_DATA_SIZE_OFFSET 28
+#define CAMF_T5_DATA_OFFSET 32
+ CAMF->decoding_size =
+ *(uint32_t *)((uint8_t *)CAMF->data + CAMF_T5_DATA_SIZE_OFFSET);
+ CAMF->decoding_start = (uint8_t *)CAMF->data + CAMF_T5_DATA_OFFSET;
+
+ /* TODO: can it be fewer than 8 bits? Maybe taken from TRU->table? */
+ new_huffman_tree(&CAMF->tree, 8);
+
+ populate_true_huffman_tree(&CAMF->tree, &CAMF->table);
+
+#ifdef DBG_PRNT
+ print_huffman_tree(CAMF->tree.nodes, 0, 0);
+#endif
+
+ camf_decode_type5(CAMF);
+}
+
+static void x3f_setup_camf_text_entry(camf_entry_t *entry)
+{
+ entry->text_size = *(uint32_t *)entry->value_address;
+ entry->text = (char *)entry->value_address + 4;
+}
+
+static void x3f_setup_camf_property_entry(camf_entry_t *entry)
+{
+ int i;
+ uint8_t *e = (uint8_t *)entry->entry;
+ uint8_t *v = (uint8_t *)entry->value_address;
+ uint32_t num = entry->property_num = *(uint32_t *)v;
+ uint32_t off = *(uint32_t *)(v + 4);
+
+ entry->property_name = (char **)malloc(num * sizeof(uint8_t *));
+ entry->property_value = (uint8_t **)malloc(num * sizeof(uint8_t *));
+
+ for (i = 0; i < (int)num; i++)
+ {
+ uint32_t name_off = off + *(uint32_t *)(v + 8 + 8 * i);
+ uint32_t value_off = off + *(uint32_t *)(v + 8 + 8 * i + 4);
+
+ entry->property_name[i] = (char *)(e + name_off);
+ entry->property_value[i] = e + value_off;
+ }
+}
+
+static void set_matrix_element_info(uint32_t type, uint32_t *size,
+ matrix_type_t *decoded_type)
+{
+ switch (type)
+ {
+ case 0:
+ *size = 2;
+ *decoded_type = M_INT; /* known to be true */
+ break;
+ case 1:
+ *size = 4;
+ *decoded_type = M_UINT; /* TODO: unknown ???? */
+ break;
+ case 2:
+ *size = 4;
+ *decoded_type = M_UINT; /* TODO: unknown ???? */
+ break;
+ case 3:
+ *size = 4;
+ *decoded_type = M_FLOAT; /* known to be true */
+ break;
+ case 5:
+ *size = 1;
+ *decoded_type = M_UINT; /* TODO: unknown ???? */
+ break;
+ case 6:
+ *size = 2;
+ *decoded_type = M_UINT; /* TODO: unknown ???? */
+ break;
+ default:
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+}
+
+static void get_matrix_copy(camf_entry_t *entry)
+{
+ uint32_t element_size = entry->matrix_element_size;
+ uint32_t elements = entry->matrix_elements;
+ int i, size = (entry->matrix_decoded_type == M_FLOAT ? sizeof(double)
+ : sizeof(uint32_t)) *
+ elements;
+
+ entry->matrix_decoded = malloc(size);
+
+ switch (element_size)
+ {
+ case 4:
+ switch (entry->matrix_decoded_type)
+ {
+ case M_INT:
+ case M_UINT:
+ memcpy(entry->matrix_decoded, entry->matrix_data, size);
+ break;
+ case M_FLOAT:
+ for (i = 0; i < (int)elements; i++)
+ ((double *)entry->matrix_decoded)[i] =
+ (double)((float *)entry->matrix_data)[i];
+ break;
+ default:
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+ break;
+ case 2:
+ switch (entry->matrix_decoded_type)
+ {
+ case M_INT:
+ for (i = 0; i < (int)elements; i++)
+ ((int32_t *)entry->matrix_decoded)[i] =
+ (int32_t)((int16_t *)entry->matrix_data)[i];
+ break;
+ case M_UINT:
+ for (i = 0; i < (int)elements; i++)
+ ((uint32_t *)entry->matrix_decoded)[i] =
+ (uint32_t)((uint16_t *)entry->matrix_data)[i];
+ break;
+ default:
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+ break;
+ case 1:
+ switch (entry->matrix_decoded_type)
+ {
+ case M_INT:
+ for (i = 0; i < (int)elements; i++)
+ ((int32_t *)entry->matrix_decoded)[i] =
+ (int32_t)((int8_t *)entry->matrix_data)[i];
+ break;
+ case M_UINT:
+ for (i = 0; i < (int)elements; i++)
+ ((uint32_t *)entry->matrix_decoded)[i] =
+ (uint32_t)((uint8_t *)entry->matrix_data)[i];
+ break;
+ default:
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+ break;
+ default:
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+}
+
+static void x3f_setup_camf_matrix_entry(camf_entry_t *entry)
+{
+ int i;
+ int totalsize = 1;
+
+ uint8_t *e = (uint8_t *)entry->entry;
+ uint8_t *v = (uint8_t *)entry->value_address;
+ uint32_t type = entry->matrix_type = *(uint32_t *)(v + 0);
+ uint32_t dim = entry->matrix_dim = *(uint32_t *)(v + 4);
+ uint32_t off = entry->matrix_data_off = *(uint32_t *)(v + 8);
+ camf_dim_entry_t *dentry = entry->matrix_dim_entry =
+ (camf_dim_entry_t *)malloc(dim * sizeof(camf_dim_entry_t));
+
+ for (i = 0; i < (int)dim; i++)
+ {
+ uint32_t size = dentry[i].size = *(uint32_t *)(v + 12 + 12 * i + 0);
+ dentry[i].name_offset = *(uint32_t *)(v + 12 + 12 * i + 4);
+ dentry[i].n = *(uint32_t *)(v + 12 + 12 * i + 8);
+ dentry[i].name = (char *)(e + dentry[i].name_offset);
+
+ if ((int)dentry[i].n != i)
+ {
+ }
+
+ totalsize *= size;
+ }
+
+ set_matrix_element_info(type, &entry->matrix_element_size,
+ &entry->matrix_decoded_type);
+ entry->matrix_data = (void *)(e + off);
+
+ entry->matrix_elements = totalsize;
+ entry->matrix_used_space = entry->entry_size - off;
+
+ /* This estimate only works for matrices above a certain size */
+ entry->matrix_estimated_element_size = entry->matrix_used_space / totalsize;
+
+ get_matrix_copy(entry);
+}
+
+static void x3f_setup_camf_entries(x3f_camf_t *CAMF)
+{
+ uint8_t *p = (uint8_t *)CAMF->decoded_data;
+ uint8_t *end = p + CAMF->decoded_data_size;
+ camf_entry_t *entry = NULL;
+ int i;
+
+ for (i = 0; p < end; i++)
+ {
+ uint32_t *p4 = (uint32_t *)p;
+
+ switch (*p4)
+ {
+ case X3F_CMbP:
+ case X3F_CMbT:
+ case X3F_CMbM:
+ break;
+ default:
+ goto stop;
+ }
+
+ /* TODO: lots of realloc - may be inefficient */
+ entry = (camf_entry_t *)realloc(entry, (i + 1) * sizeof(camf_entry_t));
+
+ /* Pointer */
+ entry[i].entry = p;
+
+ /* Header */
+ entry[i].id = *p4++;
+ entry[i].version = *p4++;
+ entry[i].entry_size = *p4++;
+ entry[i].name_offset = *p4++;
+ entry[i].value_offset = *p4++;
+
+ /* Compute addresses and sizes */
+ entry[i].name_address = (char *)(p + entry[i].name_offset);
+ entry[i].value_address = p + entry[i].value_offset;
+ entry[i].name_size = entry[i].value_offset - entry[i].name_offset;
+ entry[i].value_size = entry[i].entry_size - entry[i].value_offset;
+
+ entry[i].text_size = 0;
+ entry[i].text = NULL;
+ entry[i].property_num = 0;
+ entry[i].property_name = NULL;
+ entry[i].property_value = NULL;
+ entry[i].matrix_type = 0;
+ entry[i].matrix_dim = 0;
+ entry[i].matrix_data_off = 0;
+ entry[i].matrix_data = NULL;
+ entry[i].matrix_dim_entry = NULL;
+
+ entry[i].matrix_decoded = NULL;
+
+ switch (entry[i].id)
+ {
+ case X3F_CMbP:
+ x3f_setup_camf_property_entry(&entry[i]);
+ break;
+ case X3F_CMbT:
+ x3f_setup_camf_text_entry(&entry[i]);
+ break;
+ case X3F_CMbM:
+ x3f_setup_camf_matrix_entry(&entry[i]);
+ break;
+ }
+
+ p += entry[i].entry_size;
+ }
+
+stop:
+
+ CAMF->entry_table.size = i;
+ CAMF->entry_table.element = entry;
+}
+
+static void x3f_load_camf(x3f_info_t *I, x3f_directory_entry_t *DE)
+{
+ x3f_directory_entry_header_t *DEH = &DE->header;
+ x3f_camf_t *CAMF = &DEH->data_subsection.camf;
+
+ read_data_set_offset(I, DE, X3F_CAMF_HEADER_SIZE);
+
+ if (!CAMF->data_size)
+ CAMF->data_size = read_data_block(&CAMF->data, I, DE, 0);
+
+ switch (CAMF->type)
+ {
+ case 2: /* Older SD9-SD14 */
+ x3f_load_camf_decode_type2(CAMF);
+ break;
+ case 4: /* TRUE ... Merrill */
+ x3f_load_camf_decode_type4(CAMF);
+ break;
+ case 5: /* Quattro ... */
+ x3f_load_camf_decode_type5(CAMF);
+ break;
+ default:
+ /* TODO: Shouldn't this be treated as a fatal error? */
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+
+ if (CAMF->decoded_data != NULL)
+ x3f_setup_camf_entries(CAMF);
+ else
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+}
+
+/* extern */ x3f_return_t x3f_load_data(x3f_t *x3f, x3f_directory_entry_t *DE)
+{
+ x3f_info_t *I = &x3f->info;
+
+ if (DE == NULL)
+ return X3F_ARGUMENT_ERROR;
+
+ switch (DE->header.identifier)
+ {
+ case X3F_SECp:
+ x3f_load_property_list(I, DE);
+ break;
+ case X3F_SECi:
+ x3f_load_image(I, DE);
+ break;
+ case X3F_SECc:
+ x3f_load_camf(I, DE);
+ break;
+ default:
+ return X3F_INTERNAL_ERROR;
+ }
+ return X3F_OK;
+}
+
+/* extern */ int64_t x3f_load_data_size(x3f_t *x3f, x3f_directory_entry_t *DE)
+{
+ x3f_info_t *I = &x3f->info;
+
+ if (DE == NULL)
+ return -1;
+
+ switch (DE->header.identifier)
+ {
+ case X3F_SECi:
+ return x3f_load_image_size(I, DE);
+ default:
+ return 0;
+ }
+}
+
+/* extern */ x3f_return_t x3f_load_image_block(x3f_t *x3f,
+ x3f_directory_entry_t *DE)
+{
+ x3f_info_t *I = &x3f->info;
+
+ if (DE == NULL)
+ return X3F_ARGUMENT_ERROR;
+
+ switch (DE->header.identifier)
+ {
+ case X3F_SECi:
+ read_data_set_offset(I, DE, X3F_IMAGE_HEADER_SIZE);
+ x3f_load_image_verbatim(I, DE);
+ break;
+ default:
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ return X3F_INTERNAL_ERROR; /* unreachable code*/
+ }
+
+ return X3F_OK;
+}
+
+/* --------------------------------------------------------------------- */
+/* The End */
+/* --------------------------------------------------------------------- */
+
+#endif
diff --git a/libkdcraw/test/CMakeLists.txt b/libkdcraw/test/CMakeLists.txt
index 2e4a718..624137d 100644
--- a/libkdcraw/test/CMakeLists.txt
+++ b/libkdcraw/test/CMakeLists.txt
@@ -22,13 +22,7 @@ tde_add_executable( raw2png AUTOMOC
kdcraw-shared
)
-tde_add_executable( identify AUTOMOC
- SOURCES
- ../libraw/samples/identify.cpp
- LINK
- raw-static
-)
tde_add_executable( simple_dcraw AUTOMOC