Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
head 1.418;
access;
symbols;
locks; strict;
comment @ * @;
1.418
date 2009.02.03.04.42.52; author dcoffin; state Exp;
branches;
next 1.417;
1.417
date 2009.01.21.01.19.45; author dcoffin; state Exp;
branches;
next 1.416;
1.416
date 2009.01.15.22.10.18; author dcoffin; state Exp;
branches;
next 1.415;
1.415
date 2009.01.14.17.46.50; author dcoffin; state Exp;
branches;
next 1.414;
1.414
date 2009.01.14.03.23.23; author dcoffin; state Exp;
branches;
next 1.413;
1.413
date 2009.01.10.23.37.51; author dcoffin; state Exp;
branches;
next 1.412;
1.412
date 2009.01.08.19.39.07; author dcoffin; state Exp;
branches;
next 1.411;
1.411
date 2009.01.04.20.19.22; author dcoffin; state Exp;
branches;
next 1.410;
1.410
date 2009.01.01.09.10.46; author dcoffin; state Exp;
branches;
next 1.409;
1.409
date 2008.12.11.06.56.09; author dcoffin; state Exp;
branches;
next 1.408;
1.408
date 2008.12.06.23.35.55; author dcoffin; state Exp;
branches;
next 1.407;
1.407
date 2008.12.02.01.50.56; author dcoffin; state Exp;
branches;
next 1.406;
1.406
date 2008.11.26.08.39.39; author dcoffin; state Exp;
branches;
next 1.405;
1.405
date 2008.09.15.22.29.19; author dcoffin; state Exp;
branches;
next 1.404;
1.404
date 2008.08.12.19.39.17; author dcoffin; state Exp;
branches;
next 1.403;
1.403
date 2008.04.29.18.18.53; author dcoffin; state Exp;
branches;
next 1.402;
1.402
date 2008.04.20.08.09.37; author dcoffin; state Exp;
branches;
next 1.401;
1.401
date 2008.04.07.19.25.08; author dcoffin; state Exp;
branches;
next 1.400;
1.400
date 2008.04.06.01.18.43; author dcoffin; state Exp;
branches;
next 1.399;
1.399
date 2008.03.05.01.29.34; author dcoffin; state Exp;
branches;
next 1.398;
1.398
date 2008.02.06.21.29.13; author dcoffin; state Exp;
branches;
next 1.397;
1.397
date 2007.12.10.07.43.31; author dcoffin; state Exp;
branches;
next 1.396;
1.396
date 2007.11.16.15.24.52; author dcoffin; state Exp;
branches;
next 1.395;
1.395
date 2007.11.12.20.28.32; author dcoffin; state Exp;
branches;
next 1.394;
1.394
date 2007.11.04.02.18.54; author dcoffin; state Exp;
branches;
next 1.393;
1.393
date 2007.10.30.06.23.29; author dcoffin; state Exp;
branches;
next 1.392;
1.392
date 2007.08.10.21.09.34; author dcoffin; state Exp;
branches;
next 1.391;
1.391
date 2007.08.08.21.28.17; author dcoffin; state Exp;
branches;
next 1.390;
1.390
date 2007.08.01.17.39.28; author dcoffin; state Exp;
branches;
next 1.389;
1.389
date 2007.07.28.23.39.53; author dcoffin; state Exp;
branches;
next 1.388;
1.388
date 2007.07.23.06.52.52; author dcoffin; state Exp;
branches;
next 1.387;
1.387
date 2007.06.24.00.18.52; author dcoffin; state Exp;
branches;
next 1.386;
1.386
date 2007.06.13.22.42.15; author dcoffin; state Exp;
branches;
next 1.385;
1.385
date 2007.06.13.06.40.04; author dcoffin; state Exp;
branches;
next 1.384;
1.384
date 2007.06.08.21.29.34; author dcoffin; state Exp;
branches;
next 1.383;
1.383
date 2007.06.04.01.19.23; author dcoffin; state Exp;
branches;
next 1.382;
1.382
date 2007.06.02.04.18.22; author dcoffin; state Exp;
branches;
next 1.381;
1.381
date 2007.05.09.17.19.29; author dcoffin; state Exp;
branches;
next 1.380;
1.380
date 2007.05.06.23.05.56; author dcoffin; state Exp;
branches;
next 1.379;
1.379
date 2007.05.03.06.15.16; author dcoffin; state Exp;
branches;
next 1.378;
1.378
date 2007.04.29.19.01.29; author dcoffin; state Exp;
branches;
next 1.377;
1.377
date 2007.03.25.22.56.19; author dcoffin; state Exp;
branches;
next 1.376;
1.376
date 2007.03.19.21.09.00; author dcoffin; state Exp;
branches;
next 1.375;
1.375
date 2007.03.17.05.18.22; author dcoffin; state Exp;
branches;
next 1.374;
1.374
date 2007.03.15.05.19.10; author dcoffin; state Exp;
branches;
next 1.373;
1.373
date 2007.03.14.20.30.19; author dcoffin; state Exp;
branches;
next 1.372;
1.372
date 2007.03.13.05.04.22; author dcoffin; state Exp;
branches;
next 1.371;
1.371
date 2007.03.07.23.37.58; author dcoffin; state Exp;
branches;
next 1.370;
1.370
date 2007.03.02.17.40.15; author dcoffin; state Exp;
branches;
next 1.369;
1.369
date 2007.02.27.02.11.06; author dcoffin; state Exp;
branches;
next 1.368;
1.368
date 2007.02.25.03.09.54; author dcoffin; state Exp;
branches;
next 1.367;
1.367
date 2007.02.24.22.10.59; author dcoffin; state Exp;
branches;
next 1.366;
1.366
date 2007.02.22.16.50.08; author dcoffin; state Exp;
branches;
next 1.365;
1.365
date 2007.02.12.22.55.47; author dcoffin; state Exp;
branches;
next 1.364;
1.364
date 2007.01.21.00.41.17; author dcoffin; state Exp;
branches;
next 1.363;
1.363
date 2007.01.18.23.57.32; author dcoffin; state Exp;
branches;
next 1.362;
1.362
date 2007.01.09.02.06.51; author dcoffin; state Exp;
branches;
next 1.361;
1.361
date 2007.01.02.03.51.27; author dcoffin; state Exp;
branches;
next 1.360;
1.360
date 2006.12.22.03.56.43; author dcoffin; state Exp;
branches;
next 1.359;
1.359
date 2006.12.14.15.40.47; author dcoffin; state Exp;
branches;
next 1.358;
1.358
date 2006.12.04.03.10.46; author dcoffin; state Exp;
branches;
next 1.357;
1.357
date 2006.11.28.04.18.50; author dcoffin; state Exp;
branches;
next 1.356;
1.356
date 2006.11.21.16.32.10; author dcoffin; state Exp;
branches;
next 1.355;
1.355
date 2006.11.04.15.55.41; author dcoffin; state Exp;
branches;
next 1.354;
1.354
date 2006.10.25.22.35.03; author dcoffin; state Exp;
branches;
next 1.353;
1.353
date 2006.10.10.04.46.02; author dcoffin; state Exp;
branches;
next 1.352;
1.352
date 2006.10.06.16.35.50; author dcoffin; state Exp;
branches;
next 1.351;
1.351
date 2006.09.22.04.59.09; author dcoffin; state Exp;
branches;
next 1.350;
1.350
date 2006.09.19.20.50.11; author dcoffin; state Exp;
branches;
next 1.349;
1.349
date 2006.09.12.08.38.59; author dcoffin; state Exp;
branches;
next 1.348;
1.348
date 2006.09.08.14.52.39; author dcoffin; state Exp;
branches;
next 1.347;
1.347
date 2006.09.06.18.44.58; author dcoffin; state Exp;
branches;
next 1.346;
1.346
date 2006.09.03.16.37.49; author dcoffin; state Exp;
branches;
next 1.345;
1.345
date 2006.09.02.14.56.28; author dcoffin; state Exp;
branches;
next 1.344;
1.344
date 2006.08.31.18.43.44; author dcoffin; state Exp;
branches;
next 1.343;
1.343
date 2006.08.24.20.24.51; author dcoffin; state Exp;
branches;
next 1.342;
1.342
date 2006.08.20.05.14.23; author dcoffin; state Exp;
branches;
next 1.341;
1.341
date 2006.08.18.02.52.47; author dcoffin; state Exp;
branches;
next 1.340;
1.340
date 2006.08.08.15.06.13; author dcoffin; state Exp;
branches;
next 1.339;
1.339
date 2006.08.06.20.28.43; author dcoffin; state Exp;
branches;
next 1.338;
1.338
date 2006.07.31.21.34.50; author dcoffin; state Exp;
branches;
next 1.337;
1.337
date 2006.07.30.19.52.37; author dcoffin; state Exp;
branches;
next 1.336;
1.336
date 2006.07.27.20.04.06; author dcoffin; state Exp;
branches;
next 1.335;
1.335
date 2006.07.26.18.02.50; author dcoffin; state Exp;
branches;
next 1.334;
1.334
date 2006.07.21.14.48.23; author dcoffin; state Exp;
branches;
next 1.333;
1.333
date 2006.07.18.06.30.03; author dcoffin; state Exp;
branches;
next 1.332;
1.332
date 2006.06.23.07.36.10; author dcoffin; state Exp;
branches;
next 1.331;
1.331
date 2006.06.21.20.00.07; author dcoffin; state Exp;
branches;
next 1.330;
1.330
date 2006.05.29.18.54.35; author dcoffin; state Exp;
branches;
next 1.329;
1.329
date 2006.05.28.05.07.49; author dcoffin; state Exp;
branches;
next 1.328;
1.328
date 2006.05.21.20.04.39; author dcoffin; state Exp;
branches;
next 1.327;
1.327
date 2006.05.21.19.44.03; author dcoffin; state Exp;
branches;
next 1.326;
1.326
date 2006.05.18.06.34.26; author dcoffin; state Exp;
branches;
next 1.325;
1.325
date 2006.05.14.05.08.10; author dcoffin; state Exp;
branches;
next 1.324;
1.324
date 2006.05.04.22.45.45; author dcoffin; state Exp;
branches;
next 1.323;
1.323
date 2006.04.09.02.40.56; author dcoffin; state Exp;
branches;
next 1.322;
1.322
date 2006.04.06.18.51.37; author dcoffin; state Exp;
branches;
next 1.321;
1.321
date 2006.03.31.21.54.29; author dcoffin; state Exp;
branches;
next 1.320;
1.320
date 2006.03.29.02.44.05; author dcoffin; state Exp;
branches;
next 1.319;
1.319
date 2006.03.24.07.03.04; author dcoffin; state Exp;
branches;
next 1.318;
1.318
date 2006.03.21.20.47.06; author dcoffin; state Exp;
branches;
next 1.317;
1.317
date 2006.03.21.02.28.23; author dcoffin; state Exp;
branches;
next 1.316;
1.316
date 2006.03.20.21.50.28; author dcoffin; state Exp;
branches;
next 1.315;
1.315
date 2006.02.09.05.23.08; author dcoffin; state Exp;
branches;
next 1.314;
1.314
date 2006.02.07.06.56.51; author dcoffin; state Exp;
branches;
next 1.313;
1.313
date 2006.01.24.16.51.53; author dcoffin; state Exp;
branches;
next 1.312;
1.312
date 2006.01.24.08.47.38; author dcoffin; state Exp;
branches;
next 1.311;
1.311
date 2006.01.23.09.31.52; author dcoffin; state Exp;
branches;
next 1.310;
1.310
date 2006.01.21.10.41.56; author dcoffin; state Exp;
branches;
next 1.309;
1.309
date 2005.12.18.21.02.19; author dcoffin; state Exp;
branches;
next 1.308;
1.308
date 2005.12.11.01.07.33; author dcoffin; state Exp;
branches;
next 1.307;
1.307
date 2005.12.09.03.05.18; author dcoffin; state Exp;
branches;
next 1.306;
1.306
date 2005.12.08.01.42.17; author dcoffin; state Exp;
branches;
next 1.305;
1.305
date 2005.12.06.08.18.35; author dcoffin; state Exp;
branches;
next 1.304;
1.304
date 2005.11.29.18.59.01; author dcoffin; state Exp;
branches;
next 1.303;
1.303
date 2005.11.29.08.36.52; author dcoffin; state Exp;
branches;
next 1.302;
1.302
date 2005.11.24.01.42.35; author dcoffin; state Exp;
branches;
next 1.301;
1.301
date 2005.11.23.08.07.55; author dcoffin; state Exp;
branches;
next 1.300;
1.300
date 2005.11.13.01.46.57; author dcoffin; state Exp;
branches;
next 1.299;
1.299
date 2005.11.12.01.20.27; author dcoffin; state Exp;
branches;
next 1.298;
1.298
date 2005.11.11.01.39.54; author dcoffin; state Exp;
branches;
next 1.297;
1.297
date 2005.11.06.04.17.59; author dcoffin; state Exp;
branches;
next 1.296;
1.296
date 2005.11.04.07.11.14; author dcoffin; state Exp;
branches;
next 1.295;
1.295
date 2005.10.26.22.36.53; author dcoffin; state Exp;
branches;
next 1.294;
1.294
date 2005.10.26.07.22.16; author dcoffin; state Exp;
branches;
next 1.293;
1.293
date 2005.10.21.02.01.00; author dcoffin; state Exp;
branches;
next 1.292;
1.292
date 2005.10.19.21.55.29; author dcoffin; state Exp;
branches;
next 1.291;
1.291
date 2005.10.18.07.43.44; author dcoffin; state Exp;
branches;
next 1.290;
1.290
date 2005.10.12.03.50.10; author dcoffin; state Exp;
branches;
next 1.289;
1.289
date 2005.10.08.04.03.17; author dcoffin; state Exp;
branches;
next 1.288;
1.288
date 2005.10.03.05.31.46; author dcoffin; state Exp;
branches;
next 1.287;
1.287
date 2005.10.01.04.55.11; author dcoffin; state Exp;
branches;
next 1.286;
1.286
date 2005.09.25.22.26.03; author dcoffin; state Exp;
branches;
next 1.285;
1.285
date 2005.09.13.01.03.22; author dcoffin; state Exp;
branches;
next 1.284;
1.284
date 2005.09.08.04.31.20; author dcoffin; state Exp;
branches;
next 1.283;
1.283
date 2005.09.07.06.01.08; author dcoffin; state Exp;
branches;
next 1.282;
1.282
date 2005.09.06.19.17.07; author dcoffin; state Exp;
branches;
next 1.281;
1.281
date 2005.09.01.00.29.22; author dcoffin; state Exp;
branches;
next 1.280;
1.280
date 2005.08.30.22.53.17; author dcoffin; state Exp;
branches;
next 1.279;
1.279
date 2005.08.25.05.59.23; author dcoffin; state Exp;
branches;
next 1.278;
1.278
date 2005.08.24.20.02.34; author dcoffin; state Exp;
branches;
next 1.277;
1.277
date 2005.08.22.06.13.13; author dcoffin; state Exp;
branches;
next 1.276;
1.276
date 2005.08.16.08.48.10; author dcoffin; state Exp;
branches;
next 1.275;
1.275
date 2005.08.12.21.03.34; author dcoffin; state Exp;
branches;
next 1.274;
1.274
date 2005.08.06.01.04.30; author dcoffin; state Exp;
branches;
next 1.273;
1.273
date 2005.08.01.06.28.03; author dcoffin; state Exp;
branches;
next 1.272;
1.272
date 2005.07.31.02.51.11; author dcoffin; state Exp;
branches;
next 1.271;
1.271
date 2005.07.29.04.06.08; author dcoffin; state Exp;
branches;
next 1.270;
1.270
date 2005.07.20.22.41.33; author dcoffin; state Exp;
branches;
next 1.269;
1.269
date 2005.07.14.02.13.45; author dcoffin; state Exp;
branches;
next 1.268;
1.268
date 2005.07.13.07.25.45; author dcoffin; state Exp;
branches;
next 1.267;
1.267
date 2005.07.07.03.40.57; author dcoffin; state Exp;
branches;
next 1.266;
1.266
date 2005.07.06.05.44.34; author dcoffin; state Exp;
branches;
next 1.265;
1.265
date 2005.06.27.20.22.12; author dcoffin; state Exp;
branches;
next 1.264;
1.264
date 2005.06.27.05.12.08; author dcoffin; state Exp;
branches;
next 1.263;
1.263
date 2005.06.06.05.32.07; author dcoffin; state Exp;
branches;
next 1.262;
1.262
date 2005.05.27.01.39.38; author dcoffin; state Exp;
branches;
next 1.261;
1.261
date 2005.05.21.01.54.47; author dcoffin; state Exp;
branches;
next 1.260;
1.260
date 2005.05.20.06.18.43; author dcoffin; state Exp;
branches;
next 1.259;
1.259
date 2005.05.10.20.57.07; author dcoffin; state Exp;
branches;
next 1.258;
1.258
date 2005.05.05.06.35.59; author dcoffin; state Exp;
branches;
next 1.257;
1.257
date 2005.05.03.18.50.30; author dcoffin; state Exp;
branches;
next 1.256;
1.256
date 2005.05.03.04.16.09; author dcoffin; state Exp;
branches;
next 1.255;
1.255
date 2005.04.29.16.38.16; author dcoffin; state Exp;
branches;
next 1.254;
1.254
date 2005.04.27.20.10.40; author dcoffin; state Exp;
branches;
next 1.253;
1.253
date 2005.04.26.00.46.33; author dcoffin; state Exp;
branches;
next 1.252;
1.252
date 2005.04.22.16.03.53; author dcoffin; state Exp;
branches;
next 1.251;
1.251
date 2005.04.19.16.00.41; author dcoffin; state Exp;
branches;
next 1.250;
1.250
date 2005.04.18.03.18.57; author dcoffin; state Exp;
branches;
next 1.249;
1.249
date 2005.04.05.07.21.29; author dcoffin; state Exp;
branches;
next 1.248;
1.248
date 2005.03.31.19.42.59; author dcoffin; state Exp;
branches;
next 1.247;
1.247
date 2005.03.29.06.33.18; author dcoffin; state Exp;
branches;
next 1.246;
1.246
date 2005.03.28.19.32.13; author dcoffin; state Exp;
branches;
next 1.245;
1.245
date 2005.03.28.04.56.02; author dcoffin; state Exp;
branches;
next 1.244;
1.244
date 2005.03.25.19.39.58; author dcoffin; state Exp;
branches;
next 1.243;
1.243
date 2005.03.23.23.00.33; author dcoffin; state Exp;
branches;
next 1.242;
1.242
date 2005.03.23.17.52.43; author dcoffin; state Exp;
branches;
next 1.241;
1.241
date 2005.03.19.01.40.04; author dcoffin; state Exp;
branches;
next 1.240;
1.240
date 2005.03.18.22.15.37; author dcoffin; state Exp;
branches;
next 1.239;
1.239
date 2005.03.11.18.47.13; author dcoffin; state Exp;
branches;
next 1.238;
1.238
date 2005.03.11.00.50.22; author dcoffin; state Exp;
branches;
next 1.237;
1.237
date 2005.03.10.03.48.40; author dcoffin; state Exp;
branches;
next 1.236;
1.236
date 2005.02.27.03.26.37; author dcoffin; state Exp;
branches;
next 1.235;
1.235
date 2005.02.16.06.11.39; author dcoffin; state Exp;
branches;
next 1.234;
1.234
date 2005.02.02.22.29.22; author dcoffin; state Exp;
branches;
next 1.233;
1.233
date 2005.01.25.20.31.18; author dcoffin; state Exp;
branches;
next 1.232;
1.232
date 2005.01.25.17.31.10; author dcoffin; state Exp;
branches;
next 1.231;
1.231
date 2005.01.25.02.29.44; author dcoffin; state Exp;
branches;
next 1.230;
1.230
date 2005.01.24.05.43.59; author dcoffin; state Exp;
branches;
next 1.229;
1.229
date 2005.01.21.06.48.13; author dcoffin; state Exp;
branches;
next 1.228;
1.228
date 2005.01.19.08.50.44; author dcoffin; state Exp;
branches;
next 1.227;
1.227
date 2005.01.14.00.01.30; author dcoffin; state Exp;
branches;
next 1.226;
1.226
date 2005.01.10.07.04.46; author dcoffin; state Exp;
branches;
next 1.225;
1.225
date 2005.01.08.05.26.49; author dcoffin; state Exp;
branches;
next 1.224;
1.224
date 2005.01.04.23.08.52; author dcoffin; state Exp;
branches;
next 1.223;
1.223
date 2004.12.31.09.07.44; author dcoffin; state Exp;
branches;
next 1.222;
1.222
date 2004.12.22.20.48.54; author dcoffin; state Exp;
branches;
next 1.221;
1.221
date 2004.12.17.07.31.32; author dcoffin; state Exp;
branches;
next 1.220;
1.220
date 2004.12.08.23.50.03; author dcoffin; state Exp;
branches;
next 1.219;
1.219
date 2004.12.04.05.42.44; author dcoffin; state Exp;
branches;
next 1.218;
1.218
date 2004.12.01.21.54.52; author dcoffin; state Exp;
branches;
next 1.217;
1.217
date 2004.11.28.02.27.04; author dcoffin; state Exp;
branches;
next 1.216;
1.216
date 2004.11.22.02.34.41; author dcoffin; state Exp;
branches;
next 1.215;
1.215
date 2004.11.05.06.48.50; author dcoffin; state Exp;
branches;
next 1.214;
1.214
date 2004.10.26.02.28.46; author dcoffin; state Exp;
branches;
next 1.213;
1.213
date 2004.10.24.23.27.22; author dcoffin; state Exp;
branches;
next 1.212;
1.212
date 2004.10.23.04.40.54; author dcoffin; state Exp;
branches;
next 1.211;
1.211
date 2004.10.13.01.13.53; author dcoffin; state Exp;
branches;
next 1.210;
1.210
date 2004.10.08.02.34.46; author dcoffin; state Exp;
branches;
next 1.209;
1.209
date 2004.10.07.01.11.51; author dcoffin; state Exp;
branches;
next 1.208;
1.208
date 2004.10.04.20.33.44; author dcoffin; state Exp;
branches;
next 1.207;
1.207
date 2004.10.02.21.59.44; author dcoffin; state Exp;
branches;
next 1.206;
1.206
date 2004.09.19.05.00.32; author dcoffin; state Exp;
branches;
next 1.205;
1.205
date 2004.09.16.20.29.15; author dcoffin; state Exp;
branches;
next 1.204;
1.204
date 2004.09.14.00.35.12; author dcoffin; state Exp;
branches;
next 1.203;
1.203
date 2004.09.07.17.25.15; author dcoffin; state Exp;
branches;
next 1.202;
1.202
date 2004.09.06.05.50.09; author dcoffin; state Exp;
branches;
next 1.201;
1.201
date 2004.09.01.21.28.04; author dcoffin; state Exp;
branches;
next 1.200;
1.200
date 2004.08.04.18.40.25; author dcoffin; state Exp;
branches;
next 1.199;
1.199
date 2004.07.28.04.25.31; author dcoffin; state Exp;
branches;
next 1.198;
1.198
date 2004.07.06.18.36.13; author dcoffin; state Exp;
branches;
next 1.197;
1.197
date 2004.06.29.22.56.42; author dcoffin; state Exp;
branches;
next 1.196;
1.196
date 2004.06.29.02.23.39; author dcoffin; state Exp;
branches;
next 1.195;
1.195
date 2004.06.16.17.19.36; author dcoffin; state Exp;
branches;
next 1.194;
1.194
date 2004.05.22.15.41.31; author dcoffin; state Exp;
branches;
next 1.193;
1.193
date 2004.05.14.21.26.40; author dcoffin; state Exp;
branches;
next 1.192;
1.192
date 2004.05.11.19.09.02; author dcoffin; state Exp;
branches;
next 1.191;
1.191
date 2004.05.11.04.38.40; author dcoffin; state Exp;
branches;
next 1.190;
1.190
date 2004.05.05.17.20.10; author dcoffin; state Exp;
branches;
next 1.189;
1.189
date 2004.05.02.19.14.54; author dcoffin; state Exp;
branches;
next 1.188;
1.188
date 2004.04.29.19.11.08; author dcoffin; state Exp;
branches;
next 1.187;
1.187
date 2004.04.28.14.35.07; author dcoffin; state Exp;
branches;
next 1.186;
1.186
date 2004.04.25.20.19.33; author dcoffin; state Exp;
branches;
next 1.185;
1.185
date 2004.04.25.04.54.14; author dcoffin; state Exp;
branches;
next 1.184;
1.184
date 2004.04.22.16.53.47; author dcoffin; state Exp;
branches;
next 1.183;
1.183
date 2004.04.22.01.01.56; author dcoffin; state Exp;
branches;
next 1.182;
1.182
date 2004.04.19.22.58.46; author dcoffin; state Exp;
branches;
next 1.181;
1.181
date 2004.04.14.19.19.12; author dcoffin; state Exp;
branches;
next 1.180;
1.180
date 2004.04.01.18.17.04; author dcoffin; state Exp;
branches;
next 1.179;
1.179
date 2004.03.29.19.53.10; author dcoffin; state Exp;
branches
1.179.1.1;
next 1.178;
1.178
date 2004.03.07.02.06.59; author dcoffin; state Exp;
branches;
next 1.177;
1.177
date 2004.03.05.17.25.30; author dcoffin; state Exp;
branches;
next 1.176;
1.176
date 2004.03.01.15.17.47; author dcoffin; state Exp;
branches;
next 1.175;
1.175
date 2004.02.24.04.56.12; author dcoffin; state Exp;
branches;
next 1.174;
1.174
date 2004.02.23.00.18.33; author dcoffin; state Exp;
branches;
next 1.173;
1.173
date 2004.02.22.19.28.03; author dcoffin; state Exp;
branches;
next 1.172;
1.172
date 2004.02.22.04.02.44; author dcoffin; state Exp;
branches;
next 1.171;
1.171
date 2004.02.21.23.35.56; author dcoffin; state Exp;
branches;
next 1.170;
1.170
date 2004.02.20.18.37.17; author dcoffin; state Exp;
branches;
next 1.169;
1.169
date 2004.02.20.04.22.08; author dcoffin; state Exp;
branches;
next 1.168;
1.168
date 2004.02.18.20.29.52; author dcoffin; state Exp;
branches;
next 1.167;
1.167
date 2004.02.16.01.01.44; author dcoffin; state Exp;
branches;
next 1.166;
1.166
date 2004.02.13.16.29.33; author dcoffin; state Exp;
branches;
next 1.165;
1.165
date 2004.02.13.14.20.06; author dcoffin; state Exp;
branches;
next 1.164;
1.164
date 2004.02.12.03.44.30; author dcoffin; state Exp;
branches;
next 1.163;
1.163
date 2004.02.10.18.29.09; author dcoffin; state Exp;
branches;
next 1.162;
1.162
date 2004.02.07.13.36.34; author dcoffin; state Exp;
branches;
next 1.161;
1.161
date 2004.01.04.09.21.49; author dcoffin; state Exp;
branches;
next 1.160;
1.160
date 2004.01.04.08.09.05; author dcoffin; state Exp;
branches;
next 1.159;
1.159
date 2003.12.24.18.29.49; author dcoffin; state Exp;
branches;
next 1.158;
1.158
date 2003.12.23.04.30.39; author dcoffin; state Exp;
branches;
next 1.157;
1.157
date 2003.12.19.05.07.31; author dcoffin; state Exp;
branches;
next 1.156;
1.156
date 2003.12.17.05.08.01; author dcoffin; state Exp;
branches;
next 1.155;
1.155
date 2003.12.09.20.35.40; author dcoffin; state Exp;
branches;
next 1.154;
1.154
date 2003.12.08.07.09.16; author dcoffin; state Exp;
branches;
next 1.153;
1.153
date 2003.12.04.01.23.06; author dcoffin; state Exp;
branches;
next 1.152;
1.152
date 2003.11.25.02.25.27; author dcoffin; state Exp;
branches;
next 1.151;
1.151
date 2003.11.16.08.39.38; author dcoffin; state Exp;
branches;
next 1.150;
1.150
date 2003.11.14.23.42.33; author dcoffin; state Exp;
branches;
next 1.149;
1.149
date 2003.11.14.15.53.47; author dcoffin; state Exp;
branches;
next 1.148;
1.148
date 2003.11.09.00.44.50; author dcoffin; state Exp;
branches;
next 1.147;
1.147
date 2003.11.06.00.58.27; author dcoffin; state Exp;
branches;
next 1.146;
1.146
date 2003.11.05.18.10.17; author dcoffin; state Exp;
branches;
next 1.145;
1.145
date 2003.10.28.00.20.01; author dcoffin; state Exp;
branches;
next 1.144;
1.144
date 2003.10.20.18.35.01; author dcoffin; state Exp;
branches;
next 1.143;
1.143
date 2003.10.16.19.38.02; author dcoffin; state Exp;
branches;
next 1.142;
1.142
date 2003.10.14.20.36.32; author dcoffin; state Exp;
branches;
next 1.141;
1.141
date 2003.10.14.01.16.41; author dcoffin; state Exp;
branches;
next 1.140;
1.140
date 2003.10.13.21.21.00; author dcoffin; state Exp;
branches;
next 1.139;
1.139
date 2003.10.07.07.27.24; author dcoffin; state Exp;
branches;
next 1.138;
1.138
date 2003.10.04.19.17.37; author dcoffin; state Exp;
branches;
next 1.137;
1.137
date 2003.10.01.21.59.51; author dcoffin; state Exp;
branches;
next 1.136;
1.136
date 2003.09.23.00.38.14; author dcoffin; state Exp;
branches;
next 1.135;
1.135
date 2003.09.21.19.31.42; author dcoffin; state Exp;
branches;
next 1.134;
1.134
date 2003.09.20.01.51.39; author dcoffin; state Exp;
branches;
next 1.133;
1.133
date 2003.09.19.04.02.26; author dcoffin; state Exp;
branches;
next 1.132;
1.132
date 2003.09.18.02.21.21; author dcoffin; state Exp;
branches;
next 1.131;
1.131
date 2003.09.17.18.33.30; author dcoffin; state Exp;
branches;
next 1.130;
1.130
date 2003.09.15.03.12.54; author dcoffin; state Exp;
branches;
next 1.129;
1.129
date 2003.09.11.20.35.53; author dcoffin; state Exp;
branches;
next 1.128;
1.128
date 2003.07.17.19.06.11; author dcoffin; state Exp;
branches;
next 1.127;
1.127
date 2003.07.03.02.53.00; author dcoffin; state Exp;
branches;
next 1.126;
1.126
date 2003.07.02.04.36.23; author dcoffin; state Exp;
branches;
next 1.125;
1.125
date 2003.06.27.17.12.37; author dcoffin; state Exp;
branches;
next 1.124;
1.124
date 2003.06.24.15.07.14; author dcoffin; state Exp;
branches;
next 1.123;
1.123
date 2003.06.22.17.01.02; author dcoffin; state Exp;
branches;
next 1.122;
1.122
date 2003.06.21.02.06.35; author dcoffin; state Exp;
branches;
next 1.121;
1.121
date 2003.06.21.00.16.57; author dcoffin; state Exp;
branches;
next 1.120;
1.120
date 2003.06.12.23.13.36; author dcoffin; state Exp;
branches;
next 1.119;
1.119
date 2003.06.06.16.25.41; author dcoffin; state Exp;
branches;
next 1.118;
1.118
date 2003.06.06.15.45.57; author dcoffin; state Exp;
branches;
next 1.117;
1.117
date 2003.06.03.19.06.14; author dcoffin; state Exp;
branches;
next 1.116;
1.116
date 2003.06.02.14.49.38; author dcoffin; state Exp;
branches;
next 1.115;
1.115
date 2003.05.30.03.42.18; author dcoffin; state Exp;
branches;
next 1.114;
1.114
date 2003.05.30.02.19.44; author dcoffin; state Exp;
branches;
next 1.113;
1.113
date 2003.05.29.22.34.18; author dcoffin; state Exp;
branches;
next 1.112;
1.112
date 2003.05.28.14.10.08; author dcoffin; state Exp;
branches;
next 1.111;
1.111
date 2003.05.27.18.17.16; author dcoffin; state Exp;
branches;
next 1.110;
1.110
date 2003.04.25.17.48.05; author dcoffin; state Exp;
branches;
next 1.109;
1.109
date 2003.04.25.00.46.29; author dcoffin; state Exp;
branches;
next 1.108;
1.108
date 2003.04.12.15.31.58; author dcoffin; state Exp;
branches;
next 1.107;
1.107
date 2003.03.29.23.22.37; author dcoffin; state Exp;
branches;
next 1.106;
1.106
date 2003.03.23.02.49.33; author dcoffin; state Exp;
branches;
next 1.105;
1.105
date 2003.03.17.19.34.10; author dcoffin; state Exp;
branches;
next 1.104;
1.104
date 2003.03.14.16.43.26; author dcoffin; state Exp;
branches;
next 1.103;
1.103
date 2003.03.12.05.22.20; author dcoffin; state Exp;
branches;
next 1.102;
1.102
date 2003.03.08.02.28.12; author dcoffin; state Exp;
branches;
next 1.101;
1.101
date 2003.03.07.00.58.29; author dcoffin; state Exp;
branches;
next 1.100;
1.100
date 2003.02.25.00.41.11; author dcoffin; state Exp;
branches;
next 1.99;
1.99
date 2003.02.23.16.34.58; author dcoffin; state Exp;
branches;
next 1.98;
1.98
date 2003.02.22.20.44.54; author dcoffin; state Exp;
branches;
next 1.97;
1.97
date 2003.02.17.04.23.32; author dcoffin; state Exp;
branches;
next 1.96;
1.96
date 2003.02.16.05.01.06; author dcoffin; state Exp;
branches;
next 1.95;
1.95
date 2003.01.30.19.45.42; author dcoffin; state Exp;
branches;
next 1.94;
1.94
date 2003.01.28.06.19.40; author dcoffin; state Exp;
branches;
next 1.93;
1.93
date 2003.01.27.02.55.01; author dcoffin; state Exp;
branches;
next 1.92;
1.92
date 2003.01.13.21.54.22; author dcoffin; state Exp;
branches;
next 1.91;
1.91
date 2003.01.09.05.07.39; author dcoffin; state Exp;
branches;
next 1.90;
1.90
date 2003.01.02.23.24.00; author dcoffin; state Exp;
branches;
next 1.89;
1.89
date 2002.12.31.23.23.33; author dcoffin; state Exp;
branches;
next 1.88;
1.88
date 2002.12.19.16.33.15; author dcoffin; state Exp;
branches;
next 1.87;
1.87
date 2002.12.19.03.13.42; author dcoffin; state Exp;
branches;
next 1.86;
1.86
date 2002.12.18.03.43.08; author dcoffin; state Exp;
branches;
next 1.85;
1.85
date 2002.12.17.19.52.52; author dcoffin; state Exp;
branches;
next 1.84;
1.84
date 2002.12.17.01.45.16; author dcoffin; state Exp;
branches;
next 1.83;
1.83
date 2002.12.16.06.23.49; author dcoffin; state Exp;
branches;
next 1.82;
1.82
date 2002.12.13.02.48.35; author dcoffin; state Exp;
branches;
next 1.81;
1.81
date 2002.12.12.18.14.52; author dcoffin; state Exp;
branches;
next 1.80;
1.80
date 2002.12.12.06.31.37; author dcoffin; state Exp;
branches;
next 1.79;
1.79
date 2002.12.04.03.28.49; author dcoffin; state Exp;
branches;
next 1.78;
1.78
date 2002.12.01.04.34.57; author dcoffin; state Exp;
branches;
next 1.77;
1.77
date 2002.11.25.04.36.23; author dcoffin; state Exp;
branches;
next 1.76;
1.76
date 2002.11.24.15.00.57; author dcoffin; state Exp;
branches;
next 1.75;
1.75
date 2002.11.13.17.37.41; author dcoffin; state Exp;
branches;
next 1.74;
1.74
date 2002.11.11.02.26.53; author dcoffin; state Exp;
branches;
next 1.73;
1.73
date 2002.11.09.05.31.58; author dcoffin; state Exp;
branches;
next 1.72;
1.72
date 2002.10.27.23.55.19; author dcoffin; state Exp;
branches;
next 1.71;
1.71
date 2002.10.27.18.50.40; author dcoffin; state Exp;
branches;
next 1.70;
1.70
date 2002.10.20.19.47.30; author dcoffin; state Exp;
branches;
next 1.69;
1.69
date 2002.10.16.01.09.16; author dcoffin; state Exp;
branches;
next 1.68;
1.68
date 2002.10.15.01.28.32; author dcoffin; state Exp;
branches;
next 1.67;
1.67
date 2002.08.15.17.22.53; author dcoffin; state Exp;
branches;
next 1.66;
1.66
date 2002.08.08.13.12.37; author dcoffin; state Exp;
branches;
next 1.65;
1.65
date 2002.08.07.23.28.31; author dcoffin; state Exp;
branches;
next 1.64;
1.64
date 2002.08.07.22.50.13; author dcoffin; state Exp;
branches;
next 1.63;
1.63
date 2002.06.28.03.55.09; author dcoffin; state Exp;
branches;
next 1.62;
1.62
date 2002.06.24.14.58.04; author dcoffin; state Exp;
branches;
next 1.61;
1.61
date 2002.06.23.20.39.42; author dcoffin; state Exp;
branches;
next 1.60;
1.60
date 2002.06.20.20.32.08; author dcoffin; state Exp;
branches;
next 1.59;
1.59
date 2002.05.28.17.18.51; author dcoffin; state Exp;
branches;
next 1.58;
1.58
date 2002.05.23.16.26.47; author dcoffin; state Exp;
branches;
next 1.57;
1.57
date 2002.05.06.04.11.13; author dcoffin; state Exp;
branches;
next 1.56;
1.56
date 2002.05.05.20.35.28; author dcoffin; state Exp;
branches;
next 1.55;
1.55
date 2002.05.05.04.52.02; author dcoffin; state Exp;
branches;
next 1.54;
1.54
date 2002.05.02.19.44.17; author dcoffin; state Exp;
branches;
next 1.53;
1.53
date 2002.04.26.03.29.48; author dcoffin; state Exp;
branches;
next 1.52;
1.52
date 2002.04.17.21.29.10; author dcoffin; state Exp;
branches;
next 1.51;
1.51
date 2002.04.16.23.32.41; author dcoffin; state Exp;
branches;
next 1.50;
1.50
date 2002.04.07.19.09.14; author dcoffin; state Exp;
branches;
next 1.49;
1.49
date 2002.04.04.01.44.38; author dcoffin; state Exp;
branches;
next 1.48;
1.48
date 2002.04.02.13.44.26; author dcoffin; state Exp;
branches;
next 1.47;
1.47
date 2002.03.29.02.23.51; author dcoffin; state Exp;
branches;
next 1.46;
1.46
date 2002.03.28.01.05.30; author dcoffin; state Exp;
branches;
next 1.45;
1.45
date 2002.03.25.03.52.38; author dcoffin; state Exp;
branches;
next 1.44;
1.44
date 2002.03.24.19.29.10; author dcoffin; state Exp;
branches;
next 1.43;
1.43
date 2002.03.24.17.34.52; author dcoffin; state Exp;
branches;
next 1.42;
1.42
date 2002.02.05.22.40.25; author dcoffin; state Exp;
branches;
next 1.41;
1.41
date 2002.01.29.20.53.56; author dcoffin; state Exp;
branches;
next 1.40;
1.40
date 2002.01.13.18.05.57; author dcoffin; state Exp;
branches;
next 1.39;
1.39
date 2001.12.08.22.59.44; author dcoffin; state Exp;
branches;
next 1.38;
1.38
date 2001.12.06.04.18.11; author dcoffin; state Exp;
branches;
next 1.37;
1.37
date 2001.11.25.21.39.22; author dcoffin; state Exp;
branches;
next 1.36;
1.36
date 2001.11.22.17.13.19; author dcoffin; state Exp;
branches;
next 1.35;
1.35
date 2001.11.06.00.16.04; author dcoffin; state Exp;
branches;
next 1.34;
1.34
date 2001.10.28.01.00.19; author dcoffin; state Exp;
branches;
next 1.33;
1.33
date 2001.10.24.17.56.06; author dcoffin; state Exp;
branches;
next 1.32;
1.32
date 2001.10.23.13.45.51; author dcoffin; state Exp;
branches;
next 1.31;
1.31
date 2001.10.19.23.01.31; author dcoffin; state Exp;
branches;
next 1.30;
1.30
date 2001.10.19.20.14.37; author dcoffin; state Exp;
branches;
next 1.29;
1.29
date 2001.10.15.04.28.53; author dcoffin; state Exp;
branches;
next 1.28;
1.28
date 2001.10.14.20.46.29; author dcoffin; state Exp;
branches;
next 1.27;
1.27
date 2001.09.30.15.30.42; author dcoffin; state Exp;
branches;
next 1.26;
1.26
date 2001.09.30.00.04.43; author dcoffin; state Exp;
branches;
next 1.25;
1.25
date 2001.09.24.22.41.06; author dcoffin; state Exp;
branches;
next 1.24;
1.24
date 2000.06.23.20.19.09; author dcoffin; state Exp;
branches;
next 1.23;
1.23
date 2000.06.19.06.56.27; author dcoffin; state Exp;
branches;
next 1.22;
1.22
date 2000.05.20.20.31.28; author dcoffin; state Exp;
branches;
next 1.21;
1.21
date 2000.05.07.04.26.08; author dcoffin; state Exp;
branches;
next 1.20;
1.20
date 2000.05.06.20.28.57; author dcoffin; state Exp;
branches;
next 1.19;
1.19
date 2000.05.05.13.48.25; author dcoffin; state Exp;
branches;
next 1.18;
1.18
date 2000.05.05.04.21.40; author dcoffin; state Exp;
branches;
next 1.17;
1.17
date 2000.05.02.13.45.14; author dcoffin; state Exp;
branches;
next 1.16;
1.16
date 2000.05.02.12.18.24; author dcoffin; state Exp;
branches;
next 1.15;
1.15
date 2000.05.01.07.06.04; author dcoffin; state Exp;
branches;
next 1.14;
1.14
date 99.05.07.00.10.38; author dcoffin; state Exp;
branches;
next 1.13;
1.13
date 99.04.15.21.20.26; author dcoffin; state Exp;
branches;
next 1.12;
1.12
date 99.04.15.19.57.55; author dcoffin; state Exp;
branches;
next 1.11;
1.11
date 99.04.12.22.57.06; author dcoffin; state Exp;
branches
1.11.1.1;
next 1.10;
1.10
date 99.04.12.19.36.36; author dcoffin; state Exp;
branches;
next 1.9;
1.9
date 99.01.01.20.56.22; author dcoffin; state Exp;
branches;
next 1.8;
1.8
date 97.08.31.02.09.41; author dcoffin; state Exp;
branches;
next 1.7;
1.7
date 97.08.24.04.06.03; author dcoffin; state Exp;
branches;
next 1.6;
1.6
date 97.08.23.19.36.52; author dcoffin; state Exp;
branches;
next 1.5;
1.5
date 97.03.25.02.49.34; author dcoffin; state Exp;
branches;
next 1.4;
1.4
date 97.02.25.04.12.42; author dcoffin; state Exp;
branches;
next 1.3;
1.3
date 97.02.24.02.04.30; author dcoffin; state Exp;
branches;
next 1.2;
1.2
date 97.02.23.02.17.04; author dcoffin; state Exp;
branches;
next 1.1;
1.1
date 97.02.23.01.20.29; author dcoffin; state Exp;
branches;
next ;
1.11.1.1
date 99.04.12.23.00.06; author dcoffin; state Exp;
branches;
next 1.11.1.2;
1.11.1.2
date 99.04.15.19.17.17; author dcoffin; state Exp;
branches;
next 1.11.1.3;
1.11.1.3
date 99.04.15.19.57.17; author dcoffin; state Exp;
branches;
next ;
1.179.1.1
date 2004.04.07.07.22.56; author dcoffin; state Exp;
branches;
next ;
desc
@Command-line tool to decode raw photos from all digital cameras
@
1.418
log
@Support the Hasselblad V96C.
@
text
@/*
dcraw.c -- Dave Coffin's raw photo decoder
Copyright 1997-2009 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.
No license is required to download and use dcraw.c. However,
to lawfully redistribute dcraw, you must either (a) offer, at
no extra charge, full source code* for all executable files
containing RESTRICTED functions, (b) distribute this code under
the GPL Version 2 or later, (c) remove all RESTRICTED functions,
re-implement them, or copy them from an earlier, unrestricted
Revision of dcraw.c, or (d) purchase a license from the author.
The functions that process Foveon images have been RESTRICTED
since Revision 1.237. All other code remains free for all uses.
*If you have not modified dcraw.c in any way, a link to my
homepage qualifies as "full source code".
$Revision$
$Date$
*/
#define VERSION "8.91"
#define _GNU_SOURCE
#define _USE_MATH_DEFINES
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
NO_JPEG disables decoding of compressed Kodak DC120 files.
NO_LCMS disables the "-p" option.
*/
#ifndef NO_JPEG
#include
#endif
#ifndef NO_LCMS
#include
#endif
#ifdef LOCALEDIR
#include
#define _(String) gettext(String)
#else
#define _(String) (String)
#endif
#ifdef DJGPP
#define fseeko fseek
#define ftello ftell
#else
#define fgetc getc_unlocked
#endif
#ifdef __CYGWIN__
#include
#endif
#ifdef WIN32
#include
#include
#pragma comment(lib, "ws2_32.lib")
#define snprintf _snprintf
#define strcasecmp stricmp
#define strncasecmp strnicmp
typedef __int64 INT64;
typedef unsigned __int64 UINT64;
#else
#include
#include
#include
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.
#endif
#ifndef LONG_BIT
#define LONG_BIT (8 * sizeof (long))
#endif
#define ushort UshORt
typedef unsigned char uchar;
typedef unsigned short ushort;
/*
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.
*/
FILE *ifp;
short order;
char *ifname, *meta_data;
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;
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 zero_after_ff, is_raw, dng_version, is_foveon, data_error;
unsigned tile_width, tile_length, gpsdata[32], load_flags;
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];
float bright=1, user_mul[4]={0,0,0,0}, threshold=0;
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 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 };
float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4];
const double xyz_rgb[3][3] = { /* XYZ from RGB */
{ 0.412453, 0.357580, 0.180423 },
{ 0.212671, 0.715160, 0.072169 },
{ 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 (*load_raw)(), (*thumb_load_raw)();
jmp_buf failure;
struct decode {
struct decode *branch[2];
int leaf;
} first_decode[2048], *second_decode, *free_decode;
struct {
int width, height, bps, comp, phint, offset, flip, samples, bytes;
} tiff_ifd[10];
struct {
int format, key_off, black, black_off, split_col, tag_21a;
float tag_210;
} ph1;
#define CLASS
#define FORC(cnt) for (c=0; c < cnt; c++)
#define FORC3 FORC(3)
#define FORC4 FORC(4)
#define FORCC FORC(colors)
#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); }
/*
In order to inline this calculation, I make the risky
assumption that all filter patterns can be described
by a repeating pattern of eight rows and two columns
Do not use the FC or BAYER macros with the Leaf CatchLight,
because its pattern is 16x16, not 2x8.
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
All RGB cameras use one of these Bayer grids:
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
*/
#define FC(row,col) \
(filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
#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)]
int CLASS 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 (filters != 1) return FC(row,col);
return filter[(row+top_margin) & 15][(col+left_margin) & 15];
}
#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
void CLASS merror (void *ptr, char *where)
{
if (ptr) return;
fprintf (stderr,_("%s: Out of memory in %s\n"), ifname, where);
longjmp (failure, 1);
}
void CLASS derror()
{
if (!data_error) {
fprintf (stderr, "%s: ", ifname);
if (feof(ifp))
fprintf (stderr,_("Unexpected end of file\n"));
else
fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp));
}
data_error = 1;
}
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 (pixel, 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;
if ((diff = dark[0] - dark[1]))
for (row=0; row < height; row++)
for (col=1; col < width; col+=2)
BAYER(row,col) += diff;
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]);
}
/* 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]);
}
}
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;
}
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];
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++) {
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;
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;
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;
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)
{
static unsigned bitbuf=0;
static int vbits=0, reset=0;
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);
}
void CLASS init_decoder()
{
memset (first_decode, 0, sizeof first_decode);
free_decode = first_decode;
}
/*
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
*/
uchar * CLASS make_decoder (const uchar *source, int level)
{
struct decode *cur;
static int leaf;
int i, next;
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;
}
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;
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 if (col > 1)
dark[icol & 1] += pixel[r*raw_width+col];
}
}
}
free (pixel);
canon_black (dark);
}
/*
Not a full implementation of Lossless JPEG, just
enough to decode Canon, Kodak and Adobe DNG images.
*/
struct jhead {
int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
struct CLASS decode *huff[6];
ushort *row;
};
int CLASS ljpeg_start (struct jhead *jh, int info_only)
{
int c, tag, len;
uchar data[0x10000], *dp;
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)
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);
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;
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;
}
}
}
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] += jh.sraw+1;
rp[2] += jh.sraw+1;
pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 12);
pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 12);
pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 12);
}
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) {
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;
} 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_k10_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 vpred[2][2] = {{0,0},{0,0}}, hpred[2];
init_decoder();
make_decoder (pentax_tree, 0);
getbits(-1);
for (row=0; row < height; row++)
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)
BAYER(row,col) = hpred[col & 1];
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;
fseek (ifp, meta_offset+562, SEEK_SET);
split = get2();
} else if (ver0 != 0x46 && csize <= 0x4001)
read_shorts (curve, max=csize);
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();
if ((unsigned) (col-left_margin) < width)
BAYER(row,col-left_margin) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
}
}
}
/*
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 make[12], 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].make );
strcpy (model, table[i].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;
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)
{
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);
}
}
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 curve[0x10000], *xval[2];
if (half_size || !meta_length) return;
if (verbose) fprintf (stderr,_("Phase One correction...\n"));
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];
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];
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)];
} 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;
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);
phase_one_correct();
}
unsigned CLASS ph1_bits (int nbits)
{
static UINT64 bitbuf=0;
static int vbits=0;
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);
}
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];
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();
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);
for (i=0; i < 256; i++)
curve[i] = i*i / 3.969 + 0.5;
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();
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;
}
}
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;
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;
}
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 && (unsigned)(col+i) < width)
BAYER(row,col+i) = pred[i];
}
}
}
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 unpacked_load_raw();
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;
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);
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);
}
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)
FORC(width) black += pixel[c];
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)
{
static uchar buf[0x4000];
static int vbits;
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);
}
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();
}
}
void CLASS olympus_e300_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;
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 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) = 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;
static struct decode *dstart[18], *dindex;
static const int *s, source[] = {
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;
}
#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)
{
static uchar jpeg_buffer[4096];
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;
}
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 )) {
fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname);
jpeg_destroy_decompress (&cinfo);
longjmp (failure, 3);
}
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()");
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;
}
}
free (pixel);
if (raw_width > width+1)
black = lblack / ((raw_width - width) * height);
if (!strncmp(model,"DC2",3))
black = 0;
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();
val = curve[pixel[pi++]];
if ((unsigned) (col-left_margin) < width)
BAYER(row,col-left_margin) = val;
else black += val;
}
}
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++)
if ((BAYER(row,col+i) = curve[ret ? buf[i] :
(pred[i & 1] += buf[i])]) >> 12) derror();
}
}
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];
FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
}
}
}
}
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)
{
static unsigned pad[128], p;
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];
}
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);
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;
}
}
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)
BAYER(row,col) = curve[pix[i] << 1] >> 1;
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];
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);
}
/* RESTRICTED code starts here */
void CLASS foveon_decoder (unsigned size, unsigned code)
{
static unsigned huff[1024];
struct decode *cur;
int i, len;
if (!code) {
for (i=0; i < size; i++)
huff[i] = get4();
init_decoder();
}
cur = free_decode++;
if (free_decode > first_decode+2048) {
fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
longjmp (failure, 2);
}
if (code)
for (i=0; i < size; i++)
if (huff[i] == code) {
cur->leaf = i;
return;
}
if ((len = code >> 27) > 26) return;
code = (len+1) << 27 | (code & 0x3ffffff) << 1;
cur->branch[0] = free_decode;
foveon_decoder (size, code);
cur->branch[1] = free_decode;
foveon_decoder (size, code+1);
}
void CLASS foveon_thumb (FILE *tfp)
{
unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
char *buf;
struct decode *dindex;
short pred[3];
bwide = get4();
fprintf (tfp, "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);
}
free (buf);
return;
}
foveon_decoder (256, 0);
for (row=0; row < thumb_height; row++) {
memset (pred, 0, sizeof pred);
if (!bit) get4();
for (bit=col=0; col < thumb_width; col++)
FORC3 {
for (dindex=first_decode; dindex->branch[0]; ) {
if ((bit = (bit-1) & 31) == 31)
for (i=0; i < 4; i++)
bitbuf = (bitbuf << 8) + fgetc(ifp);
dindex = dindex->branch[bitbuf >> bit & 1];
}
pred[c] += dindex->leaf;
fputc (pred[c], tfp);
}
}
}
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()
{
struct decode *dindex;
short diff[1024];
unsigned bitbuf=0;
int pred[3], fixed, row, col, bit=-1, c, i;
fixed = get4();
read_shorts ((ushort *) diff, 1024);
if (!fixed) foveon_decoder (1024, 0);
for (row=0; row < height; row++) {
memset (pred, 0, sizeof pred);
if (!bit && !fixed && atoi(model+2) < 14) get4();
for (col=bit=0; col < width; col++) {
if (fixed) {
bitbuf = get4();
FORC3 pred[2-c] += diff[bitbuf >> c*10 & 0x3ff];
}
else FORC3 {
for (dindex=first_decode; dindex->branch[0]; ) {
if ((bit = (bit-1) & 31) == 31)
for (i=0; i < 4; i++)
bitbuf = (bitbuf << 8) + fgetc(ifp);
dindex = dindex->branch[bitbuf >> bit & 1];
}
pred[c] += diff[dindex->leaf];
if (pred[c] >> 16 && ~pred[c] >> 16) derror();
}
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();
}
const char * CLASS foveon_camf_param (const char *block, const char *param)
{
unsigned idx, num;
char *pos, *cp, *dp;
for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
pos = meta_data + idx;
if (strncmp (pos, "CMb", 3)) break;
if (pos[3] != 'P') continue;
if (strcmp (block, pos+sget4(pos+12))) continue;
cp = pos + sget4(pos+16);
num = sget4(cp);
dp = pos + sget4(cp+4);
while (num--) {
cp += 8;
if (!strcmp (param, dp+sget4(cp)))
return dp+sget4(cp+4);
}
}
return 0;
}
void * CLASS foveon_camf_matrix (unsigned dim[3], const char *name)
{
unsigned i, idx, type, ndim, size, *mat;
char *pos, *cp, *dp;
double dsize;
for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
pos = meta_data + idx;
if (strncmp (pos, "CMb", 3)) break;
if (pos[3] != 'M') continue;
if (strcmp (name, pos+sget4(pos+12))) continue;
dim[0] = dim[1] = dim[2] = 1;
cp = pos + sget4(pos+16);
type = sget4(cp);
if ((ndim = sget4(cp+4)) > 3) break;
dp = pos + sget4(cp+8);
for (i=ndim; i--; ) {
cp += 12;
dim[i] = sget4(cp);
}
if ((dsize = (double) dim[0]*dim[1]*dim[2]) > meta_length/4) break;
mat = (unsigned *) malloc ((size = dsize) * 4);
merror (mat, "foveon_camf_matrix()");
for (i=0; i < size; i++)
if (type && type != 6)
mat[i] = sget4(dp + i*4);
else
mat[i] = sget4(dp + i*2) & 0xffff;
return mat;
}
fprintf (stderr,_("%s: \"%s\" matrix not found!\n"), ifname, name);
return 0;
}
int CLASS foveon_fixed (void *ptr, int size, const char *name)
{
void *dp;
unsigned dim[3];
dp = foveon_camf_matrix (dim, name);
if (!dp) return 0;
memcpy (ptr, dp, size*4);
free (dp);
return 1;
}
float CLASS foveon_avg (short *pix, int range[2], float cfilt)
{
int i;
float val, min=FLT_MAX, max=-FLT_MAX, sum=0;
for (i=range[0]; i <= range[1]; i++) {
sum += val = pix[i*4] + (pix[i*4]-pix[(i-1)*4]) * cfilt;
if (min > val) min = val;
if (max < val) max = val;
}
if (range[1] - range[0] == 1) return sum/2;
return (sum - min - max) / (range[1] - range[0] - 1);
}
short * CLASS foveon_make_curve (double max, double mul, double filt)
{
short *curve;
unsigned i, size;
double x;
if (!filt) filt = 0.8;
size = 4*M_PI*max / filt;
if (size == UINT_MAX) size--;
curve = (short *) calloc (size+1, sizeof *curve);
merror (curve, "foveon_make_curve()");
curve[0] = size;
for (i=0; i < size; i++) {
x = i*filt/max/4;
curve[i+1] = (cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5;
}
return curve;
}
void CLASS foveon_make_curves
(short **curvep, float dq[3], float div[3], float filt)
{
double mul[3], max=0;
int c;
FORC3 mul[c] = dq[c]/div[c];
FORC3 if (max < mul[c]) max = mul[c];
FORC3 curvep[c] = foveon_make_curve (max, mul[c], filt);
}
int CLASS foveon_apply_curve (short *curve, int i)
{
if (abs(i) >= curve[0]) return 0;
return i < 0 ? -curve[1-i] : curve[1+i];
}
#define image ((short (*)[4]) image)
void CLASS foveon_interpolate()
{
static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 };
short *pix, prev[3], *curve[8], (*shrink)[3];
float cfilt=0, ddft[3][3][2], ppm[3][3][3];
float cam_xyz[3][3], correct[3][3], last[3][3], trans[3][3];
float chroma_dq[3], color_dq[3], diag[3][3], div[3];
float (*black)[3], (*sgain)[3], (*sgrow)[3];
float fsum[3], val, frow, num;
int row, col, c, i, j, diff, sgx, irow, sum, min, max, limit;
int dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3];
int work[3][3], smlast, smred, smred_p=0, dev[3];
int satlev[3], keep[4], active[4];
unsigned dim[3], *badpix;
double dsum=0, trsum[3];
char str[128];
const char* cp;
if (verbose)
fprintf (stderr,_("Foveon interpolation...\n"));
foveon_fixed (dscr, 4, "DarkShieldColRange");
foveon_fixed (ppm[0][0], 27, "PostPolyMatrix");
foveon_fixed (satlev, 3, "SaturationLevel");
foveon_fixed (keep, 4, "KeepImageArea");
foveon_fixed (active, 4, "ActiveImageArea");
foveon_fixed (chroma_dq, 3, "ChromaDQ");
foveon_fixed (color_dq, 3,
foveon_camf_param ("IncludeBlocks", "ColorDQ") ?
"ColorDQ" : "ColorDQCamRGB");
if (foveon_camf_param ("IncludeBlocks", "ColumnFilter"))
foveon_fixed (&cfilt, 1, "ColumnFilter");
memset (ddft, 0, sizeof ddft);
if (!foveon_camf_param ("IncludeBlocks", "DarkDrift")
|| !foveon_fixed (ddft[1][0], 12, "DarkDrift"))
for (i=0; i < 2; i++) {
foveon_fixed (dstb, 4, i ? "DarkShieldBottom":"DarkShieldTop");
for (row = dstb[1]; row <= dstb[3]; row++)
for (col = dstb[0]; col <= dstb[2]; col++)
FORC3 ddft[i+1][c][1] += (short) image[row*width+col][c];
FORC3 ddft[i+1][c][1] /= (dstb[3]-dstb[1]+1) * (dstb[2]-dstb[0]+1);
}
if (!(cp = foveon_camf_param ("WhiteBalanceIlluminants", model2)))
{ fprintf (stderr,_("%s: Invalid white balance \"%s\"\n"), ifname, model2);
return; }
foveon_fixed (cam_xyz, 9, cp);
foveon_fixed (correct, 9,
foveon_camf_param ("WhiteBalanceCorrections", model2));
memset (last, 0, sizeof last);
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
FORC3 last[i][j] += correct[i][c] * cam_xyz[c][j];
#define LAST(x,y) last[(i+x)%3][(c+y)%3]
for (i=0; i < 3; i++)
FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
#undef LAST
FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583;
sprintf (str, "%sRGBNeutral", model2);
if (foveon_camf_param ("IncludeBlocks", str))
foveon_fixed (div, 3, str);
num = 0;
FORC3 if (num < div[c]) num = div[c];
FORC3 div[c] /= num;
memset (trans, 0, sizeof trans);
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
FORC3 trans[i][j] += rgb_cam[i][c] * last[c][j] * div[j];
FORC3 trsum[c] = trans[c][0] + trans[c][1] + trans[c][2];
dsum = (6*trsum[0] + 11*trsum[1] + 3*trsum[2]) / 20;
for (i=0; i < 3; i++)
FORC3 last[i][c] = trans[i][c] * dsum / trsum[i];
memset (trans, 0, sizeof trans);
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
FORC3 trans[i][j] += (i==c ? 32 : -1) * last[c][j] / 30;
foveon_make_curves (curve, color_dq, div, cfilt);
FORC3 chroma_dq[c] /= 3;
foveon_make_curves (curve+3, chroma_dq, div, cfilt);
FORC3 dsum += chroma_dq[c] / div[c];
curve[6] = foveon_make_curve (dsum, dsum, cfilt);
curve[7] = foveon_make_curve (dsum*2, dsum*2, cfilt);
sgain = (float (*)[3]) foveon_camf_matrix (dim, "SpatialGain");
if (!sgain) return;
sgrow = (float (*)[3]) calloc (dim[1], sizeof *sgrow);
sgx = (width + dim[1]-2) / (dim[1]-1);
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]);
FORC3 black[row][c] =
( 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];
}
memcpy (black, black+8, sizeof *black*8);
memcpy (black+height-11, black+height-22, 11*sizeof *black);
memcpy (last, black, sizeof last);
for (row=1; row < height-1; row++) {
FORC3 if (last[1][c] > last[0][c]) {
if (last[1][c] > last[2][c])
black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c];
} else
if (last[1][c] < last[2][c])
black[row][c] = (last[0][c] < last[2][c]) ? last[0][c]:last[2][c];
memmove (last, last+1, 2*sizeof last[0]);
memcpy (last[2], black[row+1], sizeof last[2]);
}
FORC3 black[row][c] = (last[0][c] + last[1][c])/2;
FORC3 black[0][c] = (black[1][c] + black[3][c])/2;
val = 1 - exp(-1/24.0);
memcpy (fsum, black, sizeof fsum);
for (row=1; row < height; row++)
FORC3 fsum[c] += black[row][c] =
(black[row][c] - black[row-1][c])*val + black[row-1][c];
memcpy (last[0], black[height-1], sizeof last[0]);
FORC3 fsum[c] /= height;
for (row = height; row--; )
FORC3 last[0][c] = black[row][c] =
(black[row][c] - fsum[c] - last[0][c])*val + last[0][c];
memset (total, 0, sizeof total);
for (row=2; row < height; row+=4)
for (col=2; col < width; col+=4) {
FORC3 total[c] += (short) image[row*width+col][c];
total[3]++;
}
for (row=0; row < height; row++)
FORC3 black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0);
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]);
pix = image[row*width];
memcpy (prev, pix, sizeof prev);
frow = row / (height-1.0) * (dim[2]-1);
if ((irow = frow) == dim[2]-1) irow--;
frow -= irow;
for (i=0; i < dim[1]; i++)
FORC3 sgrow[i][c] = sgain[ irow *dim[1]+i][c] * (1-frow) +
sgain[(irow+1)*dim[1]+i][c] * frow;
for (col=0; col < width; col++) {
FORC3 {
diff = pix[c] - prev[c];
prev[c] = pix[c];
ipix[c] = pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt
- ddft[0][c][1] - ddft[0][c][0] * ((float) col/width - 0.5)
- black[row][c] );
}
FORC3 {
work[0][c] = ipix[c] * ipix[c] >> 14;
work[2][c] = ipix[c] * work[0][c] >> 14;
work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14;
}
FORC3 {
for (val=i=0; i < 3; i++)
for ( j=0; j < 3; j++)
val += ppm[c][i][j] * work[i][j];
ipix[c] = floor ((ipix[c] + floor(val)) *
( sgrow[col/sgx ][c] * (sgx - col%sgx) +
sgrow[col/sgx+1][c] * (col%sgx) ) / sgx / div[c]);
if (ipix[c] > 32000) ipix[c] = 32000;
pix[c] = ipix[c];
}
pix += 4;
}
}
free (black);
free (sgrow);
free (sgain);
if ((badpix = (unsigned int *) 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];
if ((unsigned)(row-1) > height-3 || (unsigned)(col-1) > width-3)
continue;
memset (fsum, 0, sizeof fsum);
for (sum=j=0; j < 8; j++)
if (badpix[i] & (1 << j)) {
FORC3 fsum[c] += (short)
image[(row+hood[j*2])*width+col+hood[j*2+1]][c];
sum++;
}
if (sum) FORC3 image[row*width+col][c] = fsum[c]/sum;
}
free (badpix);
}
/* Array for 5x5 Gaussian averaging of red values */
smrow[6] = (int (*)[3]) calloc (width*5, sizeof **smrow);
merror (smrow[6], "foveon_interpolate()");
for (i=0; i < 5; i++)
smrow[i] = smrow[6] + i*width;
/* Sharpen the reds against these Gaussian averages */
for (smlast=-1, row=2; row < height-2; row++) {
while (smlast < row+2) {
for (i=0; i < 6; i++)
smrow[(i+5) % 6] = smrow[i];
pix = image[++smlast*width+2];
for (col=2; col < width-2; col++) {
smrow[4][col][0] =
(pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4;
pix += 4;
}
}
pix = image[row*width+2];
for (col=2; col < width-2; col++) {
smred = ( 6 * smrow[2][col][0]
+ 4 * (smrow[1][col][0] + smrow[3][col][0])
+ smrow[0][col][0] + smrow[4][col][0] + 8 ) >> 4;
if (col == 2)
smred_p = smred;
i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 3);
if (i > 32000) i = 32000;
pix[0] = i;
smred_p = smred;
pix += 4;
}
}
/* Adjust the brighter pixels for better linearity */
min = 0xffff;
FORC3 {
i = satlev[c] / div[c];
if (min > i) min = i;
}
limit = min * 9 >> 4;
for (pix=image[0]; pix < image[height*width]; pix+=4) {
if (pix[0] <= limit || pix[1] <= limit || pix[2] <= limit)
continue;
min = max = pix[0];
for (c=1; c < 3; c++) {
if (min > pix[c]) min = pix[c];
if (max < pix[c]) max = pix[c];
}
if (min >= limit*2) {
pix[0] = pix[1] = pix[2] = max;
} else {
i = 0x4000 - ((min - limit) << 14) / limit;
i = 0x4000 - (i*i >> 14);
i = i*i >> 14;
FORC3 pix[c] += (max - pix[c]) * i >> 14;
}
}
/*
Because photons that miss one detector often hit another,
the sum R+G+B is much less noisy than the individual colors.
So smooth the hues without smoothing the total.
*/
for (smlast=-1, row=2; row < height-2; row++) {
while (smlast < row+2) {
for (i=0; i < 6; i++)
smrow[(i+5) % 6] = smrow[i];
pix = image[++smlast*width+2];
for (col=2; col < width-2; col++) {
FORC3 smrow[4][col][c] = (pix[c-4]+2*pix[c]+pix[c+4]+2) >> 2;
pix += 4;
}
}
pix = image[row*width+2];
for (col=2; col < width-2; col++) {
FORC3 dev[c] = -foveon_apply_curve (curve[7], pix[c] -
((smrow[1][col][c] + 2*smrow[2][col][c] + smrow[3][col][c]) >> 2));
sum = (dev[0] + dev[1] + dev[2]) >> 3;
FORC3 pix[c] += dev[c] - sum;
pix += 4;
}
}
for (smlast=-1, row=2; row < height-2; row++) {
while (smlast < row+2) {
for (i=0; i < 6; i++)
smrow[(i+5) % 6] = smrow[i];
pix = image[++smlast*width+2];
for (col=2; col < width-2; col++) {
FORC3 smrow[4][col][c] =
(pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8]+2) >> 2;
pix += 4;
}
}
pix = image[row*width+2];
for (col=2; col < width-2; col++) {
for (total[3]=375, sum=60, c=0; c < 3; c++) {
for (total[c]=i=0; i < 5; i++)
total[c] += smrow[i][col][c];
total[3] += total[c];
sum += pix[c];
}
if (sum < 0) sum = 0;
j = total[3] > 375 ? (sum << 16) / total[3] : sum * 174;
FORC3 pix[c] += foveon_apply_curve (curve[6],
((j*total[c] + 0x8000) >> 16) - pix[c]);
pix += 4;
}
}
/* Transform the image to a different colorspace */
for (pix=image[0]; pix < image[height*width]; pix+=4) {
FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]);
sum = (pix[0]+pix[1]+pix[1]+pix[2]) >> 2;
FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]-sum);
FORC3 {
for (dsum=i=0; i < 3; i++)
dsum += trans[c][i] * pix[i];
if (dsum < 0) dsum = 0;
if (dsum > 24000) dsum = 24000;
ipix[c] = dsum + 0.5;
}
FORC3 pix[c] = ipix[c];
}
/* Smooth the image bottom-to-top and save at 1/4 scale */
shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *shrink);
merror (shrink, "foveon_interpolate()");
for (row = height/4; row--; )
for (col=0; col < width/4; col++) {
ipix[0] = ipix[1] = ipix[2] = 0;
for (i=0; i < 4; i++)
for (j=0; j < 4; j++)
FORC3 ipix[c] += image[(row*4+i)*width+col*4+j][c];
FORC3
if (row+2 > height/4)
shrink[row*(width/4)+col][c] = ipix[c] >> 4;
else
shrink[row*(width/4)+col][c] =
(shrink[(row+1)*(width/4)+col][c]*1840 + ipix[c]*141 + 2048) >> 12;
}
/* From the 1/4-scale image, smooth right-to-left */
for (row=0; row < (height & ~3); row++) {
ipix[0] = ipix[1] = ipix[2] = 0;
if ((row & 3) == 0)
for (col = width & ~3 ; col--; )
FORC3 smrow[0][col][c] = ipix[c] =
(shrink[(row/4)*(width/4)+col/4][c]*1485 + ipix[c]*6707 + 4096) >> 13;
/* Then smooth left-to-right */
ipix[0] = ipix[1] = ipix[2] = 0;
for (col=0; col < (width & ~3); col++)
FORC3 smrow[1][col][c] = ipix[c] =
(smrow[0][col][c]*1485 + ipix[c]*6707 + 4096) >> 13;
/* Smooth top-to-bottom */
if (row == 0)
memcpy (smrow[2], smrow[1], sizeof **smrow * width);
else
for (col=0; col < (width & ~3); col++)
FORC3 smrow[2][col][c] =
(smrow[2][col][c]*6707 + smrow[1][col][c]*1485 + 4096) >> 13;
/* Adjust the chroma toward the smooth values */
for (col=0; col < (width & ~3); col++) {
for (i=j=30, c=0; c < 3; c++) {
i += smrow[2][col][c];
j += image[row*width+col][c];
}
j = (j << 16) / i;
for (sum=c=0; c < 3; c++) {
ipix[c] = foveon_apply_curve (curve[c+3],
((smrow[2][col][c] * j + 0x8000) >> 16) - image[row*width+col][c]);
sum += ipix[c];
}
sum >>= 3;
FORC3 {
i = image[row*width+col][c] + ipix[c] - sum;
if (i < 0) i = 0;
image[row*width+col][c] = i;
}
}
}
free (shrink);
free (smrow[6]);
for (i=0; i < 8; i++)
free (curve[i]);
/* Trim off the black border */
active[1] -= keep[1];
active[3] -= 2;
i = active[2] - active[0];
for (row=0; row < active[3]-active[1]; row++)
memcpy (image[row*i], image[(row+active[1])*width+active[0]],
i * sizeof *image);
width = i;
height = row;
}
#undef image
/* RESTRICTED code ends here */
/*
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;
if (!filters) return;
if (fname)
fp = fopen (fname, "r");
else {
for (len=32 ; ; len *= 2) {
fname = (char *) malloc (len);
if (!fname) return;
if (getcwd (fname, len-16)) break;
free (fname);
if (errno != ERANGE) return;
}
#if defined(WIN32) || defined(DJGPP)
if (fname[1] == ':')
memmove (fname, fname+2, len-2);
for (cp=fname; *cp; cp++)
if (*cp == '\\') *cp = '/';
#endif
cp = fname + strlen(fname);
if (cp[-1] == '/') cp--;
while (*fname == '/') {
strcpy (cp, "/.badpixels");
if ((fp = fopen (fname, "r"))) break;
if (cp == fname) break;
while (*--cp != '/');
}
free (fname);
}
if (!fp) 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;
if (verbose) {
if (!fixed++)
fprintf (stderr,_("Fixed dead pixels at:"));
fprintf (stderr, " %d,%d", col, row);
}
}
if (fixed) fputc ('\n', stderr);
fclose (fp);
}
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;
if (!(fp = fopen (fname, "rb"))) {
perror (fname); 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) {
fprintf (stderr,_("%s has the wrong dimensions!\n"), fname);
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;
}
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 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);
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 (" } },");
}
#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))];
}
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 };
if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
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(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(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);
}
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;
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];
}
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];
else if (cam_mul[0] && cam_mul[2])
memcpy (pre_mul, cam_mul, sizeof pre_mul);
else
fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname);
}
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;
if (verbose) {
fprintf (stderr,
_("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat);
FORC4 fprintf (stderr, " %f", pre_mul[c]);
fputc ('\n', stderr);
}
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) {
if (verbose)
fprintf (stderr,_("Correcting chromatic aberration...\n"));
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);
}
}
}
void CLASS pre_interpolate()
{
ushort (*img)[4];
int row, col, c;
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;
}
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;
if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
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];
}
}
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;
}
}
/*
This algorithm is officially called:
"Interpolation using a Threshold-based variable number of gradients"
described in http://scien.stanford.edu/class/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()
{
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 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);
merror (ip, "vng_interpolate()");
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 = 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< 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]);
}
/*
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);
if (verbose) fprintf (stderr,_("PPG interpolation...\n"));
/* Fill in the green layer with gradients and pattern recognition: */
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: */
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: */
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 */
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;
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];
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)
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);
}
#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++) {
if (verbose)
fprintf (stderr,_("Median filter pass %d...\n"), pass);
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;
if (verbose) fprintf (stderr,_("Blending highlights...\n"));
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;
}
}
#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} };
if (verbose) fprintf (stderr,_("Rebuilding highlights...\n"));
grow = pow (2, 4-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) {
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);
}
}
int CLASS parse_tiff_ifd (int base);
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];
}
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 == 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 == 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();
}
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();
break;
case 102:
fseek (ifp, 6, SEEK_CUR);
goto get2_rggb;
case 103:
fseek (ifp, 16, SEEK_CUR);
FORC4 cam_mul[c] = get2();
}
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();
}
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);
}
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 == 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;
}
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;
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;
if (tag == 0x1018 || tag == 0x20400100)
cam_mul[2] = get2() / 256.0;
if (tag == 0x2011 && len == 2) {
get2_256:
order = 0x4d4d;
cam_mul[0] = get2() / 256.0;
cam_mul[2] = get2() / 256.0;
}
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();
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];
}
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];
}
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);
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();
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]);
}
if (tag == 2317) linear_table (len);
if (tag == 6020) iso_speed = getint(type);
fseek (ifp, save, SEEK_SET);
}
}
void CLASS parse_minolta (int base);
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;
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();
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].width = getint(type);
break;
case 3: case 257: /* ImageHeight */
tiff_ifd[ifd].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].width = jh.wide << (jh.clrs == 2);
tiff_ifd[ifd].height = jh.high;
tiff_ifd[ifd].bps = jh.bits;
tiff_ifd[ifd].samples = jh.clrs;
}
}
break;
case 274: /* Orientation */
tiff_ifd[ifd].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].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);
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();
break;
case 29459:
FORC4 cam_mul[c ^ (c >> 1)] = get2();
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();
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;
}
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);
}
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);
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);
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);
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;
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];
}
if (!use_cm)
FORCC pre_mul[c] /= cc[c][c];
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].width*tiff_ifd[i].height > raw_width*raw_height) {
raw_width = tiff_ifd[i].width;
raw_height = tiff_ifd[i].height;
tiff_bps = tiff_ifd[i].bps;
tiff_compress = tiff_ifd[i].comp;
data_offset = tiff_ifd[i].offset;
tiff_flip = tiff_ifd[i].flip;
tiff_samples = tiff_ifd[i].samples;
raw = i;
}
}
fuji_width *= (raw_width+1)/2;
if (tiff_ifd[0].flip) tiff_flip = tiff_ifd[0].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].width * tiff_ifd[i].height / SQR(tiff_ifd[i].bps+1) >
thumb_width * thumb_height / SQR(thumb_misc+1)) {
thumb_width = tiff_ifd[i].width;
thumb_height = tiff_ifd[i].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();
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;
FILE *save=ifp;
ext = strrchr (ifname, '.');
file = strrchr (ifname, '/');
if (!file) file = strrchr (ifname, '\\');
if (!file) file = ifname-1;
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';
}
if (strcmp (jname, ifname)) {
if ((ifp = fopen (jname, "rb"))) {
if (verbose)
fprintf (stderr,_("Reading metadata from %s ...\n"), jname);
parse_tiff (12);
thumb_offset = 0;
is_raw = 1;
fclose (ifp);
}
}
if (!timestamp)
fprintf (stderr,_("Failed to read metadata from %s\n"), jname);
free (jname);
ifp = save;
}
/*
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, -int_to_float((get4(),get4())));
aperture = pow (2, 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();
} else { /* G2, S30, S40 */
fseek (ifp, 98, SEEK_CUR);
FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2();
}
}
if (type == 0x0032) {
if (len == 768) { /* EOS D30 */
fseek (ifp, 72, SEEK_CUR);
FORC4 cam_mul[c ^ (c >> 1)] = 1024.0 / get2();
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];
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();
}
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 (×tamp));
#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);
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.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();
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) < end)
parse_riff();
} else if (!memcmp(tag,"nctg",4)) {
while (ftell(ifp) < 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);
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;
}
char * CLASS foveon_gets (int offset, char *str, int len)
{
int i;
fseek (ifp, offset, SEEK_SET);
for (i=0; i < len-1; i++)
if ((str[i] = get2()) == 0) break;
str[i] = 0;
return str;
}
void CLASS parse_foveon()
{
int entries, img=0, off, len, tag, save, i, wide, high, pent, poff[256][2];
char name[64], value[64];
order = 0x4949; /* Little-endian */
fseek (ifp, 36, SEEK_SET);
flip = get4();
fseek (ifp, -4, SEEK_END);
fseek (ifp, get4(), SEEK_SET);
if (get4() != 0x64434553) return; /* SECd */
entries = (get4(),get4());
while (entries--) {
off = get4();
len = get4();
tag = get4();
save = ftell(ifp);
fseek (ifp, off, SEEK_SET);
if (get4() != (0x20434553 | (tag << 24))) return;
switch (tag) {
case 0x47414d49: /* IMAG */
case 0x32414d49: /* IMA2 */
fseek (ifp, 12, SEEK_CUR);
wide = get4();
high = get4();
if (wide > raw_width && high > raw_height) {
raw_width = wide;
raw_height = high;
data_offset = off+24;
}
fseek (ifp, off+28, SEEK_SET);
if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8
&& thumb_length < len-28) {
thumb_offset = off+28;
thumb_length = len-28;
write_thumb = &CLASS jpeg_thumb;
}
if (++img == 2 && !thumb_length) {
thumb_offset = off+24;
thumb_width = wide;
thumb_height = high;
write_thumb = &CLASS foveon_thumb;
}
break;
case 0x464d4143: /* CAMF */
meta_offset = off+24;
meta_length = len-28;
if (meta_length > 0x20000)
meta_length = 0x20000;
break;
case 0x504f5250: /* PROP */
pent = (get4(),get4());
fseek (ifp, 12, SEEK_CUR);
off += pent*8 + 24;
if ((unsigned) pent > 256) pent=256;
for (i=0; i < pent*2; i++)
poff[0][i] = off + get4()*2;
for (i=0; i < pent; i++) {
foveon_gets (poff[i][0], name, 64);
foveon_gets (poff[i][1], value, 64);
if (!strcmp (name, "ISO"))
iso_speed = atoi(value);
if (!strcmp (name, "CAMMANUF"))
strcpy (make, value);
if (!strcmp (name, "CAMMODEL"))
strcpy (model, value);
if (!strcmp (name, "WB_DESC"))
strcpy (model2, value);
if (!strcmp (name, "TIME"))
timestamp = atoi(value);
if (!strcmp (name, "EXPTIME"))
shutter = atoi(value) / 1000000.0;
if (!strcmp (name, "APERTURE"))
aperture = atof(value);
if (!strcmp (name, "FLENGTH"))
focal_len = atof(value);
}
#ifdef LOCALTIME
timestamp = mktime (gmtime (×tamp));
#endif
}
fseek (ifp, save, SEEK_SET);
}
is_foveon = 1;
}
/*
Thanks to Adobe for providing these excellent CAM -> XYZ matrices!
*/
void CLASS adobe_coeff (char *make, char *model)
{
static const struct {
const char *prefix;
short black, maximum, 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 } },
{ "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", 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 = (ushort) table[i].black;
if (table[i].maximum) maximum = (ushort) table[i].maximum;
for (j=0; j < 12; j++)
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];
}
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 make[12], 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" };
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;
}
colors = 3;
tiff_bps = 12;
for (i=0; i < 0x4000; 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);
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();
} 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].make );
strcpy (model, table[i].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;
} 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;
}
} 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;
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;
}
} 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;
} 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 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;
} 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;
} 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;
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;
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);
} 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 (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;
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;
} 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;
} else if (!strcmp(model,"QV-R51")) {
height = 1926;
width = 2580;
raw_width = 3904;
pre_mul[0] = 1.340;
pre_mul[2] = 1.672;
} else if (!strcmp(model,"EX-S100")) {
height = 1544;
width = 2058;
raw_width = 3136;
pre_mul[0] = 1.631;
pre_mul[2] = 1.106;
} else if (!strcmp(model,"EX-Z50")) {
height = 1931;
width = 2570;
raw_width = 3904;
pre_mul[0] = 2.529;
pre_mul[2] = 1.185;
} else if (!strcmp(model,"EX-Z55")) {
height = 1960;
width = 2570;
raw_width = 3904;
pre_mul[0] = 1.520;
pre_mul[2] = 1.316;
} 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;
} 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;
} else if (!strcmp(model,"EX-P700")) {
height = 2318;
width = 3082;
raw_width = 4672;
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)) {
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) {
fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname);
is_raw = 0;
}
#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;
}
#ifndef NO_LCMS
void CLASS apply_profile (char *input, char *output)
{
char *prof;
cmsHPROFILE hInProfile=0, hOutProfile=0;
cmsHTRANSFORM hTransform;
FILE *fp;
unsigned size;
cmsErrorAction (LCMS_ERROR_SHOW);
if (strcmp (input, "embed"))
hInProfile = cmsOpenProfileFromFile (input, "r");
else if (profile_length) {
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
fprintf (stderr,_("%s has no embedded profile.\n"), ifname);
if (!hInProfile) 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;
}
} else
fprintf (stderr,_("Cannot open file %s!\n"), output);
if (!hOutProfile) goto quit;
if (verbose)
fprintf (stderr,_("Applying color profile...\n"));
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);
}
#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];
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 };
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)
#ifdef SRGB_GAMMA
pcurve[3] = 0x2330000;
#else
pcurve[3] = 0x1f00000;
#endif
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];
}
if (verbose)
fprintf (stderr, raw_color ? _("Building histograms...\n") :
_("Converting to %s colorspace...\n"), name[output_color-1]);
memset (histogram, 0, sizeof histogram);
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;
}
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;
if (verbose)
fprintf (stderr,_("Rotating image 45 degrees...\n"));
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()");
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;
}
void CLASS stretch()
{
ushort newdim, (*img)[4], *pix0, *pix1;
int row, col, c;
double rc, frac;
if (pixel_aspect == 1) return;
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);
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;
}
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 (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;
union { char c[4]; short s[2]; int i; } val;
};
struct tiff_hdr {
ushort order, magic;
int ifd;
ushort pad, ntag;
struct tiff_tag tag[23];
int nextifd;
ushort pad2, nexif;
struct tiff_tag exif[4];
ushort pad3, ngps;
struct tiff_tag gpst[10];
short bps[4];
int rat[10];
unsigned gps[26];
char desc[512], make[64], model[64], soft[32], date[20], artist[64];
};
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->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;
th->rat[4] *= shutter;
th->rat[6] *= aperture;
th->rat[8] *= focal_len;
strncpy (th->desc, desc, 512);
strncpy (th->make, make, 64);
strncpy (th->model, model, 64);
strcpy (th->soft, "dcraw v"VERSION);
t = gmtime (×tamp);
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);
}
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);
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);
free (thumb);
}
void CLASS write_ppm_tiff (FILE *ofp)
{
struct tiff_hdr th;
uchar *ppm, lut[0x10000];
ushort *ppm2;
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_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];
if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
swab (ppm2, ppm2, width*colors*2);
fwrite (ppm, colors*output_bps/8, width, ofp);
}
free (ppm);
}
int CLASS main (int argc, char **argv)
{
int arg, status=0;
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;
struct utimbuf ut;
FILE *ofp;
#ifndef NO_LCMS
char *cam_profile=0, *out_profile=0;
#endif
#ifndef LOCALTIME
putenv ("TZ=UTC");
#endif
#ifdef LOCALEDIR
setlocale (LC_CTYPE, "");
setlocale (LC_MESSAGES, "");
bindtextdomain ("dcraw", LOCALEDIR);
textdomain ("dcraw");
#endif
if (argc == 1) {
printf(_("\nRaw photo decoder \"dcraw\" v%s"), 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"));
puts(_("-c Write image data to standard output"));
puts(_("-e Extract embedded thumbnail image"));
puts(_("-i Identify files without decoding them"));
puts(_("-i -v Identify files and show metadata"));
puts(_("-z Change file dates to camera timestamp"));
puts(_("-w Use camera white balance, if possible"));
puts(_("-a Average the whole image for white balance"));
puts(_("-A Average a grey box for white balance"));
puts(_("-r Set custom white balance"));
puts(_("+M/-M Use/don't use an embedded color matrix"));
puts(_("-C Correct chromatic aberration"));
puts(_("-P Fix the dead pixels listed in this file"));
puts(_("-K Subtract dark frame (16-bit raw PGM)"));
puts(_("-k Set the darkness level"));
puts(_("-S Set the saturation level"));
puts(_("-n 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)"));
#ifndef NO_LCMS
puts(_("-o Apply output ICC profile from file"));
puts(_("-p Apply camera ICC profile from file or \"embed\""));
#endif
puts(_("-d Document mode (no color, no interpolation)"));
puts(_("-D Document mode without scaling (totally raw)"));
puts(_("-j Don't stretch or rotate raw pixels"));
puts(_("-W Don't automatically brighten the image"));
puts(_("-b Adjust brightness (default = 1.0)"));
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 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(_("-T Write TIFF instead of PPM"));
puts("");
return 1;
}
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 (!isdigit(argv[arg+i][0])) {
fprintf (stderr,_("Non-numeric argument to \"-%c\"\n"), opt);
return 1;
}
switch (opt) {
case 'n': threshold = atof(argv[arg++]); break;
case 'b': bright = atof(argv[arg++]); break;
case 'r':
FORC4 user_mul[c] = atof(argv[arg++]); break;
case 'C': aber[0] = 1 / atof(argv[arg++]);
aber[2] = 1 / atof(argv[arg++]); 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;
case 'q': user_qual = atoi(argv[arg++]); break;
case 'm': med_passes = atoi(argv[arg++]); break;
case 'H': highlight = atoi(argv[arg++]); break;
case 's':
shot_select = abs(atoi(argv[arg]));
multi_out = !strcmp(argv[arg++],"all");
break;
case 'o':
if (isdigit(argv[arg][0]) && !argv[arg][1])
output_color = atoi(argv[arg++]);
#ifndef NO_LCMS
else out_profile = argv[arg++];
break;
case 'p': cam_profile = argv[arg++];
#endif
break;
case 'P': bpfile = argv[arg++]; break;
case 'K': dark_frame = argv[arg++]; break;
case 'z': timestamp_only = 1; break;
case 'e': thumbnail_only = 1; break;
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 '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 '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;
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;
}
if (write_to_stdout) {
if (isatty(1)) {
fprintf (stderr,_("Will not write an image to the terminal!\n"));
return 1;
}
#if defined(WIN32) || defined(DJGPP) || defined(__CYGWIN__)
if (setmode(1,O_BINARY) < 0) {
perror ("setmode()");
return 1;
}
#endif
}
for ( ; arg < argc; arg++) {
status = 1;
image = 0;
oprof = 0;
meta_data = ofname = 0;
ofp = stdout;
if (setjmp (failure)) {
if (fileno(ifp) > 2) fclose(ifp);
if (fileno(ofp) > 2) fclose(ofp);
status = 1;
goto cleanup;
}
ifname = argv[arg];
if (!(ifp = fopen (ifname, "rb"))) {
perror (ifname);
continue;
}
status = (identify(),!is_raw);
if (user_flip >= 0)
flip = user_flip;
switch ((flip+3600) % 360) {
case 270: flip = 5; break;
case 180: flip = 3; break;
case 90: flip = 6;
}
if (timestamp_only) {
if ((status = !timestamp))
fprintf (stderr,_("%s has no timestamp.\n"), ifname);
else if (identify_only)
printf ("%10ld%10d %s\n", (long) timestamp, shot_order, ifname);
else {
if (verbose)
fprintf (stderr,_("%s time set to %d.\n"), ifname, (int) timestamp);
ut.actime = ut.modtime = timestamp;
utime (ifname, &ut);
}
goto next;
}
write_fun = &CLASS write_ppm_tiff;
if (thumbnail_only) {
if ((status = !thumb_offset)) {
fprintf (stderr,_("%s has no thumbnail.\n"), ifname);
goto next;
} else if (thumb_load_raw) {
load_raw = thumb_load_raw;
data_offset = thumb_offset;
height = thumb_height;
width = thumb_width;
filters = 0;
} else {
fseek (ifp, thumb_offset, SEEK_SET);
write_fun = write_thumb;
goto thumbnail;
}
}
if (load_raw == &CLASS kodak_ycbcr_load_raw) {
height += height & 1;
width += width & 1;
}
if (identify_only && verbose && make[0]) {
printf (_("\nFilename: %s\n"), ifname);
printf (_("Timestamp: %s"), ctime(×tamp));
printf (_("Camera: %s %s\n"), make, model);
if (artist[0])
printf (_("Owner: %s\n"), artist);
if (dng_version) {
printf (_("DNG Version: "));
for (i=24; i >= 0; i -= 8)
printf ("%d%c", dng_version >> i & 255, i ? '.':'\n');
}
printf (_("ISO speed: %d\n"), (int) iso_speed);
printf (_("Shutter: "));
if (shutter > 0 && shutter < 1)
shutter = (printf ("1/"), 1 / shutter);
printf (_("%0.1f sec\n"), shutter);
printf (_("Aperture: f/%0.1f\n"), aperture);
printf (_("Focal length: %0.1f mm\n"), focal_len);
printf (_("Embedded ICC profile: %s\n"), profile_length ? _("yes"):_("no"));
printf (_("Number of raw images: %d\n"), is_raw);
if (pixel_aspect != 1)
printf (_("Pixel Aspect Ratio: %0.6f\n"), pixel_aspect);
if (thumb_offset)
printf (_("Thumb size: %4d x %d\n"), thumb_width, thumb_height);
printf (_("Full size: %4d x %d\n"), raw_width, raw_height);
} 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);
iheight = (height + shrink) >> shrink;
iwidth = (width + shrink) >> shrink;
if (identify_only) {
if (verbose) {
if (use_fuji_rotate) {
if (fuji_width) {
fuji_width = (fuji_width - 1 + shrink) >> shrink;
iwidth = fuji_width / sqrt(0.5);
iheight = (iheight - fuji_width) / sqrt(0.5);
} else {
if (pixel_aspect < 1) iheight = iheight / pixel_aspect + 0.5;
if (pixel_aspect > 1) iwidth = iwidth * pixel_aspect + 0.5;
}
}
if (flip & 4)
SWAP(iheight,iwidth);
printf (_("Image size: %4d x %d\n"), width, height);
printf (_("Output size: %4d x %d\n"), iwidth, iheight);
printf (_("Raw colors: %d"), colors);
if (filters) {
printf (_("\nFilter pattern: "));
if (!cdesc[3]) cdesc[3] = 'G';
for (i=0; i < 16; i++)
putchar (cdesc[fc(i >> 1,i & 1)]);
}
printf (_("\nDaylight multipliers:"));
FORCC printf (" %f", pre_mul[c]);
if (cam_mul[0] > 0) {
printf (_("\nCamera multipliers:"));
FORC4 printf (" %f", cam_mul[c]);
}
putchar ('\n');
} else
printf (_("%s is a %s %s image.\n"), ifname, make, model);
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 (verbose)
fprintf (stderr,_("Loading %s %s image from %s ...\n"),
make, model, ifname);
if (shot_select >= is_raw)
fprintf (stderr,_("%s: \"-s %d\" requests a nonexistent image!\n"),
ifname, shot_select);
fseeko (ifp, data_offset, SEEK_SET);
(*load_raw)();
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;
if (user_black >= 0) black = user_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();
pre_interpolate();
if (filters && !document_mode) {
if (quality == 0)
lin_interpolate();
else if (quality == 1 || colors > 3)
vng_interpolate();
else if (quality == 2)
ppg_interpolate();
else ahd_interpolate();
}
if (mix_green)
for (colors=3, i=0; i < height*width; i++)
image[i][1] = (image[i][1] + image[i][3]) >> 1;
if (!is_foveon && colors == 3) median_filter();
if (!is_foveon && highlight == 2) blend_highlights();
if (!is_foveon && highlight > 2) recover_highlights();
if (use_fuji_rotate) fuji_rotate();
#ifndef NO_LCMS
if (cam_profile) apply_profile (cam_profile, out_profile);
#endif
convert_to_rgb();
if (use_fuji_rotate) stretch();
thumbnail:
if (write_fun == &CLASS jpeg_thumb)
write_ext = ".jpg";
else if (output_tiff && write_fun == &CLASS write_ppm_tiff)
write_ext = ".tiff";
else
write_ext = ".pgm\0.ppm\0.ppm\0.pam" + colors*5-5;
ofname = (char *) malloc (strlen(ifname) + 64);
merror (ofname, "main()");
if (write_to_stdout)
strcpy (ofname,_("standard output"));
else {
strcpy (ofname, ifname);
if ((cp = strrchr (ofname, '.'))) *cp = 0;
if (multi_out)
sprintf (ofname+strlen(ofname), "_%0*d",
snprintf(0,0,"%d",is_raw-1), shot_select);
if (thumbnail_only)
strcat (ofname, ".thumb");
strcat (ofname, write_ext);
ofp = fopen (ofname, "wb");
if (!ofp) {
status = 1;
perror (ofname);
goto cleanup;
}
}
if (verbose)
fprintf (stderr,_("Writing data to %s ...\n"), ofname);
(*write_fun)(ofp);
fclose(ifp);
if (ofp != stdout) fclose(ofp);
cleanup:
if (meta_data) free (meta_data);
if (ofname) free (ofname);
if (oprof) free (oprof);
if (image) free (image);
if (multi_out) {
if (++shot_select < is_raw) arg--;
else shot_select = 0;
}
}
return status;
}
@
1.417
log
@Get camera WB from ARW files edited by Sony IDC software.
@
text
@d3 1
a3 1
Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net
d26 1
a26 1
#define VERSION "8.90"
d5160 3
d7352 5
@
1.416
log
@Fixed an overflow bug in wavelet_denoise().
@
text
@d5041 3
@
1.415
log
@Support the Samsung S85 at ISO 800 and higher.
@
text
@d3668 1
a3668 1
fimg[i] = sqrt((unsigned) (image[i][c] << (scale+16)));
@
1.414
log
@Better support the Apple QuickTake 100.
@
text
@d6578 1
d7246 1
a7246 1
raw_width = 3288;
d7249 1
a7249 1
maximum = 0xfef8;
@
1.413
log
@Support the Samsung S85.
@
text
@d7666 9
a7674 1
data_offset = 736;
d7676 1
a7676 1
goto qt_common;
a7680 1
qt_common:
@
1.412
log
@Regardless of the Software tag, a DNG file is always raw.
@
text
@d26 1
a26 1
#define VERSION "8.89"
d5456 1
a5456 1
merror (jname, "parse_external()");
d5462 4
a5465 2
memcpy (jfile, file+4, 4);
memcpy (jfile+4, file, 4);
d6577 1
d7242 7
@
1.411
log
@Support 3672 x 2486 images from the Panasonic DMC-FZ50.
@
text
@d5171 1
@
1.410
log
@Support FFF format from the Hasselblad H3D.
@
text
@d7429 1
a7429 1
height += 36;
a7430 1
filters = 0x49494949;
d7434 1
a7434 1
if ((height -= 39) == 2760)
d7436 1
@
1.409
log
@Correctly handle negative pixels in split NEF files.
@
text
@d1679 1
d1693 1
d5119 1
@
1.408
log
@Support GPS-tagged ORFs and anonymous DNGs.
@
text
@d1142 1
a1142 1
int i, max, step=0, huff=0, split=0, row, col, len, shl, diff;
d1165 1
d1170 1
a1170 1
for (row=0; row < height; row++) {
d1174 1
d1186 1
a1186 1
if (hpred[col & 1] >= max) derror();
d1188 1
a1188 1
BAYER(row,col-left_margin) = curve[hpred[col & 1] & 0x3fff];
@
1.407
log
@Correctly handle edges of Canon sRAW images.
@
text
@d4652 3
a4654 1
if (tag == 0x2010 && type == 13)
d5165 1
@
1.406
log
@Show exposure from Canon MakerNote only if EXIF values are missing.
Support the sRAW1 and sRAW2 modes of the Canon EOS 50D and 5D Mark II.
Support the Leaf AFi 7, Panasonic FX150 and G1, and Canon PowerShot G10.
@
text
@d1002 4
a1005 2
ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1;
for (col=1; col < width-1; col+=2)
d1007 3
a1009 1
ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
@
1.405
log
@Detect and correct even/odd dark skew in Canon images.
Merged three other functions into packed_12_load_raw().
Support the Panasonics LX3 and FZ28, Nikons D90 and P6000,
Canon EOS 50D, and Sony A900.
@
text
@d26 1
a26 1
#define VERSION "8.88"
d816 2
a817 2
int bits, high, wide, clrs, sraw, psv, restart, vpred[4];
struct CLASS decode *huff[4];
d823 1
a823 1
int i, tag, len;
d828 1
a828 2
for (i=0; i < 4; i++)
jh->huff[i] = free_decode;
d840 1
a840 1
jh->sraw = data[7] == 0x21;
d857 1
d865 2
a866 2
jh->huff[3] = jh->huff[2] = jh->huff[1];
jh->huff[1] = jh->huff[0];
d890 1
a890 1
int col, c, diff, pred;
d894 1
a894 1
FORC4 jh->vpred[c] = 1 << (jh->bits-1);
d904 2
a905 2
if (jh->sraw && c < 2 && (col | c))
pred = row[0][(c << 1)-3];
d919 1
d973 1
a973 1
short *rp=0, *ip;
d977 1
a977 1
jwide = (jh.wide >>= 1) * 4;
d981 5
a985 5
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) {
d988 5
a992 4
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;
d996 22
a1017 13
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);
d1019 1
d1268 1
a1268 1
int i;
d1273 3
a1275 3
for (i=0; i < sizeof tail; i++)
if (tail[i]) return 1;
return 0;
d4503 3
a4505 2
iso_speed = 50 * pow (2, (get4(),get2())/32.0 - 4);
if ((i=(get2(),get2())) != 0x7fff)
d4507 1
a4507 1
if ((i=get2()) != 0xffff)
d4658 2
a4659 2
if (tag == 0x4001 && type == 3) {
i = len == 582 ? 50 : len == 653 ? 68 : 126;
d4771 1
a4771 1
"Aptus 54S","Aptus 65S","Aptus 75S" };
d4942 1
a4942 1
if (~tiff_ifd[ifd].offset) break;
d4969 1
a4969 1
case 305: /* Software */
d4973 1
d5808 1
a5809 1
end = ftell(ifp) + size;
d5813 8
d6020 2
d6034 2
d6045 1
a6045 1
{ 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
d6066 2
d6164 2
d6272 2
a6273 2
{ "NIKON D90", 0, 0xf00, /* DJC */
{ 9692,-2519,-831,-5396,13053,2344,-1818,2682,7084 } },
d6304 2
d6372 2
d6378 2
d6394 6
d6428 2
a6429 2
{ "SONY DSLR-A900", 254, 0x1ffe, /* DJC */
{ 6971,-1730,-794,-5763,13529,2236,-1500,2251,6715 } }
d6716 2
d6751 4
d6962 6
d6972 5
a6976 1
maximum = 0x3d93;
d7335 3
d7401 1
a7401 1
width -= 16;
d7405 2
a7406 2
width = 3291;
left_margin = 9;
a7407 1
goto fz18;
d7409 3
a7411 3
width = 3288;
left_margin = 15;
fz18: if (height > 2480)
d7415 1
a7415 1
break;
d7431 1
a7431 1
break;
d7435 4
a7438 5
width += 36;
case 4060:
width -= 78;
filters = 0x16161616;
maximum = 0xfff;
d7445 7
d7462 5
@
1.404
log
@Support the Kodak C603, Nikon D700, Canon EOS 1000D,
Canon PowerShot SD300, and Olympus E-520.
Removed useless code from ppg_interpolate().
@
text
@d26 1
a26 1
#define VERSION "8.87"
d116 1
a116 1
unsigned tile_width, tile_length, gpsdata[32];
d347 14
d555 1
a555 1
if (vbits < 10)
d557 1
a557 1
pixel = buf >> (vbits -= 10) & 0x3ff;
d742 1
d802 2
a803 2
else
black += pixel[r*raw_width+col];
d808 1
a808 2
if (raw_width > width)
black /= (raw_width - width) * height;
d927 1
d956 2
a957 1
} else black += val;
d964 1
a964 2
if (raw_width > width)
black /= (raw_width - width) * height;
a1174 25
void CLASS nikon_load_raw()
{
int irow, row, col, i;
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 (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();
}
}
}
a1282 28
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);
}
}
d1595 1
a1595 1
if (vbits < nbits) {
a1598 1
vbits -= nbits;
d1758 2
a1759 1
int row, col;
d1761 29
a1789 10
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();
d1791 1
d1838 12
a1849 6
static uchar buf[16], vbits=0;
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);
d1856 1
a1856 1
raw_width = (raw_width+13)/14*14;
d1859 4
a1862 4
if ((i = col % 14) < 2)
nonz[i] = pred[i] = pana_bits(12);
else {
if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
d1866 1
a1866 2
pred[i & 1] += nonz[i & 1] ? j << sh : j;
nonz[i & 1] = 1;
d1868 2
a1869 1
}
d1871 1
a1871 1
if ((BAYER(row,col) = pred[col & 1]) >> 12) derror();
a1942 16
void CLASS olympus_cseries_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;
}
d4552 1
a4552 1
ver97 = (ver97 << 4) + fgetc(ifp)-'0';
d4554 1
a4554 1
case 0x100:
d4558 1
a4558 1
case 0x102:
d4561 1
a4561 1
case 0x103:
d4565 2
a4566 2
if (ver97 >> 8 == 2) {
if (ver97 != 0x205) fseek (ifp, 280, SEEK_CUR);
d4574 1
a4574 1
if (tag == 0xa7 && ver97 >> 8 == 2) {
d4580 3
a4582 5
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);
d4928 4
d5305 2
a5306 2
if (!strncmp(make,"NIKON",5))
load_raw = &CLASS nikon_load_raw;
a5312 2
if (tiff_bps == 12 && tiff_ifd[raw].phint == 2)
load_raw = &CLASS olympus_cseries_load_raw;
d5325 1
a5325 1
load_raw = &CLASS nikon_load_raw; break;
d5805 1
a5805 1
for (i=0; i < 12 && strcmp(mon[i],month); i++);
d6074 2
d6242 2
d6385 3
a6387 1
{ 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } }
d6539 1
a6539 1
kodak_cbpp = zero_after_ff = dng_version = 0;
d6687 6
a6692 2
if (!strcmp(make,"NIKON") && !load_raw)
load_raw = &CLASS nikon_load_raw;
d6706 1
a6706 1
} else if (is_canon && tiff_samples == 4) {
d6914 6
d6950 2
d6954 2
a6955 1
load_raw = &CLASS nikon_load_raw;
d6970 3
d6998 2
a6999 1
load_raw = &CLASS nikon_load_raw;
d7013 1
a7013 1
load_raw = &CLASS nikon_e2100_load_raw;
d7024 2
a7025 1
load_raw = &CLASS nikon_e2100_load_raw;
d7045 2
a7046 2
if (make[0] == 'M')
load_raw = &CLASS nikon_e2100_load_raw;
d7061 2
a7062 1
load_raw = &CLASS nikon_e2100_load_raw;
d7166 2
a7167 1
load_raw = &CLASS nikon_e2100_load_raw;
d7372 9
d7401 2
a7402 1
load_raw = &CLASS nikon_e2100_load_raw;
@
1.403
log
@Don't crash on corrupt CR2 files.
Extract the largest JPEG from any X3F file.
@
text
@d26 1
a26 1
#define VERSION "8.86"
d2316 24
d3849 1
a3849 1
merror (img, "unshrink()");
d4076 2
a4077 3
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 };
a4086 14
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;
}
}
a4097 1
next_pixel: ;
d6046 2
d6106 2
d6262 2
d6324 2
a6325 2
{ "OLYMPUS E-420", 0, 0xfd7, /* copied from above */
{ 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
d6330 2
d6484 5
d6514 1
d6757 8
d6908 2
d6954 4
a6976 3
} else if (!strcmp(model,"D3")) {
width -= 4;
left_margin = 2;
d7446 14
d7467 1
@
1.402
log
@Added SONY A300 (dcraw's 300th camera!), fixed camera WB on the A200.
Set model-specific saturation levels in adobe_coeff().
@
text
@d925 1
a925 1
val = curve[val];
d5944 2
a5945 1
if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8) {
@
1.401
log
@Support the Olympus E-420.
@
text
@d26 1
a26 1
#define VERSION "8.85"
a1884 2
maximum = 0xf96;
black = 15;
a2585 1
maximum = 0x1fff;
d4657 2
d5004 1
d5339 5
a5343 1
load_raw = &CLASS sony_arw2_load_raw; break;
d5418 1
a5418 1
i = strstr(model,"A200") ? 3:0;
d6005 1
a6005 1
short black, trans[12];
d6007 1
a6007 1
{ "Apple QuickTake", 0, /* DJC */
d6009 1
a6009 1
{ "Canon EOS D2000", 0,
d6011 1
a6011 1
{ "Canon EOS D6000", 0,
d6013 1
a6013 1
{ "Canon EOS D30", 0,
d6015 1
a6015 1
{ "Canon EOS D60", 0,
d6017 1
a6017 1
{ "Canon EOS 5D", 0,
d6019 3
a6021 1
{ "Canon EOS 20Da", 0,
d6023 1
a6023 1
{ "Canon EOS 20D", 0,
d6025 1
a6025 1
{ "Canon EOS 30D", 0,
d6027 1
a6027 1
{ "Canon EOS 40D", 0,
d6029 3
a6031 1
{ "Canon EOS 350D", 0,
d6033 1
a6033 1
{ "Canon EOS 400D", 0,
d6035 1
a6035 1
{ "Canon EOS 450D", 0,
d6037 1
a6037 1
{ "Canon EOS-1Ds Mark III", 0,
d6039 1
a6039 1
{ "Canon EOS-1Ds Mark II", 0,
d6041 1
a6041 1
{ "Canon EOS-1D Mark II N", 0,
d6043 1
a6043 1
{ "Canon EOS-1D Mark III", 0,
d6045 1
a6045 1
{ "Canon EOS-1D Mark II", 0,
d6047 1
a6047 1
{ "Canon EOS-1DS", 0,
d6049 1
a6049 1
{ "Canon EOS-1D", 0,
d6051 1
a6051 1
{ "Canon EOS", 0,
d6053 1
a6053 1
{ "Canon PowerShot A50", 0,
d6055 1
a6055 1
{ "Canon PowerShot A5", 0,
d6057 1
a6057 1
{ "Canon PowerShot G1", 0,
d6059 1
a6059 1
{ "Canon PowerShot G2", 0,
d6061 1
a6061 1
{ "Canon PowerShot G3", 0,
d6063 1
a6063 1
{ "Canon PowerShot G5", 0,
d6065 1
a6065 1
{ "Canon PowerShot G6", 0,
d6067 1
a6067 1
{ "Canon PowerShot G9", 0,
d6069 1
a6069 1
{ "Canon PowerShot Pro1", 0,
d6071 1
a6071 1
{ "Canon PowerShot Pro70", 34,
d6073 1
a6073 1
{ "Canon PowerShot Pro90", 0,
d6075 1
a6075 1
{ "Canon PowerShot S30", 0,
d6077 1
a6077 1
{ "Canon PowerShot S40", 0,
d6079 1
a6079 1
{ "Canon PowerShot S45", 0,
d6081 1
a6081 1
{ "Canon PowerShot S50", 0,
d6083 1
a6083 1
{ "Canon PowerShot S60", 0,
d6085 1
a6085 1
{ "Canon PowerShot S70", 0,
d6087 1
a6087 1
{ "Canon PowerShot A610", 0, /* DJC */
d6089 1
a6089 1
{ "Canon PowerShot A620", 0, /* DJC */
d6091 1
a6091 1
{ "Canon PowerShot A640", 0, /* DJC */
d6093 1
a6093 1
{ "Canon PowerShot A650", 0, /* DJC */
d6095 1
a6095 1
{ "Canon PowerShot S3 IS", 0, /* DJC */
d6097 1
a6097 1
{ "CINE 650", 0,
d6099 1
a6099 1
{ "CINE 660", 0,
d6101 1
a6101 1
{ "CINE", 0,
d6103 1
a6103 1
{ "Contax N Digital", 0,
d6105 1
a6105 1
{ "EPSON R-D1", 0,
d6107 1
a6107 1
{ "FUJIFILM FinePix E550", 0,
d6109 1
a6109 1
{ "FUJIFILM FinePix E900", 0,
d6111 1
a6111 1
{ "FUJIFILM FinePix F8", 0,
d6113 1
a6113 1
{ "FUJIFILM FinePix F7", 0,
d6115 1
a6115 1
{ "FUJIFILM FinePix S100FS", 514,
d6117 1
a6117 1
{ "FUJIFILM FinePix S20Pro", 0,
d6119 1
a6119 1
{ "FUJIFILM FinePix S2Pro", 128,
d6121 1
a6121 1
{ "FUJIFILM FinePix S3Pro", 0,
d6123 1
a6123 1
{ "FUJIFILM FinePix S5Pro", 0,
d6125 1
a6125 1
{ "FUJIFILM FinePix S5000", 0,
d6127 1
a6127 1
{ "FUJIFILM FinePix S5100", 0,
d6129 1
a6129 1
{ "FUJIFILM FinePix S5500", 0,
d6131 1
a6131 1
{ "FUJIFILM FinePix S5200", 0,
d6133 1
a6133 1
{ "FUJIFILM FinePix S5600", 0,
d6135 1
a6135 1
{ "FUJIFILM FinePix S6", 0,
d6137 1
a6137 1
{ "FUJIFILM FinePix S7000", 0,
d6139 1
a6139 1
{ "FUJIFILM FinePix S9000", 0,
d6141 1
a6141 1
{ "FUJIFILM FinePix S9500", 0,
d6143 1
a6143 1
{ "FUJIFILM FinePix S9100", 0,
d6145 1
a6145 1
{ "FUJIFILM FinePix S9600", 0,
d6147 1
a6147 1
{ "FUJIFILM IS-1", 0,
d6149 1
a6149 1
{ "Imacon Ixpress", 0, /* DJC */
d6151 1
a6151 1
{ "KODAK NC2000", 0,
d6153 1
a6153 1
{ "Kodak DCS315C", 8,
d6155 1
a6155 1
{ "Kodak DCS330C", 8,
d6157 1
a6157 1
{ "KODAK DCS420", 0,
d6159 1
a6159 1
{ "KODAK DCS460", 0,
d6161 1
a6161 1
{ "KODAK EOSDCS1", 0,
d6163 1
a6163 1
{ "KODAK EOSDCS3B", 0,
d6165 1
a6165 1
{ "Kodak DCS520C", 180,
d6167 1
a6167 1
{ "Kodak DCS560C", 188,
d6169 1
a6169 1
{ "Kodak DCS620C", 180,
d6171 1
a6171 1
{ "Kodak DCS620X", 185,
d6173 1
a6173 1
{ "Kodak DCS660C", 214,
d6175 1
a6175 1
{ "Kodak DCS720X", 0,
d6177 1
a6177 1
{ "Kodak DCS760C", 0,
d6179 1
a6179 1
{ "Kodak DCS Pro SLR", 0,
d6181 1
a6181 1
{ "Kodak DCS Pro 14nx", 0,
d6183 1
a6183 1
{ "Kodak DCS Pro 14", 0,
d6185 1
a6185 1
{ "Kodak ProBack645", 0,
d6187 1
a6187 1
{ "Kodak ProBack", 0,
d6189 1
a6189 1
{ "KODAK P712", 0,
d6191 1
a6191 1
{ "KODAK P850", 0,
d6193 1
a6193 1
{ "KODAK P880", 0,
d6195 1
a6195 1
{ "Leaf CMost", 0,
d6197 1
a6197 1
{ "Leaf Valeo 6", 0,
d6199 1
a6199 1
{ "Leaf Aptus 54S", 0,
d6201 1
a6201 1
{ "Leaf Aptus 65", 0,
d6203 1
a6203 1
{ "Leaf Aptus 75", 0,
d6205 1
a6205 1
{ "Leaf", 0,
d6207 1
a6207 1
{ "Mamiya ZD", 0,
d6209 1
a6209 1
{ "Micron 2010", 110, /* DJC */
d6211 1
a6211 1
{ "Minolta DiMAGE 5", 0,
d6213 1
a6213 1
{ "Minolta DiMAGE 7Hi", 0,
d6215 1
a6215 1
{ "Minolta DiMAGE 7", 0,
d6217 1
a6217 1
{ "Minolta DiMAGE A1", 0,
d6219 1
a6219 1
{ "MINOLTA DiMAGE A200", 0,
d6221 1
a6221 1
{ "Minolta DiMAGE A2", 0,
d6223 1
a6223 1
{ "Minolta DiMAGE Z2", 0, /* DJC */
d6225 1
a6225 1
{ "MINOLTA DYNAX 5", 0,
d6227 1
a6227 1
{ "MINOLTA DYNAX 7", 0,
d6229 1
a6229 1
{ "NIKON D100", 0,
d6231 1
a6231 1
{ "NIKON D1H", 0,
d6233 1
a6233 1
{ "NIKON D1X", 0,
d6235 1
a6235 1
{ "NIKON D1", 0, /* multiplied by 2.218750, 1.0, 1.148438 */
d6237 1
a6237 1
{ "NIKON D2H", 0,
d6239 1
a6239 1
{ "NIKON D2X", 0,
d6241 1
a6241 1
{ "NIKON D40X", 0,
d6243 1
a6243 1
{ "NIKON D40", 0,
d6245 1
a6245 1
{ "NIKON D50", 0,
d6247 1
a6247 1
{ "NIKON D60", 0,
d6249 1
a6249 1
{ "NIKON D70", 0,
d6251 1
a6251 1
{ "NIKON D80", 0,
d6253 1
a6253 1
{ "NIKON D200", 0,
d6255 1
a6255 1
{ "NIKON D300", 0,
d6257 1
a6257 1
{ "NIKON D3", 0,
d6259 1
a6259 1
{ "NIKON E950", 0, /* DJC */
d6261 1
a6261 1
{ "NIKON E995", 0, /* copied from E5000 */
d6263 1
a6263 1
{ "NIKON E2100", 0, /* copied from Z2, new white balance */
d6265 1
a6265 1
{ "NIKON E2500", 0,
d6267 1
a6267 1
{ "NIKON E4300", 0, /* copied from Minolta DiMAGE Z2 */
d6269 1
a6269 1
{ "NIKON E4500", 0,
d6271 1
a6271 1
{ "NIKON E5000", 0,
d6273 1
a6273 1
{ "NIKON E5400", 0,
d6275 1
a6275 1
{ "NIKON E5700", 0,
d6277 1
a6277 1
{ "NIKON E8400", 0,
d6279 1
a6279 1
{ "NIKON E8700", 0,
d6281 1
a6281 1
{ "NIKON E8800", 0,
d6283 1
a6283 1
{ "OLYMPUS C5050", 0,
d6285 1
a6285 1
{ "OLYMPUS C5060", 0,
d6287 1
a6287 1
{ "OLYMPUS C7070", 0,
d6289 1
a6289 1
{ "OLYMPUS C70", 0,
d6291 1
a6291 1
{ "OLYMPUS C80", 0,
d6293 1
a6293 1
{ "OLYMPUS E-10", 0,
d6295 1
a6295 1
{ "OLYMPUS E-1", 0,
d6297 1
a6297 1
{ "OLYMPUS E-20", 0,
d6299 1
a6299 1
{ "OLYMPUS E-300", 0,
d6301 1
a6301 1
{ "OLYMPUS E-330", 0,
d6303 1
a6303 1
{ "OLYMPUS E-3", 0,
d6305 1
a6305 1
{ "OLYMPUS E-400", 0,
d6307 3
a6309 1
{ "OLYMPUS E-410", 0,
d6311 1
a6311 1
{ "OLYMPUS E-500", 0,
d6313 1
a6313 1
{ "OLYMPUS E-510", 0,
d6315 1
a6315 1
{ "OLYMPUS SP350", 0,
d6317 1
a6317 1
{ "OLYMPUS SP3", 0,
d6319 1
a6319 1
{ "OLYMPUS SP500UZ", 0,
d6321 1
a6321 1
{ "OLYMPUS SP510UZ", 0,
d6323 1
a6323 1
{ "OLYMPUS SP550UZ", 0,
d6325 1
a6325 1
{ "OLYMPUS SP560UZ", 0,
d6327 1
a6327 1
{ "OLYMPUS SP570UZ", 0,
d6329 1
a6329 1
{ "PENTAX *ist DL2", 0,
d6331 1
a6331 1
{ "PENTAX *ist DL", 0,
d6333 1
a6333 1
{ "PENTAX *ist DS2", 0,
d6335 1
a6335 1
{ "PENTAX *ist DS", 0,
d6337 1
a6337 1
{ "PENTAX *ist D", 0,
d6339 1
a6339 1
{ "PENTAX K10D", 0,
d6341 1
a6341 1
{ "PENTAX K1", 0,
d6343 1
a6343 1
{ "PENTAX K20D", 0,
d6345 1
a6345 1
{ "PENTAX K200D", 0,
d6347 1
a6347 1
{ "Panasonic DMC-FZ8", 0,
d6349 1
a6349 1
{ "Panasonic DMC-FZ18", 0,
d6351 1
a6351 1
{ "Panasonic DMC-FZ30", 0,
d6353 1
a6353 1
{ "Panasonic DMC-FZ50", 0, /* aka "LEICA V-LUX1" */
d6355 1
a6355 1
{ "Panasonic DMC-L10", 0,
d6357 1
a6357 1
{ "Panasonic DMC-L1", 0, /* aka "LEICA DIGILUX 3" */
d6359 1
a6359 1
{ "Panasonic DMC-LC1", 0, /* aka "LEICA DIGILUX 2" */
d6361 1
a6361 1
{ "Panasonic DMC-LX1", 0, /* aka "LEICA D-LUX2" */
d6363 1
a6363 1
{ "Panasonic DMC-LX2", 0, /* aka "LEICA D-LUX3" */
d6365 1
a6365 1
{ "Phase One H 20", 0, /* DJC */
d6367 1
a6367 1
{ "Phase One P 2", 0,
d6369 1
a6369 1
{ "Phase One P 30", 0,
d6371 1
a6371 1
{ "Phase One P 45", 0,
d6373 1
a6373 1
{ "SAMSUNG GX-1", 0,
d6375 1
a6375 1
{ "Sinar", 0, /* DJC */
d6377 1
a6377 1
{ "SONY DSC-F828", 491,
d6379 1
a6379 1
{ "SONY DSC-R1", 512,
d6381 1
a6381 1
{ "SONY DSC-V3", 0,
d6383 1
a6383 1
{ "SONY DSLR-A100", 0,
d6385 1
a6385 1
{ "SONY DSLR-A200", 0,
d6387 3
a6389 1
{ "SONY DSLR-A3", 0,
d6391 1
a6391 1
{ "SONY DSLR-A700", 254,
d6401 2
a6402 2
if (table[i].black)
black = table[i].black;
d6688 4
a6842 1
maximum = 0xfa0;
a6870 1
maximum = 0x3f60;
a6881 1
maximum = 0x3bb0;
a6897 1
maximum = 0xe6c;
a6901 1
maximum = 0xe80;
a6909 1
maximum = 0x3bb0;
a6929 1
maximum = 0xf44;
a6932 1
maximum = 0xfbc;
a6939 1
maximum = 0xf35;
a6961 1
maximum = 0x3dd;
a7034 1
maximum = 0x3e00;
d7071 1
a7071 1
maximum = 0xf7d;
a7075 1
maximum = model[8] == '1' ? 0xf8b : 0xfff;
a7081 1
maximum = 0xffb;
a7297 1
maximum = 0xf7f0;
d7300 2
a7304 1
maximum = 0xf7fc;
a7308 1
maximum = 0xf94c;
a7342 1
maximum = 0xf7f0;
d7364 2
a7365 3
if (!strcmp(model,"E-1") ||
!strcmp(model,"E-400")) {
maximum = 0xfff0;
a7367 1
maximum = 0xffc0;
a7379 11
} else if (!strcmp(model,"E-3")) {
maximum = 0xf99;
goto e410;
} else if (!strcmp(model,"E-420")) {
maximum = 0xfd7;
goto e410;
} else if (!strcmp(model,"E-410") ||
!strcmp(model,"E-510")) {
maximum = 0xf6a;
e410: load_raw = &CLASS olympus_e410_load_raw;
black >>= 4;
a7390 1
maximum = 0xf1e;
a7409 5
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;
d7411 1
a7411 5
height = (raw_height += 8) - 4;
load_raw = &CLASS sony_arw_load_raw;
maximum = 0x1ffe;
} else if (!strncmp(model,"P850",4)) {
maximum = 0xf7c;
a7574 2
load_raw = &CLASS packed_12_load_raw;
maximum = 0xf7f;
a7578 2
load_raw = &CLASS packed_12_load_raw;
maximum = 0xf7f;
a7584 1
load_raw = &CLASS packed_12_load_raw;
a7590 2
load_raw = &CLASS packed_12_load_raw;
maximum = 0xf7f;
a7596 2
load_raw = &CLASS packed_12_load_raw;
maximum = 0xf7f;
d7603 1
a7603 1
load_raw = &CLASS packed_12_load_raw;
a7609 2
load_raw = &CLASS packed_12_load_raw;
maximum = 0xf7f;
a7615 2
load_raw = &CLASS packed_12_load_raw;
maximum = 0xf7f;
@
1.400
log
@Support the Canon EOS 450D, Nikon D60, and Fuji S100FS.
Copied new matrices from Adobe DNG Converter 4.4.
sRAW support in 1.393 broke Fuji DNG files, now fixed.
@
text
@d26 1
a26 1
#define VERSION "8.84"
d7384 3
@
1.399
log
@Copy GPS data into thumbnails and TIFF output.
Support the Apple QuickTake 200, Fuji IS-1, Sony DSLR-A350,
Pentax K20D, Nokia N95, and Canon PowerShots A460, A530, and A650.
@
text
@d26 1
a26 1
#define VERSION "8.83"
d802 1
a802 1
int bits, high, wide, clrs, psv, restart, vpred[4];
a825 1
case 0xffc0: data[7] = 0;
d827 2
d832 1
a832 1
jh->clrs = data[5] + (data[7] == 0x21);
d850 1
a850 1
if (jh->clrs == 4) {
d890 1
a890 1
if (jh->clrs == 4 && c < 2 && (col | c))
d5362 1
d6027 2
d6107 2
d6239 2
d6317 2
d6333 4
d6377 2
a6378 2
{ "SONY DSLR-A350", 0, /* copied from above */
{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
d6671 1
a6671 1
if ((is_canon = !strcmp(make,"Canon"))) {
a6673 2
maximum = 0xfff;
}
d6875 7
d6907 1
d6929 3
a6931 2
} else if (!strcmp(model,"D2X")) {
width -= 8;
@
1.398
log
@Added the "-P" and "-S" options.
Support the Sony DSLR-A200 and the PowerShots A720 and S5 IS.
@
text
@d26 1
a26 1
#define VERSION "8.82"
a57 1
#define fgetc getc_unlocked
d61 2
d116 1
a116 1
unsigned tile_width, tile_length;
d155 4
a158 3
#define FORC3 for (c=0; c < 3; c++)
#define FORC4 for (c=0; c < 4; c++)
#define FORCC for (c=0; c < colors; c++)
d534 1
a534 1
ushort data[2335], *dp, pixel;
d887 1
a887 1
for (c=0; c < jh->clrs; c++) {
d1014 1
a1014 1
for (c=0; c < tiff_samples; c++)
d1728 1
a1728 1
for (c=0; c < tiff_samples; c++) {
a1740 1
}
d1829 24
d3652 1
a3652 1
for (c=0; c < nc; c++) { /* denoise R,G1,B,G3 individually */
d3740 1
a3740 1
for (c=0; c < 8; c++) dsum[c] += sum[c];
d4738 21
d5082 4
d6081 2
d6133 2
d6137 2
a6138 2
{ "KODAK NC2000", 0, /* DJC */
{ 16475,-6903,-1218,-851,10375,477,2505,-7,1020 } },
d6363 2
d6458 2
d6465 1
d6506 1
d6586 11
d6643 4
a6646 4
if (height == 2624 && width == 3936) { /* Pentax K10D and Samsung GX10 */
height = 2616;
width = 3896;
}
d6706 17
d6764 8
d6887 4
a6894 3
} else if (!strcmp(model,"D80")) {
height -= 3;
width -= 4;
d7009 1
a7009 1
} else if (!strncmp(model,"FinePix",7)) {
d7080 2
d7129 2
d7404 4
d7517 2
a7518 1
data_offset = 738;
d7939 1
a7939 1
union { short s0, s1; int i0; } val;
d7946 1
a7946 1
struct tiff_tag tag[22];
d7950 2
d7954 1
d7962 1
d7968 5
a7972 3
if (type == 3 && count == 1)
tt->val.s0 = val;
else tt->val.i0 = val;
d7992 1
a7992 1
th->tag[th->ntag-1].val.i0 = TOFF(th->bps);
d8008 2
a8009 2
tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[6]));
tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[8]));
d8017 2
a8018 2
tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[0]));
tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[2]));
d8020 21
a8040 7
tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[4]));
for (c=0; c < 6; c++) th->rat[c] = 1000000;
th->rat[0] *= shutter;
th->rat[2] *= aperture;
th->rat[4] *= focal_len;
th->rat[6] = th->rat[8] = 300;
th->rat[7] = th->rat[9] = 1;
@
1.397
log
@Support the Panasonic DMC-L10, added the "-W" option.
@
text
@d3 1
a3 1
Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net
d26 1
a26 1
#define VERSION "8.81"
d3353 1
a3353 1
void CLASS bad_pixels()
d3356 1
a3356 1
char *fname, *cp, line[128];
d3360 10
a3369 7
for (len=32 ; ; len *= 2) {
fname = (char *) malloc (len);
if (!fname) return;
if (getcwd (fname, len-16)) break;
free (fname);
if (errno != ERANGE) return;
}
d3371 4
a3374 4
if (fname[1] == ':')
memmove (fname, fname+2, len-2);
for (cp=fname; *cp; cp++)
if (*cp == '\\') *cp = '/';
d3376 9
a3384 7
cp = fname + strlen(fname);
if (cp[-1] == '/') cp--;
while (*fname == '/') {
strcpy (cp, "/.badpixels");
if ((fp = fopen (fname, "r"))) break;
if (cp == fname) break;
while (*--cp != '/');
a3385 1
free (fname);
d3404 1
a3404 1
fprintf (stderr,_("Fixed bad pixels at:"));
d3687 1
a3687 1
int val, dblack;
d3737 2
a3738 1
dblack = black;
d3750 2
a3751 1
fprintf (stderr,_("Scaling with black %d, multipliers"), dblack);
d6307 2
d6404 1
d6652 8
d7300 3
d7991 1
a7991 1
int arg, status=0, user_flip=-1, user_black=-1, user_qual=-1;
d7993 1
d7995 1
a7995 1
char opm, opt, *ofname, *sp, *cp, *dark_frame=0;
d8029 4
a8033 2
puts(_("-k Set the black level"));
puts(_("-K Subtract dark frame (16-bit raw PGM)"));
d8059 2
a8060 2
if ((cp = strchr (sp="nbrktqmHAC", opt)))
for (i=0; i < "1141111142"[cp-sp]-'0'; i++)
d8073 1
d8091 2
a8092 2
case 'K': dark_frame = argv[arg++];
break;
d8279 1
a8279 1
bad_pixels();
d8284 1
@
1.396
log
@Cropped four columns from the Nikon D3.
@
text
@d26 1
a26 1
#define VERSION "8.80"
d125 1
d1828 35
d5969 2
d6000 1
a6000 1
{ 10823,-3042,-1842,-4562,13656,900,-1311,1670,3556 } },
d6247 2
d6271 2
d7140 2
d7195 4
d7788 1
a7788 1
perc = width * height * 0.01; /* 99th percentile white point */
d7790 1
a7790 1
if (highlight && highlight != 2) perc = -1;
a8007 1
puts(_("-b Adjust brightness (default = 1.0)"));
d8009 1
a8009 1
puts(_("-k Set black point"));
d8021 2
d8083 1
@
1.395
log
@Abolished the getrat() macro, support the Hasselblad H3D.
@
text
@d6756 3
@
1.394
log
@Added the Olympus E-3 and adjusted a few maximums.
@
text
@d26 1
a26 1
#define VERSION "8.79"
a335 1
#define getrat() getreal(10)
d1697 1
a1697 1
for (row=0; row < height; row++) {
d1699 1
a1699 1
for (col=0; col < width; col+=2) {
d1709 3
a1711 1
BAYER(row,col+i) = pred[i] += diff;
d4459 2
a4460 2
cam_mul[0] = getrat();
cam_mul[2] = getrat();
d4650 2
a4651 2
case 33434: shutter = getrat(); break;
case 33437: aperture = getrat(); break;
d4655 1
a4655 1
case 37377: if ((expo = -getrat()) < 128)
d4657 2
a4658 2
case 37378: aperture = pow (2, getrat()/2); break;
case 37386: focal_len = getrat(); break;
d4965 1
a4965 1
shutter = getrat();
d4968 1
a4968 1
aperture = getrat();
d5003 1
a5003 1
focal_len = getrat();
d5010 2
a5011 2
getrat();
FORC3 rgb_cam[i][c] = getrat();
d5102 2
a5103 2
pixel_aspect = getrat();
pixel_aspect /= getrat();
d5108 1
a5108 1
cm[c][j] = getrat();
d5114 1
a5114 1
FORCC cc[i][c] = getrat();
d5116 1
a5116 1
FORCC ab[c] = getrat();
d5122 2
a5123 2
xyz[0] = getrat();
xyz[1] = getrat();
d6149 2
a6798 2
pre_mul[0] = 1.945;
pre_mul[2] = 1.040;
d7039 7
@
1.393
log
@Support the AVT F-080C, Canon EOS 40D, Canon EOS-1Ds Mark III,
Canon PowerShot G9, Nikon Coolpix S6, Nikon D3, Nikon D300,
Panasonic DMC-FZ18, and Sony DSLR-A700.
Support the new Canon sRAW CR2 format.
Added median filtering after interpolation.
@
text
@d26 1
a26 1
#define VERSION "8.78"
d1714 1
d6186 2
d6729 3
a6731 3
} else if (!strncmp(model,"D40",3)) {
width--;
} else if (!strncmp(model,"D50",3) || !strncmp(model,"D70",3)) {
a6732 1
maximum = 0xf53;
d6843 1
d7183 3
a7187 1
load_raw = &CLASS olympus_e410_load_raw;
d7189 1
@
1.392
log
@Use fseeko() and ftello() only when needed.
@
text
@d9 6
a14 5
to lawfully redistribute this code, you must either (a) include
full source code* for all executable files containing RESTRICTED
functions, (b) remove all RESTRICTED functions, re-implement them,
or copy them from an earlier, unrestricted Revision of dcraw.c,
or (c) purchase a license from the author.
d26 1
a26 1
#define VERSION "8.77"
d41 1
d59 4
d70 1
d108 1
a108 1
off_t strip_offset, data_offset, curve_offset;
d120 1
a120 1
ushort (*image)[4], white[8][8], curve[0x1000], cr2_slice[3];
d124 1
a124 1
int output_color=1, output_bps=8, output_tiff=0;
d824 1
a824 1
case 0xffc0:
d829 1
a829 1
jh->clrs = data[5];
d847 4
d887 4
a890 2
if (!col) pred = (jh->vpred[c] += diff) - diff;
else pred = row[0][-jh->clrs];
d951 44
d1083 2
a1084 4
if (col < 2)
hpred[col] = vpred[row & 1][col] += diff;
else
hpred[col & 1] += diff;
d1093 16
a1108 5
static const uchar nikon_tree[] =
{ 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,
5,4,3,6,2,7,1,0,8,9,11,10,12 };
int csize, row, col, diff;
ushort vpred[2][2], hpred[2], *curve;
d1110 21
d1132 1
a1132 9
make_decoder (nikon_tree, 0);
fseek (ifp, curve_offset, SEEK_SET);
read_shorts (vpred[0], 4);
csize = get2();
curve = (ushort *) calloc (csize, sizeof *curve);
merror (curve, "nikon_compressed_load_raw()");
read_shorts (curve, csize);
d1135 5
a1139 1
for (row=0; row < height; row++)
d1141 12
a1152 8
diff = ljpeg_diff (first_decode);
if (col < 2)
hpred[col] = vpred[row & 1][col] += diff;
else
hpred[col & 1] += diff;
if ((unsigned) (col-left_margin) >= width) continue;
if (hpred[col & 1] >= csize) derror();
else BAYER(row,col-left_margin) = curve[hpred[col & 1]];
d1154 1
a1154 1
free (curve);
a1191 4
if (tiff_compress != 34713)
return 0;
if (strcmp(model,"D100"))
return 1;
d1848 2
a1849 4
if (!strcmp(make,"OLYMPUS")) {
maximum = 0xfff;
black >>= 4;
}
d2488 39
d2767 1
a2767 1
if (!bit && !fixed && width < 2688) get4();
d3829 1
a3829 1
*ip++ = sum[c];
d3840 1
a3840 1
pix[ip[0]] = sum[ip[0]] / ip[1];
d4181 28
d4388 1
a4388 1
short sorder;
a4393 1
sorder = order;
d4486 5
d4501 2
a4502 4
if (tag == 0x8c)
curve_offset = ftell(ifp) + 2112;
if (tag == 0x96)
curve_offset = ftell(ifp) + 2;
d4535 3
d4603 2
d4799 1
d4830 5
d4928 6
d4937 4
a5126 1
i = order;
a5127 1
order = i;
d5207 1
d5228 2
d5243 2
d5249 2
d5259 1
a5259 1
case 32867: case 34713: break;
d5300 1
d5329 1
d5784 1
a5784 4
fseek (ifp, 40, SEEK_CUR);
cam_mul[0] = 1/getreal(11);
cam_mul[2] = 1/getreal(11);
fseek (ifp, 24, SEEK_CUR);
d5791 2
a5792 1
fseek (ifp, 8, SEEK_CUR);
d5925 2
d5959 2
d6085 2
d6139 4
d6192 1
a6192 1
{ 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
d6219 2
d6252 3
a6254 1
{ 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } }
d6334 1
d6360 1
d6408 1
a6408 1
for (i=0; i < 0x1000; i++) curve[i] = i;
a6528 3
/* We'll try to decode anything from Canon or Nikon. */
d6534 2
a6535 3
if (!strcmp(make,"NIKON"))
load_raw = nikon_is_compressed() ?
&CLASS nikon_compressed_load_raw : &CLASS nikon_load_raw;
d6545 3
d6678 6
d6697 5
d6714 6
d6735 2
a6736 1
if (tiff_compress == 34713 && load_raw == &CLASS nikon_load_raw)
d6738 1
d6751 2
d6838 4
d6970 4
d7084 1
a7084 1
load_raw = &CLASS unpacked_load_raw;
d7098 1
a7098 2
load_raw = &CLASS olympus_e300_load_raw;
maximum = 0xf7f;
d7112 13
d7172 4
a7175 2
maximum = 0xfc30;
if (load_raw == &CLASS unpacked_load_raw) black = 0;
d7178 2
d7183 1
a7183 1
maximum = 0xfff;
d7383 1
d7389 1
d7404 1
d7412 1
d7427 1
d7435 1
d7912 1
a7912 1
FILE *ofp = stdout;
d7960 1
d7970 2
a7971 2
if ((cp = strchr (sp="nbrktqHAC", opt)))
for (i=0; i < "114111142"[cp-sp]-'0'; i++)
d7986 1
a8016 1
case 'm': output_color = 0; break;
d8047 1
d8208 2
a8209 2
if (mix_green && (colors = 3))
for (i=0; i < height*width; i++)
d8211 1
@
1.391
log
@Reject TIFF files with unsupported Compression tags.
@
text
@a55 1
#ifndef DJGPP
a56 2
#define fseek fseeko
#endif
d258 1
a258 1
fprintf (stderr,_("Corrupt data near 0x%lx\n"), ftell(ifp));
d7941 1
a7941 1
fseek (ifp, data_offset, SEEK_SET);
@
1.390
log
@When they differ, use DateTimeOriginal instead of DateTime.
@
text
@d1092 1
a1092 1
if (tiff_compress == 34713 && (col % 10) == 9)
d5074 2
d5086 2
a6628 3
} else if (!strncmp(model,"R-D1",4)) {
tiff_compress = 34713;
load_raw = &CLASS nikon_load_raw;
@
1.389
log
@Added color matrix for the Canon PowerShot A640.
@
text
@a4470 1
if (timestamp) return;
@
1.388
log
@Reject 8-bit grayscale TIFFs.
Decode raw CINE files, which may exceed 2GB.
Error-check the "-s" option, and enable "-s all".
Support camera WB for the Canon EOS-1D and EOS-1DS.
Use full output range for "-H 2".
@
text
@d5803 2
@
1.387
log
@Support all Lossless JPEG predictors.
@
text
@d25 1
a25 1
#define VERSION "8.76"
d58 1
d104 4
a107 3
unsigned profile_offset, profile_length, *oprof;
unsigned thumb_offset, thumb_length, thumb_misc;
unsigned data_offset, strip_offset, curve_offset, meta_offset, meta_length;
a120 1
int fuji_layout, fuji_secondary, shot_select=0;
d947 1
a947 1
if (fuji_secondary && shot_select) (*rp)++;
d955 1
a955 1
*rp += 1 + fuji_secondary;
d962 1
a962 1
if (fuji_secondary && shot_select) (*rp)--;
d978 1
a978 1
jwide >>= fuji_secondary;
d4241 1
a4241 1
unsigned ver97=0, serial=0, i, wb[4]={0,0,0,0};
d4305 2
a4306 1
shot_order = (get4(),get2(),get2());
d4376 4
d4750 4
a4753 1
if (len == 4) load_raw = &CLASS sinar_4shot_load_raw;
a5050 1
fuji_secondary = tiff_samples == 2;
d5089 2
d5576 51
d5805 6
d6201 1
a6201 1
kodak_cbpp = zero_after_ff = dng_version = fuji_secondary = 0;
d6265 2
a6266 2
fuji_secondary = (i = get4()) && 1;
if (fuji_secondary && shot_select)
d6283 2
d6327 2
a6328 2
if (!filters)
colors = tiff_samples;
d6639 1
a6639 1
if (fuji_secondary && shot_select)
d6643 1
a6643 1
if (fuji_secondary)
d6851 1
d7484 1
a7484 1
if (highlight) perc = -1;
d7719 1
a7719 1
puts(_("-s [0-99] Select a different raw image from the same file"));
d7728 2
a7729 2
if ((cp = strchr (sp="nbrktqsHAC", opt)))
for (i=0; i < "1141111142"[cp-sp]-'0'; i++)
a7743 1
case 's': shot_select = atoi(argv[arg++]); break;
d7745 4
a7875 1
printf (_("Secondary pixels: %s\n"), fuji_secondary ? _("yes"):_("no"));
d7877 1
a7877 1
printf (_("Decodable with dcraw: %s\n"), is_raw ? _("yes"):_("no"));
d7937 5
a7941 2
fprintf (stderr,
_("Loading %s %s image from %s ...\n"), make, model, ifname);
d7983 1
a7983 1
ofname = (char *) malloc (strlen(ifname) + 16);
d7990 3
d8013 4
@
1.386
log
@Reports of corruption in 16-bit linear DNGs were false.
@
text
@d25 1
a25 1
#define VERSION "8.75"
d106 1
a106 1
unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress, tile_length;
d109 1
d795 1
a795 1
int bits, high, wide, clrs, restart, vpred[4];
d825 1
a825 1
if (len == 9) getc(ifp);
d834 3
d842 1
a842 1
jh->row = (ushort *) calloc (jh->wide*jh->clrs, 2);
d862 1
a862 1
void CLASS ljpeg_row (int jrow, struct jhead *jh)
d864 2
a865 2
int col, c, diff;
ushort mark=0, *outp=jh->row;
d874 1
d878 14
a891 3
*outp = diff = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff);
if ((ushort) diff >> jh->bits) derror();
outp++;
d893 1
d901 1
d907 1
a907 1
ljpeg_row (jrow, &jh);
d909 1
a909 1
val = jh.row[jcol];
d966 1
a966 1
int save, twide, trow=0, tcol=0, jrow, jcol;
d970 1
a970 1
while (1) {
d975 10
a984 14
if (trow >= raw_height) break;
if (jh.high > raw_height-trow)
jh.high = raw_height-trow;
twide = jh.wide;
if (filters) twide *= jh.clrs;
else colors = jh.clrs;
if (fuji_secondary) twide /= 2;
if (twide > raw_width-tcol)
twide = raw_width-tcol;
for (jrow=0; jrow < jh.high; jrow++) {
ljpeg_row (jrow, &jh);
for (rp=jh.row, jcol=0; jcol < twide; jcol++)
adobe_copy_pixel (trow+jrow, tcol+jcol, &rp);
d987 2
a988 4
if ((tcol += twide) >= raw_width) {
tcol = 0;
trow += jh.high;
}
d4736 3
d6138 1
a6138 1
tile_length = INT_MAX;
@
1.385
log
@Added "+M" option for version 8.75.
@
text
@d874 1
a874 1
if (diff >> jh->bits) derror();
@
1.384
log
@Added "-M" option and improved PPG interpolation.
@
text
@d25 1
a25 1
#define VERSION "8.74"
d116 1
a116 1
int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=1;
d120 1
a120 1
float cam_mul[4], pre_mul[4], rgb_cam[3][4]; /* RGB from camera color */
a3625 1
filters = 0;
d3648 1
d4406 1
a4406 2
if (((tag == 0x1011 && len == 9) || tag == 0x20400200)
&& use_camera_matrix) {
d4408 1
a4408 3
FORC3 rgb_cam[i][c] = ((short) get2()) / 256.0;
raw_color = rgb_cam[0][0] < 0.25;
}
d4508 1
a4508 1
for (raw_color = i=0; i < 3; i++)
d4510 2
a4511 2
for (rgb_cam[i][j] = k=0; k < 3; k++)
rgb_cam[i][j] += rgb_romm[i][k] * romm_cam[k][j];
d4544 6
a4549 1
if (!strcmp(data,"CaptProf_color_matrix") && use_camera_matrix) {
a5402 1
if (!use_camera_matrix) break;
d6127 1
d7583 1
a7583 1
char opt, *ofname, *sp, *cp, *dark_frame=0;
d7615 1
a7615 1
puts(_("-M Don't use an embedded color matrix"));
d7641 1
a7641 1
for (arg=1; argv[arg][0] == '-'; ) {
d7682 1
a7682 1
case 'M': use_camera_matrix = 0; break;
d7694 2
d7839 4
@
1.383
log
@Added "-C" option to the usage message.
@
text
@d25 1
a25 1
#define VERSION "8.73"
d116 1
a116 1
int verbose=0, use_auto_wb=0, use_camera_wb=0;
d422 1
a422 1
next: continue;
d3544 1
a3544 2
skip_block:
continue;
d3855 2
a3856 2
int gr[4], dir[4] = { 1, width, -1, -width };
int row, col, avg, pat, diff[2], guess[2], c, d, i;
a3869 3
for (pat=i=0; i < 4; i++)
pat = pat << 1 | (gr[i] > avg);
if (pat & 8) pat ^= 15;
d3873 20
a3892 18
if (pat == 0 || pat == 3 || pat == 6)
pix[0][1] = (gr[1]+gr[2]) >> 3;
else {
for (i=0; (d=dir[i]) > 0; i++) {
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;
guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
- pix[-2*d][c] - pix[2*d][c];
}
d = dir[i = diff[0] > diff[1]];
if (diff[0] != diff[1])
pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
else
pix[0][1] = ULIM((guess[0]+guess[1]) >> 1, gr[1], gr[2]) >> 2;
}
d3899 2
a3900 2
pix[0][c] = CLIP(((pix[0][1] + pix[-d][c] + pix[d][c]) * 2
- pix[-d][1] - pix[d][1]) >> 2);
d3908 4
a3911 3
ABS(pix[-d][1] + pix[d][1] - 2*pix[0][1]);
guess[i] = (pix[0][1] + pix[-d][c] + pix[d][c]) * 2
- pix[-d][1] - pix[d][1];
d3914 1
a3914 1
pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 2);
d3916 1
a3916 1
pix[0][c] = CLIP((guess[0]+guess[1]) >> 3);
d4406 2
a4407 1
if (((tag == 0x1011 && len == 9) || tag == 0x20400200) && use_camera_wb) {
d4547 1
a4547 1
if (!strcmp(data,"CaptProf_color_matrix") && use_camera_wb) {
d5401 1
a5401 1
if (!use_camera_wb) break;
d5655 1
a5655 1
{ 17524,-3363,-2877,5519,6087,-1605,9082,1142,-31 } },
d7613 1
d7680 1
@
1.382
log
@Added "-C" option to correct chromatic aberration.
Support the Hasselblad CFV, Kodak EasyShare C330, and Nikon D40X.
Use a switch statement for Leica and Panasonic models.
Output seven new TIFF tags, including ImageDescription and Artist.
Generated color matrices for the Apple QuickTake and Phase One H 20.
Copied new matrices from Adobe DNG Converter 4.1.
@
text
@d7613 1
@
1.381
log
@Support 3096x2103 mode for the Panasonic DMC-FZ8.
@
text
@d25 1
a25 1
#define VERSION "8.72"
d98 2
a99 1
char *ifname, make[64], model[64], model2[64], *meta_data, cdesc[5];
d112 1
a112 1
double pixel_aspect;
d485 2
a486 2
val = (BAYER(row,col) - black) * mul[row & 3][col & 1] >> 9;
if (val < 0) val = 0;
d824 1
d1534 1
a1534 1
if (nbits == 0)
d1536 1
d1566 1
a1566 1
ph1_bits(0);
d1596 27
a1845 16
void CLASS eight_bit_load_raw()
{
uchar *pixel;
int row, col;
pixel = (uchar *) calloc (raw_width, sizeof *pixel);
merror (pixel, "eight_bit_load_raw()");
for (row=0; row < height; row++) {
if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
for (col=0; col < width; col++)
BAYER(row,col) = pixel[col];
}
free (pixel);
maximum = 0xff;
}
d2138 1
a2138 1
void CLASS kodak_easy_load_raw()
d2141 1
a2141 1
unsigned row, col, val;
a2142 2
if (raw_width > width)
black = 0;
d2144 2
a2145 1
merror (pixel, "kodak_easy_load_raw()");
d2152 1
a2152 1
else black += val;
d2156 2
a2157 2
if (raw_width > width)
black /= (raw_width - width) * height;
d3514 1
a3514 1
unsigned bottom, right, row, col, x, y, c, sum[8];
d3517 2
a3518 1
float scale_mul[4];
d3582 30
a3611 8
for (row=0; row < iheight; row++)
for (col=0; col < iwidth; col++)
FORC4 {
val = image[row*iwidth+col][c];
if (!val) continue;
val -= black;
val *= scale_mul[c];
image[row*iwidth+col][c] = CLIP(val);
d3613 3
d4297 2
d4305 1
a4305 1
if (tag == 0x11 && is_raw) {
d4313 2
d4410 1
a4410 1
raw_color = rgb_cam[0][0] < 1;
d4674 3
d4719 3
d4832 5
d4845 7
d4862 11
d5222 2
d5401 1
d5407 1
a5407 1
FORC3 cam_mul[c] = pre_mul[c] = getreal(11);
d5654 2
d5680 2
d5747 1
a5747 1
{ 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
d5860 2
d5916 2
d5920 2
d5930 2
d5960 8
d6052 2
d6111 1
a6111 1
make[0] = model[0] = model2[0] = cdesc[0] = 0;
d6224 1
a6224 1
make[63] = model[63] = model2[63] = 0;
d6727 3
a6729 8
} else if (!strcmp(make,"Imacon")) {
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;
d6779 49
a6827 12
if (width == 2568) {
adobe_coeff ("Panasonic","DMC-LC1");
} else if (width == 3130) {
left_margin = 4;
goto fz8_common;
} else if (width == 3170) {
left_margin = 18;
fz8_common:
width = 3096;
if (height > 2326) {
height = 2326;
top_margin = 13;
d6829 6
a6834 49
}
load_raw = &CLASS olympus_e300_load_raw;
maximum = 0xf7f;
adobe_coeff ("Panasonic","DMC-FZ8");
zero_is_bad = 1;
} else if (width == 3177) {
maximum = 0xf7fc;
width -= 10;
filters = 0x49494949;
adobe_coeff ("Panasonic","DMC-L1");
zero_is_bad = 1;
} else if (width == 3304) {
maximum = 0xf94c;
width -= 16;
adobe_coeff ("Panasonic","DMC-FZ30");
zero_is_bad = 1;
} else if (width == 3690) {
maximum = 0xf7f0;
height -= 3;
width = 3672;
left_margin = 3;
filters = 0x49494949;
adobe_coeff ("Panasonic","DMC-FZ50");
zero_is_bad = 1;
} else if (width == 3770) {
height = 2760;
width = 3672;
top_margin = 15;
left_margin = 17;
adobe_coeff ("Panasonic","DMC-FZ50");
zero_is_bad = 1;
} else if (width == 3880) {
maximum = 0xf7f0;
width -= 22;
left_margin = 6;
adobe_coeff ("Panasonic","DMC-LX1");
zero_is_bad = 1;
} else if (width == 4290) {
height--;
width = 4248;
left_margin = 3;
filters = 0x49494949;
adobe_coeff ("Panasonic","DMC-LX2");
} else if (width == 4330) {
height = 2400;
width = 4248;
top_margin = 15;
left_margin = 17;
adobe_coeff ("Panasonic","DMC-LX2");
d6898 13
a6940 2
if (load_raw == &CLASS eight_bit_load_raw)
load_raw = &CLASS kodak_easy_load_raw;
d6961 1
a6961 1
load_raw = &CLASS kodak_easy_load_raw;
d7427 1
a7427 1
struct tiff_tag tag[15];
d7432 2
a7433 2
int rat[6];
char make[64], model[64], soft[32], date[20];
d7462 1
d7472 1
d7483 4
d7489 1
d7500 3
d7509 1
d7639 2
a7640 2
if ((cp = strchr (sp="nbrktqsHA", opt)))
for (i=0; i < "114111114"[cp-sp]-'0'; i++)
d7650 2
d7767 2
d7792 2
a7793 1
shrink = (half_size || threshold) && filters;
@
1.380
log
@Added Patterned Pixel Grouping interpolation.
@
text
@a6692 2
height = 2326;
top_margin = 13;
a6693 1
filters = 0x49494949;
d6696 5
@
1.379
log
@Offer blended highlights with the "-H 2" option.
Set "shot_order" for ORF and CR2 files.
Support the Pentax Optio 750Z.
@
text
@d25 1
a25 1
#define VERSION "8.71"
d3813 70
d7743 4
a7746 2
else if (quality < 3 || colors > 3)
vng_interpolate();
@
1.378
log
@Added "-A" option to select a rectangle for white balance.
Protect against overflow attacks on malloc() or calloc().
Nucore raw formats are not used outside Nucore, so drop them.
Support the Canon PowerShots A630 and A640, Panasonic DMC-FZ8,
Sigma SD14, Apple QuickTake 100 & 150, Mamiya ZD, Casio QV-R41,
and Olympus E-410.
@
text
@d25 1
a25 1
#define VERSION "8.70"
d1197 2
a1198 2
uchar data[3456], *dp;
ushort pixel[2304], *pix;
d1203 2
a1204 1
fseek (ifp, ((width==1616) << 13) - (-ftell(ifp) & -2048), SEEK_SET);
d1767 1
a1767 1
BAYER(row,col) = pred + ((diff << 2) | low);
d2568 1
d3943 37
d3990 1
a3990 1
if (verbose) fprintf (stderr,_("Highlight recovery...\n"));
d4178 1
a4178 1
if (tag == 4 && len == 27) {
d4180 5
a4184 2
aperture = (get2(), pow (2, get2()/64.0));
shutter = pow (2, ((short) get2())/-32.0);
d4259 2
d5932 1
d6475 4
d6954 1
a6954 1
if (!load_raw || !height) is_raw = 0;
d7228 1
a7228 1
if (highlight) perc = 0;
d7437 1
a7437 1
puts(_("-H [0-9] Highlight mode (0=clip, 1=no clip, 2+=recover)"));
a7676 2
if (!is_foveon && highlight > 1) recover_highlights();
if (use_fuji_rotate) fuji_rotate();
d7680 3
@
1.377
log
@Better detect and reject non-raw TIFFs.
@
text
@d25 1
a25 1
#define VERSION "8.69"
d56 3
a58 1
d67 1
d101 10
a110 9
unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id, *oprof;
int profile_offset, profile_length;
int thumb_offset, thumb_length, thumb_width, thumb_height, thumb_misc;
int data_offset, strip_offset, curve_offset, meta_offset, meta_length;
int tiff_nifds, tiff_flip, tiff_bps, tiff_compress, tile_length;
int raw_height, raw_width, top_margin, left_margin;
int height, width, fuji_width, colors, tiff_samples;
int black, maximum, mix_green, raw_color, use_gamma;
int iheight, iwidth, shrink, flip;
a111 1
int zero_after_ff, is_raw, dng_version, is_foveon, data_error;
d118 1
a144 1
#define fgetc getc_unlocked
d239 1
a239 1
return NULL;
d278 1
a278 1
int CLASS sget4 (uchar *s)
d287 1
a287 1
int CLASS get4()
d294 1
a294 1
int CLASS getint (int type)
d512 11
d525 1
a525 1
ushort data[1970], *dp, pixel;
d537 2
a538 1
else black += (bc++,pixel);
d804 1
d952 2
a953 1
fseek (ifp, get4(), SEEK_SET);
d1005 2
a1006 2
int row, col, diff, i;
ushort vpred[4] = {0,0,0,0}, hpred[2];
d1014 3
a1016 5
if (col < 2) {
i = 2*(row & 1) + (col & 1);
vpred[i] += diff;
hpred[col] = vpred[i];
} else
d1029 2
a1030 2
int csize, row, col, diff, i;
ushort vpred[4], hpred[2], *curve;
d1036 1
a1036 1
read_shorts (vpred, 4);
d1047 3
a1049 5
if (col < 2) {
i = 2*(row & 1) + (col & 1);
vpred[i] += diff;
hpred[col] = vpred[i];
} else
d1272 1
a1272 1
thumb = (char *) malloc (thumb_length*colors);
d1284 5
a1288 2
int i, size = thumb_width * thumb_height;
ushort *thumb = (ushort *) calloc (size, 2);
d1291 2
a1292 2
read_shorts (thumb, size);
for (i=0; i < size; i++) {
d1466 1
a1466 1
for (i=0; i < 9; i++) head[i] = get4();
d1534 1
a1534 1
bitbuf = bitbuf << 32 | (unsigned) get4();
a1665 1
/* Here raw_width is in bytes, not pixels. */
d1670 2
d1674 2
d1678 2
a1679 2
for (col = width*3/2; col < raw_width; col++)
if (getbits(8)) derror();
a1700 6
void CLASS panasonic_load_raw()
{
unpacked_load_raw();
remove_zeroes();
}
d1708 1
d1716 1
a1716 1
if (*dp++) derror();
d1721 1
a1721 1
BAYER(row,col) = (pixel[col] & 0xfff);
d1724 45
a1768 2
maximum = 0xfff;
black >>= 4;
d1851 1
a1851 1
void CLASS nucore_load_raw()
d1853 21
a1873 2
ushort *pixel;
int irow, row, col;
d1875 38
a1912 5
pixel = (ushort *) calloc (width, 2);
merror (pixel, "nucore_load_raw()");
for (irow=0; irow < height; irow++) {
read_shorts (pixel, width);
row = irow/2 + height/2 * (irow & 1);
d1914 2
a1915 3
BAYER(row,col) = pixel[col];
}
free (pixel);
d2035 3
a2037 1
val = (BAYER(y,x)-2048)*2 + (BAYER(y,x-1)+BAYER(y,x+1))/2;
d2042 2
a2043 1
maximum = 10000;
d2559 1
a2559 1
int bwide, row, col, bit=-1, c, i;
a2562 1
unsigned bitbuf=0;
d2581 1
a2581 1
for (col=bit=0; col < thumb_width; col++)
d2622 1
a2622 1
if (!bit && !fixed) get4();
d2666 1
a2666 1
return NULL;
d2669 1
a2669 1
void * CLASS foveon_camf_matrix (int dim[3], const char *name)
d2673 1
d2689 2
a2690 2
if ((size = dim[0]*dim[1]*dim[2]) > meta_length/4) break;
mat = (unsigned *) malloc (size * 4);
d2700 1
a2700 1
return NULL;
d2706 1
a2706 1
int dim[3];
d2725 1
d2732 1
a2732 1
int i, size;
d2737 1
d2777 1
a2777 1
int dim[3], dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3];
d2780 1
a2780 1
unsigned *badpix;
d3172 1
a3172 1
FILE *fp=NULL;
d3424 1
a3424 1
float *fimg, *temp, thold, mul[2], avg, diff;
d3435 2
a3436 2
size = iheight*iwidth;
fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
d3499 2
a3500 1
int dblack, row, col, x, y, c, val, sum[8];
d3504 2
d3508 4
a3511 2
for (row=0; row < iheight-7; row += 8)
for (col=0; col < iwidth-7; col += 8) {
d3513 2
a3514 2
for (y=row; y < row+8; y++)
for (x=col; x < col+8; x++)
d3516 5
a3520 2
val = image[y*iwidth+x][c];
if (!val) continue;
d3522 1
a3522 2
val -= black;
if (val < 0) val = 0;
d3525 1
a3548 2
if (user_mul[0])
memcpy (pre_mul, user_mul, sizeof pre_mul);
d4026 1
a4026 1
if (*len * ("1112481124848"[*type < 13 ? *type:0]-'0') > 4)
d4037 1
a4037 1
if (tag == toff) thumb_offset = get4();
d4045 1
a4045 1
void CLASS parse_makernote (int base)
d4113 4
d4136 1
d4250 1
a4250 1
if (tag == 0x1011 && len == 9 && use_camera_wb) {
d4255 1
a4255 1
if (tag == 0x1012 && len == 4)
d4258 1
a4258 1
if (tag == 0x1017)
d4260 1
a4260 1
if (tag == 0x1018)
d4270 2
d4276 1
a4276 1
if (tag == 0x4001) {
d4334 1
a4334 1
case 37500: parse_makernote (base); break;
d4508 1
a4508 1
tiff_ifd[ifd].samples = len;
d4541 1
a4541 1
tiff_ifd[ifd].samples = getint(type);
d4794 4
a4797 2
if (asn[0])
FORCC pre_mul[c] = 1 / asn[c];
d4848 7
a4854 2
load_raw = tiff_bps > 8 ?
&CLASS unpacked_load_raw : &CLASS eight_bit_load_raw;
d5405 1
d5424 1
a5424 1
if (pent > 256) pent=256;
d5633 2
d5745 2
d5861 2
d5876 1
d5894 1
a5894 1
"SAMSUNG" };
d5903 1
a5903 1
load_raw = thumb_load_raw = NULL;
d5908 1
a5918 1
mix_green = profile_length = data_error = 0;
a5944 23
} else if (!memcmp (head,"BM",2) &&
head[26] == 1 && head[28] == 16 && head[30] == 0) {
data_offset = 0x1000;
order = 0x4949;
fseek (ifp, 38, SEEK_SET);
if (get4() == 2834 && get4() == 2834 && get4() == 0 && get4() == 4096) {
strcpy (model, "BMQ");
flip = 3;
goto nucore;
}
} else if (!memcmp (head,"BR",2)) {
strcpy (model, "RAW");
nucore:
strcpy (make, "Nucore");
order = 0x4949;
fseek (ifp, 10, SEEK_SET);
data_offset += get4();
raw_width = (get4(),get4());
raw_height = get4();
if (model[0] == 'B' && raw_width == 2597) {
raw_width++;
data_offset -= 0x1000;
}
d5955 6
d6008 1
a6008 1
if (!strncmp (model, make, i) && model[i++] == ' ')
a6014 2
if ((raw_height | raw_width) < 0)
raw_height = raw_width = 0;
a6034 1
FORC4 cam_mul[c] = pre_mul[c];
d6088 1
d6104 16
d6570 14
d6589 1
a6589 1
load_raw = &CLASS panasonic_load_raw;
d6594 1
a6594 1
load_raw = &CLASS panasonic_load_raw;
d6602 1
a6602 1
load_raw = &CLASS panasonic_load_raw;
d6609 1
a6609 1
load_raw = &CLASS panasonic_load_raw;
d6615 1
a6615 1
load_raw = &CLASS panasonic_load_raw;
d6651 5
d6782 11
d6837 6
a6891 8
} else if (!strcmp(make,"Nucore")) {
filters = 0x61616161;
load_raw = &CLASS unpacked_load_raw;
if (width == 2598) {
filters = 0x16161616;
load_raw = &CLASS nucore_load_raw;
flip = 2;
}
d6932 1
a6932 1
cmsHPROFILE hInProfile=NULL, hOutProfile=NULL;
d6961 1
a6961 1
oprof = NULL;
d7091 1
a7091 1
int i, wide, high, row, col;
d7095 1
a7095 1
ushort (*img)[4], (*pix)[4];
d7129 2
a7130 1
int newdim, row, col, c;
a7131 1
ushort (*img)[4], *pix0, *pix1;
d7352 1
a7352 1
char opt, *ofname, *sp, *cp, *dark_frame = NULL;
d7357 1
a7357 1
char *cam_profile = NULL, *out_profile = NULL;
a7379 1
puts(_("-a Use automatic white balance"));
d7381 3
a7383 1
puts(_("-r <4 numbers> Set custom white balance"));
d7410 2
a7411 2
if ((cp = strchr (sp="nbrktqsH", opt)))
for (i=0; i < "11411111"[cp-sp]-'0'; i++)
d7444 1
d7476 3
a7478 2
image = NULL;
oprof = NULL;
a7481 1
if (image) free (image);
d7483 1
a7483 1
continue;
d7598 1
a7598 2
image = (ushort (*)[4])
calloc (iheight*iwidth*sizeof *image + meta_length, 1);
d7600 4
a7603 1
meta_data = (char *) (image + iheight*iwidth);
d7609 1
d7668 2
d7671 1
a7671 2
free (ofname);
free (image);
@
1.376
log
@Optimized AHD interpolation to take 22% less time.
@
text
@d25 1
a25 1
#define VERSION "8.68"
d4742 3
a4744 2
if (tiff_samples == 3 && tiff_bps == 8)
if (!dng_version) is_raw = 0;
@
1.375
log
@Support the Fuji FinePix S5Pro.
@
text
@d25 1
a25 1
#define VERSION "8.67"
a3690 31
void CLASS cam_to_cielab (ushort cam[4], float lab[3])
{
int c, i, j, k;
float r, xyz[3];
static float cbrt[0x10000], xyz_cam[3][4];
if (cam == NULL) {
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];
} else {
xyz[0] = xyz[1] = xyz[2] = 0.5;
FORCC {
xyz[0] += xyz_cam[0][c] * cam[c];
xyz[1] += xyz_cam[1][c] * cam[c];
xyz[2] += xyz_cam[2][c] * cam[c];
}
xyz[0] = cbrt[CLIP((int) xyz[0])];
xyz[1] = cbrt[CLIP((int) xyz[1])];
xyz[2] = cbrt[CLIP((int) xyz[2])];
lab[0] = 116 * xyz[1] - 16;
lab[1] = 500 * (xyz[0] - xyz[1]);
lab[2] = 200 * (xyz[1] - xyz[2]);
}
}
d3699 1
a3699 1
int i, j, top, left, row, col, tr, tc, fc, c, d, val, hm[2];
d3703 1
a3703 1
float flab[3];
d3705 1
a3705 1
short (*lab)[TS][TS][3];
d3710 10
a3719 1
border_interpolate(3);
d3726 2
a3727 3
for (top=0; top < height; top += TS-6)
for (left=0; left < width; left += TS-6) {
memset (rgb, 0, 12*TS*TS);
d3730 3
a3732 4
for (row = top < 2 ? 2:top; row < top+TS && row < height-2; row++) {
col = left + (FC(row,left) == 1);
if (col < 2) col += 2;
for (fc = FC(row,col); col < left+TS && col < width-2; col+=2) {
d3734 2
a3735 2
val = ((pix[-1][1] + pix[0][fc] + pix[1][1]) * 2
- pix[-2][fc] - pix[2][fc]) >> 2;
d3737 2
a3738 2
val = ((pix[-width][1] + pix[0][fc] + pix[width][1]) * 2
- pix[-2*width][fc] - pix[2*width][fc]) >> 2;
d3744 2
a3745 2
for (row=top+1; row < top+TS-1 && row < height-1; row++)
for (col=left+1; col < left+TS-1 && col < width-1; col++) {
d3748 1
d3764 12
a3775 2
cam_to_cielab (rix[0], flab);
FORC3 lab[d][row-top][col-left][c] = 64*flab[c];
d3779 1
a3779 1
for (row=top+2; row < top+TS-2 && row < height; row++) {
d3781 1
a3781 1
for (col=left+2; col < left+TS-2 && col < width; col++) {
d3783 8
a3790 3
for (d=0; d < 2; d++)
for (i=0; i < 4; i++)
ldiff[d][i] = ABS(lab[d][tr][tc][0]-lab[d][tr][tc+dir[i]][0]);
a3792 5
for (d=0; d < 2; d++)
for (i=0; i < 4; i++)
if (i >> 1 == d || ldiff[d][i] <= leps)
abdiff[d][i] = SQR(lab[d][tr][tc][1]-lab[d][tr][tc+dir[i]][1])
+ SQR(lab[d][tr][tc][2]-lab[d][tr][tc+dir[i]][2]);
d3802 1
a3802 1
for (row=top+3; row < top+TS-3 && row < height-3; row++) {
d3804 1
a3804 1
for (col=left+3; col < left+TS-3 && col < width-3; col++) {
a7448 1
cam_to_cielab (NULL,NULL);
@
1.374
log
@Refactored wavelet_denoise() to use memory more intelligently.
@
text
@d25 1
a25 1
#define VERSION "8.66"
d5159 2
a5160 4
if (fuji_layout) {
height *= 2;
width /= 2;
}
d5431 2
d5768 1
a5768 1
raw_height = raw_width = fuji_width = cr2_slice[0] = 0;
d6220 2
a6221 2
data_offset += (shot_select > 0) * ( strcmp(model+7," S3Pro")
? (raw_width *= 2) : raw_height*raw_width*2 );
@
1.373
log
@Detect and report data errors wherever possible.
@
text
@d25 1
a25 1
#define VERSION "8.65"
d1370 1
a1370 1
if (shrink || !meta_length) return;
d1611 1
a1611 1
if ((shot = shot_select) || shrink) {
d1619 4
d1638 1
a1638 1
filters = 0;
a3306 2
for (i=0; i < size; i++)
base[st*i] = temp[i] * 0.25;
d3311 2
a3312 2
float *fimg, *temp, thold, val, mul[2], avg, diff;
int scale=1, depth=6, lev, row, col, size, nc, c, i, wlast;
d3323 1
a3323 1
fimg = (float *) calloc (depth*size+iheight+iwidth, sizeof *fimg);
d3325 1
a3325 1
temp = fimg + depth*size;
d3330 12
a3341 6
for (lev=0; lev < depth-1; lev++) {
memcpy (fimg+size*(lev+1), fimg+size*lev, size*sizeof *fimg);
for (i=0; i < iheight; i++)
hat_transform (temp, fimg+size*(lev+1)+i*iwidth,1,iwidth, 1 << lev);
for (i=0; i < iwidth; i++)
hat_transform (temp, fimg+size*(lev+1)+i,iwidth, iheight, 1 << lev);
d3343 6
a3348 5
for (i=size*lev; i < size*(lev+1); i++) {
fimg[i] -= fimg[i+size];
if (fimg[i] < -thold) fimg[i] += thold;
else if (fimg[i] > thold) fimg[i] -= thold;
else fimg[i] = 0;
d3350 1
d3352 2
a3353 5
for (i=0; i < size; i++) {
for (val=lev=0; lev < depth; lev++)
val += fimg[size*lev+i];
image[i][c] = CLIP(val*val/0x10000);
}
d3461 1
a3461 1
int row, col;
d3472 4
a3475 2
for (col=0; col < width; col++)
img[row*width+col][FC(row,col)] = BAYER(row,col);
@
1.372
log
@Use the "a trous" wavelet transform instead of the JPEG2000 method.
Apply sqrt() to denoise highlights and shadows evenly.
@
text
@d25 1
a25 1
#define VERSION "8.64"
d108 1
a108 1
int zero_after_ff, is_raw, dng_version, is_foveon;
d248 12
d330 1
a330 1
fread (pixel, 2, count, ifp);
d460 1
a460 1
fread (data, raw_width * 10 / 8, 1, ifp);
d545 1
a545 1
c = fgetc(ifp);
d547 1
a547 1
bitbuf = (bitbuf << 8) + c;
d700 1
a700 1
int lowbits, i, row, r, col, save, val;
d715 2
a716 1
for (block=0; block < raw_width >> 3; block++) {
d739 2
a740 1
pixel[(block << 6) + i] = ( base[i & 1] += diffbuf[i] );
d855 2
a856 1
*outp = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff);
d1005 1
d1039 2
a1040 3
diff = hpred[col & 1];
if (diff >= csize) diff = csize-1;
BAYER(row,col-left_margin) = curve[diff];
d1065 1
a1065 1
getbits(8);
d1215 1
a1215 1
int row, col, r, c;
d1218 2
a1219 1
pixel = (ushort *) calloc (raw_width, sizeof *pixel);
d1222 3
a1224 2
read_shorts (pixel, raw_width);
for (col=0; col < fuji_width << !fuji_layout; col++) {
d1560 1
d1656 1
a1656 1
getbits(8);
d1663 1
a1663 1
int row, col;
d1665 1
d1667 1
a1667 1
pixel = (ushort *) calloc (raw_width, sizeof *pixel);
d1670 2
a1671 1
read_shorts (pixel, raw_width);
d1673 1
a1673 1
BAYER2(row,col) = pixel[col];
d1695 1
a1695 1
fread (data, 1, dwide, ifp);
d1697 2
a1698 1
if (((dp-data) & 15) == 15) dp++;
d1732 1
a1732 1
fread (pixel, 1, 768, ifp);
d1762 1
a1762 1
fread (pixel, 1, raw_width, ifp);
d1914 2
a1915 4
if (c)
BAYER(row+y*2+c-1,x*2+2-c) = val;
else
BAYER(row+r*2+y,x*2+y) = val;
d2000 1
a2000 1
fread (pixel, 848, 1, ifp);
d2018 1
a2018 1
fread (pixel, 1, raw_width, ifp);
d2070 2
a2071 1
pixel[pi] = pred + ljpeg_diff (decode[chess]);
d2140 2
a2141 1
BAYER(row,col+i) = curve[ret ? buf[i] : (pred[i & 1] += buf[i])];
d2164 1
a2164 1
y[j][k] = y[j][k^1] + *bp++;
d2184 1
a2184 1
FORC3 ip[c] = (rgb[c] += *bp++) & 0xfff;
d2234 1
a2234 1
fread (pixel, 2, raw_width, ifp);
d2239 2
a2240 1
BAYER(row,col) = ntohs(pixel[col+left_margin]);
d2263 1
a2263 1
sum += diff;
d2498 1
a2498 1
short diff[1024], pred[3];
d2500 1
a2500 1
int fixed, row, col, bit=-1, c, i;
d2522 1
d5780 1
a5780 1
mix_green = profile_length = 0;
d6674 1
a6674 1
width = 2576;
@
1.371
log
@Added the Olympus SP550UZ.
@
text
@d25 1
a25 1
#define VERSION "8.63"
d3271 13
d3286 2
a3287 2
float *fimg, *temp, mul[2], avg, diff;
int scale=1, dim=0, row, col, size, sh, nc, c, i, j, k, m, wlast;
d3289 2
a3290 2
static const float wlet[] = /* Daubechies 9-tap/7-tap filter */
{ 1.149604398, -1.586134342, -0.05298011854, 0.8829110762, 0.4435068522 };
d3297 2
a3298 2
while (1 << dim < iwidth || 1 << dim < iheight) dim++;
fimg = (float *) calloc ((1 << dim*2)+(1 << dim)+2, sizeof *fimg);
d3300 1
a3300 1
temp = fimg + (1 << dim*2) + 1;
d3303 21
a3323 50
for (row=0; row < iheight; row++)
for (col=0; col < iwidth; col++)
fimg[(row << dim)+col] = image[row*iwidth+col][c] << scale;
for (size = 1 << dim; size > 1; size >>= 1)
for (sh=0; sh <= dim; sh += dim)
for (i=0; i < size; i++) {
for (j=0; j < size; j++)
temp[j] = fimg[(i << (dim-sh))+(j << sh)];
for (k=1; k < 5; k+=2) {
temp[size] = temp[size-2];
for (m=1; m < size; m+=2)
temp[m] += wlet[k] * (temp[m-1] + temp[m+1]);
temp[-1] = temp[1];
for (m=0; m < size; m+=2)
temp[m] += wlet[k+1] * (temp[m-1] + temp[m+1]);
}
for (m=0; m < size; m++)
temp[m] *= (m & 1) ? 1/wlet[0] : wlet[0];
for (j=k=0; j < size; j++, k+=2) {
if (k == size) k = 1;
fimg[(i << (dim-sh))+(j << sh)] = temp[k];
}
}
for (i=0; i < 1 << dim*2; i++)
if (fimg[i] < -threshold) fimg[i] += threshold;
else if (fimg[i] > threshold) fimg[i] -= threshold;
else fimg[i] = 0;
for (size = 2; size <= 1 << dim; size <<= 1)
for (sh=dim; sh >= 0; sh -= dim)
for (i=0; i < size; i++) {
for (j=k=0; j < size; j++, k+=2) {
if (k == size) k = 1;
temp[k] = fimg[(i << (dim-sh))+(j << sh)];
}
for (m=0; m < size; m++)
temp[m] *= (m & 1) ? wlet[0] : 1/wlet[0];
for (k=3; k > 0; k-=2) {
temp[-1] = temp[1];
for (m=0; m < size; m+=2)
temp[m] -= wlet[k+1] * (temp[m-1] + temp[m+1]);
temp[size] = temp[size-2];
for (m=1; m < size; m+=2)
temp[m] -= wlet[k] * (temp[m-1] + temp[m+1]);
}
for (j=0; j < size; j++)
fimg[(i << (dim-sh))+(j << sh)] = temp[j];
}
for (row=0; row < iheight; row++)
for (col=0; col < iwidth; col++)
image[row*iwidth+col][c] = CLIP(fimg[(row << dim)+col] + 0.5);
d3337 1
d3342 4
a3345 3
diff = BAYER(row,col) - avg;
if (diff < -threshold/M_SQRT2) diff += threshold/M_SQRT2;
else if (diff > threshold/M_SQRT2) diff -= threshold/M_SQRT2;
d3347 1
a3347 1
BAYER(row,col) = CLIP(avg + diff + 0.5);
@
1.370
log
@Support the Canon EOS-1D Mark III.
@
text
@d25 1
a25 1
#define VERSION "8.62"
d98 1
a98 1
unsigned shot_order, kodak_cbpp, filters, unique_id, *oprof;
d4186 1
a4186 1
unsigned kodak, entries, tag, type, len, save;
d4206 4
d4719 2
a5920 2
if (!strncmp (make,"OLYMPUS",7))
height += height & 1;
a6470 15
} else if (!strcmp(model,"E-1") ||
!strcmp(model,"E-400")) {
filters = 0x61616161;
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")) {
width -= 20;
maximum = 0xfc30;
if (load_raw == &CLASS unpacked_load_raw) black = 0;
} else if (!strcmp(model,"E-330")) {
width -= 30;
d6477 21
a6497 6
load_raw = &CLASS olympus_cseries_load_raw;
if (!strcmp(model,"C5050Z") ||
!strcmp(model,"C8080WZ"))
filters = 0x16161616;
if (!strncmp(model,"SP5",3))
filters = 0x49494949;
@
1.369
log
@As the Pentax K10D was cropped, do likewise for the Samsung GX10.
@
text
@d25 1
a25 1
#define VERSION "8.61"
d870 2
d4146 1
a4146 1
i = len == 582 ? 50 : len == 653 ? 68 : len == 796 ? 126 : 0;
d6046 6
@
1.368
log
@Found larger JPEG thumbs for Nikon D100,D1H,D1X,D2H,D2X,E5000,E5700.
@
text
@d5887 1
a5887 1
if (!strcmp(model,"K10D")) { /* Camera DNGs are not cropped! */
@
1.367
log
@Reworded the copyright notice to avoid mention of the GPL.
@
text
@d25 1
a25 1
#define VERSION "8.60"
d3917 2
d4021 4
d4326 1
a4326 1
int CLASS parse_tiff_ifd (int base, int level)
d4437 1
a4437 1
if (parse_tiff_ifd (base, level+1)) break;
d4615 1
a4615 1
parse_tiff_ifd (base, level+1);
d4643 1
a4643 1
parse_tiff_ifd (-sony_offset, level);
d4677 1
a4677 1
if (parse_tiff_ifd (base, 0)) break;
@
1.366
log
@Replaced bilateral filter with wavelet denoising.
Fixed incompatibility between "-f" and "-p".
Fixed strange color casts with the Polaroid x530.
Added Adobe matrices for the Nikon D40 and Pentax K10D.
@
text
@d8 12
a19 13
Attention! Some parts of this program are restricted under the
terms of the GNU General Public License. Such code is enclosed
in "BEGIN GPL BLOCK" and "END GPL BLOCK" declarations.
Any code not declared GPL is free for all uses.
Starting in Revision 1.237, the code to support Foveon cameras
is under GPL.
To lawfully redistribute dcraw.c, you must either (a) include
full source code for all executable files containing restricted
functions, (b) remove these functions, re-implement them, or
copy them from an earlier, non-GPL Revision of dcraw.c, or (c)
purchase a license from the author.
d2385 1
a2385 1
/* BEGIN GPL BLOCK */
d3022 1
a3022 1
/* END GPL BLOCK */
@
1.365
log
@Added a color matrix for the Fuji S6000fd.
Set aspect ratio for the Kodak DC20 and DC25.
@
text
@d26 1
a26 1
#define VERSION "8.54"
d106 1
a106 1
int black, maximum, raw_color, use_gamma;
d111 2
a112 2
float bright=1, user_mul[4]={0,0,0,0}, sigma_d=0, sigma_r=0;
int four_color_rgb=0, document_mode=0, highlight=0;
d2681 5
a2688 7
else {
#define LAST(x,y) last[(i+x)%3][(c+y)%3]
for (i=0; i < 3; i++)
FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
#undef LAST
FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583;
}
d3270 97
d3369 1
a3369 1
int row, col, x, y, c, val, sum[8];
a3372 1
maximum -= black;
d3375 2
a3376 2
for (row=0; row < height-7; row += 8)
for (col=0; col < width-7; col += 8) {
d3381 1
a3381 1
val = image[y*width+x][c];
d3383 1
a3384 1
if (val > maximum-25) goto skip_block;
d3414 3
d3426 1
a3426 1
fprintf (stderr,_("Scaling with black %d, multipliers"), black);
d3430 2
a3431 2
for (row=0; row < height; row++)
for (col=0; col < width; col++)
d3433 1
a3433 1
val = image[row*width+col][c];
d3437 1
a3437 1
image[row*width+col][c] = CLIP(val);
d3439 23
d3463 2
a3464 4
if (four_color_rgb) {
colors++;
FORC3 rgb_cam[c][3] = rgb_cam[c][1] /= 2;
} else {
a3815 57
/*
Bilateral Filtering was developed by C. Tomasi and R. Manduchi.
*/
void CLASS bilateral_filter()
{
float (**window)[7], *kernel, scale_r, elut[1024], sum[5];
int c, i, wr, ws, wlast, row, col, y, x;
unsigned sep;
if (verbose) fprintf (stderr,_("Bilateral filtering...\n"));
wr = ceil(sigma_d*2); /* window radius */
ws = 2*wr + 1; /* window size */
window = (float (**)[7]) calloc ((ws+1)*sizeof *window +
ws*width*sizeof **window + ws*sizeof *kernel, 1);
merror (window, "bilateral_filter()");
for (i=0; i <= ws; i++)
window[i] = (float (*)[7]) (window+ws+1) + i*width;
kernel = (float *) window[ws] + wr;
for (i=-wr; i <= wr; i++)
kernel[i] = 256 / (2*SQR(sigma_d)) * i*i + 0.25;
scale_r = 256 / (2*SQR(sigma_r));
for (i=0; i < 1024; i++)
elut[i] = exp (-i/256.0);
for (wlast=-1, row=0; row < height; row++) {
while (wlast < row+wr) {
wlast++;
for (i=0; i <= ws; i++) /* rotate window rows */
window[(ws+i) % (ws+1)] = window[i];
if (wlast < height)
for (col=0; col < width; col++) {
FORCC window[ws-1][col][c] = image[wlast*width+col][c];
cam_to_cielab (image[wlast*width+col], window[ws-1][col]+4);
}
}
for (col=0; col < width; col++) {
memset (sum, 0, sizeof sum);
for (y=-wr; y <= wr; y++)
if ((unsigned)(row+y) < height)
for (x=-wr; x <= wr; x++)
if ((unsigned)(col+x) < width) {
sep = ( SQR(window[wr+y][col+x][4] - window[wr][col][4])
+ SQR(window[wr+y][col+x][5] - window[wr][col][5])
+ SQR(window[wr+y][col+x][6] - window[wr][col][6]) )
* scale_r + kernel[y] + kernel[x];
if (sep < 1024) {
FORCC sum[c] += elut[sep] * window[wr+y][col+x][c];
sum[4] += elut[sep];
}
}
FORCC image[row*width+col][c] = sum[c]/sum[4];
}
}
free (window);
}
d4029 1
a4029 1
while ((c = fgetc(ifp)))
d5512 2
d5587 1
a5587 1
{ 28402,-6651,-983,-14699,32553,6467,-1746,1571,25283 } },
d5758 1
a5758 1
profile_length = 0;
d6792 1
a6792 1
int mix_green, row, col, c, i, j, k;
a6879 1
mix_green = rgb_cam[1][1] == rgb_cam[1][3];
a6893 2
else if (mix_green)
img[1] = (img[1] + img[3]) >> 1;
d6896 1
a6896 1
if (colors == 4 && (output_color || mix_green)) colors = 3;
d7161 2
a7162 2
int timestamp_only=0, thumbnail_only=0, identify_only=0, write_to_stdout=0;
int half_size=0, use_fuji_rotate=1, quality, i, c;
d7195 1
a7210 1
puts(_("-B Apply bilateral filter to smooth noise"));
d7220 2
a7221 2
if ((cp = strchr (sp="BbrktqsH", opt)))
for (i=0; i < "21411111"[cp-sp]-'0'; i++)
d7227 1
a7227 2
case 'B': sigma_d = atof(argv[arg++]);
sigma_r = atof(argv[arg++]); break;
d7368 1
a7368 1
shrink = half_size && filters;
a7417 2
height = iheight;
width = iwidth;
d7426 1
a7426 1
if (shrink) filters = 0;
a7434 1
if (sigma_d > 0 && sigma_r > 0) bilateral_filter();
d7437 3
@
1.364
log
@The last version broke 16-bit PPM byte order.
@
text
@d26 1
a26 1
#define VERSION "8.53"
d4163 2
a4164 1
"","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65" };
d5351 2
d5529 1
a5529 1
{ "Panasonic DMC-FZ50", 0,
d5531 1
a5531 1
{ "Panasonic DMC-L1", 0,
d5533 1
a5533 1
{ "Panasonic DMC-LC1", 0,
d5535 1
a5535 1
{ "Panasonic DMC-LX1", 0,
d5537 1
a5537 1
{ "Panasonic DMC-LX2", 0,
d6488 1
d6491 1
@
1.363
log
@If the JPEG thumbnail has no EXIF table, add one.
Built a color matrix for the Canon PowerShot S3 IS.
@
text
@d26 1
a26 1
#define VERSION "8.52"
d7086 1
a7086 1
if (output_bps == 16 && !output_tiff && th.order == 0x4949)
@
1.362
log
@Added the Olympus SP510UZ.
@
text
@d26 1
a26 1
#define VERSION "8.50"
d1220 1
a1220 9
void CLASS jpeg_thumb (FILE *tfp)
{
char *thumb = (char *) malloc (thumb_length);
merror (thumb, "jpeg_thumb()");
fread (thumb, 1, thumb_length, ifp);
thumb[0] = 0xff;
fwrite (thumb, 1, thumb_length, tfp);
free (thumb);
}
d5320 2
d5804 1
a5804 1
if (!is_raw) return;
a6654 2
if (flip == -1) flip = tiff_flip;
if (flip == -1) flip = 0;
d6666 3
d6978 72
a7049 1
#define TOFF(ptr) ((char *)(&(ptr)) - (char *)(&th))
a7053 1
struct tm *t;
d7056 1
a7056 1
int i, c, row, col, psize=0, soff, rstep, cstep;
a7063 39
memset (&th, 0, sizeof th);
th.order = htonl(0x4d4d4949) >> 16;
th.magic = 42;
th.ifd = 10;
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.i0 = 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, 271, 2, 64, TOFF(th.make));
tiff_set (&th.ntag, 272, 2, 72, TOFF(th.model));
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);
tiff_set (&th.ntag, 305, 2, 32, TOFF(th.soft));
tiff_set (&th.ntag, 306, 2, 20, TOFF(th.date));
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[0]));
tiff_set (&th.nexif, 33437, 5, 1, TOFF(th.rat[2]));
tiff_set (&th.nexif, 34855, 3, 1, iso_speed);
tiff_set (&th.nexif, 37386, 5, 1, TOFF(th.rat[4]));
for (i=0; i < 6; i++) th.rat[i] = 1000000;
th.rat[0] *= shutter;
th.rat[2] *= aperture;
th.rat[4] *= focal_len;
strncpy (th.make, make, 64);
strncpy (th.model, model, 64);
strcpy (th.soft, "dcraw v"VERSION);
t = gmtime (×tamp);
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);
d7065 1
d7067 2
a7068 2
if (psize)
fwrite (oprof, psize, 1, ofp);
d7236 7
a7303 7
if (user_flip >= 0)
flip = user_flip;
switch ((flip+3600) % 360) {
case 270: flip = 5; break;
case 180: flip = 3; break;
case 90: flip = 6;
}
@
1.361
log
@Support the Panasonic DMC-L1, Leica Digilux 3, and Casio EX-Z4.
Run remove_zeroes() on most Panasonic and Leica models.
Built a color matrix for the Canon PowerShot A610.
Support Sinar IA file format.
@
text
@d26 1
a26 1
#define VERSION "8.49"
d5514 2
d6419 1
a6419 1
if (!strcmp(model,"SP500UZ"))
@
1.360
log
@Support internationalization if LOCALEDIR is defined.
Added stretch() function for cameras with non-square pixels.
Support "-h" and "-s" with Sinar 4-shot files.
Never append "DNG" to the camera model.
@
text
@d3 1
a3 1
Copyright 1997-2006 by Dave Coffin, dcoffin a cybercom o net
d26 1
a26 1
#define VERSION "8.48"
d1665 6
d4952 32
d5324 2
a5325 2
{ "Canon PowerShot A610", 0, /* copied from the S60 */
{ 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } },
d5532 2
d5665 1
a5665 1
{ 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i */
d5776 2
d6199 1
a6199 1
} else if (!strncmp(model,"Optio S4",8)) {
d6344 1
d6347 6
d6357 1
d6365 1
d6372 1
d6378 1
a6391 1
load_raw = &CLASS unpacked_load_raw;
d6538 1
a6538 1
} else if (!strcmp(make,"Rollei")) {
@
1.359
log
@Added the Kodak DCS200 and Canon PowerShots A620 and S3 IS.
@
text
@d26 1
a26 1
#define VERSION "8.46"
d51 6
d96 1
a96 1
char *ifname, make[64], model[72], model2[64], *meta_data, cdesc[5];
d107 2
a108 1
int iheight, iwidth, shrink, flip, xmag, ymag;
d245 1
a245 1
fprintf (stderr, "%s: Out of memory in %s\n", ifname, where);
d584 1
a584 1
fprintf (stderr, "%s: decoder table overflow\n", ifname);
d1361 1
a1361 1
if (verbose) fprintf (stderr, "Phase One correction...\n");
d1593 2
d1600 8
d1950 1
a1950 1
fprintf (stderr, "%s: incorrect JPEG dimensions\n", ifname);
d2403 1
a2403 1
fprintf (stderr, "%s: decoder table overflow\n", ifname);
d2562 1
a2562 1
fprintf (stderr, "%s: \"%s\" matrix not found!\n", ifname, name);
d2647 1
a2647 1
fprintf (stderr, "Foveon interpolation...\n");
d2673 1
a2673 1
{ fprintf (stderr, "%s: Invalid white balance \"%s\"\n", ifname, model2);
d3080 1
a3080 1
fprintf (stderr, "Fixed bad pixels at:");
d3111 1
a3111 1
fprintf (stderr, "%s is not a valid PGM file!\n", fname);
d3114 1
a3114 1
fprintf (stderr, "%s has the wrong dimensions!\n", fname);
d3317 1
a3317 1
fprintf (stderr, "%s: Cannot use camera white balance.\n", ifname);
d3331 1
a3331 1
fprintf (stderr, "Scaling with black=%d, pre_mul[] =", black);
d3385 1
a3385 1
if (verbose) fprintf (stderr, "Bilinear interpolation...\n");
d3462 1
a3462 1
if (verbose) fprintf (stderr, "VNG interpolation...\n");
d3604 1
a3604 1
if (verbose) fprintf (stderr, "AHD interpolation...\n");
d3709 1
a3709 1
if (verbose) fprintf (stderr, "Bilateral filtering...\n");
d3767 1
a3767 1
if (verbose) fprintf (stderr, "Highlight recovery...\n");
d4267 1
a4267 1
double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num, sx, sy;
d4519 2
a4520 4
sx = getrat();
sy = getrat();
if (sx > sy) xmag = sx / sy;
else ymag = sy / sx;
d4765 1
a4765 1
fprintf (stderr, "Reading metadata from %s...\n", jname);
d4773 1
a4773 1
fprintf (stderr, "Failed to read metadata from %s\n", jname);
d5646 1
a5646 1
is_raw = raw_color = use_gamma = xmag = ymag = 1;
d5776 1
a5776 1
xmag = ymag = 1;
a5782 1
strcat (model," DNG");
d5810 2
a5811 2
if (height*2 < width) ymag = 2;
if (height > width) xmag = 2;
d5819 1
d5828 1
d5952 3
a5954 1
ymag = 2;
d6464 1
d6603 1
a6603 1
fprintf (stderr, "%s: You must link dcraw.c with libjpeg!!\n", ifname);
d6642 1
a6642 1
fprintf (stderr, "%s has no embedded profile.\n", ifname);
d6658 1
a6658 1
fprintf (stderr, "Cannot open %s!\n", output);
d6661 1
a6661 1
fprintf (stderr, "Applying color profile...\n");
d6760 2
a6761 2
fprintf (stderr, raw_color ? "Building histograms...\n" :
"Converting to %s colorspace...\n", name[output_color-1]);
d6796 1
a6796 1
fprintf (stderr, "Rotating image 45 degrees...\n");
d6824 37
d6912 1
a6912 1
char make[64], model[72], soft[32], date[20];
d6941 2
a6942 5
if (flip & 4) {
SWAP(height,width);
SWAP(ymag,xmag);
}
ppm = (uchar *) calloc (width, colors*xmag*output_bps/8);
d6950 2
a6951 2
tiff_set (&th.ntag, 256, 4, 1, xmag*width);
tiff_set (&th.ntag, 257, 4, 1, ymag*height);
d6963 2
a6964 2
tiff_set (&th.ntag, 278, 4, 1, ymag*height);
tiff_set (&th.ntag, 279, 4, 1, ymag*height*xmag*width*colors*output_bps/8);
d6978 1
a6978 1
strncpy (th.model, model, 72);
d6991 1
a6991 1
xmag*width, ymag*height, colors, (1 << output_bps)-1, cdesc);
d6994 1
a6994 1
colors/2+5, xmag*width, ymag*height, (1 << output_bps)-1);
d6996 1
a6996 2
if (output_bps == 8)
gamma_lut (lut);
d7002 3
a7004 4
FORCC for (i=0; i < xmag; i++)
if (output_bps == 8)
ppm [(col*xmag+i)*colors+c] = lut[image[soff][c]];
else ppm2[(col*xmag+i)*colors+c] = image[soff][c];
d7006 2
a7007 3
swab (ppm2, ppm2, xmag*width*colors*2);
for (i=0; i < ymag; i++)
fwrite (ppm, colors*output_bps/8, xmag*width, ofp);
d7028 7
d7036 18
a7053 19
fprintf (stderr,
"\nRaw Photo Decoder \"dcraw\" v"VERSION
"\nby Dave Coffin, dcoffin a cybercom o net"
"\n\nUsage: %s [options] file1 file2 ...\n"
"\nValid options:"
"\n-v Print verbose messages"
"\n-c Write image data to standard output"
"\n-e Extract embedded thumbnail image"
"\n-i Identify files without decoding them"
"\n-z Change file dates to camera timestamp"
"\n-a Use automatic white balance"
"\n-w Use camera white balance, if possible"
"\n-r Set raw white balance (four values required)"
"\n-b Adjust brightness (default = 1.0)"
"\n-k Set black point"
"\n-K Subtract dark frame (16-bit raw PGM)"
"\n-H [0-9] Highlight mode (0=clip, 1=no clip, 2+=recover)"
"\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)"
d7055 2
a7056 2
"\n-o Apply output ICC profile from file"
"\n-p Apply camera ICC profile from file or \"embed\""
d7058 11
a7068 11
"\n-d Document Mode (no color, no interpolation)"
"\n-D Document Mode without scaling (totally raw)"
"\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-B Apply bilateral filter to reduce noise"
"\n-j Show Fuji Super CCD images tilted 45 degrees"
"\n-s [0-99] Select a different raw image from the same file"
"\n-4 Write 16-bit linear instead of 8-bit with gamma"
"\n-T Write TIFF instead of PPM"
"\n\n", argv[0]);
a7070 1
d7077 1
a7077 1
fprintf (stderr, "Non-numeric argument to \"-%c\"\n", opt);
a7108 2
case 'd': document_mode = 1; break;
case 'D': document_mode = 2; break;
d7111 2
d7118 1
a7118 1
fprintf (stderr, "Unknown option \"-%c\".\n", opt);
d7123 1
a7123 1
fprintf (stderr, "No files to process.\n");
d7128 1
a7128 1
fprintf (stderr, "Will not write an image to the terminal!\n");
d7157 1
a7157 1
fprintf (stderr, "%s has no timestamp.\n", ifname);
d7162 1
a7162 1
fprintf (stderr, "%s time set to %d.\n", ifname, (int) timestamp);
d7171 1
a7171 1
fprintf (stderr, "%s has no thumbnail.\n", ifname);
d7190 10
a7199 5
printf ("\nFilename: %s\n", ifname);
printf ("Timestamp: %s", ctime(×tamp));
printf ("Camera: %s %s\n", make, model);
printf ("ISO speed: %d\n", (int) iso_speed);
printf ("Shutter: ");
d7202 8
a7209 6
printf ("%0.1f sec\n", shutter);
printf ("Aperture: f/%0.1f\n", aperture);
printf ("Focal Length: %0.1f mm\n", focal_len);
printf ("Secondary pixels: %s\n", fuji_secondary ? "yes":"no");
printf ("Embedded ICC profile: %s\n", profile_length ? "yes":"no");
printf ("Decodable with dcraw: %s\n", is_raw ? "yes":"no");
d7211 2
a7212 2
printf ("Thumb size: %4d x %d\n", thumb_width, thumb_height);
printf ("Full size: %4d x %d\n", raw_width, raw_height);
d7214 1
a7214 1
fprintf (stderr, "Cannot decode %s\n", ifname);
d7228 9
a7236 4
if (fuji_width && use_fuji_rotate) {
fuji_width = (fuji_width - 1 + shrink) >> shrink;
iwidth = fuji_width / sqrt(0.5);
iheight = (iheight - fuji_width) / sqrt(0.5);
a7237 2
iheight *= ymag;
iwidth *= xmag;
d7240 3
a7242 3
printf ("Image size: %4d x %d\n", width, height);
printf ("Output size: %4d x %d\n", iwidth, iheight);
printf ("Raw colors: %d", colors);
d7244 1
a7244 1
printf ("\nFilter pattern: ");
d7249 1
a7249 1
printf ("\nDaylight multipliers:");
d7252 1
a7252 1
printf ("\nCamera multipliers:");
d7257 1
a7257 1
printf ("%s is a %s %s image.\n", ifname, make, model);
d7268 1
a7268 1
"Loading %s %s image from %s...\n", make, model, ifname);
d7299 1
d7310 1
a7310 1
strcpy (ofname, "standard output");
d7325 1
a7325 1
fprintf (stderr, "Writing data to %s ...\n", ofname);
@
1.358
log
@Added the Pentax K10D.
@
text
@d26 1
a26 1
#define VERSION "8.45"
d493 1
a493 1
ushort data[1670], *dp, pixel;
d1238 4
a1241 2
char *thumb;
colors = thumb_misc >> 5;
d1245 1
a1245 1
5 + (thumb_misc >> 6), thumb_width, thumb_height);
d1248 1
a1248 1
FORCC putc (thumb[i+thumb_length*c], tfp);
d5273 2
d5564 1
a5564 1
char make[12], model[15], withjpeg;
d5568 1
d5586 2
d5837 16
d6058 2
d6448 11
@
1.357
log
@Added the Canon PowerShot A610.
Added "-K" option for dark-frame subtraction.
@
text
@d26 1
a26 1
#define VERSION "8.44"
d441 1
a441 2
for (irow=row=0; irow < height; irow++)
{
d443 1
a443 2
for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8)
{
d960 25
d987 4
a990 5
static const uchar nikon_tree[] = {
0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,
5,4,3,6,2,7,1,0,8,9,11,10,12
};
int csize, row, col, i, diff;
a1004 1
d1006 1
a1006 2
for (col=0; col < raw_width; col++)
{
d3106 1
d4638 2
d5467 2
d5756 4
d6942 1
a6942 2
if (argc == 1)
{
d6989 1
a6989 2
switch (opt)
{
@
1.356
log
@Get the Olympus black level from the ORF metadata.
Don't truncate PPM thumbnails.
@
text
@d26 1
a26 1
#define VERSION "8.43"
d476 17
d495 2
a496 3
uchar data[1940], *dp;
ushort pixel[1552], *pix;
int row, col;
d498 10
a507 12
for (row=0; row < height; row++) {
fread (data, raw_width * 10 / 8, 1, ifp);
for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=10, pix+=8)
{
pix[0] = (dp[1] << 2) + (dp[0] >> 6);
pix[1] = (dp[0] << 4) + (dp[3] >> 4);
pix[2] = (dp[3] << 6) + (dp[2] >> 2);
pix[3] = (dp[2] << 8) + (dp[5] );
pix[4] = (dp[4] << 2) + (dp[7] >> 6);
pix[5] = (dp[7] << 4) + (dp[6] >> 4);
pix[6] = (dp[6] << 6) + (dp[9] >> 2);
pix[7] = (dp[9] << 8) + (dp[8] );
a508 4
for (col=0; col < width; col++)
BAYER(row,col) = (pixel[col] & 0x3ff);
for (col=width; col < raw_width; col++)
black += pixel[col] & 0x3ff;
d510 1
a510 2
if (raw_width > width)
black /= (raw_width - width) * height;
d512 1
d3049 39
d4284 1
a4284 1
if (!tiff_ifd[ifd].width) {
d5246 2
d5555 1
d5793 8
d6902 1
a6902 1
char opt, *ofname, *sp, *cp;
d6930 1
d6982 2
d7144 1
@
1.355
log
@Support the Olympus E-400 and Sinar 4-shot files.
Updated color matrices from DNG Converter 3.6.
Changed "-s" option to support multi-shot cameras.
@
text
@d26 1
a26 1
#define VERSION "8.42"
d1195 3
a1197 1
char *thumb = (char *) malloc (thumb_length);
d1620 1
a1620 1
int dwide, row, col, bls=width, ble=raw_width;
a1621 2
if (raw_width == 3360) bls += 4;
if (raw_width == 3280) ble = bls + 8;
a1634 2
for (col=bls; col < ble; col++)
black += pixel[col] & 0xfff;
a1635 1
if (ble > bls) black /= (ble - bls) * height;
d1638 1
d1654 1
d3187 1
a3187 2
int row, col, x, y, c, val;
int min[4], max[4], sum[8];
a3192 2
FORC4 min[c] = INT_MAX;
FORC4 max[c] = 0;
a3201 2
if (min[c] > val) min[c] = val;
if (max[c] < val) max[c] = val;
d3971 3
d6208 2
a6209 1
} else if (!strcmp(model,"E-1")) {
d6212 2
a6213 5
black = 1024;
} else if (!strcmp(model,"E-10")) {
maximum = 0xfff0;
black = 2048;
} else if (!strncmp(model,"E-20",4)) {
d6215 1
a6215 1
black = 2560;
d6220 1
a6222 4
} else if (!strcmp(model,"E-400")) {
filters = 0x61616161;
maximum = 0xfff0;
black = 1552;
@
1.354
log
@Found a more reliable way to identify 4775936-byte images.
@
text
@d26 1
a26 1
#define VERSION "8.41"
d108 1
a108 1
int fuji_layout, fuji_secondary, use_secondary=0;
d135 1
d879 1
a879 1
if (fuji_secondary && use_secondary) (*rp)++;
d894 1
a894 1
if (fuji_secondary && use_secondary) (*rp)--;
a1531 1
if (filters && c != MIN(1,tiff_samples-1)) continue;
d1537 1
d1552 23
d4276 1
d4557 1
a4557 1
if (raw >= 0)
d5154 2
d5230 1
a5230 1
{ "FUJIFILM FinePix S9", 0,
d5232 6
d5330 2
a5331 2
{ "NIKON D80", 0, /* copied from above */
{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
d5376 2
d5396 2
a5397 2
{ "PENTAX K100D", 0,
{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
d5407 2
a5408 2
{ 7970,-2904,-583,-6252,13395,3191,-1641,2282,6864 } },
{ "SAMSUNG GX-1S", 0,
d5629 1
a5629 1
if (fuji_secondary && use_secondary)
d5848 1
d5952 1
a5952 1
data_offset += use_secondary * ( strcmp(model+7," S3Pro")
d6133 1
a6133 1
load_raw = &CLASS unpacked_load_raw;
d6227 4
d6892 1
a6892 1
"\n-s Use secondary pixels (Fuji Super CCD SR only)"
d6902 2
a6903 2
if ((cp = strchr (sp="BbrktqH", opt)))
for (i=0; i < "2141111"[cp-sp]-'0'; i++)
d6918 1
a6940 1
case 's': use_secondary = 1; break;
@
1.353
log
@Updated link to Ting Chen's webpage.
@
text
@d26 1
a26 1
#define VERSION "8.40"
d1075 19
a1093 21
int i, sum[] = { 0, 0 };
uchar tail[952];
fseek (ifp, -sizeof tail, SEEK_END);
fread (tail, 1, sizeof tail, ifp);
for (i=0; i < sizeof tail; i++)
sum[(i>>2) & 1] += tail[i];
if (sum[0] > 4*sum[1]) return;
if (sum[1] > 4*sum[0]) {
strcpy (make, "OLYMPUS");
strcpy (model, "C740UZ");
return;
}
sum[0] = sum[1] = 0;
for (i=0; i < sizeof tail; i++)
sum[i & 1] += tail[i];
if (sum[1] > 4*sum[0] || sum[0]+sum[1] > 216000) {
strcpy (make, "PENTAX");
strcpy (model,"Optio 33WR");
} else
strcpy (model, "E3200");
d4240 1
@
1.352
log
@Fixed "maximum" for the Canon EOS 5D.
Added the Nikon E3200.
@
text
@d3320 1
a3320 1
described in http://www-ise.stanford.edu/~tingchen/algodep/vargra.html
@
1.351
log
@Display the focal length of Canon CRW images.
@
text
@d26 1
a26 1
#define VERSION "8.39"
d1073 1
a1073 6
/*
Returns 0 for a Pentax Optio 33WR,
1 for a Nikon E3700,
2 for an Olympus C740UZ.
*/
int CLASS nikon_3700()
d1082 14
a1095 2
if (sum[1] > 4*sum[0]) return 2;
return sum[0] > 4*sum[1];
d5779 1
d5870 4
a5873 6
if ((i = nikon_3700()) == 2) {
strcpy (make, "OLYMPUS");
strcpy (model, "C740UZ");
} else if (i == 0) {
strcpy (make, "PENTAX");
strcpy (model,"Optio 33WR");
@
1.350
log
@Added color matrices from Adobe DNG Converter 3.5.
@
text
@d4773 4
d6981 1
a6981 1
printf ("Focal Length: %d mm\n", (int) focal_len);
@
1.349
log
@Fixed problems with the Panasonic DMC-FZ50 and DMC-LX2.
@
text
@d26 1
a26 1
#define VERSION "8.38"
d5235 2
d5352 1
a5352 1
{ 20129,-6819,-1857,-12757,32020,5793,-1219,1356,17788 } },
d5355 2
a5356 2
{ "Panasonic DMC-FZ50", 0, /* copied from above */
{ 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
d5361 2
a5362 2
{ "Panasonic DMC-LX2", 0, /* copied from above */
{ 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
d5374 1
a5374 1
{ 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } }
@
1.348
log
@Added the Panasonic DMC-FZ50.
@
text
@d26 1
a26 1
#define VERSION "8.37"
d4173 3
d6139 6
d6147 1
a6148 1
width -= 22;
d6150 6
a6160 1
filters = 0x16161616;
@
1.347
log
@Added the Nikon D80.
@
text
@d26 1
a26 1
#define VERSION "8.36"
d5350 2
d6129 7
@
1.346
log
@Added the Panasonic DMC-LX2.
@
text
@d26 1
a26 1
#define VERSION "8.35"
d5282 2
d5778 3
@
1.345
log
@Added the Canon EOS 400D.
@
text
@d26 1
a26 1
#define VERSION "8.34"
a5235 4
{ "LEICA DIGILUX 2", 0,
{ 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
{ "LEICA D-LUX2", 0,
{ 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
d5352 2
d6115 9
a6123 1
if (width == 3880) {
a6124 1
maximum = 0xf7f0;
d6126 9
a6134 4
} else if (width == 3304) {
maximum = 0xf94c;
width -= 16;
} else maximum = 0xfff0;
@
1.344
log
@Improved support for the Nikon D200.
@
text
@d26 1
a26 1
#define VERSION "8.33"
d5725 2
d5751 7
d5767 2
a5768 2
height = raw_height - top_margin;
width = raw_width - left_margin;
@
1.343
log
@Correctly display long exposure times for CRW files.
@
text
@d26 1
a26 1
#define VERSION "8.32"
d5773 5
@
1.342
log
@Support the Pentax K100D.
@
text
@d26 1
a26 1
#define VERSION "8.31"
d4688 1
a4688 1
int tboff, nrecs, i, c, type, len, save, wbi=-1;
d4696 1
a4696 1
for (i=0; i < nrecs; i++) {
d4725 1
a4725 1
aperture = pow (2, (get2(),get2())/64.0);
d4729 2
@
1.341
log
@Get the correct thumbnail offset and size from Sony ARW files.
@
text
@d26 1
a26 1
#define VERSION "8.30"
d4152 1
a4152 1
double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num;
d4399 4
a4402 5
i = get4();
j = get4() * get4();
i *= get4();
if (i > j) xmag = i / j;
else ymag = j / i;
d5346 2
@
1.340
log
@Clear a "struct tm" before using it.
@
text
@d26 1
a26 1
#define VERSION "8.29"
d3734 1
a3734 1
void CLASS parse_olympus_note (int base)
d3741 2
a3742 2
if (tag == 257) thumb_offset = get4();
if (tag == 258) thumb_length = get4();
d3959 5
a3963 1
parse_olympus_note (base);
@
1.339
log
@Improved support for the Olympus E-330.
@
text
@d3989 1
d4785 1
d4958 1
@
1.338
log
@Previous version segfaulted with Fuji photos.
@
text
@d26 1
a26 1
#define VERSION "8.28"
d1611 1
d4523 4
a4526 1
&CLASS unpacked_load_raw : &CLASS eight_bit_load_raw; break;
a6115 4
if (fsize <= 15728640) {
maximum = 0xfff;
load_raw = &CLASS olympus_e300_load_raw;
}
a6117 1
load_raw = &CLASS olympus_e300_load_raw;
@
1.337
log
@Halved memory usage by moving flip logic into write_ppm_tiff().
@
text
@d26 1
a26 1
#define VERSION "8.27"
d6654 2
@
1.336
log
@Support the Leaf CatchLight with VNG interpolation.
Added the Samsung GX-1S.
@
text
@d26 1
a26 1
#define VERSION "8.26"
d6578 4
a6581 29
if (flip & 1) col = width - 1 - col;
if (flip & 2) row = height - 1 - row;
return (flip & 4) ? col * height + row
: row * width + col;
}
void CLASS flip_image()
{
int row, col, soff=0, doff, rstep, cstep;
INT64 *src, *dest;
if (verbose)
fprintf (stderr, "Flipping image %c:%c:%c...\n",
flip & 1 ? 'H':'0', flip & 2 ? 'V':'0', flip & 4 ? 'T':'0');
src = (INT64 *) image;
dest = (INT64 *) calloc (height * width, sizeof *dest);
merror (dest, "flip_image()");
doff = flip_index (0, 0);
cstep = flip_index (0, 1) - doff;
rstep = flip_index (1, 0) - flip_index (0, width);
for (row=0; row < height; row++, doff += rstep)
for (col=0; col < width; col++, doff += cstep)
dest[doff] = src[soff++];
image = (ushort (*)[4]) dest;
free (src);
if (flip & 4) {
SWAP(height,width);
SWAP(ymag,xmag);
}
d6652 1
a6652 1
int i, c, row, col, psize=0;
d6654 4
d6714 5
a6718 2
for (row=0; row < height; row++) {
for (col=0; col < width; col++)
d6721 2
a6722 2
ppm [(col*xmag+i)*colors+c] = lut[image[row*width+col][c]];
else ppm2[(col*xmag+i)*colors+c] = image[row*width+col][c];
a7000 1
if (flip) flip_image();
@
1.335
log
@Udi added &CLASS qualifiers for C++ compatibility.
@
text
@d26 1
a26 1
#define VERSION "8.25"
d154 3
a157 6
*/
#define FC(row,col) \
(filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
#define BAYER(row,col) \
image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
a158 1
/*
d188 33
d1580 1
a1580 1
BAYER(row,col) = pixel[col];
d2995 2
a2996 2
(r != row || c != col) && FC(r,c) == FC(row,col)) {
tot += BAYER(r,c);
d2999 1
a2999 1
BAYER(row,col) = tot/n;
d3246 1
a3246 1
unsigned row, col, y, x, c, sum[8];
d3256 3
a3258 2
sum[FC(y,x)] += BAYER(y,x);
sum[FC(y,x)+4]++;
d3260 2
a3261 1
FORCC if (c != FC(row,col))
d3268 1
a3268 1
int code[8][2][32], *ip, sum[4];
d3275 2
a3276 2
for (row=0; row < 8; row++)
for (col=0; col < 2; col++) {
d3283 1
a3283 1
color = FC(row+y,col+x);
d3290 1
a3290 1
if (c != FC(row,col)) {
d3298 1
a3298 1
ip = code[row & 7][col & 1];
d3344 1
a3344 1
int code[8][2][320], *ip, gval[8], gmin, gmax, sum[4];
d3351 6
a3356 3
for (row=0; row < 8; row++) { /* Precalculate for VNG */
for (col=0; col < 2; col++) {
ip = code[row][col];
d3362 3
a3364 3
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;
d3377 2
a3378 2
color = FC(row,col);
if (FC(row+y,col+x) != color && FC(row+y*2,col+x*2) == color)
a3383 1
}
d3391 1
a3391 1
ip = code[row & 7][col & 1];
d3414 1
a3414 1
color = FC(row,col);
d3440 1
d4146 1
a4146 1
double dblack, cc[4][4], cm[4][3], cam_xyz[4][3];
d4287 12
d5342 2
d5469 2
a5470 1
"MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One" };
d6059 2
a6060 2
colors = 1;
filters = 0;
d6062 1
a6062 1
top_margin = 7; left_margin = 18; height = 2033; width = 2016;
d6480 1
a6480 1
oprof[oprof[0]/4] = i < 2 ? pbody[i*3+1] : 0x58595a20;
d6967 2
a6968 2
for (i=0; i < 32; i+=2)
putchar (cdesc[filters >> i & 3]);
@
1.334
log
@Replaced gmtime_r() with the more common gmtime().
@
text
@d4397 1
a4397 1
load_raw = packed_12_load_raw;
d4476 1
a4476 1
unpacked_load_raw : eight_bit_load_raw; break;
d4478 1
a4478 1
load_raw = lossless_jpeg_load_raw; break;
d4480 1
a4480 1
load_raw = kodak_262_load_raw; break;
d4482 1
a4482 1
load_raw = packed_12_load_raw; break;
d4485 3
a4487 3
case 2: load_raw = kodak_rgb_load_raw; filters = 0; break;
case 6: load_raw = kodak_ycbcr_load_raw; filters = 0; break;
case 32803: load_raw = kodak_65000_load_raw;
d4507 1
a4507 1
write_thumb = layer_thumb;
d4511 1
a4511 1
thumb_load_raw = kodak_thumb_load_raw;
d4513 1
a4513 1
write_thumb = ppm_thumb;
d4517 1
a4517 1
kodak_ycbcr_load_raw : kodak_rgb_load_raw;
d4762 1
a4762 1
write_thumb = rollei_thumb;
d4820 1
a4820 1
phase_one_load_raw : phase_one_load_raw_c;
d4933 2
a4934 2
if (ver == 6) load_raw = smal_v6_load_raw;
if (ver == 9) load_raw = smal_v9_load_raw;
d4986 1
a4986 1
write_thumb = foveon_thumb;
d5431 1
a5431 1
write_thumb = jpeg_thumb;
d5573 1
a5573 1
load_raw = adobe_dng_load_raw_nc;
d5575 1
a5575 1
load_raw = adobe_dng_load_raw_lj;
d5584 1
a5584 1
lossless_jpeg_load_raw : canon_compressed_load_raw;
d5589 1
a5589 1
nikon_compressed_load_raw : nikon_load_raw;
d5599 1
a5599 1
load_raw = foveon_load_raw;
d5607 1
a5607 1
load_raw = canon_600_load_raw;
d5615 1
a5615 1
load_raw = canon_a5_load_raw;
d5622 1
a5622 1
load_raw = canon_a5_load_raw;
d5628 1
a5628 1
load_raw = canon_a5_load_raw;
d5707 1
a5707 1
if (tiff_compress == 34713 && load_raw == nikon_load_raw)
d5719 1
a5719 1
load_raw = nikon_e900_load_raw;
d5731 1
a5731 1
load_raw = nikon_e900_load_raw;
d5741 1
a5741 1
load_raw = nikon_load_raw;
d5755 1
a5755 1
load_raw = nikon_e2100_load_raw;
d5768 1
a5768 1
load_raw = nikon_e2100_load_raw;
d5791 1
a5791 1
load_raw = nikon_e2100_load_raw;
d5804 1
a5804 1
load_raw = nikon_load_raw;
d5807 1
a5807 1
load_raw = unpacked_load_raw;
d5826 1
a5826 1
load_raw = fuji_load_raw;
d5833 1
a5833 1
load_raw = minolta_rd175_load_raw;
d5842 1
a5842 1
load_raw = unpacked_load_raw;
d5847 1
a5847 1
load_raw = packed_12_load_raw;
d5854 1
a5854 1
load_raw = packed_12_load_raw;
d5872 1
a5872 1
load_raw = unpacked_load_raw;
d5882 1
a5882 1
load_raw = eight_bit_load_raw;
d5891 1
a5891 1
load_raw = packed_12_load_raw;
d5900 1
a5900 1
load_raw = packed_12_load_raw;
d5907 1
a5907 1
load_raw = eight_bit_load_raw;
d5918 1
a5918 1
load_raw = unpacked_load_raw;
d5924 1
a5924 1
load_raw = unpacked_load_raw;
d5930 1
a5930 1
load_raw = eight_bit_load_raw;
d5934 1
a5934 1
load_raw = eight_bit_load_raw;
d5938 2
a5939 1
load_raw = (fsize < 7500000) ? eight_bit_load_raw : unpacked_load_raw;
d5944 1
a5944 1
load_raw = unpacked_load_raw;
d5952 2
a5953 1
load_raw = (fsize < 2000000) ? eight_bit_load_raw : unpacked_load_raw;
d5961 1
a5961 1
load_raw = unpacked_load_raw;
d5966 2
a5967 1
load_raw = (fsize < 10000000) ? eight_bit_load_raw : unpacked_load_raw;
d5973 1
a5973 1
load_raw = unpacked_load_raw;
d5987 1
a5987 1
load_raw = imacon_full_load_raw;
d5990 1
a5990 1
load_raw = unpacked_load_raw;
d6001 1
a6001 1
load_raw = unpacked_load_raw;
d6007 1
a6007 1
load_raw = leaf_hdr_load_raw;
d6048 1
a6048 1
load_raw = unpacked_load_raw;
d6065 1
a6065 1
load_raw = olympus_e300_load_raw;
d6069 1
a6069 1
load_raw = olympus_e300_load_raw;
d6074 1
a6074 1
load_raw = nikon_e2100_load_raw;
d6076 1
a6076 1
load_raw = olympus_cseries_load_raw;
d6087 1
a6087 1
load_raw = packed_12_load_raw;
d6093 1
a6093 1
load_raw = sony_load_raw;
d6101 1
a6101 1
load_raw = sony_load_raw;
d6108 1
a6108 1
load_raw = sony_arw_load_raw;
d6142 2
a6143 2
if (load_raw == eight_bit_load_raw)
load_raw = kodak_easy_load_raw;
d6162 1
a6162 1
load_raw = kodak_easy_load_raw;
d6168 1
a6168 1
load_raw = kodak_radc_load_raw;
d6174 1
a6174 1
load_raw = kodak_radc_load_raw;
d6179 2
a6180 2
load_raw = (tiff_compress == 7)
? kodak_jpeg_load_raw : kodak_dc120_load_raw;
d6186 1
a6186 1
load_raw = kodak_radc_load_raw;
d6204 1
a6204 1
load_raw = rollei_load_raw;
d6211 1
a6211 1
load_raw = eight_bit_load_raw;
d6218 1
a6218 1
load_raw = eight_bit_load_raw;
d6223 1
a6223 1
load_raw = eight_bit_load_raw;
d6227 1
a6227 1
load_raw = unpacked_load_raw;
d6232 1
a6232 1
load_raw = casio_qv5700_load_raw;
d6237 1
a6237 1
load_raw = packed_12_load_raw;
d6244 1
a6244 1
load_raw = packed_12_load_raw;
d6251 1
a6251 1
load_raw = packed_12_load_raw;
d6258 1
a6258 1
load_raw = packed_12_load_raw;
d6265 1
a6265 1
load_raw = packed_12_load_raw;
d6272 1
a6272 1
load_raw = packed_12_load_raw;
d6279 1
a6279 1
load_raw = packed_12_load_raw;
d6284 1
a6284 1
load_raw = unpacked_load_raw;
d6287 1
a6287 1
load_raw = nucore_load_raw;
d6305 1
a6305 1
if (load_raw == kodak_jpeg_load_raw) {
d6850 1
a6850 1
write_fun = write_ppm_tiff;
d6867 1
a6867 1
if (load_raw == kodak_ycbcr_load_raw) {
d6972 1
a6972 1
if (write_fun == jpeg_thumb)
d6974 1
a6974 1
else if (output_tiff && write_fun == write_ppm_tiff)
@
1.333
log
@New "-T" option provides TIFF output with metadata and ICC profile.
Support old Leaf cameras, plus new and obsolete Leaf image formats.
Added camera WB for the Imacon Ixpress and Kodak P850/P880.
@
text
@d6622 1
a6622 1
struct tm t;
d6665 1
a6665 1
gmtime_r (×tamp, &t);
d6667 1
a6667 1
t.tm_year+1900,t.tm_mon+1,t.tm_mday,t.tm_hour,t.tm_min,t.tm_sec);
@
1.332
log
@Support Kodak NC2000 images compressed by Photo Mechanic.
@
text
@d26 2
d93 1
a93 1
unsigned shot_order, kodak_cbpp, filters, unique_id;
d97 1
a97 1
int tiff_nifds, tiff_flip, tiff_bps, tiff_compress;
d106 2
a107 1
int verbose=0, use_auto_wb=0, use_camera_wb=0, output_color=1;
a115 1
void write_ppm(FILE *);
d413 1
a413 1
fread (data, 1120, 1, ifp);
d427 1
a427 1
for (col=width; col < 896; col++)
d431 2
a432 1
black = black / ((896 - width) * height) - 4;
d785 1
a785 1
ushort *outp=jh->row;
d789 3
a791 1
if (jrow) get2(); /* Eat the FF Dx marker */
d1129 1
d1486 1
d1489 1
a1489 1
void CLASS leaf_full_load_raw()
d1492 1
a1492 1
int r, c, row, col;
d1495 8
a1502 3
merror (pixel, "leaf_full_load_raw()");
for (r=0; r < height-32; r+=32)
FORC3 for (row=r; row < r+32; row++) {
d1504 1
d1506 2
a1507 1
image[row*width+col][c] = pixel[col];
d1509 1
d1511 4
d1545 1
d3425 9
a3433 5
for (i=0; i < 3; i++) {
for (xyz[i]=0.5, c=0; c < colors; c++)
xyz[i] += xyz_cam[i][c] * cam[c];
xyz[i] = cbrt[CLIP((int) xyz[i])];
}
d3900 6
a3905 2
if (tag == 0xf00 && len == 614 && type == 7) {
fseek (ifp, 176, SEEK_CUR);
d3931 1
d3993 3
a3995 3
{ { 2.0564, -0.7932, -0.2632 },
{ -0.2118, 1.2490, -0.0372 },
{ -0.0152, -0.1405, 1.1556 } };
d4008 3
a4010 1
static const char *mod[] = { "Aptus","Valeo","Volare" };
d4015 2
a4016 3
fread (data, 1, 8, ifp);
if (strcmp(data,"PKTS")) break;
if (!make[0]) strcpy (make, "Leaf");
d4028 4
a4031 5
if (!strcmp(data,"CaptProf_serial_number")) {
fread (data, 1, 40, ifp);
for (i=0; i < sizeof mod / sizeof *mod; i++)
if (data[0] == mod[i][0] && data[1] == toupper(mod[i][1]))
sprintf (model, "%s %d", mod[i], atoi(data+2));
d4051 1
a4051 1
if (!strcmp(data,"NeutObj_neutrals")) {
d4073 31
d4190 1
d4198 3
d4202 1
a4202 1
tiff_ifd[ifd].offset = level ? ftell(ifp) : get4();
d4240 4
d4250 3
d4255 2
d4295 3
a4297 1
fseek (ifp, 178, SEEK_CUR);
a4429 31
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();
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]);
}
if (tag == 2317) linear_table (len);
if (tag == 6020) iso_speed = getint(type);
fseek (ifp, save, SEEK_SET);
}
}
a4444 4
if (!dng_version && !strncmp(make,"Kodak",5)) {
fseek (ifp, 12+base, SEEK_SET);
parse_kodak_ifd (base);
}
d4477 1
a4477 1
case 6: case 7:
d5182 2
d5417 2
a5418 1
{ 33292868, "Sinar", "" ,0 } };
d5436 1
a5536 2
parse_mos(8);
parse_mos(3472);
d5604 1
a5818 1
data_offset += (top_margin*raw_width + left_margin) * 2;
d5976 2
a5977 3
data_offset = (2048 * 16 + 28) * 2;
height -= 16;
width -= 28;
a5985 1
data_offset += (top_margin*raw_width + left_margin) * 2;
a6000 2
if (tiff_compress == 99)
load_raw = lossless_jpeg_load_raw;
d6002 33
a6034 5
if (filters == 0) {
strcpy (model, "Volare");
load_raw = leaf_full_load_raw;
maximum = 0xffff;
raw_color = 0;
d6038 1
a6038 1
data_offset += 12;
d6326 1
a6326 1
cmsHPROFILE hInProfile=NULL, hOutProfile;
d6328 2
d6344 15
a6358 2
hOutProfile = output ? cmsOpenProfileFromFile (output, "r")
: cmsCreate_sRGBProfile();
d6378 7
d6389 1
a6389 1
static const double wgd65_rgb[3][3] =
d6394 3
a6396 3
{ { 0.522966, 0.346773, 0.130274 },
{ 0.089210, 0.862705, 0.048090 },
{ 0.017725, 0.109450, 0.872912 } };
d6398 1
a6398 1
{ adobe_rgb, wgd65_rgb, prophoto_rgb, xyz_rgb };
d6400 17
a6416 1
{ "sRGB", "Adobe 1998 RGB", "Wide Gamut D65", "ProPhoto D65", "XYZ" };
d6419 40
a6458 7
raw_color |= colors == 1 || output_color < 1 || output_color > 5;
if (!raw_color)
if (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-2][i][k] * rgb_cam[k][j];
d6463 1
a6463 1
mix_green = raw_color && rgb_cam[1][1] == rgb_cam[1][3];
d6465 12
a6476 4
for (row=0; row < height; row++)
for (col=0; col < width; col++) {
img = image[row*width+col];
if (document_mode && filters)
a6479 5
else if (!raw_color) {
FORC3 for (out[c]=i=0; i < colors; i++)
out[c] += img[i] * out_cam[c][i];
FORC3 img[c] = CLIP((int) out[c]);
}
d6557 1
a6557 1
void CLASS write_ppm (FILE *ofp)
d6559 1
a6559 2
uchar *ppm, lut[0x10000];
int perc, c, val, total, i, row, col;
a6561 10
ppm = (uchar *) calloc (width, colors*xmag);
merror (ppm, "write_ppm()");
if (colors > 3)
fprintf (ofp,
"P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL 255\nTUPLTYPE %s\nENDHDR\n",
xmag*width, ymag*height, colors, cdesc);
else
fprintf (ofp, "P%d\n%d %d\n255\n", colors/2+5, xmag*width, ymag*height);
a6581 8
for (row=0; row < height; row++) {
for (col=0; col < width; col++)
FORCC for (i=0; i < xmag; i++)
ppm[(col*xmag+i)*colors+c] = lut[image[row*width+col][c]];
for (i=0; i < ymag; i++)
fwrite (ppm, colors*xmag, width, ofp);
}
free (ppm);
d6584 21
a6604 1
void CLASS write_ppm16 (FILE *ofp)
d6606 1
a6606 2
int row, col, c;
ushort *ppm;
d6608 66
a6673 3
ppm = (ushort *) calloc (width, 2*colors);
merror (ppm, "write_ppm16()");
if (colors > 3)
d6676 1
a6676 1
width, height, colors, 65535, cdesc);
d6679 1
a6679 1
colors/2+5, width, height, 65535);
d6681 2
d6685 8
a6692 2
FORCC ppm[col*colors+c] = htons(image[row*width+col][c]);
fwrite (ppm, 2*colors, width, ofp);
a6696 38
void CLASS write_psd (FILE *ofp)
{
char head[] = {
'8','B','P','S', /* signature */
0,1,0,0,0,0,0,0, /* version and reserved */
0,3, /* number of channels */
0,0,0,0, /* height, big-endian */
0,0,0,0, /* width, big-endian */
0,16, /* 16-bit color */
0,3, /* mode (1=grey, 3=rgb) */
0,0,0,0, /* color mode data */
0,0,0,0, /* image resources */
0,0,0,0, /* layer/mask info */
0,0 /* no compression */
};
int hw[2], psize, row, col, c;
ushort *buffer, *pred;
hw[0] = htonl(height); /* write the header */
hw[1] = htonl(width);
memcpy (head+14, hw, sizeof hw);
head[13] = head[25] = colors;
fwrite (head, 40, 1, ofp);
psize = height*width;
buffer = (ushort *) calloc (colors, psize*2);
merror (buffer, "write_psd()");
pred = buffer;
for (row=0; row < height; row++)
for (col=0; col < width; col++) {
FORCC pred[c*psize] = htons(image[row*width+col][c]);
pred++;
}
fwrite(buffer, psize*2, colors, ofp);
free (buffer);
}
a6705 1
void (*write_image)(FILE *) = write_ppm;
d6716 1
a6716 1
"\nRaw Photo Decoder \"dcraw\" v8.23"
d6745 2
a6746 3
"\n-2 Write 8-bit non-linear PPM (default)"
"\n-4 Write 16-bit linear PPM"
"\n-3 Write 16-bit linear PSD (Adobe Photoshop)"
a6792 1
case 'n': highlight = 1; break;
d6794 2
a6795 5
case '2': write_image = write_ppm; break;
case '4': write_image = write_ppm16; break;
case '3': write_image = write_psd; break;
d6820 1
d6847 1
a6847 1
write_fun = write_image;
d6879 1
d6905 2
a6906 4
if (write_fun == write_ppm) {
iheight *= ymag;
iwidth *= xmag;
}
d6971 2
a6972 2
else if (write_fun == write_psd)
write_ext = ".psd";
d6998 1
@
1.331
log
@Added the Sony DSLR-A100, Minolta DiMAGE G530, and Sinar 4080x4080.
Support software white balance for Kodak DSLRs.
Correctly decode Phase One IIQ Small images.
@
text
@d1866 1
a1866 1
unsigned row, col, icol;
d1875 4
a1878 5
icol = col - left_margin;
if (icol < width)
BAYER(row,icol) = (ushort) curve[pixel[col]];
else
black += curve[pixel[col]];
d1889 48
d4432 18
a4449 14
if (raw >= 0) {
if (tiff_compress < 2)
load_raw = tiff_bps > 8 ? unpacked_load_raw : eight_bit_load_raw;
if (tiff_compress/2 == 3)
load_raw = lossless_jpeg_load_raw;
if (tiff_compress == 32773)
load_raw = packed_12_load_raw;
if (tiff_compress == 65000)
switch (tiff_ifd[raw].phint) {
case 2: load_raw = kodak_rgb_load_raw; filters = 0; break;
case 6: load_raw = kodak_ycbcr_load_raw; filters = 0; break;
case 32803: load_raw = kodak_65000_load_raw;
}
}
d6544 1
a6544 1
"\nRaw Photo Decoder \"dcraw\" v8.22"
@
1.330
log
@Fixed the filter pattern on the Micron 2010.
@
text
@d1450 2
d1468 2
d2053 20
d3677 1
a3677 1
unsigned ver97=0, serial=0, i;
d3687 1
a3687 3
if (!strncmp (buf,"KC" ,2) || /* these aren't TIFF format */
!strncmp (buf,"KDK" ,3) ||
!strncmp (buf,"MLY" ,3) ||
d3691 12
d3997 2
d4094 4
d4255 4
a4258 1
fseek (ifp, get4()+base, SEEK_SET);
d4311 1
a4311 4
int i, c, wbi=-2, wbtemp;
char line[128];
static const char *wbs[] =
{ "Auto","Daylight","Tungsten","Fluorescent","Flash" };
d4318 7
a4324 11
if (tag == 1009)
while ((int) len > 0) {
fgets (line, 128, ifp);
len -= strlen(line) + 1;
if (!strncmp (line, "White bal", 9)) {
wbtemp = atoi (line + strlen(line) - 5);
if (wbtemp < 1000) wbtemp = 6500;
for (i=0; i < 5; i++)
if (strstr (line, wbs[i])) wbi = i-1;
}
}
a4336 1
if (wbi == -1) cam_mul[0] = -1;
d4431 1
a4431 1
void CLASS parse_minolta()
d4435 4
a4438 2
fseek (ifp, 4, SEEK_SET);
offset = get4() + 8;
d4440 2
a4441 1
tag = get4();
d4456 1
a4461 1
data_offset = offset;
d4963 2
d5045 1
a5045 1
{ "KODAK NC2000F", 0, /* DJC */
d5093 4
d5177 2
d5183 2
d5187 2
d5210 3
a5212 1
{ 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } }
d5323 2
a5324 1
{ 12582980, "Sinar", "" ,0 } };
d5372 2
a5373 1
fseek (ifp, 4 + get2(), SEEK_SET);
d5431 1
a5431 1
parse_minolta();
d5459 2
d5741 1
a5741 1
} else if (!strcmp(model,"Digital Camera KD-400Z")) {
a5744 2
data_offset = 4034;
fseek (ifp, 2032, SEEK_SET);
d5746 1
a5746 5
} else if (!strcmp(model,"Digital Camera KD-510Z")) {
data_offset = 4032;
pre_mul[0] = 1.297;
pre_mul[2] = 1.438;
fseek (ifp, 2032, SEEK_SET);
d5759 2
a5760 1
sprintf (model, "DYNAX %s", model+6 + (model[0]=='M'));
a5764 4
data_offset = 5056;
pre_mul[0] = 1.602;
pre_mul[2] = 1.441;
fseek (ifp, 2078, SEEK_SET);
a5767 2
data_offset = 4016;
fseek (ifp, 1936, SEEK_SET);
a5772 2
data_offset = 4032;
fseek (ifp, 2030, SEEK_SET);
d5776 1
a5781 5
FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
}
if (pre_mul[0] == 1 && pre_mul[2] == 1) {
pre_mul[0] = 1.42;
pre_mul[2] = 1.25;
d5986 4
d5994 1
a5994 1
if (!strcmp(model,"NC2000F")) {
d6043 1
a6043 1
} else if (!strcmp(model,"Digital Camera 40")) {
d6493 1
a6493 1
"\nRaw Photo Decoder \"dcraw\" v8.21"
@
1.329
log
@Added the Sony XCD-SX910CR and Micron 2010 sensors.
Added camera WB for the Kodak DCS Pro SLR models.
After scale_colors(), use "65535" instead of "maximum".
@
text
@d5055 2
d5824 1
d6450 1
a6450 1
"\nRaw Photo Decoder \"dcraw\" v8.20"
@
1.328
log
@Changed the "-H" option so the user can control color spread.
@
text
@d3326 1
a3326 1
r = (float) i / maximum;
d3953 10
a4170 1
case 2317:
d4172 1
a4172 6
if (len > 0x1000)
len = 0x1000;
read_shorts (curve, len);
for (i=len; i < 0x1000; i++)
curve[i] = curve[i-1];
maximum = curve[0xfff];
d4265 39
d4321 1
a4321 1
parse_tiff_ifd (base, 2);
d5240 3
d5811 14
a6186 1
maximum = 0xffff;
d6447 1
a6447 1
"\nRaw Photo Decoder \"dcraw\" v8.19"
@
1.327
log
@Added pointer casts for C++ compatibility.
@
text
@d3515 1
a3515 1
#define SCALE (8 >> shrink)
d3518 1
a3518 1
float *map, sum, wgt;
d3527 2
a3528 1
FORCC hsat[c] = 31000 * pre_mul[c];
d3552 1
a3552 1
for (spread = 100; spread--; ) {
d3566 1
a3566 1
map[mrow*wide+mcol] = -sum / count * (15/16.0) - (1/16.0);
d6279 1
d6388 1
a6388 1
"\nRaw Photo Decoder \"dcraw\" v8.18"
d6402 1
a6402 1
"\n-H [0-2] Highlight mode (0=clip, 1=no clip, 2=recover)"
@
1.326
log
@Greatly improved the highlight recovery.
@
text
@d648 1
a648 1
pixel = calloc (raw_width*8, sizeof *pixel);
d759 1
a759 1
jh->row = calloc (jh->wide*jh->clrs, 2);
d901 1
a901 1
pixel = calloc (raw_width * tiff_samples, sizeof *pixel);
d932 1
a932 1
curve = calloc (csize, sizeof *curve);
d1124 1
a1124 1
pixel = calloc (raw_width, sizeof *pixel);
d1144 1
a1144 1
char *thumb = malloc (thumb_length);
d1154 1
a1154 1
char *thumb = malloc (thumb_length);
d1167 1
a1167 1
thumb = malloc (thumb_length*colors);
d1180 1
a1180 1
ushort *thumb = calloc (size, 2);
d1231 1
a1231 1
mrow = calloc (nc*wide, sizeof *mrow);
d1359 1
a1359 1
yval[0] = calloc (head[1]*head[3] + head[2]*head[4], 6);
d1401 1
a1401 1
pixel = calloc (raw_width, sizeof *pixel);
d1440 1
a1440 1
pixel = calloc (raw_width + raw_height*4, 2);
d1483 1
a1483 1
pixel = calloc (raw_width, sizeof *pixel);
d1522 1
a1522 1
pixel = calloc (raw_width, sizeof *pixel);
d1541 1
a1541 1
data = malloc (dwide + raw_width*2);
d1608 1
a1608 1
pixel = calloc (raw_width, sizeof *pixel);
d1644 1
a1644 1
pixel = calloc (width, 2);
d1829 1
a1829 1
pixel = (void *) buf[0];
d1866 1
a1866 1
pixel = calloc (raw_width, sizeof *pixel);
d2029 1
a2029 1
sony_decrypt ((void *) head, 10, 1, key);
d2033 1
a2033 1
pixel = calloc (raw_width, sizeof *pixel);
d2037 1
a2037 1
sony_decrypt ((void *) pixel, raw_width/2, !row, key);
d2234 1
a2234 1
buf = malloc (bwide);
d2313 1
a2313 1
char * CLASS foveon_camf_param (char *block, char *param)
d2335 1
a2335 1
void * CLASS foveon_camf_matrix (int dim[3], char *name)
d2355 1
a2355 1
mat = malloc (size * 4);
d2368 1
a2368 1
int CLASS foveon_fixed (void *ptr, int size, char *name)
d2401 1
a2401 1
curve = calloc (size+1, sizeof *curve);
d2445 2
a2446 1
char str[128], *cp;
d2519 1
a2519 1
sgain = foveon_camf_matrix (dim, "SpatialGain");
d2521 1
a2521 1
sgrow = calloc (dim[1], sizeof *sgrow);
d2524 1
a2524 1
black = calloc (height, sizeof *black);
d2613 1
a2613 1
if ((badpix = foveon_camf_matrix (dim, "BadPixels"))) {
d2632 1
a2632 1
smrow[6] = calloc (width*5, sizeof **smrow);
d2755 1
a2755 1
shrink = calloc ((width/4) * (height/4), sizeof *shrink);
d2843 1
a2843 1
fname = malloc (len);
d3260 1
a3260 1
brow[4] = calloc (width*3, sizeof **brow);
d3365 1
a3365 1
buffer = malloc (26*TS*TS); /* 1664 kB */
d3367 3
a3369 3
rgb = (void *) buffer;
lab = (void *) (buffer + 12*TS*TS);
homo = (void *) (buffer + 24*TS*TS);
d3471 2
a3472 2
window = calloc ((ws+1)*sizeof *window +
ws*width*sizeof **window + ws*sizeof *kernel, 1);
d3532 1
a3532 1
map = calloc (high*wide, sizeof *map);
d4133 1
a4133 1
if (!(cbuf = malloc(len))) break;
d4231 1
a4231 1
if (sony_length && (buf = malloc(sony_length))) {
d4398 1
a4398 1
jname = malloc (strlen(ifname) + 1);
d6109 1
a6109 1
prof = malloc (profile_length);
d6204 1
a6204 1
img = calloc (wide*high, sizeof *img);
d6244 1
a6244 1
dest = calloc (height * width, sizeof *dest);
d6266 1
a6266 1
ppm = calloc (width, colors*xmag);
d6310 1
a6310 1
ppm = calloc (width, 2*colors);
d6353 1
a6353 1
buffer = calloc (colors, psize*2);
d6371 2
a6372 1
char opt, *write_ext, *ofname, *sp, *cp;
d6606 2
a6607 1
image = calloc (iheight*iwidth*sizeof *image + meta_length, 1);
d6650 1
a6650 1
ofname = malloc (strlen(ifname) + 16);
@
1.325
log
@Replaced "-r" and "-l" options with raw white balance.
Added "-H 2" option for rudimentary highlight recovery.
@
text
@d3514 1
a3514 2
#define SIGMA 3
#define FS 13
d3517 6
a3522 4
float base[FS][FS], (*filt)[FS];
int c, y, x, s, ns, row, col, val, sat[4];
double sum, wgt;
ushort *cent, *test;
d3526 19
a3544 19
filt = (float (*)[FS]) &base[FS/2][FS/2];
for (y=-FS/2; y <= FS/2; y++)
for (x=-FS/2; x <= FS/2; x++)
filt[y][x] = exp(-(x*x+y*y)/(2*SIGMA*SIGMA));
for (ns=0, c=1; c < colors; c++)
if (pre_mul[ns] < pre_mul[c]) ns = c;
FORCC sat[c] = 62000 * pre_mul[c];
for (row=0; row < height; row++)
for (col=0; col < width; col++) {
cent = image[row*width+col];
for (s=0; s < colors; s++) {
if (s == ns || cent[s] < sat[s]) continue;
sum = wgt = 4;
for (y = MAX(-FS/2,-row); y <= MIN(FS/2,height-row-1); y++)
for (x = MAX(-FS/2,-col); x <= MIN(FS/2,width-col-1); x++) {
test = image[(row+y)*width+col+x];
if (2*test[s]/sat[s] == 1 && test[ns]/32700 == 1) {
sum += filt[y][x] * test[s] / test[ns];
wgt += filt[y][x];
d3547 2
a3548 2
if (cent[s] < (val = sum*cent[ns]/wgt))
cent[s] = CLIP(val);
d3550 22
d3573 15
d3589 1
a3589 2
#undef SIGMA
#undef FS
d6384 1
a6384 1
"\nRaw Photo Decoder \"dcraw\" v8.17"
@
1.324
log
@Improved support for Leaf, Imacon, Sinar, and Phase One backs.
Rewrote Canon CRW parsing to get correct camera WB.
@
text
@d98 1
a98 1
int black, maximum, clip_max, raw_color, use_gamma;
d102 2
a103 2
float bright=1, red_scale=1, blue_scale=1, sigma_d=0, sigma_r=0;
int four_color_rgb=0, document_mode=0, clip_color=1;
d144 1
a144 1
#define CLIP(x) LIM(x,0,clip_max)
d1468 5
a1472 3
for (col=0; col < width; col++)
BAYER(row-top_margin,col) = (pixel[col+left_margin] << 2)
- ph1.black + black[row][col >= ph1.split_col];
a2310 1
clip_max = 0xffff;
d3037 1
a3037 1
int row, col, x, y, c, val, shift=0;
d3039 2
a3040 1
double dsum[8], dmin;
d3047 2
a3048 2
for (row=0; row < height-7; row++)
for (col=0; col < width-7; col++) {
d3050 2
a3051 2
for (y=row; y < row+7; y++)
for (x=col; x < col+7; x++)
d3085 2
a3086 4
if (raw_color || !output_color) {
pre_mul[0] *= red_scale;
pre_mul[2] *= blue_scale;
}
d3088 5
a3092 14
dmin = DBL_MAX;
FORC4 if (dmin > pre_mul[c])
dmin = pre_mul[c];
FORC4 pre_mul[c] /= dmin;
while (maximum << shift < 0x8000) shift++;
FORC4 pre_mul[c] *= 1 << shift;
maximum <<= shift;
if (write_fun != write_ppm || bright < 1) {
maximum *= bright;
if (maximum > 0xffff)
maximum = 0xffff;
FORC4 pre_mul[c] *= bright;
d3094 2
a3100 1
clip_max = clip_color ? maximum : 0xffff;
d3107 1
a3107 1
val *= pre_mul[c];
d3514 40
d4969 2
d6121 1
a6121 1
if (!raw_color) {
a6126 5
FORCC {
out_cam[0][c] *= red_scale;
out_cam[2][c] *= blue_scale;
}
}
a6273 1
if (maximum < 256) maximum = 256;
d6277 1
a6277 1
width, height, colors, maximum, cdesc);
d6280 1
a6280 1
colors/2+5, width, height, maximum);
d6333 1
a6333 1
char opt, *write_ext, *ofname, *cp;
d6347 1
a6347 1
"\nRaw Photo Decoder \"dcraw\" v8.15"
d6358 2
a6359 3
"\n-r Set red multiplier (default = 1.0)"
"\n-l Set blue multiplier (default = 1.0)"
"\n-b Set brightness (default = 1.0)"
d6361 2
a6362 1
"\n-n Don't clip colors"
a6375 1
"\n-t [0-7] Flip image (0 = none, 3 = 180, 5 = 90CCW, 6 = 90CW)"
d6386 6
a6391 5
if ((strchr("Bbrlktq", opt) && !isdigit(argv[arg][0])) ||
(opt == 'B' && !isdigit(argv[arg+1][0]))) {
fprintf (stderr, "Non-numeric argument to \"-%c\"\n", opt);
return 1;
}
d6397 2
a6398 2
case 'r': red_scale = atof(argv[arg++]); break;
case 'l': blue_scale = atof(argv[arg++]); break;
d6402 1
d6425 1
a6425 1
case 'n': clip_color = 0; break;
d6596 1
@
1.323
log
@Fixed camera WB for Canon EOS 10D, 300D, and clones.
Use the correct color matrix for the Canon EOS Kiss Digital N.
@
text
@a111 2
#define camera_red cam_mul[0]
#define camera_blue cam_mul[2]
d127 5
d255 3
a257 1
double num;
d261 2
a262 2
case 5: num = (unsigned int) get4();
return num / (unsigned int) get4();
d265 2
a266 2
case 10: num = (signed int) get4();
return num / (signed int) get4();
d269 4
a272 2
fprintf (stderr, "%s: TIFF doubles not supported!\n", ifname);
longjmp (failure, 4);
d1223 44
d1270 2
a1271 1
int len, i, j, val[4], dev[4], sum, max;
d1275 2
d1278 2
a1279 1
if (!meta_length) return;
d1291 20
a1310 1
if (tag == 0x400) /* Sensor defects */
d1340 14
d1356 33
d1396 1
a1396 1
fseek (ifp, curve_offset, SEEK_SET);
d1399 1
a1399 1
mask = tiff_compress == 1 ? 0x5555:0x1354;
a1414 1
maximum = 0xffff;
d1438 1
d1440 1
a1440 1
pixel = calloc (raw_width + raw_height*2, 2);
d1446 4
d1469 2
a1470 1
BAYER(row-top_margin,col) = pixel[col+left_margin];
a1472 1
maximum = 0x3fff;
d1476 1
a1476 1
void CLASS hdr_load_raw()
d1482 1
a1482 1
merror (pixel, "hdr_load_raw()");
d1492 9
d3041 1
a3041 1
if (use_auto_wb || (use_camera_wb && camera_red == -1)) {
d3067 1
a3067 1
if (use_camera_wb && camera_red != -1) {
d3078 1
a3078 1
else if (camera_red && camera_blue)
d3633 2
a3634 2
camera_red = getrat();
camera_blue = getrat();
d3721 2
a3722 2
camera_red = get2() * 508 * 1.078 / 0x10000;
camera_blue = get2() * 382 * 1.173 / 0x10000;
d3734 1
a3734 1
camera_red = get2() / 256.0;
d3736 1
a3736 1
camera_blue = get2() / 256.0;
d3740 2
a3741 2
camera_red = get2() / 256.0;
camera_blue = get2() / 256.0;
d3809 14
d3828 1
a3828 2
static const unsigned bayer[] =
{ 0x94949494, 0x61616161, 0x16161616, 0x49494949 };
d3852 5
d3878 2
a3879 1
filters = (planes == 1) * bayer[(flip/90 + frot) & 3];
d3885 1
a3885 1
int ifd, use_cm=0, cfa, i, j, c;
d4044 1
d4050 10
d4391 1
a4391 1
int tboff, nrecs, i, c, type, len, roff, aoff, save, wbi=-1;
a4393 5
if (strcmp(model,"Canon PowerShot G6") &&
strcmp(model,"Canon PowerShot S60") &&
strcmp(model,"Canon PowerShot S70") &&
strcmp(model,"Canon PowerShot Pro1"))
key[0] = key[1] = 0;
d4402 6
a4407 5
roff = get4();
aoff = offset + roff;
save = ftell(ifp);
if (type == 0x080a) { /* Get the camera make and model */
fseek (ifp, aoff, SEEK_SET);
d4409 1
a4409 1
fseek (ifp, aoff+strlen(make)+1, SEEK_SET);
d4412 18
a4429 5
if (type == 0x102a) { /* Exposure info */
fseek (ifp, aoff+4, SEEK_SET);
iso_speed = 50 * pow (2, get2()/32.0 - 4);
aperture = (get2(), pow (2, get2()/64.0));
shutter = pow (2, ((short) get2())/-32.0);
d4433 3
a4435 4
if (type == 0x102c) { /* Get white balance (G2) */
if (!strcmp(model,"Canon PowerShot G1") ||
!strcmp(model,"Canon PowerShot Pro90 IS")) {
fseek (ifp, aoff+120, SEEK_SET);
d4437 21
a4457 3
} else {
fseek (ifp, aoff+100, SEEK_SET);
goto common;
d4460 4
a4463 30
if (type == 0x0032) { /* Get white balance (D30 & G3) */
if (!strcmp(model,"Canon EOS D30")) {
fseek (ifp, aoff+72, SEEK_SET);
common:
camera_red = get2() ^ key[0];
camera_red =(get2() ^ key[1]) / camera_red;
camera_blue = get2() ^ key[0];
camera_blue /= get2() ^ key[1];
if (!wbi) camera_red = -1; /* Use my auto WB for this photo */
} else if (key[0]) {
fseek (ifp, aoff+96 + 8*("01345:000000006008"[wbi]-'0'), SEEK_SET);
goto common;
} else {
fseek (ifp, aoff+80 + (wbi < 6 ? 8*("123451"[wbi]-'0') : 0), SEEK_SET);
if (!camera_red)
goto common;
}
}
if (type == 0x10a9) { /* Get white balance (D60) */
if (strcmp(model,"Canon EOS D60"))
wbi = "0134567028"[wbi]-'0';
fseek (ifp, aoff+2 + wbi*8, SEEK_SET);
camera_red = get2();
camera_red /= get2();
camera_blue = get2();
camera_blue = get2() / camera_blue;
}
if (type == 0x1030 && (wbi == 6 || wbi == 15)) {
fseek (ifp, aoff, SEEK_SET); /* Get white sample */
ciff_block_1030();
d4465 4
a4468 3
if (type == 0x1031) { /* Get the raw width and height */
fseek (ifp, aoff+2, SEEK_SET);
raw_width = get2();
d4471 6
a4476 6
if (type == 0x180e) { /* Get the timestamp */
fseek (ifp, aoff, SEEK_SET);
timestamp = get4();
}
if (type == 0x580e)
timestamp = len;
a4480 27
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 == 0x1810) { /* Get the rotation */
fseek (ifp, aoff+12, SEEK_SET);
flip = get4();
}
if (type == 0x1818) {
fseek (ifp, aoff+4, SEEK_SET);
shutter = pow (2, -int_to_float(get4()));
aperture = pow (2, int_to_float(get4())/2);
}
if (type == 0x1835) { /* Get the decoder table */
fseek (ifp, aoff, SEEK_SET);
tiff_compress = get4();
}
if (type == 0x2007) { /* Found the JPEG thumbnail */
thumb_offset = aoff;
thumb_length = len;
}
if (type >> 8 == 0x28 || type >> 8 == 0x30) /* Get sub-tables */
parse_ciff(aoff, len);
d4525 1
d4528 1
d4545 3
a4547 2
for (raw_color = i=0; i < 3; i++)
FORC3 rgb_cam[i][c] = int_to_float(get4());
d4550 1
a4550 1
FORC3 cam_mul[c] = pre_mul[c] = int_to_float(get4());
d4558 1
a4558 1
case 0x10e: tiff_compress = data; break;
d4561 8
a4568 3
meta_length = len; break;
case 0x112: curve_offset = save - 4; break;
case 0x21c: strip_offset = data+base; break;
d4576 1
a4576 1
load_raw = tiff_compress < 3 ?
d4578 1
d4889 2
d5017 2
d5035 2
d5427 2
a5428 2
camera_red *= 256/527.0;
camera_blue *= 256/317.0;
d5531 1
a5531 1
} else if (!strcmp(model,"R-D1")) {
d5630 2
a5631 2
camera_red *= 4;
camera_blue *= 4;
d5717 5
a5721 6
if (raw_width < 4096) {
data_offset += 6 + raw_width*12;
height = raw_height - 6;
width = raw_width - 10;
filters = 0x61616161;
flip = height > width+10 ? 5:3;
a5722 1
load_raw = unpacked_load_raw;
a5723 2
pre_mul[0] = 1.963;
pre_mul[2] = 1.430;
d5740 1
a5740 1
load_raw = hdr_load_raw;
a5753 2
} else if (!strcmp(model,"P 30") || !strcmp(model,"P 45")) {
black = 256;
d5807 2
a5808 1
} else if (!strcmp(model,"DSC-R1")) {
d6077 3
a6079 3
{ { 0.529317, 0.330092, 0.140588 },
{ 0.098368, 0.873465, 0.028169 },
{ 0.016879, 0.117663, 0.865457 } };
d6319 1
a6319 1
"\nRaw Photo Decoder \"dcraw\" v8.13"
d6529 1
a6529 1
FORCC printf (" %f", cam_mul[c]);
@
1.322
log
@Added the Leica D-Lux 2.
@
text
@d91 1
a91 1
unsigned shot_order, kodak_cbpp, filters;
d3502 2
a4258 3
if (((!strcmp(model,"Canon EOS DIGITAL REBEL") ||
!strcmp(model,"Canon EOS 300D DIGITAL"))) && wbi == 6)
wbi++;
d4289 2
a4290 2
if (!strcmp(model,"Canon EOS 10D"))
wbi = "0134560028"[wbi]-'0';
d4322 2
a4665 2
{ "Canon EOS DIGITAL REBEL XT", 0,
{ 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
d5006 1
a5006 1
iso_speed = shutter = aperture = focal_len = 0;
d5255 2
d6171 1
a6171 1
"\nRaw Photo Decoder \"dcraw\" v8.12"
@
1.321
log
@Added the Leaf Aptus 75.
Correctly handle the DNG AsShotWhiteXY tag.
@
text
@d4787 2
d6170 1
a6170 1
"\nRaw Photo Decoder \"dcraw\" v8.11"
@
1.320
log
@Better support the Imacon Ixpress 22-Mp.
@
text
@d111 1
d1351 1
a1351 1
void CLASS leaf_load_raw()
d1357 1
a1357 1
merror (pixel, "leaf_load_raw()");
a3194 1
static const float d65[3] = { 0.950456, 1, 1.088754 };
d3205 1
a3205 1
xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65[i];
d3676 2
a3677 1
int skip, from, i, c, neut[4];
d3697 16
a3712 5
if (!strcmp(data,"CaptProf_number_of_planes")) {
fscanf (ifp, "%d", &i);
if (i > 1) filters = 0;
}
if (!strcmp(data,"CaptProf_raw_data_rotation") && filters) {
d3714 1
a3714 1
filters = bayer[i/90];
d3717 1
a3717 2
for (i=0; i < 4; i++)
fscanf (ifp, "%d", neut+i);
d3723 2
d3853 7
a3859 4
case 33434: shutter = getrat(); break;
case 33437: aperture = getrat(); break;
case 37386: focal_len = getrat(); break;
case 34310:
d3874 7
a3880 1
case 37400:
d3886 1
a3886 1
case 46275:
d3970 1
d4787 1
a4787 1
{ "Leaf Valeo", 0,
a5585 1
strcpy (model, "Valeo");
d5587 2
a5588 1
load_raw = leaf_load_raw;
d5590 1
a5590 1
strcpy (model, "Volare");
d6168 1
a6168 1
"\nRaw Photo Decoder \"dcraw\" v8.10"
@
1.319
log
@Don't search for the best black value in colorcheck().
Added new color matrix for the Nikon E700, E800, and E950.
@
text
@d3867 5
a3871 2
raw_width = 4090;
raw_height = len / raw_width / 2;
a5536 4
height = raw_height - 6;
width = raw_width - 10;
data_offset += 6 + raw_width*12;
flip = height > width+10 ? 5:3;
d5538 7
a5544 1
filters = 0x61616161;
d6145 1
a6145 1
"\nRaw Photo Decoder \"dcraw\" v8.09"
@
1.318
log
@Added getreal(), and use getint() more often.
@
text
@d2753 1
a2753 1
void CLASS pseudoinverse (const double (*in)[3], double (*out)[3], int size)
d2799 1
a2799 1
pseudoinverse ((const double (*)[3]) cam_rgb, inverse, colors);
d2837 28
a2864 28
static const double gmb_xyz[NSQ][3] = {
{ 11.078, 9.870, 6.738 }, // Dark Skin
{ 37.471, 35.004, 26.057 }, // Light Skin
{ 18.187, 19.306, 35.425 }, // Blue Sky
{ 10.825, 13.827, 7.600 }, // Foliage
{ 24.769, 23.304, 43.943 }, // Blue Flower
{ 31.174, 42.684, 45.277 }, // Bluish Green
{ 36.238, 29.188, 6.222 }, // Orange
{ 13.661, 11.845, 38.929 }, // Purplish Blue
{ 27.999, 19.272, 14.265 }, // Moderate Red
{ 8.398, 6.309, 14.211 }, // Purple
{ 33.692, 44.346, 11.288 }, // Yellow Green
{ 45.000, 42.144, 8.429 }, // Orange Yellow
{ 8.721, 6.130, 31.181 }, // Blue
{ 14.743, 24.049, 9.778 }, // Green
{ 19.777, 11.530, 5.101 }, // Red
{ 55.978, 59.599, 10.047 }, // Yellow
{ 29.421, 19.271, 31.167 }, // Magenta
{ 13.972, 18.952, 37.646 }, // Cyan
{ 82.819, 87.727, 94.479 }, // White
{ 55.950, 58.959, 64.375 }, // Neutral 8
{ 32.877, 34.536, 38.097 }, // Neutral 6.5
{ 18.556, 19.701, 21.487 }, // Neutral 5
{ 8.353, 8.849, 9.812 }, // Neutral 3.5
{ 2.841, 2.980, 3.332 } }; // Black
double inverse[NSQ][3], gmb_cam[NSQ][4], cam_xyz[4][3];
double num, error, minerr=DBL_MAX, best[4][3];
int b, c, i, j, k, sq, row, col, count[4];
d2876 5
a2880 1
FORCC gmb_cam[sq][c] /= count[c];
d2882 6
a2887 22
for (b=0; b < 1; b++) {
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];
for (error=sq=0; sq < NSQ; sq++)
FORCC {
for (num=j=0; j < 3; j++)
num += cam_xyz[c][j] * gmb_xyz[sq][j];
if (num < 0) num=0;
error += pow (num - gmb_cam[sq][c], 2);
gmb_cam[sq][c]--; // for the next black value
}
if (error < minerr) {
black = b;
minerr = error;
memcpy (best, cam_xyz, sizeof best);
}
}
cam_xyz_coeff (best);
d2890 1
a2890 1
num = 10000 / (best[1][0] + best[1][1] + best[1][2]);
d2892 1
a2892 1
printf ("%c%d", (c | j) ? ',':' ', (int) (best[c][j] * num + 0.5));
d4617 1
a4617 1
void CLASS adobe_coeff()
d4799 2
d4889 1
a4889 1
/* index 3 -- Nikon E700, E800, and E950 */
d5282 1
a5282 4
simple_coeff(3);
pre_mul[0] = 1.18193;
pre_mul[2] = 1.16452;
pre_mul[3] = 1.17250;
d5816 1
a5816 1
if (raw_color) adobe_coeff();
d6140 1
a6140 1
"\nRaw Photo Decoder \"dcraw\" v8.08"
d6370 3
a6375 3
quality = 2 + !fuji_width;
if (user_qual >= 0) quality = user_qual;
if (user_black >= 0) black = user_black;
@
1.317
log
@Use unmagnified dimensions in write_ppm16().
@
text
@a241 6
double CLASS getrat()
{
double num = get4();
return num / get4();
}
d249 21
d3924 1
a3924 1
dblack += getrat();
d3928 1
a3928 1
maximum = get2();
d3951 1
a3951 1
FORCC asn[c] = type == 3 ? get2() : getrat();
d3967 4
a3970 4
top_margin = get4();
left_margin = get4();
height = get4() - top_margin;
width = get4() - left_margin;
d6153 1
a6153 1
"\nRaw Photo Decoder \"dcraw\" v8.07"
@
1.316
log
@Support the Olympus E-330.
Added "-D" option to output unscaled raw pixels.
For DNG, support ICC profiles and short AsShotNeutral tags.
Fix defective pixels and columns in Phase One images.
@
text
@d6068 1
a6068 1
xmag*width, ymag*height, colors, maximum, cdesc);
d6071 1
a6071 1
colors/2+5, xmag*width, ymag*height, maximum);
d6138 1
a6138 1
"\nRaw Photo Decoder \"dcraw\" v8.06"
@
1.315
log
@Improved detection of non-raw files.
@
text
@d1195 59
d1279 1
d1332 1
d1384 1
a1384 1
int dwide, row, col;
d1386 2
d1401 1
a1401 1
for (col=width+4; col < raw_width; col++)
d1404 1
a1404 1
black /= (raw_width - width - 4) * height;
d2155 3
d3848 1
d3936 1
a3936 1
FORCC asn[c] = getrat();
d4389 2
d5592 3
d5926 1
a5926 1
if (document_mode)
d5938 1
a5938 1
if (document_mode) colors = 1;
d6138 1
a6138 1
"\nRaw Photo Decoder \"dcraw\" v8.05"
d6160 1
d6210 1
d6374 2
a6375 2
if (is_foveon) foveon_interpolate();
else scale_colors();
@
1.314
log
@Updated color matrices based on Adobe DNG Converter 3.3.
Added Kodak ProPhoto D65 as an output option.
@
text
@d3392 1
d3417 1
d3988 1
a3988 5
if (((strstr(make,"Minolta") || strstr(make,"MINOLTA")) && tiff_bps == 8)
|| (!strncmp(make,"NIKON",5) && filters == UINT_MAX)
|| (!strcmp(make,"SONY") && tiff_bps != 14)
|| (!strcmp(make,"Canon") && tiff_bps == 8)
|| (tiff_samples == 3 && data_offset == 8))
d6066 1
a6066 1
"\nRaw Photo Decoder \"dcraw\" v8.04"
@
1.313
log
@Improved Phase One code, set black=256 for P 30 and P 45.
@
text
@d2093 1
a2093 1
maximum = clip_max = 0xffff;
d3521 1
a3521 1
if (tag == 0x1011 && len == 9) {
d3989 1
d4562 3
a4564 1
{ 6228,-404,-967,-8314,16108,2312,-1923,2179,7499 } },
d4621 2
d4639 4
d4646 1
a4646 1
{ 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
d4685 4
a4688 2
{ "KODAK P8", 0, /* DJC */
{ 17293,-6824,-2050,-3999,12397,1602,-1209,2283,5375 } },
d4717 2
a4718 2
{ "NIKON D1", 0,
{ 7559,-2130,-965,-7611,15713,1972,-2478,3042,8290 } },
d4727 2
d4773 2
d4787 2
a4788 2
{ "SONY DSC-R1", 512, /* DJC */
{ 10528,-3695,-517,-2822,10699,2124,406,1240,5342 } },
d5825 4
d5830 1
a5830 1
{ adobe_rgb, wgd65_rgb, xyz_rgb };
d5832 1
a5832 1
{ "sRGB", "Adobe 1998 RGB", "Wide Gamut D65", "XYZ" };
d5835 1
a5835 1
raw_color |= colors == 1 || output_color < 1 || output_color > 4;
d6068 1
a6068 1
"\nRaw Photo Decoder \"dcraw\" v8.03"
d6084 1
a6084 1
"\n-o [0-4] Output colorspace (raw,sRGB,Adobe,Wide,XYZ)"
d6345 1
a6345 1
fprintf (stderr, "Writing data to %s...\n", ofname);
@
1.312
log
@Added the Phase One P 30 and P 45.
@
text
@d94 1
a94 1
int data_offset, meta_offset, meta_length, nikon_curve_offset;
d906 1
a906 1
fseek (ifp, nikon_curve_offset, SEEK_SET);
d1200 1
a1200 1
fseek (ifp, nikon_curve_offset, SEEK_SET);
d1246 1
d1250 1
a1250 1
fseek (ifp, 20 + offset[row], SEEK_SET);
d3460 1
a3460 1
nikon_curve_offset = ftell(ifp) + 2112;
d3462 1
a3462 1
nikon_curve_offset = ftell(ifp) + 2;
d4315 10
a4324 11
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: tiff_compress = data; break;
case 0x10f: case 0x21c:
data_offset = data + base; break;
case 0x112:
nikon_curve_offset = save - 4; break;
d4326 3
a4328 3
fread (model, 64, 1, ifp);
cp = strstr(model," camera");
if (cp && cp < model+64) *cp = 0;
d5490 2
d6049 1
a6049 1
"\nRaw Photo Decoder \"dcraw\" v8.02"
@
1.311
log
@Changed auto white balance to better handle saturated pixels.
Allow "dcraw -i -v" to work with non-raw photos.
@
text
@d1142 1
d1144 1
a1144 1
char *thumb = malloc (thumb_length*colors);
d1240 1
a1240 1
int len[2], pred[2], row, col, ncols, i, j;
d1243 1
a1243 2
ncols = (raw_width + 7) & -8;
pixel = calloc (ncols, sizeof *pixel);
d1245 3
d1249 1
d1252 1
a1252 1
for (col=0; col < ncols; col++) {
d4321 2
a4322 1
case 0x10f: data_offset = data+base; break;
d6047 1
a6047 1
"\nRaw Photo Decoder \"dcraw\" v8.01"
@
1.310
log
@Dcraw v8.00 major release:
* Added "-e" option to extract thumbnail images.
* Added "-o" option to select output colorspace.
* Enabled "-p" option for ICC color profiles by default.
* Generate monochrome or four-color output in some cases.
* Use more memory to flip images five times faster.
* Use the correct formula for Kodak YCbCr images.
@
text
@d91 1
a91 1
unsigned shot_order, kodak_cbpp;
d98 1
a98 1
int black, maximum, clip_max, clip_color=1;
d100 1
a100 3
int dng_version, is_foveon, raw_color, use_gamma;
int zero_after_ff;
unsigned filters;
d103 1
a103 1
int four_color_rgb=0, document_mode=0;
d624 1
d2005 1
a2005 1
int width, height, bwide, row, col, bit=-1, c, i;
d2011 2
a2012 4
width = get4();
height = get4();
bwide = get4();
fprintf (tfp, "P6\n%d %d\n255\n", width, height);
d2016 1
a2016 1
for (row=0; row < height; row++) {
d2018 1
a2018 1
fwrite (buf, 3, width, tfp);
d2025 1
a2025 1
for (row=0; row < height; row++) {
d2028 1
a2028 1
for (col=bit=0; col < width; col++)
d2827 3
a2829 3
int row, col, c, val, shift=0;
int min[4], max[4], count[4];
double sum[4], dmin;
d2834 23
a2856 15
FORC4 max[c] = count[c] = sum[c] = 0;
for (row=0; row < height; row++)
for (col=0; col < width; col++)
FORC4 {
val = image[row*width+col][c];
if (!val) continue;
if (min[c] > val) min[c] = val;
if (max[c] < val) max[c] = val;
val -= black;
if (val > maximum-25) continue;
if (val < 0) val = 0;
sum[c] += val;
count[c]++;
}
FORC4 if (sum[c]) pre_mul[c] = count[c] / sum[c];
d2859 1
a2859 1
FORC4 count[c] = sum[c] = 0;
d2865 1
a2865 1
count[c]++;
d2868 1
a2868 1
FORC4 pre_mul[c] = count[c] / sum[c];
d3415 5
d3724 1
a3724 1
make[0] = 0;
d3982 1
d3985 1
a3985 1
if (!dng_version) make[0] = 0;
d4085 1
d4234 1
a4234 1
crw_init_tables (get4());
d4370 1
a4370 1
int len, save, hlen;
d4375 1
a4375 1
while (fgetc(ifp) == 0xff && fgetc(ifp) >> 4 != 0xd) {
d4379 5
d4490 3
a4492 1
thumb_offset = off+16;
d4835 1
a4882 2
/* What format is this file? Set make[] if we recognize it. */
d4895 1
a4895 1
raw_color = use_gamma = xmag = ymag = 1;
a4921 2
if (!dng_version && !strncmp(make,"NIKON",5) && filters == UINT_MAX)
make[0] = 0;
d4998 2
a4999 4
if (make[0] == 0) {
parse_jpeg(0);
make[0] = 0;
}
d5013 1
a5013 1
if (make[0] == 0) return;
d5723 7
d5731 7
d6042 1
a6042 1
"\nRaw Photo Decoder \"dcraw\" v8.00"
d6160 1
a6160 1
identify();
d6191 1
a6191 13
if ((status = !make[0])) {
fprintf (stderr, "%s: unsupported file format.\n", ifname);
goto next;
} else if ((status = !load_raw || !height)) {
fprintf (stderr, "%s: Cannot decode %s %s images.\n",
ifname, make, model);
goto next;
#ifdef NO_JPEG
} else if (load_raw == kodak_jpeg_load_raw) {
fprintf (stderr, "%s: dcraw was not linked with libjpeg.\n", ifname);
goto next;
#endif
} else if (load_raw == kodak_ycbcr_load_raw) {
d6195 19
d6226 13
a6238 10
printf ("Filename: %s\n", ifname);
printf ("Timestamp: %s", ctime(×tamp));
printf ("Camera: %s %s\n", make, model);
printf ("ISO speed: %d\n", (int) iso_speed);
printf ("Shutter: ");
if (shutter > 0 && shutter < 1)
shutter = (printf ("1/"), 1 / shutter);
printf ("%0.1f sec\n", shutter);
printf ("Aperture: f/%0.1f\n", aperture);
printf ("Focal Length: %d mm\n", (int) focal_len);
d6252 1
a6252 14
printf ("\nRaw size: %d x %d\n", raw_width, raw_height);
printf ("Image size: %d x %d\n", width, height);
if (fuji_width && use_fuji_rotate) {
fuji_width = (fuji_width - 1 + shrink) >> shrink;
iwidth = fuji_width / sqrt(0.5);
iheight = (iheight - fuji_width) / sqrt(0.5);
}
if (write_fun == write_ppm) {
iheight *= ymag;
iwidth *= xmag;
}
if (flip & 4)
SWAP(iheight,iwidth);
printf ("Output size: %d x %d\n\n", iwidth, iheight);
@
1.309
log
@Apply DiMAGE Z2 color matrix to the Nikon E4300.
Added the Canon EOS-1D Mark II N.
@
text
@d3 1
a3 1
Copyright 1997-2005 by Dave Coffin, dcoffin a cybercom o net
d40 2
a41 2
By defining NO_JPEG, you lose only the ability to
decode compressed .KDC files from the Kodak DC120.
d46 3
d88 1
a88 1
char *ifname, make[64], model[70], model2[64], *meta_data;
d92 2
d95 1
a95 1
int tiff_bps, tiff_data_compression, kodak_data_compression;
d99 1
a99 1
int iheight, iwidth, shrink;
a100 1
int flip, xmag, ymag;
a103 1
void (*load_raw)();
d106 1
a106 1
int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_rgb=0;
d115 1
a115 1
int histogram[3][0x2000];
d117 2
a118 1
void (*write_fun)(FILE *) = write_ppm;
a120 5
#ifdef USE_LCMS
#include
int profile_offset, profile_length;
#endif
d126 4
d239 5
d700 1
a700 1
int CLASS ljpeg_start (struct jhead *jh)
d703 1
a703 1
uchar data[256], *dp;
d710 1
a710 1
if (data[0] != 0xff || data[1] != 0xd8) return 0;
d715 1
a715 1
if (tag <= 0xff00 || len > 255) return 0;
d718 1
d726 1
d736 1
d739 1
a739 2
zero_after_ff = 1;
return 1;
d777 1
a777 1
int jwide, jrow, jcol, val, jidx, i, j, row, col;
d781 1
a781 1
if (!ljpeg_start (&jh)) return;
a789 1
jidx = jrow*jwide + jcol;
d791 1
a797 3
} else {
row = jidx / raw_width;
col = jidx % raw_width;
d799 8
a806 6
if ((unsigned) (row-top_margin) >= height) continue;
if ((unsigned) (col-left_margin) < width) {
BAYER(row-top_margin,col-left_margin) = val;
if (min > val) min = val;
} else
black += val;
d849 1
a849 1
if (!ljpeg_start (&jh)) break;
d954 1
a954 1
if (tiff_data_compression == 34713 && (col % 10) == 9)
d970 1
a970 1
if (tiff_data_compression != 34713)
d1120 49
d1203 1
a1203 1
mask = tiff_data_compression == 1 ? 0x5555:0x1354;
a1621 1
d1667 1
a1667 1
void CLASS kodak_compressed_load_raw()
d1669 1
a1669 1
uchar c, blen[256];
a1670 1
unsigned row, col, len, save, i, israw=0, bits=0, pred[2];
d1672 45
a1716 1
int diff;
d1719 6
a1724 49
for (col=0; col < width; col++)
{
if ((col & 255) == 0) { /* Get the bit-lengths of the */
len = width - col; /* next 256 pixel values */
if (len > 256) len = 256;
save = ftell(ifp);
for (israw=i=0; i < len; i+=2) {
c = fgetc(ifp);
if ((blen[i+0] = c & 15) > 12 ||
(blen[i+1] = c >> 4) > 12 )
israw = 1;
}
bitbuf = bits = pred[0] = pred[1] = 0;
if (len % 8 == 4) {
bitbuf = fgetc(ifp) << 8;
bitbuf += fgetc(ifp);
bits = 16;
}
if (israw)
fseek (ifp, save, SEEK_SET);
}
if (israw) { /* If the data is not compressed */
switch (col & 7) {
case 0:
read_shorts (raw, 6);
diff = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
break;
case 1:
diff = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
break;
default:
diff = raw[(col & 7) - 2] & 0xfff;
}
} else { /* If the data is compressed */
len = blen[col & 255]; /* Number of bits for this pixel */
if (bits < len) { /* Got enough bits in the buffer? */
for (i=0; i < 32; i+=8)
bitbuf += (INT64) fgetc(ifp) << (bits+(i^8));
bits += 32;
}
diff = bitbuf & (0xffff >> (16-len)); /* Pull bits from buffer */
bitbuf >>= len;
bits -= len;
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
pred[col & 1] += diff;
diff = pred[col & 1];
}
BAYER(row,col) = curve[diff];
d1728 1
a1728 1
void CLASS kodak_yuv_load_raw()
d1730 2
a1731 4
uchar c, blen[384];
unsigned row, col, len, bits=0;
INT64 bitbuf=0;
int i, li=0, si, diff, six[6], y[4], cb=0, cr=0, rgb[3];
d1735 16
a1750 42
for (col=0; col < width; col+=2) {
if ((col & 127) == 0) {
len = (width - col + 1) * 3 & -4;
if (len > 384) len = 384;
for (i=0; i < len; ) {
c = fgetc(ifp);
blen[i++] = c & 15;
blen[i++] = c >> 4;
}
li = bitbuf = bits = y[1] = y[3] = cb = cr = 0;
if (len % 8 == 4) {
bitbuf = fgetc(ifp) << 8;
bitbuf += fgetc(ifp);
bits = 16;
}
}
for (si=0; si < 6; si++) {
len = blen[li++];
if (bits < len) {
for (i=0; i < 32; i+=8)
bitbuf += (INT64) fgetc(ifp) << (bits+(i^8));
bits += 32;
}
diff = bitbuf & (0xffff >> (16-len));
bitbuf >>= len;
bits -= len;
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
six[si] = diff;
}
y[0] = six[0] + y[1];
y[1] = six[1] + y[0];
y[2] = six[2] + y[3];
y[3] = six[3] + y[2];
cb += six[4];
cr += six[5];
for (i=0; i < 4; i++) {
ip = image[(row+(i >> 1))*width + col+(i & 1)];
rgb[0] = y[i] + cr;
rgb[1] = y[i];
rgb[2] = y[i] + cb;
FORC3 if (rgb[c] > 0) ip[c] = curve[rgb[c]];
d1755 26
d1973 1
a1973 1
void CLASS foveon_decoder (unsigned huff[1024], unsigned code)
d1975 1
d1979 5
d1990 1
a1990 1
for (i=0; i < 1024; i++)
d1999 1
a1999 1
foveon_decoder (huff, code);
d2001 42
a2042 1
foveon_decoder (huff, code+1);
d2063 1
a2063 1
unsigned huff[1024], bitbuf=0;
d2068 2
a2069 6
if (!fixed) {
for (i=0; i < 1024; i++)
huff[i] = get4();
init_decoder();
foveon_decoder (huff, 0);
}
d2622 1
a2622 1
for (len=16 ; ; len *= 2) {
d2625 1
a2625 1
if (getcwd (fname, len-12)) break;
d2629 1
a2629 1
#ifdef WIN32
d2869 1
a2869 1
if (raw_color) {
d3309 25
a3333 1
void CLASS parse_makernote()
d3368 1
a3368 1
unsigned base=0, offset=0, entries, tag, type, len, save, c;
a3370 1
static const int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 };
d3379 5
a3383 3
if (!strncmp (buf,"KC" ,2) || /* these aren't TIFF format */
!strncmp (buf,"KDK",3) ||
!strncmp (buf,"MLY",3)) return;
d3407 1
a3407 7
tag = get2();
type = get2();
len = get4();
save = ftell(ifp);
if (len * size[type < 13 ? type:0] > 4)
fseek (ifp, get4()+base, SEEK_SET);
d3427 17
a3476 4
if (tag == 0xe0 && len == 17) {
raw_width = (get2(),get2());
raw_height = get2();
}
d3503 1
a3503 1
fseek (ifp, 188, SEEK_CUR);
d3521 2
d3529 1
a3529 1
fseek (ifp, save+4, SEEK_SET);
d3562 2
a3563 2
int kodak, entries, tag, type, len, save;
static const int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 };
d3568 1
a3568 6
tag = get2();
type = get2();
len = get4();
save = ftell(ifp);
if (len * size[type < 13 ? type:0] > 4)
fseek (ifp, get4()+base, SEEK_SET);
d3575 2
a3576 1
case 37377: shutter = pow (2, -getrat()); break;
d3579 1
a3579 1
case 37500: parse_makernote(); break;
d3583 1
a3583 1
fseek (ifp, save+4, SEEK_SET);
d3587 40
a3626 2
void CLASS parse_mos (int offset);
void CLASS sony_decrypt (unsigned *data, int len, int start, int key);
d3631 1
a3631 2
int done=0, use_cm=0, cfa, i, j, c;
static const int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 };
a3632 1
static const int flip_map[] = { 0,1,3,2,4,6,7,5 };
d3637 1
d3640 3
d3649 1
a3649 7
tag = get2();
type = get2();
len = get4();
save = ftell(ifp);
if (tag > 50700 && tag < 50800) done = 1;
if (len * size[type < 13 ? type:0] > 4)
fseek (ifp, get4()+base, SEEK_SET);
d3651 1
a3651 2
case 0x11:
case 0x12:
d3653 1
a3653 1
cam_mul[(tag-0x11)*2] = get2() / 256.0;
d3655 1
a3655 3
case 0x24:
case 0x25:
case 0x26:
d3658 1
a3658 1
case 0x27:
d3663 2
a3664 13
case 0x2:
case 0x100: /* ImageWidth */
if ((strcmp(make,"Canon") || level) && len == 1)
raw_width = type==3 ? get2() : get4();
break;
case 0x3:
case 0x101: /* ImageHeight */
if ((strcmp(make,"Canon") || level) && len == 1)
raw_height = type==3 ? get2() : get4();
break;
case 0x102: /* Bits per sample */
fuji_secondary = len == 2;
maximum = (1 << (tiff_bps = get2())) - 1;
d3666 2
a3667 2
case 0x103: /* Compression */
tiff_data_compression = get2();
d3669 3
a3671 2
case 0x106: /* Kodak color format */
kodak_data_compression = get2();
d3673 7
a3679 1
case 0x10f: /* Make */
d3682 1
a3682 1
case 0x110: /* Model */
d3685 16
a3700 2
case 0x111: /* StripOffset */
data_offset = get4();
d3702 2
a3703 2
case 0x112: /* Orientation */
flip = flip_map[(get2()-1) & 7];
d3705 3
a3707 2
case 0x115: /* SamplesPerPixel */
tiff_samples = get2();
d3709 1
a3709 1
case 0x131: /* Software tag */
d3716 1
a3716 1
case 0x132: /* DateTime tag */
d3719 2
a3720 7
case 0x144: /* TileOffsets */
if (level) {
data_offset = ftell(ifp);
} else {
data_offset = get4();
done = 1;
}
d3722 1
a3722 3
case 0x14a: /* SubIFD tag */
if (len > 2 && !dng_version && !strcmp(make,"Kodak"))
len = 2;
d3730 4
d3764 4
a3781 1
done = 1;
d3801 1
d3807 1
a3807 1
fuji_width = (raw_width+1)/2;
d3811 2
a3812 2
case 0x123:
case 0x90d:
d3818 2
a3819 1
maximum = curve[i] = curve[i-1];
d3880 1
a3880 1
fseek (ifp, save+4, SEEK_SET);
a3895 2
if (!(base | level | dng_version) &&
(strstr(make,"Minolta") || strstr(make,"MINOLTA"))) make[0] = 0;
d3908 1
a3908 1
return done;
d3913 2
a3914 1
int doff, maxifd=1000;
d3920 3
a3922 1
while ((doff = get4()) && maxifd--) {
a3924 1
if (!dng_version && data_offset == 8) make[0] = 0;
d3930 73
d4073 1
a4113 3
static const int remap[] = { 1,2,3,4,5,1 };
static const int remap_10d[] = { 0,1,3,4,5,6,0,0,2,8 };
static const int remap_s70[] = { 0,1,3,4,5,10,0,0,0,0,0,0,0,0,6,0,0,8 };
d4169 1
a4169 1
fseek (ifp, aoff+96 + remap_s70[wbi]*8, SEEK_SET);
d4172 1
a4172 1
fseek (ifp, aoff+80 + (wbi < 6 ? remap[wbi]*8 : 0), SEEK_SET);
d4179 1
a4179 1
wbi = remap_10d[wbi];
d4224 4
a4236 1
int tx=0, ty=0;
d4251 1
a4251 1
data_offset = atoi(val);
d4257 1
a4257 1
tx = atoi(val);
d4259 1
a4259 1
ty = atoi(val);
d4261 1
a4265 1
data_offset += tx * ty * 2;
d4268 1
a4268 39
}
void CLASS parse_mos (int offset)
{
char data[40];
int skip, from, i, c, neut[4];
static const unsigned bayer[] =
{ 0x94949494, 0x61616161, 0x16161616, 0x49494949 };
fseek (ifp, offset, SEEK_SET);
while (1) {
fread (data, 1, 8, ifp);
if (strcmp(data,"PKTS")) break;
if (!make[0]) strcpy (make, "Leaf");
fread (data, 1, 40, ifp);
skip = get4();
from = ftell(ifp);
#ifdef USE_LCMS
if (!strcmp(data,"icc_camera_profile")) {
profile_length = skip;
profile_offset = from;
}
#endif
if (!strcmp(data,"CaptProf_number_of_planes")) {
fscanf (ifp, "%d", &i);
if (i > 1) filters = 0;
}
if (!strcmp(data,"CaptProf_raw_data_rotation") && filters) {
fscanf (ifp, "%d", &i);
filters = bayer[i/90];
}
if (!strcmp(data,"NeutObj_neutrals")) {
for (i=0; i < 4; i++)
fscanf (ifp, "%d", neut+i);
FORC3 cam_mul[c] = (float) neut[0] / neut[c+1];
}
parse_mos (from);
fseek (ifp, skip+from, SEEK_SET);
}
d4290 1
d4304 1
a4304 1
case 0x10e: tiff_data_compression = data; break;
d4315 2
a4316 2
load_raw = tiff_data_compression < 3 ?
phase_one_load_raw:phase_one_load_raw_c;
a4318 1
sprintf (model, "%dx%d", width, height);
d4329 1
a4329 1
int entries, tag, len, save, c;
d4439 1
a4439 1
int entries, off, len, tag, save, i, wide, high, pent, poff[256][2];
d4467 9
d4810 1
a4810 1
accordingly. Return nonzero if the file cannot be decoded.
d4812 1
a4812 1
int CLASS identify (int no_decode)
d4815 1
a4815 1
unsigned hlen, fsize, i, c, is_jpeg=0, is_canon;
d4861 1
a4861 1
"MINOLTA", "Minolta", "Konica", "CASIO", "Sinar" };
d4865 4
a4868 4
load_raw = NULL;
raw_height = raw_width = fuji_width = flip = cr2_slice[0] = 0;
height = width = top_margin = left_margin = 0;
make[0] = model[0] = model2[0] = 0;
d4871 4
a4874 1
data_offset = meta_length = tiff_bps = tiff_data_compression = 0;
a4877 1
filters = UINT_MAX; /* 0 = no filters, UINT_MAX = unknown */
d4884 1
a4885 2
maximum = 0xfff;
#ifdef USE_LCMS
a4886 1
#endif
d4894 2
a4895 2
if ((cp = memmem (head, 32, "MMMM", 4)) ||
(cp = memmem (head, 32, "IIII", 4)))
d4897 2
a4898 1
else if (order == 0x4949 || order == 0x4d4d) {
d4913 1
d4948 3
d4953 1
a4953 2
fseek (ifp, 84, SEEK_SET);
if ((hlen = get4()) > 120) {
d4960 2
a4961 3
i = get4();
parse_tiff (hlen+12);
data_offset = i;
d4982 4
a4985 3
if (make[0] == 0) is_jpeg = parse_jpeg(0);
if (no_decode) return !timestamp;
d4999 1
a5000 4
if (make[0] == 0) {
fprintf (stderr, "%s: unsupported file format.\n", ifname);
return 1;
}
d5003 1
d5016 1
a5016 1
if (tiff_data_compression == 1)
d5018 1
a5018 1
if (tiff_data_compression == 7)
a5025 1
if (filters == UINT_MAX) filters = 0x94949494;
a5118 10
} else if (!strcmp(model,"EOS-1D")) {
raw_height = height = 1662;
raw_width = width = 2496;
data_offset = 288912;
filters = 0x61616161;
} else if (!strcmp(model,"EOS-1DS")) {
raw_height = height = 2718;
raw_width = width = 4082;
data_offset = 289168;
filters = 0x61616161;
d5148 1
a5148 1
if (tiff_data_compression == 34713 && load_raw == nikon_load_raw)
d5247 1
a5247 1
tiff_data_compression = 34713;
d5338 2
a5339 3
} else if (!strncmp(model,"*ist D",6)) {
load_raw = model[6] ? packed_12_load_raw : unpacked_load_raw;
if (model[6] == 'S') height -= 2;
d5428 1
a5428 1
sprintf (model, "%dx%d", width, height);
d5452 1
a5452 2
load_raw = unpacked_load_raw;
if (tiff_data_compression == 99)
a5472 1
load_raw = unpacked_load_raw;
a5475 1
load_raw = unpacked_load_raw;
a5478 1
load_raw = unpacked_load_raw;
d5484 4
a5487 5
load_raw = olympus_e300_load_raw;
maximum = 0xfff;
if (fsize > 15728640) {
load_raw = unpacked_load_raw;
maximum = 0xfc30;
d5515 1
a5523 1
load_raw = unpacked_load_raw;
d5526 2
a5527 2
} else if (!strcasecmp(make,"KODAK") && !load_raw) {
filters = 0x61616161;
d5556 1
a5556 3
switch (tiff_data_compression) {
case 0: /* No compression */
case 1:
a5557 20
break;
case 7: /* Lossless JPEG */
load_raw = lossless_jpeg_load_raw;
case 32867:
break;
case 65000: /* Kodak DCR compression */
if (kodak_data_compression == 32803)
load_raw = kodak_compressed_load_raw;
else {
load_raw = kodak_yuv_load_raw;
height = (height+1) & -2;
width = (width +1) & -2;
filters = 0;
}
break;
default:
fprintf (stderr, "%s: %s %s uses unsupported compression method %d.\n",
ifname, make, model, tiff_data_compression);
return 1;
}
d5593 2
a5594 4
if (tiff_data_compression == 7)
load_raw = kodak_jpeg_load_raw;
else
load_raw = kodak_dc120_load_raw;
d5705 3
d5710 4
a5713 11
if (!load_raw || !height || is_jpeg) {
fprintf (stderr, "%s: Cannot decode %s %s%s images.\n",
ifname, make, model, is_jpeg ? " JPEG":"");
return 1;
}
#ifdef NO_JPEG
if (load_raw == kodak_jpeg_load_raw) {
fprintf (stderr, "%s: decoder was not linked with libjpeg.\n", ifname);
return 1;
}
#endif
a5715 5
raw_color |= use_camera_rgb && colors == 3;
FORCC { /* Apply user-selected color balance */
rgb_cam[0][c] *= red_scale;
rgb_cam[2][c] *= blue_scale;
}
a5722 2
fseek (ifp, data_offset, SEEK_SET);
return 0;
d5725 2
a5726 2
#ifdef USE_LCMS
void CLASS apply_profile (char *pfname)
d5732 3
a5734 2
if (pfname)
hInProfile = cmsOpenProfileFromFile (pfname, "r");
d5742 2
a5743 1
}
d5745 3
a5749 5
maximum = 0xffff;
use_gamma = 0;
raw_color = 1; /* Don't use rgb_cam with a profile */
hOutProfile = cmsCreate_sRGBProfile();
d5753 2
a5754 1
d5756 2
a5758 1
cmsCloseProfile (hOutProfile);
a5761 3
/*
Convert the entire image to RGB colorspace and build a histogram.
*/
d5764 1
a5764 1
int row, col, c, i, fc=0;
d5766 27
a5792 2
float rgb[3];
d5794 2
a5795 2
fprintf (stderr, raw_color ?
"Building histograms...\n" : "Converting to sRGB colorspace...\n");
d5797 1
a5797 2
if (document_mode)
colors = 1;
d5803 2
a5804 2
fc = FC(row,col);
if (colors == 4 && raw_color) /* Recombine the greens */
d5806 6
a5811 10
if (colors == 1) /* RGB from grayscale */
FORC3 rgb[c] = img[fc];
else if (raw_color) /* RGB from RGB (easy) */
goto norgb;
else FORC3 /* RGB via rgb_cam */
for (rgb[c]=i=0; i < colors; i++)
rgb[c] += img[i] * rgb_cam[c][i];
FORC3 img[c] = CLIP((int) rgb[c]);
norgb:
FORC3 histogram[c][img[c] >> 3]++;
d5813 2
d5855 8
d5865 2
a5866 3
unsigned *flag;
int size, base, dest, next, row, col;
INT64 *img, hold;
d5871 11
a5881 31
img = (INT64 *) image;
size = height * width;
flag = calloc ((size+31) >> 5, sizeof *flag);
merror (flag, "flip_image()");
for (base=0; base < size; base++) {
if (flag[base >> 5] & (1 << (base & 31)))
continue;
dest = base;
hold = img[base];
while (1) {
if (flip & 4) {
row = dest % height;
col = dest / height;
} else {
row = dest / width;
col = dest % width;
}
if (flip & 2)
row = height - 1 - row;
if (flip & 1)
col = width - 1 - col;
next = row * width + col;
if (next == base) break;
flag[next >> 5] |= 1 << (next & 31);
img[dest] = img[next];
dest = next;
}
img[dest] = hold;
}
free (flag);
a5887 3
/*
Write the image to an 8-bit PPM file.
*/
d5890 1
a5890 1
uchar (*ppm)[3], lut[0x10000];
d5894 1
a5894 2
fprintf (ofp, "P6\n%d %d\n255\n", xmag*width, ymag*height);
ppm = calloc (width, 3*xmag);
d5897 7
d5906 1
a5906 1
FORC3 {
d5925 2
a5926 2
FORC3 for (i=0; i < xmag; i++)
ppm[xmag*col+i][c] = lut[image[row*width+col][c]];
d5928 25
a5952 1
fwrite (ppm, width, 3*xmag, ofp);
a5956 3
/*
Write the image to a 16-bit Photoshop file.
*/
d5978 1
d5982 1
a5982 1
buffer = calloc (6, psize);
d5988 1
a5988 1
FORC3 pred[c*psize] = htons(image[row*width+col][c]);
d5991 1
a5991 1
fwrite(buffer, psize, 6, ofp);
a5994 22
/*
Write the image to a 16-bit PPM file.
*/
void CLASS write_ppm16 (FILE *ofp)
{
int row, col, c;
ushort (*ppm)[3];
if (maximum < 256) maximum = 256;
fprintf (ofp, "P6\n%d %d\n%d\n", width, height, maximum);
ppm = calloc (width, 6);
merror (ppm, "write_ppm16()");
for (row=0; row < height; row++) {
for (col=0; col < width; col++)
FORC3 ppm[col][c] = htons(image[row*width+col][c]);
fwrite (ppm, width, 6, ofp);
}
free (ppm);
}
d5998 1
a5998 1
int timestamp_only=0, identify_only=0, write_to_stdout=0;
d6000 1
a6000 1
char opt, *ofname, *cp;
a6001 1
const char *write_ext = ".ppm";
d6003 3
a6005 2
#ifdef USE_LCMS
char *profile = NULL;
d6014 1
a6014 1
"\nRaw Photo Decoder \"dcraw\" v7.94"
d6019 3
a6022 2
"\n-i Identify files without decoding them"
"\n-c Write to standard output"
d6030 4
a6033 3
"\n-m Don't convert camera RGB to sRGB"
#ifdef USE_LCMS
"\n-p Apply color profile from file"
d6043 2
a6044 1
"\n-2 Write 8-bit PPM with 0.45 gamma (default)"
a6045 1
"\n-4 Write 16-bit linear PPM"
d6068 7
a6074 2
#ifdef USE_LCMS
case 'p': profile = argv[arg++] ; break;
d6076 1
d6078 1
d6090 1
a6090 1
case 'm': use_camera_rgb = 1; break;
d6092 3
a6094 3
case '2': write_fun = write_ppm; write_ext = ".ppm"; break;
case '3': write_fun = write_psd; write_ext = ".psd"; break;
case '4': write_fun = write_ppm16; write_ext = ".ppm"; break;
d6132 1
d6134 1
a6134 1
if ((status = identify(1)))
d6137 1
a6137 1
printf ("%10ld%10d %s\n", timestamp, shot_order, ifname);
d6146 33
a6178 1
if ((status = identify(0))) goto next;
d6204 1
a6204 2
cp = "RGBGMCYRGBE" + (colors == 3 ? 0 :
strcmp(model,"DSC-F828") ? 3 : 7);
d6206 1
a6206 1
putchar (cp[filters >> i & 3]);
d6240 1
d6264 2
a6265 2
#ifdef USE_LCMS
apply_profile (profile);
d6269 7
a6275 1
fclose(ifp);
d6283 2
d6296 2
a6297 2
if (ofp != stdout)
fclose(ofp);
@
1.308
log
@Improved camera WB for Panasonic DMC-FZ30 and DMC-LX1.
@
text
@d99 1
a99 1
ushort (*image)[4], white[8][8], curve[0x1000];
d767 1
a767 1
int jwide, jrow, jcol, val, jidx, i, row, col;
d781 7
a787 17
if (raw_width == 5108) {
i = jidx / (1680*jh.high);
if (i < 2) {
row = jidx / 1680 % jh.high;
col = jidx % 1680 + i*1680;
} else {
jidx -= 2*1680*jh.high;
row = jidx / 1748;
col = jidx % 1748 + 2*1680;
}
} else if (raw_width == 4476 || raw_width == 3516) {
row = jidx / (raw_width/2);
col = jidx % (raw_width/2);
if (row >= raw_height) {
row -= raw_height;
col += raw_width/2;
}
d3392 2
a3393 2
fseek (ifp, strstr(model,"EOS-1D") ? 68 :
strstr(model,"EOS 5D") ? 126 : 50, SEEK_CUR);
d3692 3
d4329 2
d4453 1
a4453 1
{ "MINOLTA DiMAGE Z2", 0, /* DJC */
d4479 2
d4649 1
a4649 1
raw_height = raw_width = fuji_width = flip = 0;
d5018 1
a5018 2
} else if (!strcmp(model,"E4300")) {
if (!timestamp && minolta_z2()) goto dimage_z2;
d5022 6
a5027 11
pre_mul[0] = 508;
pre_mul[1] = 256;
pre_mul[2] = 322;
} else if (!strcmp(model,"DiMAGE Z2")) {
dimage_z2:
strcpy (make, "MINOLTA");
strcpy (model,"DiMAGE Z2");
height = 1710;
width = 2288;
filters = 0x16161616;
load_raw = nikon_e2100_load_raw;
d5836 1
a5836 1
"\nRaw Photo Decoder \"dcraw\" v7.93"
@
1.307
log
@Added the Olympus C3030Z.
New color matrices for the Minolta Z2 and Kodak P850/P880.
@
text
@d3504 5
d3510 1
a3510 1
if (len < 50) break;
d5845 1
a5845 1
"\nRaw Photo Decoder \"dcraw\" v7.92"
@
1.306
log
@Moved constant black values from identify() to adobe_coeff().
@
text
@d943 1
a943 1
if (model[0] == 'E') {
d983 1
a983 1
Returns 1 for a Coolpix 990, 0 for a Coolpix 995.
d985 1
a985 1
int CLASS nikon_e990()
d991 1
a991 1
fseek (ifp, 2064*1540*3/4, SEEK_SET);
d995 3
a997 3
if (histo[often[i]] > 400)
return 1;
return 0;
d2707 1
a2707 1
for (b=0; b < 2000; b++) {
d3807 1
a3807 1
if (strlen(ext) != 4 || ext-file != 8) return;
d4435 2
a4436 2
{ "KODAK P880", 0, /* DJC */
{ 22050,-9634,-1863,-1864,9899,1966,-349,1453,4769 } },
d4453 2
a4454 2
{ "MINOLTA DiMAGE Z2", 68, /* DJC */
{ 11222,-3449,-1675,-5789,13566,2225,-2339,2670,5549 } },
d4620 1
a4620 1
{ 4771840, "NIKON", "E990" ,1 }, /* or E995 */
d4970 1
a4970 14
} else if (!strcmp(model,"E880") ||
!strcmp(model,"E990")) {
if (!timestamp && !nikon_e990()) goto cp_e995;
height = 1540;
width = 2064;
colors = 4;
filters = 0xb4b4b4b4;
simple_coeff(3);
pre_mul[0] = 1.196;
pre_mul[1] = 1.246;
pre_mul[2] = 1.018;
} else if (!strcmp(model,"E995")) {
cp_e995:
strcpy (model, "E995");
d4975 10
d5840 1
a5840 1
"\nRaw Photo Decoder \"dcraw\" v7.91"
@
1.305
log
@Collect interesting metadata and display it with "dcraw -i -v"
@
text
@d2730 1
a2730 1
fprintf (stderr, " { \"%s %s\",\n\t{ ", make, model);
d2733 2
a2734 2
fprintf (stderr, "%d,", (int) (best[c][j] * num + 0.5));
fprintf (stderr, "\b } },\n");
d4311 1
a4311 1
short trans[12];
d4313 1
a4313 1
{ "Canon EOS D2000",
d4315 1
a4315 1
{ "Canon EOS D6000",
d4317 1
a4317 1
{ "Canon EOS D30",
d4319 1
a4319 1
{ "Canon EOS D60",
d4321 1
a4321 1
{ "Canon EOS 5D",
d4323 1
a4323 1
{ "Canon EOS 20D",
d4325 1
a4325 1
{ "Canon EOS 350D",
d4327 1
a4327 1
{ "Canon EOS DIGITAL REBEL XT",
d4329 1
a4329 1
{ "Canon EOS-1Ds Mark II",
d4331 1
a4331 1
{ "Canon EOS-1D Mark II",
d4333 1
a4333 1
{ "Canon EOS-1DS",
d4335 1
a4335 1
{ "Canon EOS-1D",
d4337 1
a4337 1
{ "Canon EOS",
d4339 1
a4339 1
{ "Canon PowerShot A50",
d4341 1
a4341 1
{ "Canon PowerShot A5",
d4343 1
a4343 1
{ "Canon PowerShot G1",
d4345 1
a4345 1
{ "Canon PowerShot G2",
d4347 1
a4347 1
{ "Canon PowerShot G3",
d4349 1
a4349 1
{ "Canon PowerShot G5",
d4351 1
a4351 1
{ "Canon PowerShot G6",
d4353 1
a4353 1
{ "Canon PowerShot Pro1",
d4355 1
a4355 1
{ "Canon PowerShot Pro70",
d4357 1
a4357 1
{ "Canon PowerShot Pro90",
d4359 1
a4359 1
{ "Canon PowerShot S30",
d4361 1
a4361 1
{ "Canon PowerShot S40",
d4363 1
a4363 1
{ "Canon PowerShot S45",
d4365 1
a4365 1
{ "Canon PowerShot S50",
d4367 1
a4367 1
{ "Canon PowerShot S60",
d4369 1
a4369 1
{ "Canon PowerShot S70",
d4371 1
a4371 1
{ "Contax N Digital",
d4373 1
a4373 1
{ "EPSON R-D1",
d4375 1
a4375 1
{ "FUJIFILM FinePix E550",
d4377 1
a4377 1
{ "FUJIFILM FinePix F8",
d4379 1
a4379 1
{ "FUJIFILM FinePix F7",
d4381 1
a4381 1
{ "FUJIFILM FinePix S20Pro",
d4383 1
a4383 1
{ "FUJIFILM FinePix S2Pro",
d4385 1
a4385 1
{ "FUJIFILM FinePix S3Pro",
d4387 1
a4387 1
{ "FUJIFILM FinePix S5000",
d4389 1
a4389 1
{ "FUJIFILM FinePix S5100",
d4391 1
a4391 1
{ "FUJIFILM FinePix S5500",
d4393 1
a4393 1
{ "FUJIFILM FinePix S7000",
d4395 1
a4395 1
{ "FUJIFILM FinePix S9",
d4397 1
a4397 1
{ "KODAK NC2000F", /* DJC */
d4399 1
a4399 1
{ "Kodak DCS315C",
d4401 1
a4401 1
{ "Kodak DCS330C",
d4403 1
a4403 1
{ "KODAK DCS420",
d4405 1
a4405 1
{ "KODAK DCS460",
d4407 1
a4407 1
{ "KODAK EOSDCS1",
d4409 1
a4409 1
{ "KODAK EOSDCS3B",
d4411 1
a4411 1
{ "Kodak DCS520C",
d4413 1
a4413 1
{ "Kodak DCS560C",
d4415 1
a4415 1
{ "Kodak DCS620C",
d4417 1
a4417 1
{ "Kodak DCS620X",
d4419 1
a4419 1
{ "Kodak DCS660C",
d4421 1
a4421 1
{ "Kodak DCS720X",
d4423 1
a4423 1
{ "Kodak DCS760C",
d4425 1
a4425 1
{ "Kodak DCS Pro SLR",
d4427 1
a4427 1
{ "Kodak DCS Pro 14nx",
d4429 1
a4429 1
{ "Kodak DCS Pro 14",
d4431 1
a4431 1
{ "Kodak ProBack645",
d4433 1
a4433 1
{ "Kodak ProBack",
d4435 1
a4435 1
{ "KODAK P880", /* DJC */
d4437 1
a4437 1
{ "LEICA DIGILUX 2",
d4439 1
a4439 1
{ "Leaf Valeo",
d4441 1
a4441 1
{ "Minolta DiMAGE 5",
d4443 1
a4443 1
{ "Minolta DiMAGE 7Hi",
d4445 1
a4445 1
{ "Minolta DiMAGE 7",
d4447 1
a4447 1
{ "Minolta DiMAGE A1",
d4449 1
a4449 1
{ "MINOLTA DiMAGE A200",
d4451 1
a4451 1
{ "Minolta DiMAGE A2",
d4453 1
a4453 1
{ "MINOLTA DiMAGE Z2", /* DJC */
d4455 1
a4455 1
{ "MINOLTA DYNAX 5",
d4457 1
a4457 1
{ "MINOLTA DYNAX 7",
d4459 1
a4459 1
{ "NIKON D100",
d4461 1
a4461 1
{ "NIKON D1H",
d4463 1
a4463 1
{ "NIKON D1X",
d4465 1
a4465 1
{ "NIKON D1",
d4467 1
a4467 1
{ "NIKON D2H",
d4469 1
a4469 1
{ "NIKON D2X",
d4471 1
a4471 1
{ "NIKON D50",
d4473 1
a4473 1
{ "NIKON D70",
d4475 1
a4475 1
{ "NIKON E995", /* copied from E5000 */
d4477 1
a4477 1
{ "NIKON E2500",
d4479 1
a4479 1
{ "NIKON E4500",
d4481 1
a4481 1
{ "NIKON E5000",
d4483 1
a4483 1
{ "NIKON E5400",
d4485 1
a4485 1
{ "NIKON E5700",
d4487 1
a4487 1
{ "NIKON E8400",
d4489 1
a4489 1
{ "NIKON E8700",
d4491 1
a4491 1
{ "NIKON E8800",
d4493 1
a4493 1
{ "OLYMPUS C5050",
d4495 1
a4495 1
{ "OLYMPUS C5060",
d4497 1
a4497 1
{ "OLYMPUS C7070",
d4499 1
a4499 1
{ "OLYMPUS C70",
d4501 1
a4501 1
{ "OLYMPUS C80",
d4503 1
a4503 1
{ "OLYMPUS E-10",
d4505 1
a4505 1
{ "OLYMPUS E-1",
d4507 1
a4507 1
{ "OLYMPUS E-20",
d4509 1
a4509 1
{ "OLYMPUS E-300",
d4511 1
a4511 1
{ "OLYMPUS E-500",
d4513 1
a4513 1
{ "OLYMPUS SP500UZ",
d4515 1
a4515 1
{ "PENTAX *ist DL",
d4517 1
a4517 1
{ "PENTAX *ist DS",
d4519 1
a4519 1
{ "PENTAX *ist D",
d4521 1
a4521 1
{ "Panasonic DMC-FZ30",
d4523 1
a4523 1
{ "Panasonic DMC-LC1",
d4525 1
a4525 1
{ "Panasonic DMC-LX1",
d4527 1
a4527 1
{ "SONY DSC-F828",
d4529 1
a4529 1
{ "SONY DSC-R1", /* DJC */
d4531 1
a4531 1
{ "SONY DSC-V3",
d4541 2
a4851 1
black = 34;
a5034 1
black = 68;
a5056 1
black = 128;
a5319 1
black = 491;
a5328 1
black = 512;
a5341 4
} else if (!strcmp(model,"DCS315C")) {
black = 8;
} else if (!strcmp(model,"DCS330C")) {
black = 8;
a5352 10
} else if (!strcmp(model,"DCS520C")) {
black = 180;
} else if (!strcmp(model,"DCS560C")) {
black = 188;
} else if (!strcmp(model,"DCS620C")) {
black = 180;
} else if (!strcmp(model,"DCS620X")) {
black = 185;
} else if (!strcmp(model,"DCS660C")) {
black = 214;
d5843 1
a5843 1
"\nRaw Photo Decoder \"dcraw\" v7.90"
@
1.304
log
@Added Adobe matrix for the PENTAX *ist DL.
@
text
@d86 1
a86 1
float flash_used, canon_5814;
d140 1
d312 1
a312 1
i = canon_5814 + 0.5;
d3301 2
d3354 1
a3354 2
get2();
raw_width = get2();
d3440 2
a3441 1
int entries, tag, type, len, val, save;
d3443 1
a3448 1
val = get4();
d3450 14
a3463 8
fseek (ifp, base+val, SEEK_SET);
if (tag == 0x9003 || tag == 0x9004)
get_timestamp(0);
if (tag == 0x927c)
parse_makernote();
if (!strncmp(make,"EASTMAN",7)) {
if (tag == 0xa002) raw_width = val;
if (tag == 0xa003) raw_height = val;
d3465 1
a3465 1
fseek (ifp, save, SEEK_SET);
d3592 3
d3849 1
a3849 3
get2();
if (get4() != 0x80008) return;
if (get4() == 0) return;
d3897 6
a3902 3
if (type == 0x102a) { /* Find the White Balance index */
fseek (ifp, aoff+14, SEEK_SET); /* 0=auto, 1=daylight, 2=cloudy ... */
wbi = get2();
a3957 2
if (type == 0x5817)
shot_order = len;
d3967 3
a3969 1
canon_5814 = int_to_float(len);
d3974 5
d4058 1
a4058 1
FORC3 cam_mul[c] = 1.0 / neut[c+1];
d4234 1
a4234 1
char name[64];
d4242 1
a4242 2
get4();
entries = get4();
d4269 1
a4269 2
get4();
pent = get4();
d4277 3
d4281 1
a4281 1
foveon_gets (poff[i][1], make, 64);
d4283 1
a4283 1
foveon_gets (poff[i][1], model, 64);
d4285 1
a4285 1
foveon_gets (poff[i][1], model2, 64);
d4287 7
a4293 1
timestamp = atoi (foveon_gets (poff[i][1], name, 64));
d4391 2
d4542 1
a4542 1
cam_xyz[0][j] = table[i].trans[j];
d4648 1
d4708 1
a4708 2
get4();
raw_width = get4();
d5051 1
a5051 1
maximum = 0xffff;
d5694 1
a5694 1
int size, base, dest, next, row, col, temp;
d5732 2
a5733 6
temp = height;
height = width;
width = temp;
temp = ymag;
ymag = xmag;
xmag = temp;
d5845 1
a5845 1
int half_size=0, use_fuji_rotate=1, quality;
d5860 1
a5860 1
"\nRaw Photo Decoder \"dcraw\" v7.86"
d5990 3
d5994 41
a6034 1
fprintf (stderr, "%s is a %s %s image.\n", ifname, make, model);
a6038 3
shrink = half_size && filters;
iheight = (height + shrink) >> shrink;
iwidth = (width + shrink) >> shrink;
@
1.303
log
@Added the Kodak P880, Olympus C7070WZ, and Olympus SP500UZ.
@
text
@d4488 2
@
1.302
log
@Correctly parse Sony JPEG makernotes.
Fixed "memmem" conflict.
@
text
@d3452 4
d3573 1
d3690 7
d4368 1
a4368 1
{ "FUJIFILM FinePix S9", /* copied from S7000 */
d4408 2
d4470 2
d4484 4
a4487 2
{ "OLYMPUS E-500", /* copied from E-300 */
{ 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
d5276 2
d5304 2
a5305 6
height = 1950;
width = 2608;
data_offset = 76456;
filters = 0x16161616;
load_raw = packed_12_load_raw;
} else if (!strcasecmp(make,"KODAK")) {
d5835 1
a5835 1
"\nRaw Photo Decoder \"dcraw\" v7.85"
@
1.301
log
@Improved camera WB for the Canon PowerShot G6, S60, S70, and Pro1.
Avoid an infinite loop with Kodak DX3600 JPEG files.
Added the AVT F-145C.
@
text
@d185 1
a185 1
char *memmem (char *haystack, size_t haystacklen,
d194 1
d3277 1
@
1.300
log
@Correctly parse Ricoh makernotes.
Support the Casio QV-R61.
@
text
@d3267 1
d3848 1
a3848 1
static const int remap_s70[] = { 0,1,2,9,4,3,6,7,8,9,10,0,0,0,7,0,0,8 };
d3876 1
d3900 1
a3900 3
} else if (!strcmp(model,"Canon PowerShot G6") ||
!strcmp(model,"Canon PowerShot S60") ||
!strcmp(model,"Canon PowerShot S70")) {
a3902 3
} else if (!strcmp(model,"Canon PowerShot Pro1")) {
fseek (ifp, aoff+96 + wbi*8, SEEK_SET);
goto common;
d4557 1
d5141 4
d5817 1
a5817 1
"\nRaw Photo Decoder \"dcraw\" v7.84"
@
1.299
log
@Olympus ORF metadata contains an excellent rgb_cam[] matrix.
@
text
@d3280 1
d5479 1
a5479 1
} else if (!strcmp(model,"EX-P600")) {
@
1.298
log
@Added the Kodak KAI-0340 imaging module.
@
text
@d3380 5
d5814 1
a5814 1
"\nRaw Photo Decoder \"dcraw\" v7.83"
@
1.297
log
@Trim garbage pixels from several Nikon cameras.
@
text
@d4550 1
d5123 8
d5809 1
a5809 1
"\nRaw Photo Decoder \"dcraw\" v7.82"
@
1.296
log
@Updated the color matrices based on Adobe DNG Converter 3.2.
Added the Panasonic DMC-LX1.
@
text
@d4877 1
a4877 1
width = 4024;
d4879 2
a4880 1
} else if (!strcmp(model,"D70")) {
d4886 1
a4886 2
} else if (!strcmp(model,"D2H")) {
width = 2482;
d4888 1
d4890 1
a4890 1
width = 4312;
@
1.295
log
@Support the Sinar STI file format.
@
text
@a526 1
a528 1
a531 1
a547 1
a562 1
a578 1
a3535 1
if (!make[0]) strcpy (make, "Leaf");
d3712 1
a3712 1
int doff;
d3718 1
a3718 1
while ((doff = get4())) {
d4002 1
d4280 1
a4280 3
{ 7082,-1419,-376,-6858,14220,2900,-969,1328,7630 } },
{ "Canon EOS 10D",
{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
d4283 4
d4294 1
a4294 1
{ 6906,-278,-1017,-6649,15074,1621,-2848,3897,7611 } },
d4397 2
d4409 1
a4409 1
{ "MINOLTA DYNAX 5D",
d4411 1
a4411 1
{ "MINOLTA DYNAX 7D",
d4414 1
a4414 1
{ 5915,-949,-778,-7516,15364,2282,-1228,1337,6404 } },
d4418 1
a4418 1
{ 7620,-2173,-966,-7604,15843,1805,-2356,2811,8439 } },
d4469 2
d4473 2
a4474 2
{ "Panasonic DMC-FZ30",
{ 10473,-3277,-1222,-6421,14252,2352,-1907,2596,7460 } },
d4480 1
a4480 1
{ 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } }
d4636 2
a4637 1
} else if (!memcmp (head,"BM",2)) {
d4641 1
a4641 1
if (get4() == 2834 && get4() == 2834) {
d5048 1
a5048 1
sprintf (model, "DYNAX%s", strchr (model,' '));
d5197 8
a5204 1
if (width == 3304) width -= 16;
a5205 1
maximum = 0xfff0;
d5799 1
a5799 1
"\nRaw Photo Decoder \"dcraw\" v7.81"
@
1.294
log
@Added the Olympus E-500.
@
text
@d3461 1
a3461 1
char software[64];
d3542 1
a3542 1
strcpy (make, "Leaf");
d3544 1
d3599 9
d4586 1
a4586 1
"MINOLTA", "Minolta", "Konica", "CASIO" };
d4716 1
a4716 1
if (!strncmp (model, make, i++))
d5174 8
a5181 6
} else if (!strcmp(make,"Sinar") && !memcmp(head,"8BPS",4)) {
fseek (ifp, 14, SEEK_SET);
height = get4();
width = get4();
filters = 0x61616161;
data_offset = 68;
d5183 1
a5183 1
maximum = 0xffff;
d5792 1
a5792 1
"\nRaw Photo Decoder \"dcraw\" v7.80"
@
1.293
log
@Added casts to avoid signedness warnings with GCC 4.0.
@
text
@d1290 2
d1293 1
d4455 2
d5200 3
a5202 2
} else if (!strcmp(model,"E-300")) {
width -= 21;
d5208 1
a5208 2
} else
black = 62;
d5780 1
a5780 1
"\nRaw Photo Decoder \"dcraw\" v7.79"
@
1.292
log
@Smoothed out single-pixel artifacts in ahd_interpolate().
@
text
@d225 1
d1526 1
a1526 1
static char jpeg_buffer[4096];
d1976 1
a1976 1
read_shorts (diff, 1024);
d2116 1
a2116 1
int CLASS foveon_apply_curve (ushort *curve, int i)
d2122 2
d2364 1
a2364 1
for (pix=image[0]; pix < (short *) image[height*width]; pix+=4) {
d2433 1
a2433 1
for (pix=image[0]; pix < (short *) image[height*width]; pix+=4) {
d2520 1
d3987 1
a3987 1
uchar data[40];
@
1.291
log
@Silently ignore the "-w" flag for DNG files.
Refactored Fuji FinePix support yet again.
@
text
@d135 5
a139 3
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define CLIP(x) (MAX(0,MIN((x),clip_max)))
d3086 1
a3086 1
rgb[0][row-top][col-left][1] = CLIP(val);
d3089 1
a3089 1
rgb[1][row-top][col-left][1] = CLIP(val);
d5771 1
a5771 1
"\nRaw Photo Decoder \"dcraw\" v7.78"
@
1.290
log
@Support "-w" with the Fuji FinePix S9000/S9500.
@
text
@d104 1
a104 1
int fuji_secondary, use_secondary=0;
d1099 1
a1099 1
void CLASS fuji_s2_load_raw()
d1101 1
a1101 31
ushort pixel[2944];
int row, col, r, c;
for (row=0; row < 2144; row++) {
read_shorts (pixel, 2944);
for (col=0; col < 2880; col++) {
r = row + ((col+1) >> 1);
c = 2143 - row + (col >> 1);
BAYER(r,c) = pixel[col];
}
}
}
void CLASS fuji_s3_load_raw()
{
ushort pixel[4352];
int row, col, r, c;
for (row=0; row < 1440; row++) {
read_shorts (pixel, 4352);
for (col=0; col < 4288; col++) {
r = 2143 + row - (col >> 1);
c = row + ((col+1) >> 1);
BAYER(r,c) = pixel[col];
}
}
}
void CLASS fuji_common_load_raw()
{
ushort pixel[2944];
d1104 2
d1108 8
a1115 3
for (col=0; col <= fuji_width; col++) {
r = fuji_width - col + (row >> 1);
c = col + ((row+1) >> 1);
d1119 1
d4084 8
d4096 4
d4652 6
a4657 1
parse_tiff (get4()+12);
d4659 3
a4661 2
fread (&data_offset, 4, 1, ifp);
data_offset = ntohl(data_offset);
d4721 1
a4970 19
} else if (!strcmp(model,"FinePixS2Pro")) {
height = 3584;
width = 3583;
fuji_width = 2144;
data_offset += (24*2944+32)*2;
filters = 0x61616161;
load_raw = fuji_s2_load_raw;
black = 128;
strcpy (model+7, " S2Pro");
} else if (!strcmp(model,"FinePix S3Pro")) {
height = 3583;
width = 3584;
fuji_width = 2144;
data_offset += (2*4352+32)*2;
if (fsize > 18000000 && use_secondary)
data_offset += 1444*4352*2;
filters = 0x49494949;
load_raw = fuji_s3_load_raw;
maximum = 0x3dfd;
a4972 4
height = 1735;
width = 2304;
data_offset += width*10;
filters = 0x49494949;
d4975 21
a4995 31
} else if (!strcmp(model,"FinePix S5000")) {
raw_height = 2152;
raw_width = 1472;
fuji_width = 1423;
data_offset += (4*raw_width+24)*2;
goto fuji_common;
} else if (!strcmp(model,"FinePix E550") ||
!strncmp(model,"FinePix F8",10) ||
!strcmp(model,"FinePix S7000")) {
raw_height = 3080;
raw_width = 2048;
fuji_width = 2047;
goto fuji_common;
} else if (!strcmp(model,"FinePix S9000") ||
!strcmp(model,"FinePix S9500")) {
raw_height = 3688;
raw_width = 2512;
fuji_width = 2447;
data_offset += 64;
goto fuji_common;
} else if (!strncmp(model,"FinePix F7",10) ||
!strcmp(model,"FinePix S20Pro")) {
raw_height = 2168;
raw_width = 2944;
fuji_width = 1439;
data_offset += 32 + use_secondary*2944;
fuji_common:
width = 1 + (height = raw_height/2 + fuji_width);
load_raw = fuji_common_load_raw;
filters = 0x49494949;
maximum = 0x3e00;
d5569 1
a5569 1
fuji_width = (fuji_width + shrink) >> shrink;
d5752 1
a5752 1
int arg, status=0, user_flip=-1, user_black=-1;
d5754 1
a5754 1
int half_size=0, use_fuji_rotate=1, quality=3;
d5769 1
a5769 1
"\nRaw Photo Decoder \"dcraw\" v7.77"
d5789 1
a5789 1
"\n-q [0-3] Set the interpolation quality (default = 3)"
d5820 1
a5820 1
case 'q': quality = atoi(argv[arg++]); break;
d5921 2
d5931 1
a5931 1
else if (quality < 3 || colors > 3 || fuji_width)
@
1.289
log
@Added the Fuji S9000/S9500 and refactored Fuji code.
Added camera white balance for Sony SR2 files.
Improved color for the Kodak DC40/DC50/DC120, fixed DC50 bug.
Detect and reject more non-raw images.
@
text
@d4101 1
a4101 1
if (entries > 60) return;
@
1.288
log
@Added the Canon EOS 5D.
@
text
@d88 1
a88 1
unsigned shot_order;
a1103 1
fseek (ifp, (2944*24+32)*2, SEEK_CUR);
a1118 1
fseek (ifp, (4352*2+32)*2, SEEK_CUR);
d1129 1
a1129 1
void CLASS fuji_common_load_raw (int ncol, int icol, int nrow)
d1131 1
a1131 1
ushort pixel[2048];
d1134 4
a1137 4
for (row=0; row < nrow; row++) {
read_shorts (pixel, ncol);
for (col=0; col <= icol; col++) {
r = icol - col + (row >> 1);
a1143 32
void CLASS fuji_s5000_load_raw()
{
fseek (ifp, (1472*4+24)*2, SEEK_CUR);
fuji_common_load_raw (1472, 1423, 2152);
}
void CLASS fuji_s7000_load_raw()
{
fuji_common_load_raw (2048, 2047, 3080);
}
/*
The Fuji Super CCD SR has two photodiodes for each pixel.
The secondary has about 1/16 the sensitivity of the primary,
but this ratio may vary.
*/
void CLASS fuji_f700_load_raw()
{
ushort pixel[2944];
int row, col, r, c, val;
for (row=0; row < 2168; row++) {
read_shorts (pixel, 2944);
for (col=0; col < 1440; col++) {
r = 1439 - col + (row >> 1);
c = col + ((row+1) >> 1);
val = pixel[col+16 + use_secondary*1472];
BAYER(r,c) = val;
}
}
}
d1456 2
a1457 2
if (model[2] == '5')
return (getbits(6) << 2) + 2; /* DC50 */
d1532 1
a1532 1
maximum = 0x1fff; /* wild guess */
d3045 1
a3045 1
static float cbrt[0x10000], xyz_cam[3][3];
d3466 2
a3467 1
void parse_mos(int offset);
d3479 2
d3569 6
d3595 9
d3676 5
d3689 16
d3731 1
d4346 2
d4492 3
a4494 1
/* index 2 -- Nikon E700, E800, and E950 */
d4585 1
a4585 1
zero_after_ff = dng_version = fuji_secondary = 0;
d4879 1
a4879 1
simple_coeff(2);
d4891 1
a4891 1
simple_coeff(2);
d4902 1
a4902 1
simple_coeff(2);
d4978 1
d4987 1
d4989 1
a4989 1
data_offset += 4352*2*1444;
a4992 7
} else if (!strcmp(model,"FinePix S5000")) {
height = 2499;
width = 2500;
fuji_width = 1423;
filters = 0x49494949;
load_raw = fuji_s5000_load_raw;
maximum = 0x3e00;
d5001 6
d5010 2
a5011 2
height = 3587;
width = 3588;
d5013 8
a5020 3
filters = 0x49494949;
load_raw = fuji_s7000_load_raw;
maximum = 0x3e00;
d5023 7
a5029 3
height = 2523;
width = 2524;
fuji_width = 1440;
a5030 1
load_raw = fuji_f700_load_raw;
d5389 1
d5805 1
a5805 1
"\nRaw Photo Decoder \"dcraw\" v7.74"
@
1.287
log
@Interpolate every pixel -- do not trim borders.
Changed "-q" flag to take a numeric argument.
Allow "-z" to work with Canon camera AVI files.
@
text
@d95 1
a95 1
int dng_version, is_canon, is_foveon, raw_color, use_gamma;
d792 3
a794 3
} else if (raw_width == 3516) {
row = jidx / 1758;
col = jidx % 1758;
d797 1
a797 1
col += 1758;
a1787 1
maximum = 0xe74;
d3444 2
a3445 1
fseek (ifp, strstr(model,"EOS-1D") ? 68:50, SEEK_CUR);
d3549 1
a3549 1
if (level) maximum = (1 << (tiff_bps = get2())) - 1;
d4270 2
d4521 1
a4521 1
unsigned hlen, fsize, i, c, is_jpeg=0;
d4721 1
a4721 1
if ((is_canon = !strcmp(make,"Canon")))
d4724 2
d4833 4
d5209 1
d5785 1
a5785 1
"\nRaw Photo Decoder \"dcraw\" v7.73"
@
1.286
log
@Removed edge-sensing from ahd_interpolate() to save time.
Added bilateral_filter() to smooth noise while preserving edges.
If a file contains multiple timestamps, use only the first.
If a Canon CRW camera is set to Auto WB, use _my_ Auto WB.
@
text
@d88 1
d90 1
a90 1
int tiff_data_compression, kodak_data_compression;
d96 1
a96 1
int trim, flip, xmag, ymag;
d102 1
a102 1
int four_color_rgb=0, document_mode=0, quick_interpolate=0;
d879 1
a879 1
int row, col, nbits;
a882 1
for (nbits=0; 1 << nbits <= maximum; nbits++);
d884 1
a884 1
if (nbits == 16)
d889 1
a889 1
pixel[col] = getbits(nbits);
d1071 2
a1072 2
uchar data[3432], *dp;
ushort pixel[2288], *pix;
d1515 1
a1515 2
for (i=0; i < 3; i++)
mul[i] = getbits(6);
d2881 61
d2980 1
a2980 1
int row, col, shift, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
d2983 2
a2984 37
if (verbose)
fprintf (stderr, "%s interpolation...\n",
quick_interpolate ? "Bilinear":"VNG");
for (row=0; row < 8; row++) { /* Precalculate for bilinear */
for (col=1; col < 3; col++) {
ip = code[row][col & 1];
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++ = sum[c];
}
}
}
for (row=1; row < height-1; row++) { /* Do bilinear interpolation */
for (col=1; col < width-1; col++) {
pix = image[row*width+col];
ip = code[row & 7][col & 1];
memset (sum, 0, sizeof sum);
for (g=8; g--; ip+=3)
sum[ip[2]] += pix[ip[0]] << ip[1];
for (g=colors; --g; ip+=2)
pix[ip[0]] = sum[ip[0]] / ip[1];
}
}
if (quick_interpolate) return;
d3121 2
d3133 2
a3134 2
/* Horizontally interpolate green into rgb[0]: */
for (row = top; row < top+TS && row < height; row++) {
a3141 7
}
}
/* Vertically interpolate green into rgb[1]: */
for (row = top < 2 ? 2:top; row < top+TS && row < height-2; row++) {
col = left + (FC(row,left) == 1);
for (fc = FC(row,col); col < left+TS && col < width; col+=2) {
pix = image + row*width+col;
d3149 1
a3149 2
for (row=top+1; row < top+TS-1 && row < height-1; row++) {
tr = row-top;
a3150 1
tc = col-left;
d3152 1
a3152 1
rix = &rgb[d][tr][tc];
d3169 1
a3169 1
FORC3 lab[d][tr][tc][c] = 64*flab[c];
a3170 1
}
a3212 1
trim = 3;
d3350 2
a3461 1
time_t ts;
d3476 2
a3477 3
putenv ("TZ=UTC"); /* Remove this to assume local time */
if ((ts = mktime(&t)) > 0)
timestamp = ts;
d3549 1
a3549 1
if (level) maximum = (1 << get2()) - 1;
d3574 3
a3576 1
if (!strncmp(software,"Adobe",5))
d3932 2
d3936 4
a3962 1
time_t ts;
d3988 2
a3989 3
putenv ("TZ=");
if ((ts = mktime(&t)) > 0)
timestamp = ts;
d4127 31
d4244 3
d4516 1
a4516 1
int CLASS identify (int will_decode)
d4572 1
a4572 1
data_offset = meta_length = tiff_data_compression = 0;
d4574 1
a4574 1
timestamp = tiff_samples = black = is_foveon = 0;
d4654 3
d4675 1
d5466 2
a5467 3
if (will_decode)
fprintf (stderr, "%s: Cannot decode %s %s%s images.\n",
ifname, make, model, is_jpeg ? " JPEG":"");
d5545 2
a5546 2
for (row = trim; row < height-trim; row++)
for (col = trim; col < width-trim; col++) {
d5662 2
a5663 3
fprintf (ofp, "P6\n%d %d\n255\n",
xmag*(width-trim*2), ymag*(height-trim*2));
ppm = calloc (width-trim*2, 3*xmag);
d5685 2
a5686 2
for (row=trim; row < height-trim; row++) {
for (col=trim; col < width-trim; col++)
d5688 1
a5688 1
ppm[xmag*(col-trim)+i][c] = lut[image[row*width+col][c]];
d5690 1
a5690 1
fwrite (ppm, width-trim*2, 3*xmag, ofp);
d5716 2
a5717 2
hw[0] = htonl(height-trim*2); /* write the header */
hw[1] = htonl(width-trim*2);
d5721 1
a5721 1
psize = (height-trim*2) * (width-trim*2);
d5726 2
a5727 2
for (row = trim; row < height-trim; row++)
for (col = trim; col < width-trim; col++) {
d5744 1
a5744 2
fprintf (ofp, "P6\n%d %d\n%d\n",
width-trim*2, height-trim*2, maximum);
d5746 1
a5746 1
ppm = calloc (width-trim*2, 6);
d5749 4
a5752 4
for (row = trim; row < height-trim; row++) {
for (col = trim; col < width-trim; col++)
FORC3 ppm[col-trim][c] = htons(image[row*width+col][c]);
fwrite (ppm, width-trim*2, 6, ofp);
d5761 1
a5761 1
int half_size=0, use_fuji_rotate=1, use_vng=0;
d5770 3
d5776 1
a5776 1
"\nRaw Photo Decoder \"dcraw\" v7.70"
d5796 2
a5797 3
"\n-V Use VNG interpolation"
"\n-q Quick, low-quality bilinear interpolation"
"\n-h Half-size color image (3x faster than -q)"
d5813 1
a5813 1
if ((strchr("Bbrlkt", opt) && !isdigit(argv[arg][0])) ||
d5827 1
a5837 2
case 'V': use_vng = 1; break;
case 'q': quick_interpolate = 1; break;
d5886 1
a5886 2
identify(0);
if ((status = !timestamp))
d5888 2
d5898 1
a5898 1
if ((status = identify(1))) goto next;
d5933 4
a5936 2
if ((trim = filters && !document_mode)) {
if (quick_interpolate || use_vng || colors > 3)
@
1.285
log
@Added the Kodak P850.
@
text
@d100 1
a100 1
float bright=1.0, red_scale=1.0, blue_scale=1.0;
d3050 28
d3086 1
a3086 2
int i, j, k, top, left, row, col, tr, tc, fc, c, d, val;
int west, east, north, south, num, total[3], hm[3];
d3089 2
a3090 3
static const float d65[3] = { 0.950456, 1, 1.088754 };
unsigned ldiff[3][4], abdiff[3][4], leps, abeps;
float r, *cbrt, xyz[3], xyz_cam[3][3];
d3096 1
a3096 1
buffer = malloc (0x40000 + 39*TS*TS); /* 2752 kB */
d3098 3
a3100 14
cbrt = (void *) buffer;
rgb = (void *) (buffer + 0x40000);
lab = (void *) (buffer + 0x40000 + 18*TS*TS);
homo = (void *) (buffer + 0x40000 + 36*TS*TS);
/* Prepare conversion from raw color to CIELab: */
for (i=0; i < 0x10000; i++) {
r = (float) i / maximum;
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 < 3; j++)
for (xyz_cam[i][j] = k=0; k < 3; k++)
xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65[i];
d3104 1
a3104 1
memset (rgb, 0, 18*TS*TS);
a3126 23
/* Combine these into rgb[2] using edge-sensing: */
for (row = top < 1 ? 1:top; row < top+TS && row < height-1; row++) {
tr = row - top;
col = left + (FC(row,left) == 1);
if (col < 1) col += 2;
for ( ; col < left+TS && col < width-1; col+=2) {
tc = col - left;
pix = image + row*width+col;
west = rgb[0][tr][tc][1] - pix[-1][1];
east = rgb[0][tr][tc][1] - pix[+1][1];
north = rgb[1][tr][tc][1] - pix[-width][1];
south = rgb[1][tr][tc][1] - pix[+width][1];
if ((val = ABS(west) + ABS(east) - ABS(north) - ABS(south)))
rgb[2][tr][tc][1] = rgb[val > 0][tr][tc][1];
else {
west *= east;
north *= south;
rgb[2][tr][tc][1] = (west*north < 0)
? rgb[west > 0][tr][tc][1]
: (rgb[0][tr][tc][1] + rgb[1][tr][tc][1]) >> 1;
}
}
}
d3128 1
a3128 1
for (d=0; d < 3; d++)
d3137 2
a3138 2
val = ( pix[-1][2-c] + pix[1][2-c] +
2*pix[0][1] - rix[-1][1] - rix[1][1] ) >> 1;
d3140 7
a3146 14
val = ( pix[-width][c] + pix[width][c] +
2*pix[0][1] - rix[-TS][1] - rix[TS][1] ) >> 1;
} else {
north = 2*rix[0][1] - (rix[-TS-1][1] + rix[TS+1][1]);
west = 2*rix[0][1] - (rix[-TS+1][1] + rix[TS-1][1]);
val = (d < 2) ? 0 :
ABS(pix[-width-1][c] - pix[width+1][c]) + ABS(north)
- ABS(pix[-width+1][c] - pix[width-1][c]) - ABS(west);
north += pix[-width-1][c] + pix[width+1][c];
west += pix[-width+1][c] + pix[width-1][c];
if (val == 0) val = (north + west) >> 2;
else if (val < 0) val = north >> 1;
else val = west >> 1;
}
d3150 2
a3151 8
for (i=0; i < 3; i++) {
for (xyz[i]=0.5, c=0; c < 3; c++)
xyz[i] += xyz_cam[i][c] * rix[0][c];
xyz[i] = cbrt[CLIP((int) xyz[i])];
}
lab[d][tr][tc][0] = 32*116 * xyz[1] - 32*16;
lab[d][tr][tc][1] = 32*500 * (xyz[0] - xyz[1]);
lab[d][tr][tc][2] = 32*200 * (xyz[1] - xyz[2]);
d3155 1
a3155 1
memset (homo, 0, 3*TS*TS);
d3160 1
a3160 1
for (d=0; d < 3; d++)
d3165 1
a3165 1
for (d=0; d < 3; d++)
d3172 1
a3172 1
for (d=0; d < 3; d++)
d3183 1
a3183 1
for (d=0; d < 3; d++)
d3187 5
a3191 7
FORC3 total[c] = 0;
for (num=d=0; d < 3; d++)
if (hm[d] >= hm[0] && hm[d] >= hm[1] && hm[d] >= hm[2]) {
FORC3 total[c] += rgb[d][tr][tc][c];
num++;
}
FORC3 image[row*width+col][c] = total[c] / num;
d3200 57
d3448 1
d3877 1
a3931 2
if (wbi == 0 && !strcmp(model,"Canon EOS D30"))
camera_red = -1; /* Use my auto WB for this photo */
d5716 1
a5716 1
"\nRaw Photo Decoder \"dcraw\" v7.65"
d5740 1
d5754 3
a5756 2
if (strchr ("brlkt", opt) && !isdigit(argv[arg][0])) {
fprintf (stderr, "\"-%c\" requires a numeric argument.\n", opt);
d5761 2
d5873 1
d5879 1
@
1.284
log
@For CIELab, divide XYZ by the D65 white point.
Added "-V" flag to always use vng_interpolate().
@
text
@d4472 1
a4472 1
{ "Canon", "NIKON", "EPSON", "Kodak", "OLYMPUS", "PENTAX",
d5147 6
d5682 1
a5682 1
"\nRaw Photo Decoder \"dcraw\" v7.64"
@
1.283
log
@Added the SONY DSC-R1.
@
text
@d3062 1
d3085 1
a3085 1
xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j];
d5664 1
a5664 1
int half_size=0, use_fuji_rotate=1;
d5676 1
a5676 1
"\nRaw Photo Decoder \"dcraw\" v7.63"
d5696 2
a5697 1
"\n-q Quick, low-quality color interpolation"
d5734 1
d5830 1
a5830 1
if (quick_interpolate || colors > 3)
@
1.282
log
@Always treat RGB as four colors until the end of scale_colors().
Read bit-packed uncompressed DNG files (untested).
@
text
@d2754 1
d2838 1
d4365 2
d5141 5
a5389 2
if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
if (cam_mul[3] == 0) cam_mul[3] = colors < 4 ? cam_mul[1] : 1;
d5675 1
a5675 1
"\nRaw Photo Decoder \"dcraw\" v7.62"
@
1.281
log
@Don't add integers to a void pointer.
@
text
@d443 1
a443 1
static unsigned long bitbuf=0;
d445 1
a445 1
unsigned c, ret;
a446 3
if (nbits == 0 || nbits > vbits) return 0;
if (nbits == -2)
return ftell(ifp) + (-vbits >> 3);
d448 3
a450 6
ret = bitbuf = vbits = reset = 0;
else {
ret = bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - nbits);
vbits -= nbits;
}
while (!reset && vbits < LONG_BIT - 7) {
d452 1
a452 1
if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) break;
d456 2
a457 1
return ret;
d754 1
d878 1
a878 1
int row, col;
d882 1
d884 7
a890 1
read_shorts (pixel, raw_width * tiff_samples);
d1898 1
a1898 1
if (getbits(-2) + 12 > seg[1][1])
d2800 2
a2801 2
FORCC min[c] = INT_MAX;
FORCC max[c] = count[c] = sum[c] = 0;
d2804 1
a2804 1
FORCC {
d2815 1
a2815 1
FORCC pre_mul[c] = count[c] / sum[c];
d2818 1
a2818 1
FORCC count[c] = sum[c] = 0;
d2826 2
a2827 4
val = 1;
FORCC if (sum[c] == 0) val = 0;
if (val)
FORCC pre_mul[c] = count[c] / sum[c];
d2838 1
a2838 1
FORCC if (dmin > pre_mul[c])
d2840 1
a2840 1
FORCC pre_mul[c] /= dmin;
d2843 1
a2843 1
FORCC pre_mul[c] *= 1 << shift;
d2850 1
a2850 1
FORCC pre_mul[c] *= bright;
d2854 1
a2854 1
FORCC fprintf (stderr, " %f", pre_mul[c]);
d2860 1
a2860 1
FORCC {
d2867 11
d3440 2
a3441 6
if (tag == 0x927c) {
if (!strncmp(make,"SONY",4))
data_offset = base+val+len;
else
parse_makernote();
}
d3939 1
a3939 1
int skip, from, i, neut[4];
d3967 1
a3967 2
camera_red = (float) neut[2] / neut[1];
camera_blue = (float) neut[2] / neut[3];
d4483 2
a4484 2
cam_mul[i] = 1 & i;
pre_mul[i] = 1;
d5127 1
d5135 1
d5374 1
a5374 1
if (four_color_rgb && filters && colors == 3) {
d5381 2
a5382 5
colors++;
cam_mul[3] = cam_mul[1];
pre_mul[3] = pre_mul[1];
FORC3 rgb_cam[c][3] = rgb_cam[c][1] /= 2;
}
d5668 1
a5668 1
"\nRaw Photo Decoder \"dcraw\" v7.60"
@
1.280
log
@Renamed "coeff" to "rgb_cam", and "!use_coeff" to "raw_color".
Added SRGB_GAMMA compile option and "-k" flag to set black point.
Use Adaptive Homogeneity-Directed interpolation when colors == 3.
@
text
@d3058 3
a3060 3
rgb = (void *) buffer + 0x40000;
lab = (void *) buffer + 0x40000 + 18*TS*TS;
homo = (void *) buffer + 0x40000 + 36*TS*TS;
@
1.279
log
@Added the Pentax *ist DL.
@
text
@d94 1
a94 1
int dng_version, is_canon, is_foveon, use_coeff, use_gamma;
d104 5
a108 1
float cam_mul[4], pre_mul[4], coeff[3][4];
d132 6
d362 2
a363 3
for (i=0; i < 3; i++)
FORCC coeff[i][c] = table[t][i*4 + c] / 1024.0;
use_coeff = 1;
d2245 1
a2245 1
FORC3 trans[i][j] += coeff[i][c] * last[c][j] * div[j];
a2662 4
static const double xyz_rgb[3][3] = { /* XYZ from RGB */
{ 0.412453, 0.357580, 0.180423 },
{ 0.212671, 0.715160, 0.072169 },
{ 0.019334, 0.119193, 0.950227 } };
d2679 1
a2679 1
for (i=0; i < 3; i++)
d2681 1
a2681 2
coeff[i][j] = inverse[j][i];
use_coeff = 1;
d2832 1
a2832 1
if (!use_coeff) {
d2864 1
a2864 3
if (val < 0) val = 0;
if (val > clip_max) val = clip_max;
image[row*width+col][c] = val;
d2939 4
a2942 9
for (g=8; g--; ) {
diff = pix[*ip++];
diff <<= *ip++;
sum[*ip++] += diff;
}
for (g=colors; --g; ) {
c = *ip++;
pix[c] = sum[c] / *ip++;
}
d2945 1
a2945 2
if (quick_interpolate)
return;
d2988 2
a2989 2
num = (diff = pix[g] - pix[ip[1]]) >> 31;
gval[ip[3]] += (diff = ((diff ^ num) - num) << ip[2]);
d3021 3
a3023 6
if (c != color) {
t += (sum[c] - sum[color])/num;
if (t < 0) t = 0;
if (t > clip_max) t = clip_max;
}
brow[2][col][c] = t;
d3036 172
d3987 3
a3989 1
use_coeff = 1;
d3991 1
a3991 5
for (i=0; i < 3; i++)
if (tag == 0x106)
FORC3 coeff[i][c] = int_to_float(get4());
else
cam_mul[i] = pre_mul[i] = int_to_float(get4());
d4387 2
a4388 3
for (i=0; i < 3; i++)
FORCC coeff[i][c] = table[index][i*colors+c];
use_coeff = 1;
a4469 1
timestamp = tiff_samples = 0;
d4472 2
a4473 2
black = is_foveon = use_coeff = 0;
use_gamma = xmag = ymag = 1;
d4478 1
d5344 1
a5344 1
if (!use_coeff) adobe_coeff();
d5360 5
a5364 7
if (use_camera_rgb && colors == 3)
use_coeff = 0;
if (use_coeff) /* Apply user-selected color balance */
for (i=0; i < colors; i++) {
coeff[0][i] *= red_scale;
coeff[2][i] *= blue_scale;
}
d5375 1
a5375 2
if (use_coeff)
FORC3 coeff[c][3] = coeff[c][1] /= 2;
d5402 2
a5403 1
use_gamma = use_coeff = 0;
d5421 1
a5421 1
int row, col, r, g, c=0;
d5426 2
a5427 2
fprintf (stderr, use_coeff ?
"Converting to sRGB colorspace...\n" : "Building histograms...\n");
d5436 2
a5437 2
c = FC(row,col);
if (colors == 4 && !use_coeff) /* Recombine the greens */
d5440 2
a5441 7
for (r=0; r < 3; r++)
rgb[r] = img[c];
else if (use_coeff) { /* RGB via coeff[][] */
for (r=0; r < 3; r++)
for (rgb[r]=g=0; g < colors; g++)
rgb[r] += img[g] * coeff[r][g];
} else /* RGB from RGB (easy) */
d5443 4
a5446 5
for (r=0; r < 3; r++) {
if (rgb[r] < 0) rgb[r] = 0;
if (rgb[r] > clip_max) rgb[r] = clip_max;
img[r] = rgb[r];
}
d5448 1
a5448 2
for (r=0; r < 3; r++)
histogram[r][img[r] >> 3]++;
d5565 3
d5569 1
d5648 1
a5648 1
int arg, status=0, user_flip=-1;
d5662 1
a5662 1
"\nRaw Photo Decoder \"dcraw\" v7.53"
d5675 1
d5698 1
a5698 1
if (strchr ("brlt", opt) && !isdigit(argv[arg][0])) {
d5707 1
d5809 1
d5813 5
a5817 1
if ((trim = filters && !document_mode)) vng_interpolate();
@
1.278
log
@Added the Panasonic DMC-FZ30.
@
text
@d4183 2
d4802 3
a4804 5
} else if (!strcmp(model,"*ist D")) {
load_raw = unpacked_load_raw;
} else if (!strcmp(model,"*ist DS")) {
height--;
load_raw = packed_12_load_raw;
d5505 1
a5505 1
"\nRaw Photo Decoder \"dcraw\" v7.52"
@
1.277
log
@Added the Olympus C740UZ.
@
text
@d3301 3
a3303 1
camera_red = get4() / 256.0;
d3305 4
a3308 2
case 0x12:
camera_blue = get4() / 256.0;
d3310 1
d3312 1
a3312 1
if (strcmp(make,"Canon") || level)
d3315 1
d3317 1
a3317 1
if (strcmp(make,"Canon") || level)
d4187 2
d4913 2
a4914 4
} else if (!strcmp(model,"DIGILUX 2") || !strcmp(model,"DMC-LC1")) {
height = 1928;
width = 2568;
data_offset = 1024;
d5505 1
a5505 1
"\nRaw Photo Decoder \"dcraw\" v7.51"
@
1.276
log
@Added the Minolta RD175.
@
text
@d1008 3
a1010 1
Separates a Pentax Optio 33WR from a Nikon E3700.
d1012 1
a1012 1
int CLASS pentax_optio33()
d1021 2
a1022 1
return sum[0] < sum[1]*4;
d4631 1
a4631 2
} else if (!strcmp(model,"E3700")) {
if (!timestamp && pentax_optio33()) goto optio_33wr;
d4637 11
a4647 11
} else if (!strcmp(model,"Optio 33WR")) {
optio_33wr:
strcpy (make, "PENTAX");
strcpy (model,"Optio 33WR");
height = 1542;
width = 2064;
load_raw = nikon_e2100_load_raw;
flip = 1;
filters = 0x16161616;
pre_mul[0] = 1.331;
pre_mul[2] = 1.820;
d5210 1
a5210 2
for (i=0; i < 3; i++)
coeff[i][3] = coeff[i][1] /= 2;
d5499 1
a5499 1
"\nRaw Photo Decoder \"dcraw\" v7.50"
@
1.275
log
@Added the Olympus C770UZ.
@
text
@d1347 28
d4251 1
d4725 6
d4837 1
a4837 1
height = 1210;
d5498 1
a5498 1
"\nRaw Photo Decoder \"dcraw\" v7.49"
@
1.274
log
@Fixed the Kodak NC2000F, and improved the Minolta DYNAX 5D.
Correctly flip NEF files that Nikon Capture has modified.
@
text
@d4231 1
d4895 5
d5463 1
a5463 1
"\nRaw Photo Decoder \"dcraw\" v7.48"
@
1.273
log
@Support Adobe DNG version 1.1.0.0.
@
text
@d2714 5
a2718 5
for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++)
FORCC if (image[row*width+col][c]) {
gmb_cam[sq][c] += image[row*width+col][c];
count[c]++;
}
d3149 13
d4038 2
d4092 2
d4719 1
d4921 1
a4921 5
left_margin = 1;
for (i=176; i < 0x1000; i++)
curve[i] = curve[i-1];
pre_mul[0] = 1.509;
pre_mul[2] = 2.686;
d5457 1
a5457 1
"\nRaw Photo Decoder \"dcraw\" v7.46"
@
1.272
log
@Added the Leaf Aptus 17.
@
text
@d94 1
a94 1
int is_dng, is_canon, is_foveon, use_coeff, use_gamma;
d734 4
a737 1
diff = getbits (len = dindex->leaf);
d814 1
a814 1
unsigned r=row, c=col;
d816 2
d827 6
a832 5
} else
for (c=0; c < tiff_samples; c++) {
image[row*width+col][c] = **rp < 0x1000 ? curve[**rp] : **rp;
(*rp)++;
}
a3238 1
ushort scale[4];
d3312 1
a3312 1
if (len > 2 && !is_dng && !strcmp(make,"Kodak"))
d3349 1
a3349 1
is_dng = 1;
d3386 5
a3390 3
for (i=0; i < 4; i++)
scale[i] = get4();
if (scale[1]*scale[2] == 2*scale[0]*scale[3]) ymag = 2;
d3412 6
d3448 1
a3448 1
if (!is_dng && !strncmp(make,"Kodak",5)) {
d4250 1
a4250 1
zero_after_ff = is_dng = fuji_secondary = 0;
d4280 1
a4280 1
if (!is_dng && !strncmp(make,"NIKON",5) && filters == UINT_MAX)
d4374 1
a4374 1
ymag = 1;
d4376 1
a4376 1
if (is_dng) {
d5443 1
a5443 1
"\nRaw Photo Decoder \"dcraw\" v7.45"
@
1.271
log
@Fixed gcc warning.
@
text
@d435 1
a435 1
static int vbits=0;
d438 1
a438 1
if (nbits == 0) return 0;
d442 1
a442 1
ret = bitbuf = vbits = 0;
d447 1
a447 1
while (vbits < LONG_BIT - 7) {
d449 1
a450 2
if (c == 0xff && zero_after_ff)
fgetc(ifp);
d683 1
a683 1
int bits, high, wide, clrs, vpred[4];
d696 1
d717 3
a723 2
for (i=0; i < 4; i++)
jh->vpred[i] = 1 << (jh->bits-1);
a724 1
getbits(-1);
d740 1
a740 1
void CLASS ljpeg_row (struct jhead *jh)
d745 4
d767 1
a767 1
ljpeg_row (&jh);
d769 3
a771 1
val = curve[jh.row[jcol]];
d851 1
a851 1
ljpeg_row (&jh);
d3223 2
d3329 3
d4827 2
d5430 1
a5430 1
"\nRaw Photo Decoder \"dcraw\" v7.43"
@
1.270
log
@Fixed serious problems with the Imacon Ixpress.
Moved most verbose messages out of main().
@
text
@d226 1
a226 1
float CLASS get_float()
d228 3
a230 2
int i = get4();
return *((float *) &i);
d3631 1
a3631 1
flash_used = *((float *) &len);
d3633 1
a3633 1
canon_5814 = *((float *) &len);
d3752 1
a3752 1
FORC3 coeff[i][c] = get_float();
d3754 1
a3754 1
cam_mul[i] = pre_mul[i] = get_float();
@
1.269
log
@Various changes regarding headerless raw photos.
Support the Nikon D50 with camera white balance.
@
text
@d2138 3
d2863 4
d3324 7
a3407 9
if (is_dng || level) return done;
if ((raw_height & 1) && !strncmp (make,"OLYMPUS",7))
raw_height++;
if (make[0] == 0 && raw_width == 680)
strcpy (make, "Imacon");
d3802 1
a3802 1
void CLASS parse_jpeg (int offset)
d3807 1
a3807 1
if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return;
d3820 1
a3820 1
strcat (model," JPEG");
d4172 1
a4172 1
unsigned hlen, fsize, i, c;
a4320 1
if (make[0] == 0) parse_jpeg(0);
d4322 1
d4372 2
d4795 4
a4798 11
height = 5444;
width = 4080;
raw_width = 4090;
data_offset = 314 + raw_width*12;
flip = 5;
if (raw_height == 680) {
order = 0x4949;
height = 4084;
data_offset -= 10;
flip = 3;
}
d5094 1
a5094 1
if (!load_raw || !height || strstr(model,"JPEG")) {
d5096 2
a5097 2
fprintf (stderr, "%s: Cannot decode %s %s images.\n",
ifname, make, model);
d5176 4
d5254 4
d5368 1
a5368 1
for (row = trim; row < height-trim; row++) {
a5372 1
}
d5416 1
a5416 1
"\nRaw Photo Decoder \"dcraw\" v7.42"
a5557 5
if (is_foveon) {
if (verbose)
fprintf (stderr, "Foveon interpolation...\n");
foveon_interpolate();
} else {
d5559 1
a5559 1
colorcheck();
d5561 2
a5562 2
scale_colors();
}
d5564 1
a5564 8
trim = 0;
if (filters && !document_mode) {
trim = 1;
if (verbose)
fprintf (stderr, "%s interpolation...\n",
quick_interpolate ? "Bilinear":"VNG");
vng_interpolate();
}
a5568 2
if (verbose)
fprintf (stderr, "Converting to RGB colorspace...\n");
d5570 1
a5570 6
if (flip) {
if (verbose)
fprintf (stderr, "Flipping image %c:%c:%c...\n",
flip & 1 ? 'H':'0', flip & 2 ? 'V':'0', flip & 4 ? 'T':'0');
flip_image();
}
@
1.268
log
@Added AVT and ISG cameras.
@
text
@d3082 2
a3083 1
fscanf (ifp, "%d", &serial);
d3104 1
a3104 1
fseek (ifp, 280, SEEK_CUR);
d3114 2
a3115 1
FORC4 cam_mul[c ^ (c >> 1)] = sget2 (buf97+6+c*2);
d4061 2
d4176 1
a4176 1
{ 3840000, "Foculus", "503c" ,0 },
d4190 1
a4190 1
{ 5865472, "NIKON", "E4500" ,0 },
d4192 3
a4194 3
{ 1976352, "CASIO", "QV-2000UX" ,0 },
{ 3217760, "CASIO", "QV-3*00EX" ,0 },
{ 6218368, "CASIO", "QV-5700" ,0 },
d4196 2
a4197 2
{ 7684000, "CASIO", "QV-4000" ,0 },
{ 4948608, "CASIO", "EX-S100" ,0 },
d4744 1
a4744 1
} else if (!strcmp(model,"503c")) {
d5020 1
a5020 1
} else if (!strcmp(model,"QV-3*00EX")) {
d5046 2
d5409 1
a5409 1
"\nRaw Photo Decoder \"dcraw\" v7.40"
@
1.267
log
@Added the Casio EX-S100, Pixelink 782c1, and RoverShot 3320af.
@
text
@d4137 19
d4173 7
a4201 2
{ 13248000, "Pixelink", "782c1" ,0 },
{ 6291456, "RoverShot","3320af" ,0 },
d4746 15
a4760 1
} else if (!strcmp(model,"782c1")) {
d4764 1
a4764 1
load_raw = unpacked_load_raw;
d4766 1
a4766 1
} else if (!strcmp(model,"3320af")) {
d4768 1
a4768 2
width = 2048;
order = 0x4949;
d4774 9
d5403 1
a5403 1
"\nRaw Photo Decoder \"dcraw\" v7.39"
@
1.266
log
@Decode the raw formats used by SMaL cameras.
@
text
@d4167 1
d4176 2
d4222 1
a4222 1
if (!strncmp(make,"NIKON",5) && filters == UINT_MAX)
d4722 15
d4991 5
d5357 1
a5357 1
"\nRaw Photo Decoder \"dcraw\" v7.38"
@
1.265
log
@Improved support for Phase One files.
@
text
@d438 2
d1785 141
d3818 1
a3818 1
int i, ver;
a3824 2
else
if (ver >> 1 != 4) return;
d3826 1
a3826 1
if (ver > 6) get4();
a3828 5
if (ver > 6) {
i = get2();
height = get2();
width = get2();
}
d3831 2
d5334 1
a5334 1
"\nRaw Photo Decoder \"dcraw\" v7.36"
@
1.264
log
@Added the Polaroid x530 and Phase One P 25.
@
text
@d1182 1
a1182 1
mask = model[0] == 'P' ? 0x1354:0x5555;
d3584 1
a3584 4
i = get4();
if (i == 0x52617754) load_raw = phase_one_load_raw; /* RawT */
if (i == 0x52617743) load_raw = phase_one_load_raw_c; /* RawC */
if (!load_raw) return;
d3611 1
d3622 2
d5196 1
a5196 1
"\nRaw Photo Decoder \"dcraw\" v7.35"
@
1.263
log
@Added the Foculus 503c.
Don't assume that Nikon D2X/D2Hs files are big-endian.
Added special auto white balance for the PowerShot 600.
Fixed camera white balance for the PowerShot G1 and Pro90.
@
text
@d56 1
d62 1
d1198 49
d1829 1
a1829 1
int row, col, bit=-1, c, i;
d1831 1
d1833 6
a1838 6
for (i=0; i < 1024; i++)
huff[i] = get4();
init_decoder();
foveon_decoder (huff, 0);
d1841 1
a1841 1
if (!bit) get4();
d1843 5
a1847 1
FORC3 {
d1949 1
d1982 1
a1982 1
float cfilt=0.8, ddft[3][3][2], ppm[3][3][3];
d1988 1
a1988 1
int dim[3], dscr[2][2], (*smrow[7])[3], total[4], ipix[3];
a1996 2
foveon_fixed (ddft[1][0], 12, "DarkDrift");
foveon_fixed (&cfilt, 1, "ColumnFilter");
d2004 13
d2166 2
a2167 1
FORC3 fsum[c] += image[(row+hood[j*2])*width+col+hood[j*2+1]][c];
d2209 1
d2212 1
a2212 1
if (maximum > i) maximum = i;
d2214 1
a2214 2
clip_max = maximum;
limit = maximum * 9 >> 4;
d2223 8
a2230 4
i = 0x4000 - ((min - limit) << 14) / limit;
i = 0x4000 - (i*i >> 14);
i = i*i >> 14;
FORC3 pix[c] += (max - pix[c]) * i >> 14;
a3173 1
if (flip == 7) flip = 4; /* Adobe didn't read the TIFF spec. */
d3582 6
a3587 1
fseek (ifp, base+8, SEEK_SET);
d3709 1
a3709 1
int entries, off, len, tag, save, i, pent, poff[256][2];
d3729 1
a3729 2
if (data_offset) break;
data_offset = off + 28;
d3731 7
a3737 2
raw_width = get4();
raw_height = get4();
d4044 1
d4072 2
a4073 2
if ((cp = memmem (head, 32, "MMMMRawT", 8)) ||
(cp = memmem (head, 32, "IIIITwaR", 8)))
a4167 4
/* File format is OK. Do we support this camera? */
/* Start with some useful defaults: */
a4176 1
load_raw = NULL;
d4203 1
a4203 1
if (width < height) xmag = 2;
a4580 3
} else if (!strcmp(make,"Phase One")) {
load_raw = phase_one_load_raw;
maximum = 0xffff;
d5196 1
a5196 1
"\nRaw Photo Decoder \"dcraw\" v7.30"
@
1.262
log
@Added support for the Phase One P 20.
Changed maximums for the Nikon D70 and D100.
@
text
@d84 1
d188 8
a195 4
/*
Get a 2-byte integer, making no assumptions about CPU byte order.
Nor should we assume that the compiler evaluates left-to-right.
*/
d198 4
a201 1
uchar a, b;
d203 6
a208 6
a = fgetc(ifp); b = fgetc(ifp);
if (order == 0x4949) /* "II" means little-endian */
return a | b << 8;
else /* "MM" means big-endian */
return a << 8 | b;
a210 3
/*
Same for a 4-byte integer.
*/
d213 4
a216 1
uchar a, b, c, d;
d218 5
a222 2
a = fgetc(ifp); b = fgetc(ifp);
c = fgetc(ifp); d = fgetc(ifp);
d224 4
a227 4
if (order == 0x4949)
return a | b << 8 | c << 16 | d << 24;
else
return a << 24 | b << 16 | c << 8 | d;
a229 3
/*
Faster than calling get2() multiple times.
*/
d237 117
d358 3
a360 1
int irow, orow, col;
d362 1
a362 1
for (irow=orow=0; irow < height; irow++)
d377 1
a377 1
BAYER(orow,col) = pixel[col];
d380 1
a380 2
if ((orow+=2) > height)
orow = 1;
d382 12
a393 2
black /= (896 - width) * height;
maximum = 0x3ff;
a1806 5
int CLASS sget4 (uchar *s)
{
return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
}
a2775 6
double getrat()
{
double num = get4();
return num / get4();
}
d2897 1
a2897 1
FORC4 cam_mul[c ^ (c >> 1)] = (buf97[c*2+6] << 8) + buf97[c*2+7];
d3316 1
a3316 1
int tboff, nrecs, i, type, len, roff, aoff, save, wbi=-1;
d3355 1
a3355 4
white[0][1] = get2();
white[0][0] = get2();
white[1][0] = get2();
white[1][1] = get2();
d3407 4
a3504 6
float CLASS get_float()
{
int i = get4();
return *((float *) &i);
}
a3719 2
{ "Canon PowerShot 600",
{ -3822,10019,1311,4085,-157,3386,-5341,10829,4812,-1969,10969,1126 } },
d3934 1
d4498 6
d5122 1
a5122 1
"\nRaw Photo Decoder \"dcraw\" v7.24"
@
1.261
log
@Phase One gives me coeff[][] in the metadata. Nice!
@
text
@a768 1
maximum = curve[csize-1];
d1039 1
a1039 1
ushort *pixel, akey, bkey;
d1044 1
d1053 2
a1054 2
pixel[col+0] = (b & 0xaaaa) | (a & 0x5555);
pixel[col+1] = (a & 0xaaaa) | (b & 0x5555);
d3388 1
d3399 2
a3404 2
save = ftell(ifp);
fseek (ifp, base+data, SEEK_SET);
a3409 1
fseek (ifp, save, SEEK_SET);
d3419 5
a3423 1
nikon_curve_offset = ftell(ifp) - 4;
d3425 1
d3428 8
d4117 2
d4122 1
a4122 1
maximum = 0xd2c;
a4379 7
sprintf (model, "%dx%d", width, height);
switch (raw_height) { /* purely cosmetic */
case 2060: strcpy (model,"LightPhase"); break;
case 2682: strcpy (model,"H10"); break;
case 4128: strcpy (model,"H20"); break;
case 5488: strcpy (model,"H25"); break;
}
d4997 1
a4997 1
"\nRaw Photo Decoder \"dcraw\" v7.23"
@
1.260
log
@Added color matrices for the Canon EOS D6000 and NIKON D2X.
Identify SMaL raw files, but still can't decode them.
@
text
@d3379 6
d3387 1
a3387 1
unsigned entries, tag, type, len, data;
d3399 12
d4365 6
a4370 18
switch (raw_height) {
case 2060:
strcpy (model, "LightPhase");
pre_mul[0] = 1.331;
pre_mul[2] = 1.154;
break;
case 2682:
strcpy (model, "H10");
break;
case 4128:
strcpy (model, "H20");
pre_mul[0] = 1.963;
pre_mul[2] = 1.430;
break;
case 5488:
strcpy (model, "H25");
pre_mul[0] = 2.80;
pre_mul[2] = 1.20;
d4703 1
d4989 1
a4989 1
"\nRaw Photo Decoder \"dcraw\" v7.22"
@
1.259
log
@Set "filters" based on rotation for Leaf Valeo backs.
@
text
@d3445 24
d3547 1
a3547 1
{ "Canon EOS D2000C",
d3549 2
d3689 2
d3916 1
a4094 2
pre_mul[0] = 1.514;
pre_mul[2] = 1.727;
d4982 1
a4982 1
"\nRaw Photo Decoder \"dcraw\" v7.21"
@
1.258
log
@Added "-z" option to fix timestamps.
@
text
@a38 1
#include
d51 1
d58 1
d2279 1
a2279 1
pseudoinverse ((void *) cam_rgb, inverse, colors);
d3344 2
d3360 8
d3791 1
a3791 1
zero_after_ff = is_dng = fuji_secondary = filters = 0;
d3794 1
d3821 1
a3821 1
if (!strncmp(make,"NIKON",5) && filters == 0)
d3923 1
d3935 1
a3935 1
if (!filters) filters = 0x94949494;
a4367 2
if (height > width)
filters = 0x16161616;
d4371 1
a4371 2
if (raw_width == 2060) {
filters = 0;
d4955 1
a4955 1
"\nRaw Photo Decoder \"dcraw\" v7.20"
@
1.257
log
@Refactored to reduce the line count.
@
text
@d39 1
d2819 1
a2819 1
void CLASS get_timestamp()
d2823 2
d2826 6
a2831 1
if (fscanf (ifp, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
d2854 1
a2854 1
get_timestamp();
d2936 1
a2936 1
get_timestamp();
d3413 21
d3734 1
a3734 1
int CLASS identify()
d3812 1
a3812 3
} else if (!memcmp (head,"\0MRM",4))
parse_minolta();
else if (!memcmp (head,"\xff\xd8\xff\xe1",4) &&
d3844 2
d3861 2
d3875 1
d4631 3
a4633 2
if (!load_raw || !height) {
fprintf (stderr, "%s: %s %s is not yet supported.\n",
d4932 2
a4933 1
int identify_only=0, write_to_stdout=0, half_size=0, use_fuji_rotate=1;
d4935 1
d4945 1
a4945 1
"\nRaw Photo Decoder \"dcraw\" v7.19"
d4949 3
a4951 1
"\n-i Identify files but don't decode them"
a4952 1
"\n-v Print verbose messages while decoding"
d4993 1
d5048 11
a5058 3
if ((status = identify())) {
fclose(ifp);
continue;
d5060 1
d5070 1
@
1.256
log
@Added colorcheck() function, and used it to create
a color matrix for the MINOLTA DiMAGE Z2.
@
text
@d2227 57
a2284 2
void CLASS dng_coeff (double[4][4], double[4][3], double[3]);
d2290 1
a2290 1
int cut[NSQ][4] = {
d2316 1
a2316 1
float gmb_xyz[NSQ][3] = {
d2341 2
d2344 1
a2344 7
double invert[3][6], num, error, minerr=DBL_MAX;
double gmb_cam[NSQ][4], xyz_gmb[3][NSQ], cam_xyz[4][3];
double cc[4][4], cm[4][3], xyz[] = { 1,1,1 };
for (i=0; i < 4; i++)
for (j=0; j < 4; j++)
cc[i][j] = i == j;
d2357 1
a2357 29
/*
Compute:
xyz_gmb = inverse(transpose(gmb_xyz)*gmb_xyz) * transpose(gmb_xyz)
cam_xyz = transpose(gmb_cam) * transpose(xyz_gmb)
*/
for (i=0; i < 3; i++) {
for (j=0; j < 6; j++)
invert[i][j] = j == i+3;
for (j=0; j < 3; j++)
for (k=0; k < NSQ; k++)
invert[i][j] += gmb_xyz[k][i] * gmb_xyz[k][j];
}
for (i=0; i < 3; i++) {
num = invert[i][i];
for (j=0; j < 6; j++) // Normalize row i
invert[i][j] /= num;
for (k=0; k < 3; k++) { // Subtract it from the other rows
if (k==i) continue;
num = invert[k][i];
for (j=0; j < 6; j++)
invert[k][j] -= invert[i][j] * num;
}
}
memset (xyz_gmb, 0, sizeof xyz_gmb);
for (i=0; i < 3; i++)
for (j=0; j < NSQ; j++)
for (k=0; k < 3; k++)
xyz_gmb[i][j] += invert[i][k+3] * gmb_xyz[j][k];
memset (cam_xyz, 0, sizeof cam_xyz);
d2360 2
a2361 2
for (k=0; k < NSQ; k++)
cam_xyz[i][j] += gmb_cam[k][i] * xyz_gmb[j][k];
d2374 1
a2374 1
memcpy (cm, cam_xyz, sizeof cm);
d2377 1
a2377 1
dng_coeff (cc, cm, xyz);
d2380 1
a2380 1
num = 10000 / (cm[1][0] + cm[1][1] + cm[1][2]);
d2382 1
a2382 1
fprintf (stderr, "%d,", (int) (cm[c][j] * num + 0.5));
a2856 57
void CLASS dng_coeff (double cc[4][4], double cm[4][3], double xyz[3])
{
static const double xyz_rgb[3][3] = { /* XYZ from RGB */
{ 0.412453, 0.357580, 0.180423 },
{ 0.212671, 0.715160, 0.072169 },
{ 0.019334, 0.119193, 0.950227 } };
double cam_xyz[4][3], cam_rgb[4][3], invert[3][6], num;
int i, j, k;
memset (cam_xyz, 0, sizeof cam_xyz);
for (i=0; i < colors; i++)
for (j=0; j < 3; j++)
for (k=0; k < colors; k++)
cam_xyz[i][j] += cc[i][k] * cm[k][j] * xyz[j];
memset (cam_rgb, 0, sizeof cam_rgb); /* Multiply out XYZ colorspace */
for (i=0; i < colors; i++)
for (j=0; j < 3; j++)
for (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;
}
/* Compute coeff = pseudoinverse(cam_rgb), or
coeff = inverse (transpose(cam_rgb) * cam_rgb) * transpose(cam_rgb)
*/
for (i=0; i < 3; i++) {
for (j=0; j < 6; j++)
invert[i][j] = j == i+3;
for (j=0; j < 3; j++)
for (k=0; k < colors; k++)
invert[i][j] += cam_rgb[k][i] * cam_rgb[k][j];
}
for (i=0; i < 3; i++) {
num = invert[i][i];
for (j=0; j < 6; j++) /* Normalize row i */
invert[i][j] /= num;
for (k=0; k < 3; k++) { /* Subtract it from other rows */
if (k==i) continue;
num = invert[k][i];
for (j=0; j < 6; j++)
invert[k][j] -= invert[i][j] * num;
}
}
use_coeff = 1;
memset (coeff, 0, sizeof coeff);
for (i=0; i < 3; i++)
for (j=0; j < colors; j++)
for (k=0; k < 3; k++)
coeff[i][j] += invert[i][k+3] * cam_rgb[j][k];
}
d2866 1
a2866 1
double dblack, cc[4][4], cm[4][3];
d3033 6
a3038 2
if (use_cm)
dng_coeff (cc, cm, xyz);
d3668 1
a3668 1
double cc[4][4], cm[4][3], xyz[] = { 1,1,1 };
a3671 3
for (i=0; i < 4; i++)
for (j=0; j < 4; j++)
cc[i][j] = i == j;
d3676 2
a3677 2
cm[0][j] = table[i].trans[j];
dng_coeff (cc, cm, xyz);
d4910 1
a4910 1
"\nRaw Photo Decoder \"dcraw\" v7.18"
@
1.255
log
@Added "-j" option, check for corrupt CRW files.
@
text
@d2227 139
d3639 2
d4146 1
a4146 3
pre_mul[0] = 508;
pre_mul[1] = 256;
pre_mul[2] = 450;
d4943 1
a4943 1
"\nRaw Photo Decoder \"dcraw\" v7.17"
d5078 3
@
1.254
log
@Added the Nikon E880.
@
text
@d3088 1
d4793 1
a4793 1
int identify_only=0, write_to_stdout=0, half_size=0;
d4804 1
a4804 1
"\nRaw Photo Decoder \"dcraw\" v7.16"
d4825 1
d4860 1
d4950 1
a4950 1
fuji_rotate();
@
1.253
log
@Added the Casio EX-P505.
@
text
@d3938 2
a3939 1
} else if (!strcmp(model,"E990")) {
@
1.252
log
@Support little-endian Phase One images.
@
text
@d3623 1
d4459 7
d4802 1
a4802 1
"\nRaw Photo Decoder \"dcraw\" v7.15"
@
1.251
log
@Added camera white balance for the Nikon D2Hs.
@
text
@d1040 1
a1040 2
fseek (ifp, 8, SEEK_CUR);
fseek (ifp, get4() + 296, SEEK_CUR);
d1043 1
a1043 1
fseek (ifp, data_offset + 12 + top_margin*raw_width*2, SEEK_SET);
d3250 28
d3636 1
d3661 4
a3664 9
if ((cp = memmem (head, 32, "MMMMRawT", 8))) {
strcpy (make, "Phase One");
data_offset = cp - head;
fseek (ifp, data_offset + 8, SEEK_SET);
fseek (ifp, get4() + 136, SEEK_CUR);
raw_width = get4();
fseek (ifp, 12, SEEK_CUR);
raw_height = get4();
} else if (order == 0x4949 || order == 0x4d4d) {
a3756 1
top_margin = left_margin = 0;
d3759 2
a3760 2
height = raw_height;
width = raw_width;
a4168 4
height = 2048;
width = 3080;
top_margin = 5;
left_margin = 22;
a4173 4
height = 2672;
width = 4012;
top_margin = 5;
left_margin = 26;
a4176 4
height = 4098;
width = 4098;
top_margin = 20;
left_margin = 26;
a4181 4
height = 5458;
width = 4098;
top_margin = 20;
left_margin = 26;
a4184 1
filters = top_margin & 1 ? 0x94949494 : 0x49494949;
d4794 1
a4794 1
"\nRaw Photo Decoder \"dcraw\" v7.14"
@
1.250
log
@Added camera white balance for the Nikon D2X.
@
text
@d2597 4
a2600 4
break;
case 0x204:
fseek (ifp, 280, SEEK_CUR);
fread (buf97, 324, 1, ifp);
d2603 1
a2603 1
if (tag == 0xa7 && ver97 == 0x204) {
d4789 1
a4789 1
"\nRaw Photo Decoder \"dcraw\" v7.13"
@
1.249
log
@Added camera WB for the Canon S60 and all Fuji cameras.
@
text
@d2490 33
d2524 2
d2577 2
d2584 17
a2600 9
if (!strcmp(model,"NIKON D100 ")) {
fseek (ifp, 72, SEEK_CUR);
FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
} else if (!strcmp(model,"NIKON D2H")) {
fseek (ifp, 10, SEEK_CUR);
goto get2_rggb;
} else if (!strcmp(model,"NIKON D70")) {
fseek (ifp, 20, SEEK_CUR);
FORC4 cam_mul[c] = get2();
d2603 8
d4789 1
a4789 1
"\nRaw Photo Decoder \"dcraw\" v7.12"
@
1.248
log
@Added support for 22-megapixel Imacon Ixpress.
Moved some flip logic and adjusted the Casio EX-Z50.
@
text
@d120 1
d2490 1
a2490 1
unsigned base=0, offset=0, entries, tag, type, len, save;
d2549 1
a2549 2
camera_red = get2() / 256.0;
camera_blue = get2() / 256.0;
d2555 1
a2555 4
camera_red = get2();
camera_red /= get2();
camera_blue = get2();
camera_blue/= get2();
d2565 2
a2566 6
if (tag == 0x201 && len == 4) {
camera_red = get2();
camera_red /= get2();
camera_blue = get2();
camera_blue = get2() / camera_blue;
}
d2592 1
a2592 4
camera_red = get2();
camera_red /= get2();
camera_blue = get2();
camera_blue = get2() / camera_blue;
d2914 1
a2914 1
int save, tag, len, offset, high=0, wide=0;
d2929 2
a2930 4
camera_red = get2();
camera_red /= get2();
camera_blue = get2();
camera_blue = get2() / camera_blue;
d3028 1
d3077 1
d3198 17
d3518 2
a3519 2
char head[32], *c;
unsigned hlen, fsize, i;
a3551 1
float tmp;
d3580 1
a3580 1
if ((c = memmem (head, 32, "MMMMRawT", 8))) {
d3582 1
a3582 1
data_offset = c - head;
d3632 1
a3632 4
camera_red = get4();
camera_red /= get4();
camera_blue = get4();
camera_blue = get4() / camera_blue;
d3637 2
d3664 4
a3667 4
c = make + strlen(make); /* Remove trailing spaces */
while (*--c == ' ') *c = 0;
c = model + strlen(model);
while (*--c == ' ') *c = 0;
d4009 1
a4009 1
if (!strcmp(model,"DiMAGE A200")) {
a4010 4
tmp = camera_red;
camera_red = 1 / camera_blue;
camera_blue = 1 / tmp;
}
d4044 1
a4044 4
camera_red = get2();
camera_blue = get2();
camera_red /= get2();
camera_blue /= get2();
d4736 1
a4736 1
"\nRaw Photo Decoder \"dcraw\" v7.10"
@
1.247
log
@Added the Logitech Fotoman Pixtura, matrix for Fuji F810.
@
text
@a1059 14
void CLASS ixpress_load_raw()
{
ushort pixel[4090];
int row, col;
order = 0x4949;
fseek (ifp, 304 + 6*2*4090, SEEK_SET);
for (row=height; --row >= 0; ) {
read_shorts (pixel, 4090);
for (col=0; col < width; col++)
BAYER(row,col) = pixel[width-1-col];
}
}
d2898 1
a2898 1
if (make[0] == 0 && raw_width == 680 && raw_height == 680) {
d2900 1
a2900 2
strcpy (model,"Ixpress");
}
d4131 2
a4132 2
} else if (!strcmp(model,"Ixpress")) {
height = 4084;
d4134 12
a4145 2
filters = 0x49494949;
load_raw = ixpress_load_raw;
d4389 2
a4390 2
height = 1932;
width = 2602;
d4393 2
a4394 2
pre_mul[0] = 1.969;
pre_mul[2] = 1.570;
a4580 5
switch ((flip+3600) % 360) {
case 270: flip = 5; break;
case 180: flip = 3; break;
case 90: flip = 6;
}
d4738 1
a4738 1
"\nRaw Photo Decoder \"dcraw\" v7.09"
d4841 7
a4888 2
if (user_flip >= 0)
flip = user_flip;
@
1.246
log
@Added the Fuji F710 and F800.
@
text
@d1257 2
a1258 2
if (model[2] == '4')
return (getbits(5) << 3) + 4; /* DC40 */
d1260 1
a1260 1
return (getbits(6) << 2) + 2; /* DC50 */
d3361 2
d3645 3
d4336 6
d4748 1
a4748 1
"\nRaw Photo Decoder \"dcraw\" v7.08"
@
1.245
log
@Added the Nikon E900 and Casio EX-Z50.
Rewrote dng_coeff() to show saturated pixels as pure white.
@
text
@d3361 1
a3361 1
{ "FUJIFILM FinePix F700",
d3981 1
a3981 1
!strcmp(model,"FinePix F810") ||
d3989 1
a3989 1
} else if (!strcmp(model,"FinePix F700") ||
@
1.244
log
@Fixed the maximum for the FinePix S3Pro.
@
text
@d779 1
a779 1
if (row == 1 && atoi(model+1) < 5000) {
d882 17
a925 15
void CLASS nikon_e950_load_raw()
{
int irow, row, col;
getbits(-1);
for (irow=0; irow < height; irow++) {
row = irow * 2 % height;
for (col=0; col < width; col++)
BAYER(row,col) = getbits(10);
for (col=28; col--; )
getbits(8);
}
maximum = 0x3dd;
}
d1090 1
a1090 3
/*
For this function only, raw_width is in bytes, not pixels!
*/
a2668 5
static const double rgb_xyz[3][3] = { /* RGB from XYZ */
{ 3.240479, -1.537150, -0.498535 },
{ -0.969256, 1.875992, 0.041556 },
{ 0.055648, -0.204043, 1.057311 } };
#if 0
d2673 1
a2673 2
#endif
double cam_xyz[4][3], xyz_cam[3][4], invert[3][6], num;
d2682 2
a2683 3
for (i=0; i < colors; i++) {
for (num=j=0; j < 3; j++)
num += cam_xyz[i][j];
d2685 8
a2692 1
cam_xyz[i][j] /= num;
d2695 3
d2703 1
a2703 1
invert[i][j] += cam_xyz[k][i] * cam_xyz[k][j];
d2716 1
a2716 6
memset (xyz_cam, 0, sizeof xyz_cam);
for (i=0; i < 3; i++)
for (j=0; j < colors; j++)
for (k=0; k < 3; k++)
xyz_cam[i][j] += invert[i][k+3] * cam_xyz[j][k];
d2721 1
a2721 8
coeff[i][j] += rgb_xyz[i][k] * xyz_cam[k][j];
for (num=j=0; j < colors; j++)
num += coeff[1][j];
for (i=0; i < 3; i++)
for (j=0; j < colors; j++)
coeff[i][j] /= num;
use_coeff = 1;
d3534 1
d3541 1
d3547 1
d3835 1
d3843 12
d3858 3
a3863 1
load_raw = nikon_e950_load_raw;
a3885 1
width = 1616;
d3887 1
a3893 1
width = 1616;
d3895 1
d3940 5
d4313 1
a4313 1
width = 768;
d4319 1
a4319 1
width = 768;
d4325 1
a4325 1
width = 848;
d4382 7
d4737 1
a4737 1
"\nRaw Photo Decoder \"dcraw\" v7.06"
@
1.243
log
@Added color matrix for the PowerShot S60.
@
text
@d3950 1
a3950 1
maximum = 0xffff;
@
1.242
log
@Fixed Kodak DC25 color and condensed three functions into simple_coeff().
@
text
@d2727 1
a2727 1
for (i=0; i < 3; i++) {
a2729 1
}
d3360 2
d4716 1
a4716 1
"\nRaw Photo Decoder \"dcraw\" v7.05"
@
1.241
log
@Added the Canon EOS 350D with more general CR2 support.
@
text
@d27 1
a1414 18
void CLASS kodak_dc20_coeff (float juice)
{
static const float my_coeff[3][4] =
{ { 2.25, 0.75, -1.75, -0.25 },
{ -0.25, 0.75, 0.75, -0.25 },
{ -0.25, -1.75, 0.75, 2.25 } };
static const float flat[3][4] =
{ { 1, 0, 0, 0 },
{ 0, 0.5, 0.5, 0 },
{ 0, 0, 0, 1 } };
int r, g;
for (r=0; r < 3; r++)
for (g=0; g < 4; g++)
coeff[r][g] = my_coeff[r][g] * juice + flat[r][g] * (1-juice);
use_coeff = 1;
}
a3301 28
void CLASS foveon_coeff()
{
static const float foveon[3][3] =
{ { 1.4032, -0.2231, -0.1016 },
{ -0.5263, 1.4816, 0.0170 },
{ -0.0112, 0.0183, 0.9113 } };
int i, j;
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
coeff[i][j] = foveon[i][j];
use_coeff = 1;
}
void CLASS nikon_e950_coeff()
{
int r, g;
static const float my_coeff[3][4] =
{ { -1.936280, 1.800443, -1.448486, 2.584324 },
{ 1.405365, -0.524955, -0.289090, 0.408680 },
{ -1.204965, 1.082304, 2.941367, -1.818705 } };
for (r=0; r < 3; r++)
for (g=0; g < 4; g++)
coeff[r][g] = my_coeff[r][g];
use_coeff = 1;
}
d3507 19
d3730 1
a3730 1
foveon_coeff();
d3850 1
d3852 1
a3852 1
colors = 4;
a3853 1
nikon_e950_coeff();
d3863 1
a3863 1
nikon_e950_coeff();
d4276 5
a4280 1
if (!strcmp(model,"DC20")) {
d4283 1
a4283 2
width = 249;
raw_width = 256;
d4285 1
a4285 2
width = 501;
raw_width = 512;
d4287 1
a4287 1
data_offset = raw_width + 1;
d4290 1
a4290 1
kodak_dc20_coeff (1.0);
a4294 15
} else if (strstr(model,"DC25")) {
strcpy (model, "DC25");
height = 242;
if (fsize < 100000) {
width = 249;
raw_width = 256;
data_offset = 15681;
} else {
width = 501;
raw_width = 512;
data_offset = 15937;
}
colors = 4;
filters = 0xb4b4b4b4;
load_raw = kodak_easy_load_raw;
d4715 1
a4715 1
"\nRaw Photo Decoder \"dcraw\" v7.04"
@
1.240
log
@Support "-w" for Canon CR2 and Contax N Digital images.
New cam_mul[] array will support 4-color cameras in the future.
@
text
@d2592 5
d2784 2
a2785 1
raw_width = type==3 ? get2() : get4();
d2788 2
a2789 1
raw_height = type==3 ? get2() : get4();
a2938 3
if (!strcmp(make,"Canon") && strcmp(model,"EOS D2000C"))
raw_width = raw_height = 0;
d3742 3
a3744 7
if ((is_canon = !strcmp(make,"Canon"))) {
if (memcmp (head+6,"HEAPCCDR",8)) {
filters = 0x61616161;
load_raw = lossless_jpeg_load_raw;
} else if (raw_width)
load_raw = canon_compressed_load_raw;
}
d3829 3
d3833 2
a3834 2
height = 1662;
width = 2496;
d3836 1
d3838 2
a3839 2
height = 2718;
width = 4082;
d3841 6
a3846 4
} else if (!strcmp(model,"EOS-1D Mark II") ||
!strcmp(model,"EOS 20D")) {
raw_height = 2360;
raw_width = 3596;
d3850 1
a3850 3
} else if (!strcmp(model,"EOS-1Ds Mark II")) {
raw_height = 3349;
raw_width = 5108;
a3853 6
goto canon_cr2;
} else if (!strcmp(model,"EOS DIGITAL REBEL XT")) {
raw_height = 2328;
raw_width = 3516;
top_margin = 14;
left_margin = 42;
a3856 3
filters = 0x94949494;
} else if (!strcmp(model,"EOS D2000C")) {
black = curve[200];
d4754 1
a4754 1
"\nRaw Photo Decoder \"dcraw\" v7.03"
@
1.239
log
@Fixed array bounds error in foveon_interpolate().
Don't use snprintf(), but keep strings safe anyway.
@
text
@d98 3
a100 2
float camera_red, camera_blue;
float pre_mul[4], coeff[3][4];
d2296 3
a2298 5
else if (camera_red && camera_blue) {
pre_mul[0] = camera_red;
pre_mul[2] = camera_blue;
pre_mul[1] = pre_mul[3] = 1.0;
} else
d2583 1
a2583 4
camera_red = get2();
camera_red /= get2();
camera_blue = get2();
camera_blue = get2() / camera_blue;
d2622 8
d3592 1
a3592 1
camera_red = camera_blue = timestamp = tiff_samples = 0;
a3595 1
pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = 1;
d3597 4
d3665 5
d4759 1
a4759 1
"\nRaw Photo Decoder \"dcraw\" v7.02"
@
1.238
log
@Added the Canon EOS DIGITAL REBEL XT.
@
text
@d11 1
d13 2
a14 2
All the code currently under GPL is specific to Foveon cameras.
This began in Revision 1.237.
d1858 1
a1858 1
snprintf (str, 128, "%sRGBNeutral", model2);
d1908 1
a1908 1
memcpy (black+1520, black+1509, sizeof *black*11);
a2850 1
strcat (model," DNG");
d3528 1
a3528 1
char name[96];
d3534 1
a3534 1
snprintf (name, 96, "%s %s", make, model);
d3691 1
d3713 1
d3741 1
d4747 1
a4747 1
"\nRaw Photo Decoder \"dcraw\" v7.01"
@
1.237
log
@Dcraw 7.00 is a major rewrite:
* It decodes all Adobe DNG files, and applies the same color matrices
to non-DNG files. Color science replaces black magic.
* It correctly decodes all Foveon images based on encrypted metadata.
* It decodes the Casio QV-R51, Casio EX-Z55, Minolta Alpha-7, Nikon D2X,
and ST Micro STV680.
@
text
@d630 7
d3828 1
a3828 3
height = raw_height - top_margin;
width = raw_width - left_margin;
filters = 0x94949494;
d3834 8
a3844 1
maximum = 0xe80;
d4744 1
a4744 1
"\nRaw Photo Decoder \"dcraw\" v7.00"
@
1.236
log
@Fixed divide by zero error.
@
text
@d5 2
a6 5
This is a portable ANSI C program to convert raw image files from
any digital camera into PPM format. TIFF and CIFF parsing are
based upon public specifications, but no such documentation is
available for the raw sensor data, so writing this program has
been an immense effort.
d8 12
a19 2
This code is freely licensed for all uses, commercial and
otherwise. Comments, questions, and encouragement are welcome.
d45 3
d79 1
a79 1
char *ifname, make[64], model[64], model2[64];
d81 1
a81 1
int data_offset, curve_offset, curve_length;
d84 2
a85 1
int height, width, fuji_width, colors, black, rgb_max;
d87 1
a87 1
int is_canon, is_cmy, is_foveon, use_coeff, use_gamma;
d91 1
a91 1
ushort (*image)[4], white[8][8];
d95 2
a96 1
int verbose=0, use_auto_wb=0, use_camera_wb=0, use_secondary=0;
d99 1
a99 1
int histogram[0x2000];
d116 3
d133 2
a134 9
PowerShot 600 uses 0xe1e4e1e4:
0 1 2 3 4 5
0 G M G M G M
1 C Y C Y C Y
2 M G M G M G
3 C Y C Y C Y
PowerShot A5 uses 0x1e4e1e4e:
d136 9
a150 30
PowerShot A50 uses 0x1b4e4b1e:
0 1 2 3 4 5
0 C Y C Y C Y
1 M G M G M G
2 Y C Y C Y C
3 G M G M G M
4 C Y C Y C Y
5 G M G M G M
6 Y C Y C Y C
7 M G M G M G
PowerShot Pro70 uses 0x1e4b4e1b:
0 1 2 3 4 5
0 Y C Y C Y C
1 M G M G M G
2 C Y C Y C Y
3 G M G M G M
4 Y C Y C Y C
5 G M G M G M
6 C Y C Y C Y
7 M G M G M G
PowerShots Pro90 and G1 use 0xb4b4b4b4:
0 1 2 3 4 5
0 G M G M G M
1 Y C Y C Y C
a159 1
d185 1
a185 1
ushort CLASS fget2 (FILE *f)
d189 1
a189 1
a = fgetc(f); b = fgetc(f);
d200 1
a200 1
int CLASS fget4 (FILE *f)
d204 2
a205 1
a = fgetc(f); b = fgetc(f); c = fgetc(f); d = fgetc(f);
d214 1
a214 1
Faster than calling fget2() multiple times.
d244 1
a244 1
BAYER(orow,col) = pixel[col] << 4;
d250 2
a251 1
black = ((INT64) black << 4) / ((896 - width) * height);
d274 1
a274 1
BAYER(row,col) = (pixel[col] & 0x3ff) << 4;
d279 2
a280 1
black = ((INT64) black << 4) / ((raw_width - width) * height);
d462 1
a462 1
int lowbits, shift, i, row, r, col, save, val;
a466 1
INT64 bblack=0;
d471 1
a471 1
shift = 4 - lowbits*2;
d503 1
a503 1
save = ftell(ifp); /* Don't lose our place */
d521 1
a521 1
BAYER(irow,icol) = pixel[r*raw_width+col] << shift;
d523 1
a523 1
bblack += pixel[r*raw_width+col];
d529 1
a529 33
black = (bblack << shift) / ((raw_width - width) * height);
}
void CLASS kodak_curve (ushort *curve)
{
int i, entries, tag, type, len, val;
for (i=0; i < 0x1000; i++)
curve[i] = i;
if (strcasecmp(make,"KODAK")) return;
if (!curve_offset) {
fseek (ifp, 12, SEEK_SET);
entries = fget2(ifp);
while (entries--) {
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
val = fget4(ifp);
if (tag == 0x90d) {
curve_offset = val;
curve_length = len;
}
}
}
if (curve_offset) {
fseek (ifp, curve_offset, SEEK_SET);
for (i=0; i < curve_length && i < 0x1000; i++)
curve[i] = fget2(ifp);
for ( ; i < 0x1000; i++)
curve[i] = curve[i-1];
rgb_max = curve[i-1] << 2;
}
fseek (ifp, data_offset, SEEK_SET);
d533 2
a534 2
Not a full implementation of Lossless JPEG,
just enough to decode Canon and Kodak images.
d536 7
a542 1
void CLASS lossless_jpeg_load_raw()
d544 1
a544 1
int tag, len, jhigh=0, jwide=0, jrow, jcol, jidx, diff, i, row, col;
a545 5
int vpred[2] = { 0x800, 0x800 }, hpred[2];
struct decode *dstart[2], *dindex;
ushort curve[0x1000];
INT64 bblack=0;
int min=INT_MAX;
d547 5
a551 3
kodak_curve (curve);
order = 0x4d4d;
if (fget2(ifp) != 0xffd8) return;
d553 4
a556 3
tag = fget2(ifp);
len = fget2(ifp) - 2;
if (tag <= 0xff00 || len > 255) return;
d560 4
a563 2
jhigh = (data[1] << 8) + data[2];
jwide =((data[3] << 8) + data[4])*2;
d566 2
a567 4
init_decoder();
dstart[0] = dstart[1] = free_decode;
for (dp = data; dp < data+len && *dp < 2; ) {
dstart[*dp] = free_decode;
d572 4
a575 1
d578 41
a618 17
for (jrow=0; jrow < jhigh; jrow++)
for (jcol=0; jcol < jwide; jcol++)
{
for (dindex = dstart[jcol & 1]; dindex->branch[0]; )
dindex = dindex->branch[getbits(1)];
len = dindex->leaf;
diff = getbits(len);
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
if (jcol < 2) {
vpred[jcol] += diff;
hpred[jcol] = vpred[jcol];
} else
hpred[jcol & 1] += diff;
diff = hpred[jcol & 1];
if (diff < 0) diff = 0;
if (diff > 0xfff) diff = 0xfff;
d621 1
a621 1
i = jidx / (1680*jhigh);
d623 1
a623 1
row = jidx / 1680 % jhigh;
d626 1
a626 1
jidx -= 2*1680*jhigh;
d634 1
a634 2
if ((unsigned) (row-top_margin) >= height)
continue;
d636 2
a637 3
BAYER(row-top_margin,col-left_margin) = curve[diff] << 2;
if (min > curve[diff])
min = curve[diff];
d639 1
a639 1
bblack += curve[diff];
d641 2
d644 1
a644 1
black = (bblack << 2) / ((raw_width - width) * height);
d646 71
a716 1
black = min << 2;
d725 2
a726 3
int vpred[4], hpred[2], csize, row, col, i, len, diff;
ushort *curve;
struct decode *dindex;
d731 3
a733 4
fseek (ifp, curve_offset, SEEK_SET);
for (i=0; i < 4; i++)
vpred[i] = fget2(ifp);
csize = fget2(ifp);
d736 1
a736 2
for (i=0; i < csize; i++)
curve[i] = fget2(ifp);
d744 1
a744 6
for (dindex=first_decode; dindex->branch[0]; )
dindex = dindex->branch[getbits(1)];
len = dindex->leaf;
diff = getbits(len);
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
a752 1
if (diff < 0) diff = 0;
d754 1
a754 1
BAYER(row,col-left_margin) = curve[diff] << 2;
d756 1
d778 1
a778 1
BAYER(row,col-left_margin) = i << 2;
d895 1
a895 1
BAYER(row,col) = (pixel[col] & 0xfff) << 2;
d907 1
a907 1
BAYER(row,col) = getbits(10) << 4;
d911 1
d928 1
a928 1
BAYER(r,c) = pixel[col] << 2;
d944 1
a944 1
BAYER(r,c) = pixel[col] << 2;
d959 1
a959 1
BAYER(r,c) = pixel[col] << 2;
d1016 1
a1016 1
BAYER(row,col) = (todo[i+1] & 0x3ff) << 4;
d1019 1
d1028 3
a1030 3
fseek (ifp, fget4(ifp) + 296, SEEK_CUR);
akey = fget2(ifp);
bkey = fget2(ifp);
d1070 5
a1074 6
for (c=0; c < 3; c++)
for (row=r; row < r+32; row++) {
read_shorts (pixel, raw_width);
for (col=0; col < width; col++)
image[row*width+col][c] = pixel[col];
}
d1078 3
a1080 1
/* For this function only, raw_width is in bytes, not pixels! */
d1088 1
a1088 1
BAYER(row,col) = getbits(12) << 2;
d1094 1
a1094 1
void CLASS unpacked_load_raw (int rsh)
d1104 1
a1104 1
BAYER(row,col) = pixel[col] << 8 >> (8+rsh);
a1108 20
void CLASS all_16_load_raw()
{
unpacked_load_raw (0);
}
void CLASS high_12_load_raw()
{
unpacked_load_raw (2);
}
void CLASS low_12_load_raw()
{
unpacked_load_raw (-2);
}
void CLASS low_10_load_raw()
{
unpacked_load_raw (-4);
}
d1127 1
a1127 1
BAYER(row,col) = (pixel[col] & 0xfff) << 2;
d1143 1
a1143 1
BAYER(row,col) = getbits(12) << 2;
d1157 1
a1157 1
BAYER(row,col) = pixel[col] << 6;
d1160 1
d1178 1
a1178 1
BAYER(row,col) = (pixel[col] & 0x3ff) << 4;
d1180 1
d1194 1
a1194 1
BAYER(row,col) = pixel[col] << 2;
d1274 1
a1274 1
for (c=0; c < 3; c++) {
d1324 1
d1376 4
a1379 4
BAYER(row+0,col+0) = pixel[col+0][1] << 6;
BAYER(row+1,col+1) = pixel[col+1][1] << 6;
BAYER(row+0,col+1) = (pixel[col][0] + pixel[col+1][0]) << 5;
BAYER(row+1,col+0) = (pixel[col][2] + pixel[col+1][2]) << 5;
d1384 1
d1396 1
a1396 2
for (row=0; row < height; row++)
{
d1400 1
a1400 1
BAYER(row,col) = (ushort) pixel[(col + shift) % 848] << 6;
d1402 1
a1425 1
ushort curve[0x1000];
a1427 1
kodak_curve (curve);
d1437 1
a1437 1
BAYER(row,icol) = (ushort) curve[pixel[col]] << 2;
d1442 1
d1444 1
a1444 1
black = ((INT64) black << 2) / ((raw_width - width) * height);
d1447 1
a1447 1
free (pixel);
d1453 1
a1453 1
ushort raw[6], curve[0x1000];
a1457 1
kodak_curve (curve);
d1507 1
a1507 1
BAYER(row,col) = curve[diff] << 2;
d1517 1
a1517 1
ushort *ip, curve[0x1000];
a1518 1
kodak_curve (curve);
d1561 1
a1561 2
for (c=0; c < 3; c++)
if (rgb[c] > 0) ip[c] = curve[rgb[c]] << 2;
d1564 1
a1588 1
INT64 bblack=0;
d1593 1
a1593 1
key = fget4(ifp);
d1606 1
a1606 1
bblack += ntohs(pixel[col]);
d1611 3
a1613 2
if (bblack)
black = bblack / ((left_margin-9) * height);
d1616 1
a1616 13
void CLASS sony_rgbe_coeff()
{
int r, g;
static const float my_coeff[3][4] =
{ { 1.321918, -0.471747, 0.149829, 0.000000 },
{ -0.288764, 0.646067, -0.486517, 1.129213 },
{ 0.061336, 0.000000, 1.138007, -0.199343 } };
for (r=0; r < 3; r++)
for (g=0; g < 4; g++)
coeff[r][g] = my_coeff[r][g];
use_coeff = 1;
}
d1628 1
a1628 1
if (code) {
a1633 1
}
d1643 14
d1664 1
a1664 3
fseek (ifp, 260, SEEK_SET);
for (i=0; i < 1024; i++)
diff[i] = fget2(ifp);
d1666 1
a1666 1
huff[i] = fget4(ifp);
d1671 1
a1671 1
for (row=0; row < raw_height; row++) {
d1673 3
a1675 3
if (!bit) fget4(ifp);
for (col=bit=0; col < raw_width; col++) {
for (c=0; c < 3; c++) {
d1684 29
a1712 5
if ((unsigned) (row-top_margin) >= height ||
(unsigned) (col-left_margin) >= width ) continue;
for (c=0; c < 3; c++)
if (pred[c] > 0)
image[(row-top_margin)*width+(col-left_margin)][c] = pred[c];
d1715 59
d1776 1
a1776 1
int CLASS apply_curve (int i, const int *curve)
d1778 30
a1807 8
if (i <= -curve[0])
return -curve[curve[0]]-1;
else if (i < 0)
return -curve[1-i];
else if (i < curve[0])
return curve[1+i];
else
return curve[curve[0]]+1;
d1812 123
a1934 42
float mul[3] =
{ 1.0321, 1.0, 1.1124 };
static const int weight[3][3][3] =
{ { { 4141, 37726, 11265 },
{ -30437, 16066, -41102 },
{ 326, -413, 362 } },
{ { 1770, -1316, 3480 },
{ -2139, 213, -4998 },
{ -2381, 3496, -2008 } },
{ { -3838, -24025, -12968 },
{ 20144, -12195, 30272 },
{ -631, -2025, 822 } } },
curve1[73] = { 72,
0,1,2,2,3,4,5,6,6,7,8,9,9,10,11,11,12,13,13,14,14,
15,16,16,17,17,18,18,18,19,19,20,20,20,21,21,21,22,
22,22,23,23,23,23,23,24,24,24,24,24,25,25,25,25,25,
25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26 },
curve2[21] = { 20,
0,1,1,2,3,3,4,4,5,5,6,6,6,7,7,7,7,7,7,7 },
curve3[73] = { 72,
0,1,1,2,2,3,4,4,5,5,6,6,7,7,8,8,8,9,9,10,10,10,10,
11,11,11,12,12,12,12,12,12,13,13,13,13,13,13,13,13,
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 },
curve4[37] = { 36,
0,1,1,2,3,3,4,4,5,6,6,7,7,7,8,8,9,9,9,10,10,10,
11,11,11,11,11,12,12,12,12,12,12,12,12,12 },
curve5[111] = { 110,
0,1,1,2,3,3,4,5,6,6,7,7,8,9,9,10,11,11,12,12,13,13,
14,14,15,15,16,16,17,17,18,18,18,19,19,19,20,20,20,
21,21,21,21,22,22,22,22,22,23,23,23,23,23,24,24,24,24,
24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,26,26,
26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,
26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26 },
*curves[3] = { curve3, curve4, curve5 },
trans[3][3] =
{ { 7576, -2933, 1279 },
{ -11594, 29911, -12394 },
{ 4000, -18850, 20772 } };
ushort *pix, prev[3], (*shrink)[3];
int row, col, c, i, j, diff, sum, ipix[3], work[3][3], total[4];
int (*smrow[7])[3], smlast, smred, smred_p=0, hood[7], min, max;
a1935 1
/* Sharpen all colors */
d1937 3
d1942 6
d1949 1
a1949 1
for (c=0; c < 3; c++) {
d1952 7
a1958 5
ipix[c] = pix[c] + ((diff + (diff*diff >> 14)) * 0x3333 >> 14);
}
for (c=0; c < 3; c++) {
work[0][c] = ipix[c]*ipix[c] >> 14;
work[2][c] = ipix[c]*work[0][c] >> 14;
d1961 2
a1962 2
for (c=0; c < 3; c++) {
for (sum=i=0; i < 3; i++)
d1964 4
a1967 3
sum += weight[c][i][j] * work[i][j];
ipix[c] = (ipix[c] + (sum >> 14)) * mul[c];
if (ipix[c] < 0) ipix[c] = 0;
d1974 21
d2015 3
a2017 2
smred = (smrow[2][col][0]*6 + (smrow[1][col][0]+smrow[3][col][0])*4
+ smrow[0][col][0]+smrow[4][col][0] + 8) >> 4;
d2020 2
a2021 3
i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 2);
if (i < 0) i = 0;
if (i > 10000) i = 10000;
d2027 20
a2046 23
/* Limit each color value to the range of its neighbors */
hood[0] = 4;
for (i=0; i < 3; i++) {
hood[i+1] = (i-width-1)*4;
hood[i+4] = (i+width-1)*4;
}
for (row=1; row < height-1; row++) {
pix = image[row*width+1];
memcpy (prev, pix-4, sizeof prev);
for (col=1; col < width-1; col++) {
for (c=0; c < 3; c++) {
for (min=max=prev[c], i=0; i < 7; i++) {
j = pix[hood[i]];
if (min > j) min = j;
if (max < j) max = j;
}
prev[c] = *pix;
if (*pix < min) *pix = min;
if (*pix > max) *pix = max;
pix++;
}
pix++;
}
d2059 21
a2079 2
for (c=0; c < 3; c++)
smrow[4][col][c] = pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8];
d2085 1
a2085 1
for (total[3]=1500, sum=60, c=0; c < 3; c++) {
d2091 4
a2094 12
j = (sum << 16) / total[3];
for (c=0; c < 3; c++) {
i = apply_curve ((total[c] * j >> 16) - pix[c], curve1);
i += pix[c] - 13 - (c==1);
ipix[c] = i - apply_curve (i, curve2);
}
sum = (ipix[0]+ipix[1]+ipix[1]+ipix[2]) >> 2;
for (c=0; c < 3; c++) {
i = ipix[c] - apply_curve (ipix[c] - sum, curve2);
if (i < 0) i = 0;
pix[c] = i;
}
d2098 12
a2109 9
/* Translate the image to a different colorspace */
for (pix=image[0]; pix < image[height*width]; pix+=4) {
for (c=0; c < 3; c++) {
for (i=j=0; j < 3; j++)
i += trans[c][j] * pix[j];
i = (i+0x1000) >> 13;
if (i < 0) i = 0;
if (i > 24000) i = 24000;
ipix[c] = i;
d2111 1
a2111 2
for (c=0; c < 3; c++)
pix[c] = ipix[c];
d2113 1
d2122 2
a2123 3
for (c=0; c < 3; c++)
ipix[c] += image[(row*4+i)*width+col*4+j][c];
for (c=0; c < 3; c++)
d2128 1
a2128 1
(shrink[(row+1)*(width/4)+col][c]*1840 + ipix[c]*141) >> 12;
a2129 1
d2135 2
a2136 3
for (c=0; c < 3; c++)
smrow[0][col][c] = ipix[c] =
(shrink[(row/4)*(width/4)+col/4][c]*1485 + ipix[c]*6707) >> 13;
d2141 2
a2142 3
for (c=0; c < 3; c++)
smrow[1][col][c] = ipix[c] =
(smrow[0][col][c]*1485 + ipix[c]*6707) >> 13;
d2149 2
a2150 3
for (c=0; c < 3; c++)
smrow[2][col][c] =
(smrow[2][col][c]*6707 + smrow[1][col][c]*1485) >> 13;
d2154 1
a2154 1
for (i=j=60, c=0; c < 3; c++) {
d2160 2
a2161 2
i = (smrow[2][col][c] * j >> 16) - image[row*width+col][c];
ipix[c] = apply_curve (i, curves[c]);
d2165 1
a2165 1
for (c=0; c < 3; c++) {
d2174 12
d2188 2
d2251 1
a2251 1
int row, col, c, val;
d2253 1
a2253 1
double sum[4], dmin, dmax;
d2255 1
a2255 1
rgb_max -= black;
d2257 2
a2258 4
for (c=0; c < 4; c++) {
min[c] = INT_MAX;
max[c] = count[c] = sum[c] = 0;
}
d2261 1
a2261 1
for (c=0; c < colors; c++) {
d2267 1
a2267 1
if (val > rgb_max-100) continue;
d2272 1
a2272 6
for (dmax=c=0; c < colors; c++) {
sum[c] /= count[c];
if (dmax < sum[c]) dmax = sum[c];
}
for (c=0; c < colors; c++)
pre_mul[c] = dmax / sum[c];
d2275 1
a2275 2
for (c=0; c < 4; c++)
count[c] = sum[c] = 0;
d2283 4
a2286 8
for (dmin=DBL_MAX, dmax=c=0; c < colors; c++) {
sum[c] /= count[c];
if (dmin > sum[c]) dmin = sum[c];
if (dmax < sum[c]) dmax = sum[c];
}
if (dmin > 0)
for (c=0; c < colors; c++)
pre_mul[c] = dmax / sum[c];
d2298 15
d2315 1
a2315 2
for (c=0; c < colors; c++)
fprintf (stderr, " %f", pre_mul[c]);
d2318 1
d2321 1
a2321 1
for (c=0; c < colors; c++) {
d2327 1
a2327 1
if (val > rgb_max) val = rgb_max;
d2387 1
a2387 1
for (c=0; c < colors; c++)
d2477 1
a2477 1
for (c=0; c < colors; c++)
d2485 1
a2485 1
for (c=0; c < colors; c++) { /* Save to buffer */
d2490 1
a2490 1
if (t > rgb_max) t = rgb_max;
d2505 1
a2505 1
void CLASS tiff_parse_subifd (int base)
d2507 2
a2508 47
int entries, tag, type, len, val, save;
entries = fget2(ifp);
while (entries--) {
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
if (type == 3 && len < 3) {
val = fget2(ifp); fget2(ifp);
} else
val = fget4(ifp);
switch (tag) {
case 0x100: /* ImageWidth */
raw_width = val;
break;
case 0x101: /* ImageHeight */
raw_height = val;
break;
case 0x102: /* Bits per sample */
break;
case 0x103: /* Compression */
tiff_data_compression = val;
break;
case 0x106: /* Kodak color format */
kodak_data_compression = val;
break;
case 0x111: /* StripOffset */
if (len == 1)
data_offset = val;
else {
save = ftell(ifp);
fseek (ifp, base+val, SEEK_SET);
data_offset = fget4(ifp);
fseek (ifp, save, SEEK_SET);
}
break;
case 0x115: /* SamplesPerRow */
break;
case 0x116: /* RowsPerStrip */
break;
case 0x117: /* StripByteCounts */
break;
case 0x123:
curve_offset = val;
curve_length = len;
}
}
d2513 2
a2514 1
int base=0, offset=0, entries, tag, type, len, val, save;
a2516 1
d2523 3
a2525 1
if (!strcmp (buf,"Nikon")) { /* starts with "Nikon\0\2\0\0\0" ? */
d2527 3
a2529 3
order = fget2(ifp); /* might differ from file-wide byteorder */
val = fget2(ifp); /* should be 42 decimal */
offset = fget4(ifp);
d2531 2
a2532 1
} else if (!strncmp (buf,"FUJIFILM",8)) {
d2535 3
a2537 1
} else if (!strcmp (buf,"OLYMP"))
d2539 2
a2540 1
else if (!strcmp (buf,"AOC"))
d2542 1
a2542 2
else
fseek (ifp, -10, SEEK_CUR);
d2544 1
a2544 1
entries = fget2(ifp);
d2546 3
a2548 7
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
if (type == 3 && len < 3) {
val = fget2(ifp); fget2(ifp);
} else
val = fget4(ifp);
d2550 3
d2554 10
a2563 5
fseek (ifp, base+val, SEEK_SET);
camera_red = fget4(ifp);
camera_red /= fget4(ifp);
camera_blue = fget4(ifp);
camera_blue/= fget4(ifp);
d2566 1
a2566 1
curve_offset = base+val + 2112;
d2568 1
a2568 1
curve_offset = base+val + 2;
d2571 3
a2573 3
fseek (ifp, base+val + 72, SEEK_SET);
camera_red = fget2(ifp) / 256.0;
camera_blue = fget2(ifp) / 256.0;
d2575 5
a2579 5
fseek (ifp, base+val + 10, SEEK_SET);
camera_red = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue = fget2(ifp);
camera_blue = fget2(ifp) / camera_blue;
d2581 26
a2606 13
fseek (ifp, base+val + 20, SEEK_SET);
camera_red = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue = fget2(ifp);
camera_blue/= fget2(ifp);
}
}
if (tag == 0x201 && len == 4) { /* Pentax */
fseek (ifp, base+val, SEEK_SET);
camera_red = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue = fget2(ifp);
camera_blue = fget2(ifp) / camera_blue;
d2608 2
a2609 2
if (tag == 0x1017) /* Olympus */
camera_red = val / 256.0;
d2611 8
a2618 2
camera_blue = val / 256.0;
fseek (ifp, save, SEEK_SET);
d2620 1
d2647 1
a2647 1
entries = fget2(ifp);
d2649 4
a2652 4
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
val = fget4(ifp);
d2667 68
a2734 4
/*
Parse a TIFF file looking for camera model and decompress offsets.
*/
void CLASS parse_tiff (int base)
d2736 3
a2738 1
int doff, entries, tag, type, len, val, save;
a2739 1
int wide=0, high=0, offset=0, i;
d2741 176
a2916 1
static const char *corp[] = { "OLYMPUS", "PENTAX", "SONY" };
d2918 2
a2919 95
fseek (ifp, base, SEEK_SET);
order = fget2(ifp);
val = fget2(ifp); /* Should be 42 for standard TIFF */
while ((doff = fget4(ifp))) {
fseek (ifp, doff+base, SEEK_SET);
entries = fget2(ifp);
while (entries--) {
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
if (type == 3 && len < 3) {
val = fget2(ifp); fget2(ifp);
} else
val = fget4(ifp);
save = ftell(ifp);
fseek (ifp, base+val, SEEK_SET);
switch (tag) {
case 0x11:
camera_red = val / 256.0;
break;
case 0x12:
camera_blue = val / 256.0;
break;
case 0x100: /* ImageWidth */
wide = val;
break;
case 0x101: /* ImageHeight */
high = val;
break;
case 0x10f: /* Make tag */
fgets (make, 64, ifp);
break;
case 0x110: /* Model tag */
fgets (model, 64, ifp);
break;
case 0x111: /* StripOffset */
if (len == 1)
offset = val;
else
offset = fget4(ifp);
break;
case 0x112: /* Rotation */
flip = flip_map[(val-1) & 7];
break;
case 0x123:
curve_offset = val;
curve_length = len;
break;
case 0x827d: /* Model2 tag */
fgets (model2, 64, ifp);
break;
case 0x131: /* Software tag */
fgets (software, 64, ifp);
if (!strncmp(software,"Adobe",5))
make[0] = 0;
break;
case 0x132: /* DateTime tag */
get_timestamp();
break;
case 0x144:
strcpy (make, "Leaf");
raw_width = wide;
raw_height = high;
if (len > 1)
data_offset = fget4(ifp);
else
data_offset = val;
break;
case 0x14a: /* SubIFD tag */
if (len > 2 && !strcmp(make,"Kodak"))
len = 2;
if (len > 1)
while (len--) {
fseek (ifp, base+val, SEEK_SET);
fseek (ifp, fget4(ifp)+base, SEEK_SET);
tiff_parse_subifd(base);
val += 4;
}
else
tiff_parse_subifd(base);
break;
case 0x8769: /* EXIF tag */
parse_exif (base);
break;
}
fseek (ifp, save, SEEK_SET);
}
}
for (i=0; i < sizeof corp / sizeof *corp; i++)
if (!strncmp (make, corp[i], strlen(corp[i]))) {
if ((high & 1) && make[0] == 'O') high++;
raw_width = wide;
raw_height = high;
if (offset) data_offset = offset;
}
d2922 1
a2922 1
data_offset = offset;
d2924 1
a2924 1
if (make[0] == 0 && wide == 680 && high == 680) {
d2928 19
d2951 1
a2951 1
int save, tag, len;
d2954 4
a2957 4
data_offset = fget4(ifp) + 8;
while ((save=ftell(ifp)) < data_offset) {
tag = fget4(ifp);
len = fget4(ifp);
d2961 2
a2962 2
raw_height = fget2(ifp);
raw_width = fget2(ifp);
d2965 5
a2969 5
fget4(ifp);
camera_red = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue = fget2(ifp);
camera_blue = fget2(ifp) / camera_blue;
d2976 50
d3038 4
a3041 4
fget2(ifp);
if (fget4(ifp) != 0x80008) return;
if (fget4(ifp) == 0) return;
bpp = fget2(ifp);
d3046 1
a3046 1
bitbuf = bitbuf << 16 | (fget2(ifp) ^ key[i++ & 1]);
d3050 1
a3050 1
bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp) << (14-bpp);
d3056 1
a3056 2
Parse the CIFF structure looking for two pieces of information:
The camera model, and the decode table number.
d3071 1
a3071 1
tboff = fget4(ifp) + offset;
d3073 1
a3073 1
nrecs = fget2(ifp);
d3075 3
a3077 3
type = fget2(ifp);
len = fget4(ifp);
roff = fget4(ifp);
d3088 1
a3088 1
wbi = fget2(ifp);
d3097 4
a3100 4
white[0][1] = fget2(ifp) << 4;
white[0][0] = fget2(ifp) << 4;
white[1][0] = fget2(ifp) << 4;
white[1][1] = fget2(ifp) << 4;
d3110 4
a3113 4
camera_red = fget2(ifp) ^ key[0];
camera_red =(fget2(ifp) ^ key[1]) / camera_red;
camera_blue = fget2(ifp) ^ key[0];
camera_blue /= fget2(ifp) ^ key[1];
d3131 4
a3134 4
camera_red = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue = fget2(ifp);
camera_blue = fget2(ifp) / camera_blue;
d3142 2
a3143 2
raw_width = fget2(ifp);
raw_height = fget2(ifp);
d3147 1
a3147 1
timestamp = fget4(ifp);
d3153 1
a3153 1
flip = fget4(ifp);
d3157 1
a3157 1
crw_init_tables (fget4(ifp));
d3216 1
a3216 1
skip = fget4(ifp);
d3224 2
a3225 2
if (!strcmp(data,"NeutObj_neutrals"))
for (i=0; i < 4; i++) {
d3227 3
a3229 2
if (i) pre_mul[i-1] = (float) neut[0] / neut[i];
}
d3235 10
d3247 2
a3248 2
char *buf, *bp, *np;
int off1, off2, len, i;
d3251 2
d3254 48
a3301 28
off2 = fget4(ifp);
fseek (ifp, off2, SEEK_SET);
while (fget4(ifp) != 0x464d4143) /* Search for "CAMF" */
if (feof(ifp)) return;
off1 = fget4(ifp);
fseek (ifp, off1+8, SEEK_SET);
off1 += (fget4(ifp)+3) * 8;
len = (off2 - off1)/2;
fseek (ifp, off1, SEEK_SET);
buf = malloc (len);
merror (buf, "parse_foveon()");
for (i=0; i < len; i++) /* Convert Unicode to ASCII */
buf[i] = fget2(ifp);
for (bp=buf; bp < buf+len; bp=np) {
np = bp + strlen(bp) + 1;
if (!strcmp(bp,"CAMMANUF"))
strcpy (make, np);
if (!strcmp(bp,"CAMMODEL"))
strcpy (model, np);
if (!strcmp(bp,"TIME"))
timestamp = atoi(np);
}
fseek (ifp, 248, SEEK_SET);
raw_width = fget4(ifp);
raw_height = fget4(ifp);
fseek (ifp, 36, SEEK_SET);
flip = fget4(ifp);
free (buf);
d3306 4
a3309 5
static const float foveon[3][3] = {
{ 2.0343955, -0.727533, -0.3067457 },
{ -0.2287194, 1.231793, -0.0028293 },
{ -0.0086152, -0.153336, 1.1617814 }
};
d3314 1
a3314 1
coeff[i][j] = foveon[i][j] * pre_mul[i];
d3333 1
a3333 4
Given a matrix that converts RGB to GMCY, create a matrix to do
the opposite. Only square matrices can be inverted, so I create
four 3x3 matrices by omitting a different GMCY color in each one.
The final coeff[][] matrix is the sum of these four.
d3335 1
a3335 1
void CLASS gmcy_coeff()
d3337 182
a3518 6
static const float gmcy[4][3] = {
/* red green blue */
{ 0.11, 0.86, 0.08 }, /* green */
{ 0.50, 0.29, 0.51 }, /* magenta */
{ 0.11, 0.92, 0.75 }, /* cyan */
{ 0.81, 0.98, 0.08 } /* yellow */
d3520 3
a3522 2
double invert[3][6], num;
int ignore, i, j, k, r, g;
d3524 10
a3533 24
memset (coeff, 0, sizeof coeff);
for (ignore=0; ignore < 4; ignore++) {
for (j=0; j < 3; j++) {
g = (j < ignore) ? j : j+1;
for (r=0; r < 3; r++) {
invert[j][r] = gmcy[g][r]; /* 3x3 matrix to invert */
invert[j][r+3] = (r == j); /* Identity matrix */
}
}
for (j=0; j < 3; j++) {
num = invert[j][j]; /* Normalize this row */
for (i=0; i < 6; i++)
invert[j][i] /= num;
for (k=0; k < 3; k++) { /* Subtract it from the other rows */
if (k==j) continue;
num = invert[k][j];
for (i=0; i < 6; i++)
invert[k][i] -= invert[j][i] * num;
}
}
for (j=0; j < 3; j++) { /* Add the result to coeff[][] */
g = (j < ignore) ? j : j+1;
for (r=0; r < 3; r++)
coeff[r][g] += invert[r][j+3];
a3534 8
}
for (r=0; r < 3; r++) { /* Normalize such that: */
for (num=g=0; g < 4; g++) /* (1,1,1,1) x coeff = (1,1,1) */
num += coeff[r][g];
for (g=0; g < 4; g++)
coeff[r][g] /= num;
}
use_coeff = 1;
d3547 1
a3547 1
char make[12], model[16];
d3549 22
a3570 18
{ 62464, "Kodak", "DC20" },
{ 124928, "Kodak", "DC20" },
{ 2465792, "NIKON", "E950" },
{ 2940928, "NIKON", "E2100" },
{ 4771840, "NIKON", "E990" },
{ 4775936, "NIKON", "E3700" },
{ 5865472, "NIKON", "E4500" },
{ 5869568, "NIKON", "E4300" },
{ 787456, "Creative", "PC-CAM 600" },
{ 1976352, "Casio", "QV-2000UX" },
{ 3217760, "Casio", "QV-3*00EX" },
{ 6218368, "Casio", "QV-5700" },
{ 7684000, "Casio", "QV-4000" },
{ 9313536, "Casio", "EX-P600" },
{ 10979200, "Casio", "EX-P700" },
{ 4841984, "Pentax", "Optio S" },
{ 6114240, "Pentax", "Optio S4" },
{ 12582980, "Sinar", "" } };
d3573 1
a3573 1
"MINOLTA", "Minolta", "Konica" };
d3578 1
a3578 1
raw_height = raw_width = flip = 0;
d3581 4
a3584 1
camera_red = camera_blue = timestamp = 0;
d3586 4
a3589 2
data_offset = curve_offset = tiff_data_compression = 0;
zero_after_ff = 0;
d3594 2
a3595 2
order = fget2(ifp);
hlen = fget4(ifp);
d3604 2
a3605 2
fseek (ifp, fget4(ifp) + 136, SEEK_CUR);
raw_width = fget4(ifp);
d3607 1
a3607 1
raw_height = fget4(ifp);
d3614 1
a3614 1
if (!strncmp(make,"NIKON",5) && raw_width == 0)
d3622 1
a3622 1
fseek (ifp, 4 + fget2(ifp), SEEK_SET);
d3629 1
a3629 1
if (fget4(ifp) == 2834 && fget4(ifp) == 2834) {
d3640 4
a3643 4
data_offset += fget4(ifp);
fget4(ifp);
raw_width = fget4(ifp);
raw_height = fget4(ifp);
d3649 2
a3650 2
strcpy (make, "CONTAX");
strcpy (model,"N DIGITAL");
d3653 1
a3653 1
parse_tiff (fget4(ifp)+12);
d3666 2
d3693 3
a3695 1
load_raw = NULL;
d3698 15
a3712 6
fuji_width = top_margin = left_margin = 0;
colors = 3;
filters = 0x94949494;
black = is_cmy = is_foveon = use_coeff = 0;
use_gamma = xmag = ymag = 1;
rgb_max = 0x3fff;
d3716 1
d3728 8
a3735 1
if (!strcmp(model,"PowerShot 600")) {
a3740 2
pre_mul[0] = 1.137;
pre_mul[1] = 1.257;
d3743 1
a3743 1
height = 776;
a3748 3
pre_mul[0] = 1.5842;
pre_mul[1] = 1.2966;
pre_mul[2] = 1.0419;
a3755 3
pre_mul[0] = 1.750;
pre_mul[1] = 1.381;
pre_mul[3] = 1.182;
d3762 1
a3762 3
pre_mul[0] = 1.389;
pre_mul[1] = 1.343;
pre_mul[3] = 1.034;
a3766 3
pre_mul[0] = 1.496;
pre_mul[1] = 1.509;
pre_mul[3] = 1.009;
a3774 6
pre_mul[0] = 1.446;
pre_mul[1] = 1.405;
pre_mul[2] = 1.016;
} else {
pre_mul[0] = 1.785;
pre_mul[2] = 1.266;
a3780 2
pre_mul[0] = 1.592;
pre_mul[2] = 1.261;
a3785 8
if (!strcmp(model,"PowerShot G2") ||
!strcmp(model,"PowerShot S40")) {
pre_mul[0] = 1.965;
pre_mul[2] = 1.208;
} else { /* G3 and S45 */
pre_mul[0] = 1.855;
pre_mul[2] = 1.339;
}
a3790 2
pre_mul[0] = 1.895;
pre_mul[2] = 1.403;
d3796 1
a3796 7
pre_mul[0] = 2.242;
pre_mul[2] = 1.245;
if (!strcmp(model,"EOS Kiss Digital")) {
pre_mul[0] = 1.882;
pre_mul[2] = 1.094;
}
rgb_max = 16000;
a3801 2
pre_mul[0] = 1.85;
pre_mul[2] = 1.53;
a3806 2
pre_mul[0] = 1.621;
pre_mul[2] = 1.528;
a3810 2
pre_mul[0] = 1.976;
pre_mul[2] = 1.282;
a3814 3
pre_mul[0] = 1.66;
pre_mul[2] = 1.13;
rgb_max = 14464;
a3823 2
pre_mul[0] = 1.95;
pre_mul[2] = 1.36;
d3832 1
a3832 3
pre_mul[0] = 1.609;
pre_mul[2] = 1.848;
rgb_max = 0x3a00;
d3834 1
a3834 2
black = 800;
pre_mul[2] = 1.25;
d3836 2
a3837 7
filters = 0x16161616;
pre_mul[0] = 0.838;
pre_mul[2] = 1.095;
} else if (!strcmp(model,"D1H")) {
filters = 0x16161616;
pre_mul[0] = 2.301;
pre_mul[2] = 1.129;
a3839 1
filters = 0x16161616;
a3840 2
pre_mul[0] = 1.910;
pre_mul[2] = 1.220;
a3843 4
filters = 0x61616161;
pre_mul[0] = 2.374;
pre_mul[2] = 1.677;
rgb_max = 15632;
d3847 5
a3851 8
filters = 0x49494949;
pre_mul[0] = 2.8;
pre_mul[2] = 1.2;
} else if (!strcmp(model,"D70")) {
filters = 0x16161616;
pre_mul[0] = 2.043;
pre_mul[2] = 1.625;
} else if (!strcmp(model,"E950")) {
d3862 1
d3866 12
a3877 13
if (nikon_e990()) {
filters = 0xb4b4b4b4;
nikon_e950_coeff();
pre_mul[0] = 1.196;
pre_mul[1] = 1.246;
pre_mul[2] = 1.018;
} else {
strcpy (model, "E995");
filters = 0xe1e1e1e1;
pre_mul[0] = 1.253;
pre_mul[1] = 1.178;
pre_mul[3] = 1.035;
}
d3879 9
d3889 3
a3891 11
if (nikon_e2100()) {
height = 1206;
load_raw = nikon_e2100_load_raw;
pre_mul[0] = 1.945;
pre_mul[2] = 1.040;
} else {
strcpy (model, "E2500");
height = 1204;
filters = 0x4b4b4b4b;
goto coolpix;
}
d3893 1
d3899 11
a3909 8
if (pentax_optio33()) {
strcpy (make, "Pentax");
strcpy (model,"Optio 33WR");
flip = 1;
filters = 0x16161616;
pre_mul[0] = 1.331;
pre_mul[2] = 1.820;
}
d3911 11
d3925 4
a3928 5
if (minolta_z2()) {
strcpy (make, "Minolta");
strcpy (model,"DiMAGE Z2");
load_raw = nikon_e2100_load_raw;
}
d3932 1
a3933 18
goto coolpix;
} else if (!strcmp(model,"E5000") || !strcmp(model,"E5700")) {
filters = 0xb4b4b4b4;
coolpix:
colors = 4;
pre_mul[0] = 1.300;
pre_mul[1] = 1.300;
pre_mul[3] = 1.148;
} else if (!strcmp(model,"E5400")) {
filters = 0x16161616;
pre_mul[0] = 1.700;
pre_mul[2] = 1.344;
} else if (!strcmp(model,"E8400") ||
!strcmp(model,"E8700") ||
!strcmp(model,"E8800")) {
filters = 0x16161616;
pre_mul[0] = 2.131;
pre_mul[2] = 1.400;
a3936 3
black = 256;
pre_mul[0] = 2.322;
pre_mul[2] = 1.404;
d3943 1
a3943 3
black = 512;
pre_mul[0] = 1.424;
pre_mul[2] = 1.718;
d3953 1
a3953 1
rgb_max = 0xffff;
d3960 1
a3960 3
pre_mul[0] = 1.639;
pre_mul[2] = 1.438;
rgb_max = 0xf800;
d3967 2
a3968 8
load_raw = low_12_load_raw;
pre_mul[0] = 1.755;
pre_mul[2] = 1.542;
rgb_max = 0xffff;
} else if (!strcmp(model,"FinePix S7000")) {
pre_mul[0] = 1.62;
pre_mul[2] = 1.38;
goto fuji_s7000;
d3970 2
a3971 4
!strcmp(model,"FinePix F810")) {
pre_mul[0] = 1.65;
pre_mul[2] = 1.29;
fuji_s7000:
d3977 1
a3977 1
rgb_max = 0xf800;
d3985 1
a3985 3
pre_mul[0] = 1.639;
pre_mul[2] = 1.438;
rgb_max = 0x3e00;
d3995 2
d4000 2
a4001 2
load_raw = low_12_load_raw;
rgb_max = 15860;
d4010 3
a4012 2
rgb_max = model[8] == '1' ? 15916:16380;
} else if (!strncmp(model,"DYNAX",5) ||
d4015 1
a4015 1
rgb_max = 16364;
d4019 2
d4039 2
a4040 2
load_raw = low_10_load_raw;
rgb_max = 15856;
d4042 8
a4049 4
camera_red = fget2(ifp);
camera_blue = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue /= fget2(ifp);
a4050 2
pre_mul[0] = 1.42;
pre_mul[2] = 1.25;
d4052 1
a4052 3
load_raw = low_12_load_raw;
pre_mul[0] = 1.76;
pre_mul[1] = 1.07;
d4057 18
a4074 7
height = 1544;
width = 2068;
raw_width = 3136;
load_raw = packed_12_load_raw;
pre_mul[0] = 1.506;
pre_mul[2] = 1.152;
} else if (!strcmp(model,"Optio S4")) {
d4079 12
a4090 2
pre_mul[0] = 1.308;
pre_mul[2] = 1.275;
d4129 1
a4129 1
rgb_max = 0xffff;
d4135 1
a4137 1
rgb_max = 0xffff;
d4140 2
a4141 2
height = fget4(ifp);
width = fget4(ifp);
d4144 2
a4145 2
load_raw = all_16_load_raw;
rgb_max = 0xffff;
d4149 2
a4150 1
load_raw = low_12_load_raw;
d4155 1
a4157 1
rgb_max = 0xffff;
d4162 2
a4163 3
load_raw = high_12_load_raw;
pre_mul[0] = 1.883;
pre_mul[2] = 1.367;
d4166 3
a4168 3
load_raw = high_12_load_raw;
pre_mul[0] = 1.57;
pre_mul[2] = 1.48;
d4170 3
a4172 3
load_raw = high_12_load_raw;
pre_mul[0] = 1.43;
pre_mul[2] = 1.77;
d4174 3
a4176 4
load_raw = high_12_load_raw;
black = 640;
pre_mul[0] = 1.43;
pre_mul[2] = 1.77;
d4181 2
a4182 2
load_raw = all_16_load_raw;
rgb_max = 64560;
d4184 2
a4185 5
black = 248;
pre_mul[0] = 1.718;
pre_mul[2] = 1.235;
} else if (!strcmp(model,"C5050Z")) {
filters = 0x16161616;
d4187 4
a4190 16
pre_mul[0] = 1.533;
pre_mul[2] = 1.880;
} else if (!strcmp(model,"C5060WZ")) {
load_raw = olympus_cseries_load_raw;
pre_mul[0] = 2.285;
pre_mul[2] = 1.023;
} else if (!strncmp(model,"C70Z",4)) {
load_raw = olympus_cseries_load_raw;
pre_mul[0] = 1.648;
pre_mul[2] = 1.660;
} else if (!strcmp(model,"C8080WZ")) {
filters = 0x16161616;
load_raw = olympus_cseries_load_raw;
pre_mul[0] = 2.335;
pre_mul[2] = 1.323;
} else if (!strcmp(model,"N DIGITAL")) {
d4196 1
a4196 2
pre_mul[0] = 1.366;
pre_mul[2] = 1.251;
d4201 1
a4201 2
sony_rgbe_coeff();
filters = 0xb4b4b4b4;
a4202 3
pre_mul[0] = 1.512;
pre_mul[1] = 1.020;
pre_mul[2] = 1.405;
a4207 2
pre_mul[0] = 2.014;
pre_mul[2] = 1.744;
d4213 2
a4214 1
curve_length = 176;
a4219 2
pre_mul[0] = 1.629;
pre_mul[2] = 2.767;
a4222 2
pre_mul[0] = 1.386;
pre_mul[2] = 2.405;
d4224 1
a4224 3
black = 32;
pre_mul[1] = 1.068;
pre_mul[2] = 1.036;
d4226 1
a4226 3
black = 32;
pre_mul[1] = 1.012;
pre_mul[2] = 1.804;
a4229 2
pre_mul[0] = 1.327;
pre_mul[2] = 2.074;
a4232 2
pre_mul[0] = 1.724;
pre_mul[2] = 2.411;
d4239 1
a4239 3
black = 720;
pre_mul[0] = 1.006;
pre_mul[2] = 1.858;
d4241 1
a4241 3
black = 750;
pre_mul[1] = 1.053;
pre_mul[2] = 1.703;
d4243 1
a4243 3
black = 720;
pre_mul[1] = 1.002;
pre_mul[2] = 1.818;
d4245 1
a4245 4
black = 740;
pre_mul[0] = 1.486;
pre_mul[2] = 1.280;
is_cmy = 1;
d4247 1
a4247 3
black = 855;
pre_mul[0] = 1.156;
pre_mul[2] = 1.626;
d4249 1
a4249 1
black = 855;
a4251 7
} else if (!strcmp(model,"DCS720X")) {
pre_mul[0] = 1.35;
pre_mul[2] = 1.18;
is_cmy = 1;
} else if (!strcmp(model,"DCS760C")) {
pre_mul[0] = 1.06;
pre_mul[2] = 1.72;
a4254 24
} else if (!strcmp(model,"ProBack")) {
pre_mul[0] = 1.06;
pre_mul[2] = 1.385;
} else if (!strncmp(model2,"PB645C",6)) {
pre_mul[0] = 1.0497;
pre_mul[2] = 1.3306;
} else if (!strncmp(model2,"PB645H",6)) {
pre_mul[0] = 1.2010;
pre_mul[2] = 1.5061;
} else if (!strncmp(model2,"PB645M",6)) {
pre_mul[0] = 1.01755;
pre_mul[2] = 1.5424;
} else if (!strcasecmp(model,"DCS Pro 14n")) {
pre_mul[1] = 1.0323;
pre_mul[2] = 1.258;
} else if (!strcasecmp(model,"DCS Pro 14nx")) {
pre_mul[0] = 1.336;
pre_mul[2] = 1.3155;
} else if (!strcasecmp(model,"DCS Pro SLR/c")) {
pre_mul[0] = 1.425;
pre_mul[2] = 1.293;
} else if (!strcasecmp(model,"DCS Pro SLR/n")) {
pre_mul[0] = 1.324;
pre_mul[2] = 1.483;
d4292 1
a4292 1
kodak_dc20_coeff (0.5);
a4350 21
} else if (!strcmp(make,"SIGMA")) {
switch (raw_height) {
case 763: height = 756; top_margin = 2; break;
case 1531: height = 1514; top_margin = 7; break;
}
switch (raw_width) {
case 1152: width = 1136; left_margin = 8; break;
case 2304: width = 2271; left_margin = 17; break;
}
if (height*2 < width) ymag = 2;
filters = 0;
load_raw = foveon_load_raw;
is_foveon = 1;
pre_mul[0] = 1.179;
pre_mul[2] = 0.713;
if (!strcmp(model,"SD10")) {
pre_mul[0] *= 2.07;
pre_mul[2] *= 2.30;
}
foveon_coeff();
rgb_max = 5600;
d4371 2
a4372 1
load_raw = high_12_load_raw;
d4377 14
d4396 2
a4397 2
pre_mul[0] = 2.356;
pre_mul[1] = 1.069;
d4403 2
a4404 2
pre_mul[0] = 2.34;
pre_mul[2] = 1.24;
d4407 1
a4407 1
load_raw = low_12_load_raw;
d4414 2
d4429 2
a4430 2
if (colors == 4 && !use_coeff)
gmcy_coeff();
a4455 1
int shift=0, size, i;
d4473 2
a4474 8
while (rgb_max << shift < 0x8000) shift++;
size = width * height * 4;
if (shift)
for (i=0; i < size; i++)
image[0][i] <<= shift;
rgb_max = 0xffff;
use_gamma = use_coeff = is_cmy = 0;
d4494 1
a4494 1
float rgb[3], mag;
d4509 1
a4509 1
else if (use_coeff) { /* RGB from GMCY or Foveon */
a4512 4
} else if (is_cmy) { /* RGB from CMY */
rgb[0] = img[0] + img[1] - img[2];
rgb[1] = img[1] + img[2] - img[0];
rgb[2] = img[2] + img[0] - img[1];
d4516 2
a4517 4
if (rgb[r] < 0)
rgb[r] = 0;
if (rgb[r] > rgb_max)
rgb[r] = rgb_max;
d4521 2
a4522 9
if (write_fun == write_ppm) {
for (mag=r=0; r < 3; r++)
mag += (unsigned) img[r]*img[r];
mag = sqrt(mag)/2;
if (mag > 0xffff)
mag = 0xffff;
img[3] = mag;
histogram[img[3] >> 3]++;
}
d4552 1
a4552 1
for (i=0; i < 4; i++)
d4616 1
a4616 1
Write the image to a 24-bpp PPM file.
d4620 3
a4622 12
int row, col, i, c, val, total;
float white, r, scale[0x10000];
ushort *rgb;
uchar (*ppm)[3];
/* Set the white point to the 99th percentile. */
i = width * height * 0.01;
if (fuji_width) i /= 2;
for (val=0x2000, total=0; --val; )
if ((total += histogram[val]) > i) break;
white = (val << 3) / bright;
a4625 1
d4628 10
a4637 2
scale[0] = 0;
for (i=1; i < 0x10000; i++) {
d4639 1
a4639 1
scale[i] = 221.7025 / i * ( !use_gamma ? r :
d4641 2
d4645 3
a4647 9
for (col=trim; col < width-trim; col++) {
rgb = image[row*width+col];
for (c=0; c < 3; c++) {
val = rgb[c] * scale[rgb[3]];
if (val > 255) val=255;
for (i=0; i < xmag; i++)
ppm[xmag*(col-trim)+i][c] = val;
}
}
d4655 1
a4655 1
Write the image to a 48-bpp Photoshop file.
d4672 2
a4673 2
int hw[2], psize, row, col, c, val;
ushort *buffer, *pred, *rgb;
d4687 1
a4687 7
rgb = image[row*width+col];
for (c=0; c < 3; c++) {
val = rgb[c] * bright;
if (val > 0xffff)
val = 0xffff;
pred[c*psize] = htons(val);
}
d4696 1
a4696 1
Write the image to a 48-bpp PPM file.
d4700 2
a4701 2
int row, col, c, val;
ushort *rgb, (*ppm)[3];
d4703 1
a4703 5
val = rgb_max * bright;
if (val < 256)
val = 256;
if (val > 0xffff)
val = 0xffff;
d4705 1
a4705 1
width-trim*2, height-trim*2, val);
d4711 2
a4712 9
for (col = trim; col < width-trim; col++) {
rgb = image[row*width+col];
for (c=0; c < 3; c++) {
val = rgb[c] * bright;
if (val > 0xffff)
val = 0xffff;
ppm[col-trim][c] = htons(val);
}
}
d4732 1
a4732 1
"\nRaw Photo Decoder \"dcraw\" v6.35"
d4744 2
d4788 2
d4809 1
a4809 1
#if defined(WIN32) || defined(DJGPP)
d4816 1
a4816 3
for ( ; arg < argc; arg++)
{
d4843 1
a4843 1
image = calloc (iheight * iwidth, sizeof *image);
d4845 1
@
1.235
log
@Added the Casio EX-P700.
Fixed three potential buffer overruns.
@
text
@d4111 2
a4112 1
for (i=0; i < 0x10000; i++) {
@
1.234
log
@Call fuji_rotate() before apply_profile().
Do not use the gamma curve after applying a profile.
@
text
@d567 1
a567 1
for (i=0; i < curve_length; i++)
d974 1
a974 1
ushort pixel[4134], akey, bkey;
d981 2
d994 1
d1554 1
a1554 1
ushort pixel[3360];
d1568 2
d1578 1
d2907 1
d3853 7
d3932 1
a3932 1
image[0][i] <<= 2;
d4227 1
a4227 1
"\nRaw Photo Decoder \"dcraw\" v6.34"
@
1.233
log
@Improved Pentax Optio 33WR detection.
@
text
@d76 2
a77 1
int is_canon, is_cmy, is_foveon, use_coeff, trim, flip, xmag, ymag;
d3026 1
a3026 1
xmag = ymag = 1;
d3920 1
a3920 1
use_coeff = is_cmy = 0;
d4099 2
a4100 1
scale[i] = (r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099) * 221.7025 / i;
d4213 1
a4213 1
"\nRaw Photo Decoder \"dcraw\" v6.33"
d4347 1
a4350 1
fuji_rotate();
@
1.232
log
@Changed default rgb_max from 0x4000 to 0x3fff.
@
text
@d797 2
a798 2
int i;
char tail[952];
d803 2
a804 2
if (!tail[i]) return 0;
return 1;
@
1.231
log
@Added the Pentax Optio 33WR.
Flip the Nucore images to proper orientation.
Do fuji_rotate() before convert_to_rgb().
@
text
@d3026 1
a3026 1
rgb_max = 0x4000;
@
1.230
log
@For Leaf cameras, get pre_mul[] values from the metadata.
Added preliminary support for color profiles using LCMS.
@
text
@d793 15
d1154 1
a1154 4
if (model[0] == 'B' && width == 2598)
row = height - 1 - irow/2 - height/2 * (irow & 1);
else
row = irow;
d2958 1
d3269 8
d3847 6
a3852 1
load_raw = nucore_load_raw;
d4019 1
d4211 1
a4211 1
"\nRaw Photo Decoder \"dcraw\" v6.32"
d4348 1
a4351 1
fuji_rotate();
@
1.229
log
@Added the Nikon E8400.
Tweaked the gamma curve yet again.
@
text
@d91 5
d2715 28
d2902 1
d2905 3
d2981 2
a3011 1
pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = 1;
d3493 1
a3493 3
load_raw = all_16_load_raw;
pre_mul[0] = 1.1629;
pre_mul[2] = 1.3556;
a3497 3
pre_mul[0] = 2.103;
pre_mul[1] = 1.256;
pre_mul[2] = 1.0;
d3865 41
d4177 3
d4184 1
a4184 1
"\nRaw Photo Decoder \"dcraw\" v6.31"
d4191 8
a4198 1
"\n-f Interpolate RGBG as four colors"
d4202 1
a4203 5
"\n-b Set brightness (1.0 by default)"
"\n-a Use automatic white balance"
"\n-w Use camera white balance, if possible"
"\n-r Set red multiplier (daylight = 1.0)"
"\n-l Set blue multiplier (daylight = 1.0)"
d4225 3
a4227 1
a4298 1
fclose(ifp);
d4318 3
d4333 1
@
1.228
log
@Use the standard video gamma function -- no more "-g".
Enable "-s" option for the Fuji S3.
Fixed segfault in fuji_rotate().
Added the Leaf Volare.
Removed unused canon_rgb_coeff() function.
@
text
@d3243 2
a3244 1
} else if (!strcmp(model,"E8700") ||
d3248 1
a3248 1
pre_mul[2] = 1.300;
d3988 1
a3988 1
white = (val << 4) / bright;
d3997 1
a3997 1
scale[i] = (r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099) * 256 / i;
d4107 1
a4107 1
"\nRaw Photo Decoder \"dcraw\" v6.30"
@
1.227
log
@Added fuji_rotate() function; fujiturn is no longer needed.
@
text
@d81 1
a81 1
float gamma_val=0.6, bright=1.0, red_scale=1.0, blue_scale=1.0;
d987 17
a2761 18
/*
The grass is always greener in my PowerShot G2 when this
function is called. Use at your own risk!
*/
void CLASS canon_rgb_coeff (float juice)
{
static const float my_coeff[3][3] =
{ { 1.116187, -0.107427, -0.008760 },
{ -1.551374, 4.157144, -1.605770 },
{ 0.090939, -0.399727, 1.308788 } };
int i, j;
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
coeff[i][j] = my_coeff[i][j] * juice + (i==j) * (1-juice);
use_coeff = 1;
}
a3061 4
#ifdef CUSTOM
if (write_fun == write_ppm) /* Pro users may not want my matrix */
canon_rgb_coeff (0.1);
#endif
d3268 2
d3457 9
d3905 1
a3905 1
if (ur >= height || uc >= width) continue;
d3977 1
a3977 1
float max, mul, scale[0x10000];
d3987 1
a3987 1
max = val << 4;
d3994 4
a3997 5
mul = bright * 442 / max;
scale[0] = 0;
for (i=1; i < 0x10000; i++)
scale[i] = mul * pow (i*2/max, gamma_val-1);
d4106 1
a4106 1
"\nRaw Photo Decoder \"dcraw\" v6.25"
a4117 1
"\n-g Set gamma (0.6 by default, only for 24-bpp output)"
d4124 3
a4126 3
"\n-2 Write 24-bpp PPM (default)"
"\n-3 Write 48-bpp PSD (Adobe Photoshop)"
"\n-4 Write 48-bpp PPM"
d4134 1
a4134 1
if (strchr ("gbrl", opt) && !isdigit(argv[arg][0])) {
a4139 1
case 'g': gamma_val = atof(argv[arg++]); break;
@
1.226
log
@Added the Epson R-D1.
Added the read_shorts() function and refactored.
@
text
@d74 1
a74 1
int height, width, colors, black, rgb_max;
d2970 1
a2970 1
top_margin = left_margin = 0;
d3262 1
d3272 1
d3279 1
d3306 1
d3314 1
d3877 37
d3978 1
a3978 1
if (!strcmp(make,"FUJIFILM") && abs(width-height) < 2) i /= 2;
d4101 1
a4101 1
"\nRaw Photo Decoder \"dcraw\" v6.23"
d4236 1
@
1.225
log
@Added the Fuji FinePix S3Pro and Minolta DiMAGE A200.
@
text
@d197 2
a198 2
a = fgetc(f);
b = fgetc(f);
d200 1
a200 1
return a + (b << 8);
d202 1
a202 1
return (a << 8) + b;
d212 2
a213 4
a = fgetc(f);
b = fgetc(f);
c = fgetc(f);
d = fgetc(f);
d215 1
a215 1
return a + (b << 8) + (c << 16) + (d << 24);
d217 11
a227 1
return (a << 24) + (b << 16) + (c << 8) + d;
d853 1
a853 1
fread (pixel, 2, 2944, ifp);
d857 1
a857 1
BAYER(r,c) = ntohs(pixel[col]) << 2;
d869 1
a869 3
fread (pixel, 2, 4352, ifp);
if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */
swab (pixel, pixel, 4352*2);
d884 1
a884 3
fread (pixel, 2, ncol, ifp);
if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */
swab (pixel, pixel, ncol*2);
d915 1
a915 3
fread (pixel, 2, 2944, ifp);
if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */
swab (pixel, pixel, 2944*2);
d961 1
a961 1
fread (pixel, 2, raw_width, ifp);
d963 2
a964 2
a = ntohs(pixel[col+0]) ^ akey;
b = ntohs(pixel[col+1]) ^ bkey;
d978 1
d981 1
a981 3
fread (pixel, 2, 4090, ifp);
if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */
swab (pixel, pixel, 4090*2);
d1001 1
a1001 1
void CLASS unpacked_load_raw (int order, int rsh)
d1009 1
a1009 3
fread (pixel, 2, raw_width, ifp);
if (order != ntohs(0x55aa))
swab (pixel, pixel, width*2);
d1016 1
a1016 1
void CLASS be_16_load_raw() /* "be" = "big-endian" */
d1018 1
a1018 1
unpacked_load_raw (0x55aa, 0);
d1021 1
a1021 1
void CLASS be_high_12_load_raw()
d1023 1
a1023 1
unpacked_load_raw (0x55aa, 2);
d1026 1
a1026 1
void CLASS be_low_12_load_raw()
d1028 1
a1028 1
unpacked_load_raw (0x55aa,-2);
d1031 1
a1031 1
void CLASS be_low_10_load_raw()
d1033 1
a1033 16
unpacked_load_raw (0x55aa,-4);
}
void CLASS le_16_load_raw() /* "le" = "little-endian" */
{
unpacked_load_raw (0xaa55, 0);
}
void CLASS le_high_12_load_raw()
{
unpacked_load_raw (0xaa55, 2);
}
void CLASS le_low_12_load_raw()
{
unpacked_load_raw (0xaa55,-2);
d1110 1
a1110 1
uchar *data, *dp;
d1113 2
a1114 2
data = calloc (width, 2);
merror (data, "nucore_load_raw()");
d1116 1
a1116 1
fread (data, 2, width, ifp);
d1121 2
a1122 2
for (dp=data, col=0; col < width; col++, dp+=2)
BAYER(row,col) = (dp[0] << 2) + (dp[1] << 10);
d1124 1
a1124 1
free (data);
d1411 1
a1411 3
fread (raw, 2, 6, ifp);
for (i=0; i < 6; i++)
raw[i] = ntohs(raw[i]);
d2860 1
a2860 1
{ "Canon", "NIKON", "Kodak", "OLYMPUS", "PENTAX",
a2931 1
order = 0x4d4d;
d2933 2
a2934 1
data_offset = fget4(ifp);
d3253 6
d3288 1
a3288 1
load_raw = le_low_12_load_raw;
d3327 1
a3327 1
load_raw = be_low_12_load_raw;
d3363 1
a3363 1
load_raw = be_low_10_load_raw;
d3374 1
a3374 1
load_raw = be_low_12_load_raw;
d3447 1
a3447 1
load_raw = be_16_load_raw;
d3452 1
a3452 1
load_raw = be_16_load_raw;
d3460 1
a3460 1
load_raw = le_high_12_load_raw;
d3465 1
a3465 1
load_raw = le_high_12_load_raw;
d3469 1
a3469 1
load_raw = be_high_12_load_raw;
d3473 1
a3473 1
load_raw = be_high_12_load_raw;
d3481 1
a3481 1
load_raw = le_16_load_raw;
d3767 1
a3767 1
load_raw = be_high_12_load_raw;
d4059 1
a4059 1
"\nRaw Photo Decoder \"dcraw\" v6.22"
@
1.224
log
@Improved support for the Canon S70 and Olympus E-300.
@
text
@d854 18
d2880 1
d3279 7
d3342 6
d4071 1
a4071 1
"\nRaw Photo Decoder \"dcraw\" v6.21"
@
1.223
log
@Fixed camera white balance for the PowerShots G6, S70, and Pro1.
@
text
@d3 1
a3 1
Copyright 1997-2004 by Dave Coffin, dcoffin a cybercom o net
d1019 6
a1024 1
void CLASS le_high_12_load_raw() /* "le" = "little-endian" */
d2550 1
d2603 1
a2603 1
fseek (ifp, aoff+104 + wbi*8, SEEK_SET);
d2623 1
a2623 1
if (type == 0x1030 && (wbi == 6 || wbi > 14)) {
d3460 5
d3913 2
a3914 3
/*
Set the white point to the 99th percentile
*/
d4039 1
a4039 1
"\nRaw Photo Decoder \"dcraw\" v6.20"
@
1.222
log
@Added the Olympus C70Z,C7000Z.
@
text
@d2545 1
d2547 4
d2584 1
a2584 6
if (wbi == 6 && fget4(ifp) == 0)
wbi = 15;
else {
fseek (ifp, aoff+100, SEEK_SET);
goto common;
}
d2591 11
a2601 4
camera_red = fget2(ifp);
camera_red = fget2(ifp) / camera_red;
camera_blue = fget2(ifp);
camera_blue /= fget2(ifp);
d2617 2
a2618 2
if (type == 0x1030 && wbi > 14) { /* Get white sample */
fseek (ifp, aoff, SEEK_SET);
d4029 1
a4029 1
"\nRaw Photo Decoder \"dcraw\" v6.19"
@
1.221
log
@Added the Nikon E3700 and Olympus E-300.
@
text
@d3458 4
d4022 1
a4022 1
"\nRaw Photo Decoder \"dcraw\" v6.18"
@
1.220
log
@Minolta "MAXXUM" is the same as "DYNAX".
@
text
@d802 1
a802 1
fseek (ifp, width==1616 ? 8792:424, SEEK_CUR);
d1029 23
d2834 1
d3203 6
d3444 5
d4018 1
a4018 1
"\nRaw Photo Decoder \"dcraw\" v6.17"
@
1.219
log
@Added the Fuji FinePix F810.
@
text
@d3275 2
a3276 1
} else if (!strncmp(model,"DYNAX",5)) {
@
1.218
log
@Added the Pentax *ist DS.
@
text
@d3239 4
a3242 3
} else if (!strcmp(model,"FinePix E550")) {
pre_mul[0] = 1.45;
pre_mul[2] = 1.25;
d3982 1
a3982 1
"\nRaw Photo Decoder \"dcraw\" v6.16"
@
1.217
log
@Flip Foveon images, allow camera white balance for the Pentax *ist D.
Added the Fuji FinePix S5100/S5500, Minolta Dynax 7D, and Sony DSC-V3.
@
text
@d2287 1
a2287 1
camera_blue/= fget2(ifp);
d2348 1
a2348 1
int wide=0, high=0, cr2_offset=0, offset=0;
d2350 1
d2388 4
a2391 2
cr2_offset = val;
offset = fget4(ifp);
d2440 9
a2448 4
if (!strncmp(make,"OLYMPUS",7)) {
make[7] = 0;
raw_width = wide;
raw_height = - (-high & -2);
a2449 7
}
if (!strncmp(make,"SONY",4)) {
raw_width = wide;
raw_height = high;
}
if (!strcmp(make,"Canon") && strcmp(model,"EOS D2000C"))
data_offset = cr2_offset;
d2823 2
a2824 1
{ "Canon", "NIKON", "Kodak", "PENTAX", "MINOLTA", "Minolta", "Konica" };
a3308 3
height = 2024;
width = 3040;
data_offset = 0x10000;
d3312 3
d3981 1
a3981 1
"\nRaw Photo Decoder \"dcraw\" v6.15"
@
1.216
log
@Sony DSC-F828 matrix had green and emerald swapped. Oops.
@
text
@d1024 5
d1489 1
a1489 1
unsigned i, key, row, col, icol;
d1501 1
a1501 1
fseek (ifp, 862144, SEEK_SET);
d1505 4
a1508 5
for (col=0; col < 3343; col++)
if ((icol = col-left_margin) < width)
BAYER(row,icol) = ntohs(pixel[col]);
else
bblack += ntohs(pixel[col]);
d1510 2
a1511 1
black = bblack / ((3343 - width) * height);
d2196 1
a2196 1
fseek (ifp, val+base, SEEK_SET);
d2214 1
a2214 1
void CLASS nef_parse_makernote()
d2232 3
d2237 2
d2247 1
a2247 1
if (type == 3) { /* short int */
d2252 1
a2252 1
if (tag == 0xc) {
d2282 8
a2289 1
if (tag == 0x1017) /* Olympus */
d2317 1
a2317 1
void CLASS nef_parse_exif (int base)
d2328 1
a2328 1
fseek (ifp, val+base, SEEK_SET);
d2331 6
a2336 3
if (tag == 0x927c &&
(!strncmp(make,"NIKON",5) || !strncmp(make,"OLYMPUS",7)))
nef_parse_makernote();
d2366 1
a2366 1
fseek (ifp, val+base, SEEK_SET);
d2422 1
a2422 1
fseek (ifp, val+base, SEEK_SET);
d2430 2
a2431 2
case 0x8769: /* Nikon EXIF tag */
nef_parse_exif(base);
d2443 4
d2456 29
d2603 1
a2603 5
switch (fget4(ifp)) {
case 270: flip = 5; break;
case 180: flip = 3; break;
case 90: flip = 6;
}
d2688 2
d2856 3
a2858 15
} else if (!memcmp (head,"\0MRM",4)) {
parse_tiff(48);
fseek (ifp, 4, SEEK_SET);
data_offset = fget4(ifp) + 8;
fseek (ifp, 24, SEEK_SET);
raw_height = fget2(ifp);
raw_width = fget2(ifp);
fseek (ifp, 12, SEEK_SET); /* PRD */
fseek (ifp, fget4(ifp) + 4, SEEK_CUR); /* TTW */
fseek (ifp, fget4(ifp) + 12, SEEK_CUR); /* WBG */
camera_red = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue = fget2(ifp);
camera_blue = fget2(ifp) / camera_blue;
} else if (!memcmp (head,"\xff\xd8\xff\xe1",4) &&
d3223 10
d3272 3
a3432 1
height = 2460;
a3433 1
raw_width = 3360;
d3442 7
d3797 5
d3855 2
a3856 1
i = width * height * (strcmp(make,"FUJIFILM") ? 0.01 : 0.005);
d3979 1
a3979 1
"\nRaw Photo Decoder \"dcraw\" v6.12"
@
1.215
log
@Don't segfault when lossless JPEG data is corrupt.
@
text
@d1513 3
a1515 3
{ { 1.321918, 0.000000, 0.149829, -0.471747 },
{ -0.288764, 1.129213, -0.486517, 0.646067 },
{ 0.061336, -0.199343, 1.138007, 0.000000 } };
d3916 1
a3916 1
"\nRaw Photo Decoder \"dcraw\" v6.11"
@
1.214
log
@Macintosh mktime() chokes on "TZ=". Better to use "TZ=UTC".
@
text
@d572 1
a572 1
ushort curve[0x10000];
d617 1
d3916 1
a3916 1
"\nRaw Photo Decoder \"dcraw\" v6.10"
@
1.213
log
@Added the Canon EOS-1Ds Mark II.
@
text
@d2294 1
a2294 1
putenv ("TZ="); /* Remove this to assume local time */
@
1.212
log
@Added the Minolta DiMAGE G400 and Fuji FinePix S20Pro.
Added the "-s" option for Fuji secondary sensors.
@
text
@d568 1
a568 1
int tag, len, jhigh=0, jwide=0, trick, row, col, diff;
d587 1
a587 1
jwide = (data[3] << 8) + data[4];
a598 1
trick = 2 * jwide / width;
d601 2
a602 2
for (row=0; row < raw_height; row++)
for (col=0; col < raw_width; col++)
d604 1
a604 1
for (dindex = dstart[col & 1]; dindex->branch[0]; )
d610 3
a612 3
if (col < 2 && (row % trick == 0)) {
vpred[col] += diff;
hpred[col] = vpred[col];
d614 2
a615 2
hpred[col & 1] += diff;
diff = hpred[col & 1];
d617 15
d3052 11
d3915 1
a3915 1
"\nRaw Photo Decoder \"dcraw\" v6.09"
@
1.211
log
@Added the Nikon E8800.
@
text
@d83 1
a83 1
int verbose=0, use_auto_wb=0, use_camera_wb=0;
d884 1
a884 7
val = pixel[col+16];
if (val == 0x3fff) { /* If the primary is maxed, */
val = pixel[col+1488] << 4; /* use the secondary. */
rgb_max = 0xffff;
}
if (val > 0xffff)
val = 0xffff;
d2756 1
a2756 1
{ "Canon", "NIKON", "Kodak", "PENTAX", "Minolta", "Konica" };
d3157 1
a3157 1
rgb_max = 0xf7ff;
d3170 3
a3172 2
rgb_max = 0xf7ff;
} else if (!strcmp(model,"FinePix F700")) {
d3179 1
a3179 1
rgb_max = 14000;
d3191 1
a3191 1
} else if (!strcmp(make,"Minolta")) {
d3198 6
a3203 1
if (model[8] <= '5') {
d3890 1
a3890 1
"\nRaw Photo Decoder \"dcraw\" v6.08"
d3901 1
d3940 1
@
1.210
log
@Added the Minolta DiMAGE Z2.
@
text
@d3143 2
a3144 1
} else if (!strcmp(model,"E8700")) {
d3890 1
a3890 1
"\nRaw Photo Decoder \"dcraw\" v6.07"
@
1.209
log
@Added the Minolta DiMAGE G600.
Changed Fuji E550, Fuji S7000, and Minolta white balances.
@
text
@d764 15
d781 2
a782 2
uchar data[2424], *dp;
ushort pixel[1616], *pix;
d787 1
a787 1
fseek (ifp, 8792, SEEK_CUR);
d790 10
a799 11
fread (data, 2424, 1, ifp);
for (dp=data, pix=pixel; dp < data+2424; dp+=12, pix+=8)
{
pix[0] = (dp[ 3] << 2) + (dp[2] >> 6);
pix[1] = (dp[ 1] >> 2) + (dp[2] << 6);
pix[2] = (dp[ 0] << 2) + (dp[7] >> 6);
pix[3] = (dp[ 6] >> 2) + (dp[7] << 6);
pix[4] = (dp[ 5] << 2) + (dp[4] >> 6);
pix[5] = (dp[11] >> 2) + (dp[4] << 6);
pix[6] = (dp[10] << 2) + (dp[9] >> 6);
pix[7] = (dp[ 8] >> 2) + (dp[9] << 6);
d802 1
a802 1
BAYER(row,col) = (pixel[col] & 0x3ff) << 4;
d3122 5
d3889 1
a3889 1
"\nRaw Photo Decoder \"dcraw\" v6.06"
@
1.208
log
@Added the Konica KD-400Z.
Fixed rgb_max for all Minolta cameras.
Range of tm_mon is 0 to 11, not 1 to 12!
@
text
@d3144 8
a3151 2
} else if (!strcmp(model,"FinePix S7000") ||
!strcmp(model,"FinePix E550")) {
a3155 2
pre_mul[0] = 1.81;
pre_mul[2] = 1.38;
a3168 1
filters = 0x94949494;
d3183 3
a3185 2
data_offset = 4016;
fseek (ifp, 1936, SEEK_SET);
d3187 9
a3195 3
height = 1956;
width = 2607;
raw_width = 2624;
d3206 1
a3206 1
pre_mul[0] = 2.00;
d3870 1
a3870 1
"\nRaw Photo Decoder \"dcraw\" v6.05"
@
1.207
log
@Fixed vng_interpolate() to match Ting Chen's vargra.m.
Use putenv() instead of setenv() for portability.
Correctly parse .badpixels when it lacks a final newline.
Added the FUJIFILM FinePix E550.
@
text
@d1899 2
a1903 2
if (min[c] > val) min[c] = val;
if (max[c] < val) max[c] = val;
d2271 1
d2575 1
d2748 1
a2748 1
{ "Canon", "NIKON", "Kodak", "PENTAX", "Minolta" };
d3161 8
d3175 2
a3176 1
if (!strncmp(model,"DiMAGE A",8))
d3178 2
a3179 1
else if (!strncmp(model,"DiMAGE G",8)) {
a3182 1
load_raw = be_low_10_load_raw;
d3187 2
d3860 1
a3860 1
"\nRaw Photo Decoder \"dcraw\" v6.04"
@
1.206
log
@Added "CLASS" macro for easier conversion to C++.
@
text
@d1857 1
a1857 3
while (1) {
fgets (line, 128, fp);
if (feof(fp)) break;
d1976 1
a1976 1
-2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,0,0x01,
d1978 1
a1978 1
-2,+1,-1,+0,0,0x04, -2,+1,+0,-1,0,0x04, -2,+1,+0,+0,0,0x06,
d1981 1
a1981 1
-1,-2,+1,+0,0,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
d1984 2
a1985 2
-1,+0,+1,-2,0,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
-1,+0,+1,+1,0,0x33, -1,+0,+1,+2,0,0x10, -1,+1,+1,-1,1,0x44,
d1987 1
a1987 1
-1,+2,+0,+1,0,0x04, -1,+2,+1,+0,0,0x04, -1,+2,+1,+1,0,0x04,
d1990 1
a1990 1
+0,-1,+2,+0,0,0x30, +0,-1,+2,+1,0,0x10, +0,+0,+0,+2,1,0x08,
d1993 1
a1993 1
+0,+1,+1,+2,0,0x10, +0,+1,+2,-1,0,0x40, +0,+1,+2,+0,0,0x60,
d1999 1
a1999 1
int code[8][640], *ip, gval[8], gmin, gmax, sum[4];
a2003 1
ip = code[row];
d2005 1
a2024 1
pix = image[row*width+1];
d2026 2
a2027 2
if (col & 1)
ip = code[row & 7];
a2037 1
pix += 4;
a2043 1
ip = code[row];
d2045 1
d2067 1
a2067 2
if ((g & 1) == 0 &&
FC(row+y,col+x) != color && FC(row+y*2,col+x*2) == color)
a2078 1
pix = image[row*width+2];
d2080 2
a2081 2
if ((col & 1) == 0)
ip = code[row & 7];
d2098 4
a2123 1
pix += 4;
d2271 1
a2271 1
setenv ("TZ", "", 1); /* Remove this to assume local time */
d2574 1
a2574 1
setenv ("TZ", "", 1);
d3142 2
a3143 1
} else if (!strcmp(model,"FinePix S7000")) {
d3604 1
d3847 1
a3847 1
"\nRaw Photo Decoder \"dcraw\" v6.02"
@
1.205
log
@Get UNIX timestamps from all image formats.
Added the Konica KD-510Z.
@
text
@d62 5
a66 2
/* Global Variables */
d96 2
d182 1
a182 1
void merror (void *ptr, char *where)
d193 1
a193 1
ushort fget2 (FILE *f)
d208 1
a208 1
int fget4 (FILE *f)
d222 1
a222 1
void canon_600_load_raw()
d252 1
a252 1
void canon_a5_load_raw()
d284 1
a284 1
unsigned getbits (int nbits)
d307 1
a307 1
void init_decoder()
d339 1
a339 1
uchar *make_decoder (const uchar *source, int level)
d365 1
a365 1
void crw_init_tables (unsigned table)
d441 1
a441 1
int canon_has_lowbits()
d456 1
a456 1
void canon_compressed_load_raw()
d530 1
a530 1
void kodak_curve (ushort *curve)
d566 1
a566 1
void lossless_jpeg_load_raw()
d633 1
a633 1
void nikon_compressed_load_raw()
d682 1
a682 1
void nikon_load_raw()
d712 1
a712 1
int nikon_is_compressed()
d731 1
a731 1
int nikon_e990()
d749 1
a749 1
int nikon_e2100()
d764 1
a764 1
void nikon_e2100_load_raw()
d792 1
a792 1
void nikon_e950_load_raw()
d809 1
a809 1
void fuji_s2_load_raw()
d825 1
a825 1
void fuji_common_load_raw (int ncol, int icol, int nrow)
d842 1
a842 1
void fuji_s5000_load_raw()
d848 1
a848 1
void fuji_s7000_load_raw()
d858 1
a858 1
void fuji_f700_load_raw()
d882 1
a882 1
void rollei_load_raw()
d907 1
a907 1
void phase_one_load_raw()
d930 1
a930 1
void ixpress_load_raw()
d946 1
a946 1
void packed_12_load_raw()
d959 1
a959 1
void unpacked_load_raw (int order, int rsh)
d976 1
a976 1
void be_16_load_raw() /* "be" = "big-endian" */
d981 1
a981 1
void be_high_12_load_raw()
d986 1
a986 1
void be_low_12_load_raw()
d991 1
a991 1
void be_low_10_load_raw()
d996 1
a996 1
void le_high_12_load_raw() /* "le" = "little-endian" */
d1001 1
a1001 1
void olympus_cseries_load_raw()
d1016 1
a1016 1
void eight_bit_load_raw()
d1031 1
a1031 1
void casio_qv5700_load_raw()
d1050 1
a1050 1
void nucore_load_raw()
d1069 1
a1069 1
const int *make_decoder_int (const int *source, int level)
d1086 1
a1086 1
int radc_token (int tree)
d1132 1
a1132 1
void kodak_radc_load_raw()
d1200 1
a1200 1
void kodak_jpeg_load_raw() {}
d1216 1
a1216 1
void kodak_jpeg_load_raw()
d1257 1
a1257 1
void kodak_dc120_load_raw()
d1273 1
a1273 1
void kodak_dc20_coeff (float juice)
d1291 1
a1291 1
void kodak_easy_load_raw()
d1319 1
a1319 1
void kodak_compressed_load_raw()
d1383 1
a1383 1
void kodak_yuv_load_raw()
d1440 1
a1440 1
void sony_decrypt (unsigned *data, int len, int start, int key)
d1457 1
a1457 1
void sony_load_raw()
d1486 1
a1486 1
void sony_rgbe_coeff()
d1500 1
a1500 1
void foveon_decoder (unsigned huff[1024], unsigned code)
d1526 1
a1526 1
void foveon_load_raw()
d1564 1
a1564 1
int apply_curve(int i, const int *curve)
d1576 1
a1576 1
void foveon_interpolate()
d1827 1
a1827 1
void bad_pixels()
d1884 1
a1884 1
void scale_colors()
d1974 1
a1974 1
void vng_interpolate()
d2138 1
a2138 1
void tiff_parse_subifd(int base)
d2189 1
a2189 1
void nef_parse_makernote()
d2265 1
a2265 1
void get_timestamp()
d2279 1
a2279 1
void nef_parse_exif(int base)
d2303 1
a2303 1
void parse_tiff(int base)
d2415 1
a2415 1
void ciff_block_1030()
d2442 1
a2442 1
void parse_ciff(int offset, int length)
d2547 1
a2547 1
void parse_rollei()
d2585 1
a2585 1
void parse_foveon()
d2620 1
a2620 1
void foveon_coeff()
d2639 1
a2639 1
void canon_rgb_coeff (float juice)
d2653 1
a2653 1
void nikon_e950_coeff()
d2673 1
a2673 1
void gmcy_coeff()
d2724 1
a2724 1
int identify()
d3617 1
a3617 1
void convert_to_rgb()
d3666 1
a3666 1
void flip_image()
d3715 1
a3715 1
void write_ppm(FILE *ofp)
d3759 1
a3759 1
void write_psd(FILE *ofp)
d3806 1
a3806 1
void write_ppm16(FILE *ofp)
d3837 1
a3837 1
int main(int argc, char **argv)
@
1.204
log
@Handle Windows paths in bad_pixels().
@
text
@d29 1
d67 2
a68 1
int data_offset, curve_offset, curve_length, timestamp;
d2256 19
a2274 1
void nef_parse_exif()
d2285 3
d2289 1
a2289 2
(!strncmp(make,"NIKON",5) || !strncmp(make,"OLYMPUS",7))) {
fseek (ifp, val, SEEK_SET);
d2291 1
a2291 2
fseek (ifp, save, SEEK_SET);
}
d2359 3
d2385 1
a2385 1
nef_parse_exif();
d2520 2
d2546 2
d2556 4
d2571 4
d2606 2
d2743 2
d2840 4
a2843 8
/* Remove excess wordage */
if (!strncmp(make,"NIKON",5) || !strncmp(make,"Canon",5))
make[5] = 0;
if (!strncmp(make,"PENTAX",6))
make[6] = 0;
if (strstr(make,"Minolta"))
strcpy (make, "Minolta");
if (!strncmp(make,"KODAK",5))
d2845 1
a2845 8
if (!strcmp(make,"Eastman Kodak Company"))
strcpy (make, "Kodak");
i = strlen(make);
if (!strncmp(model,make,i++))
memmove (model, model+i, 64-i);
/* Remove trailing spaces */
c = make + strlen(make);
d2849 3
d3156 4
d3165 3
a3172 1
data_offset = 4016;
a3174 1
fseek (ifp, 1936, SEEK_SET);
d3843 1
a3843 1
"\nRaw Photo Decoder \"dcraw\" v6.00"
@
1.203
log
@Fixed the Nikon D70 color balance.
@
text
@d1834 6
@
1.202
log
@Added automatic image flipping, with manual override.
@
text
@d3020 2
a3021 2
pre_mul[0] = 2.8;
pre_mul[2] = 1.2;
@
1.201
log
@Added the PowerShot G6/S70 and the EOS 20D.
@
text
@d71 1
a71 1
int is_canon, is_cmy, is_foveon, use_coeff, trim, ymag;
d2276 1
d2317 3
d2490 8
d2702 1
a2702 1
raw_height = raw_width = 0;
d2830 2
a2831 1
pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = ymag = 1;
d3618 46
d3683 1
a3683 1
width-trim*2, ymag*(height-trim*2));
d3685 1
a3685 1
ppm = calloc (width-trim*2, 3);
d3698 2
a3699 1
ppm[col-trim][c] = val;
d3703 1
a3703 1
fwrite (ppm, width-trim*2, 3, ofp);
d3791 2
a3792 1
int arg, status=0, identify_only=0, write_to_stdout=0, half_size=0;
d3800 1
a3800 1
"\nRaw Photo Decoder \"dcraw\" v5.90"
d3817 1
d3838 1
d3933 8
@
1.200
log
@Eliminated the crw_decompress() function.
@
text
@d57 1
d2363 1
a2363 1
if (!strcmp(model,"Canon EOS-1D Mark II"))
d2937 7
d2964 2
a2965 1
} else if (!strcmp(model,"EOS-1D Mark II")) {
d2973 2
a2974 2
pre_mul[0] = 2.248;
pre_mul[2] = 1.174;
d3517 1
a3517 1
if (!load_raw) {
d3739 1
a3739 1
"\nRaw Photo Decoder \"dcraw\" v5.88"
d3780 1
a3780 1
case 'h': half_size = 1;
@
1.199
log
@Added the Canon PowerShot A5 Zoom.
@
text
@a427 47
Decompress "count" blocks of 64 samples each.
*/
void crw_decompress (ushort *outbuf, int count)
{
struct decode *decode, *dindex;
int i, leaf, len, diff, diffbuf[64];
static int carry, pixel, base[2];
zero_after_ff = 1;
if (!outbuf) { /* Initialize */
carry = pixel = 0;
fseek (ifp, count, SEEK_SET);
getbits(-1);
return;
}
while (count--) {
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 (pixel++ % raw_width == 0)
base[0] = base[1] = 512;
outbuf[i] = ( base[i & 1] += diffbuf[i] );
}
outbuf += 64;
}
}
/*
d453 2
d462 3
a464 1
crw_decompress (0, 540 + lowbits*raw_height*raw_width/4);
d466 26
a491 1
crw_decompress (pixel, raw_width/8); /* Get eight rows */
@
1.198
log
@Don't be fooled by camera-generated Nikon TIFFs.
@
text
@d2844 1
a2844 1
} else
d2859 2
a2860 1
} else if (!strcmp(model,"PowerShot A5")) {
d3748 1
a3748 1
"\nRaw Photo Decoder \"dcraw\" v5.87"
@
1.197
log
@Allocate enough bytes for the G500.
@
text
@d2732 1
a2732 1
} else
d2734 3
d3747 1
a3747 1
"\nRaw Photo Decoder \"dcraw\" v5.86"
@
1.196
log
@Added the Minolta DiMAGE G500.
Set black=640 for the Olympus E-20.
@
text
@d974 1
a974 1
pixel = calloc (width, sizeof *pixel);
@
1.195
log
@Fixed color problems with the Nikon E995, Nikon E5400,
and Leaf Valeo 22.
@
text
@d977 1
a977 1
fread (pixel, 2, width, ifp);
d1001 5
d2748 6
d3114 15
d3232 1
d3744 1
a3744 1
"\nRaw Photo Decoder \"dcraw\" v5.85"
@
1.194
log
@vng_interpolate() must clip to rgb_max, not 0xffff.
@
text
@d739 18
d2687 1
a2687 1
{ 4771840, "NIKON", "E990/995" },
d3013 1
a3013 1
} else if (!strcmp(model,"E990/995")) {
a3015 1
filters = 0xb4b4b4b4;
d3017 13
a3029 4
nikon_e950_coeff();
pre_mul[0] = 1.196;
pre_mul[1] = 1.246;
pre_mul[2] = 1.018;
d3059 4
d3182 2
d3717 1
a3717 1
"\nRaw Photo Decoder \"dcraw\" v5.84"
@
1.193
log
@Found the curve tables for all Kodak cameras,
and re-balanced the colors accordingly.
@
text
@d2103 1
a2103 1
if (t > 0xffff) t = 0xffff;
d3685 1
a3685 1
"\nRaw Photo Decoder \"dcraw\" v5.83"
@
1.192
log
@Major speed increase in convert_to_rgb().
@
text
@d65 1
a65 1
int data_offset, nef_curve_offset, timestamp;
d181 33
d540 31
a570 2
ushort fget2 (FILE *);
int fget4 (FILE *);
d578 1
a578 1
int tag, len, jhigh=0, jwide=0, trick, row, col, irow, icol, diff;
d582 1
d584 1
d586 1
d628 1
a628 1
if ((unsigned) (irow = row-top_margin) >= height)
d630 6
a635 4
if ((unsigned) (icol = col-left_margin) < width)
BAYER(irow,icol) = diff << 2;
else
bblack += diff;
d639 2
d656 1
a656 1
fseek (ifp, nef_curve_offset, SEEK_SET);
a1180 1
black = 0;
d1281 1
d1284 2
a1285 1
if (width < raw_width)
d1294 1
a1294 1
BAYER(row,icol) = (ushort) pixel[col] << 6;
d1296 1
a1296 1
black += pixel[col];
d1300 1
a1300 1
black = ((INT64) black << 6) / ((raw_width - width) * height);
a1305 19
void kodak_dcr_curve (ushort *curve)
{
int i, j;
for (i=0; i < 0x1000; i++)
curve[i] = i;
if (strncmp(model,"DCS Pro",7)) return;
fseek (ifp, 0x4000, SEEK_SET);
for (i=j=0; j < 100; i++) {
if (i > 0x10000) return;
if (fget2(ifp) == j) j++;
else j=0;
}
fseek (ifp, 7992, SEEK_CUR);
for (i=0; i < 0x400; i++)
curve[i] = fget2(ifp);
rgb_max = curve[i-1] << 2;
}
d1314 1
a1314 3
kodak_dcr_curve (curve);
fseek (ifp, data_offset, SEEK_SET);
d1378 1
a1378 3
kodak_dcr_curve (curve);
fseek (ifp, data_offset, SEEK_SET);
a2118 33
/*
Get a 2-byte integer, making no assumptions about CPU byte order.
Nor should we assume that the compiler evaluates left-to-right.
*/
ushort fget2 (FILE *f)
{
uchar a, b;
a = fgetc(f);
b = fgetc(f);
if (order == 0x4949) /* "II" means little-endian */
return a + (b << 8);
else /* "MM" means big-endian */
return (a << 8) + b;
}
/*
Same for a 4-byte integer.
*/
int fget4 (FILE *f)
{
uchar a, b, c, d;
a = fgetc(f);
b = fgetc(f);
c = fgetc(f);
d = fgetc(f);
if (order == 0x4949)
return a + (b << 8) + (c << 16) + (d << 24);
else
return (a << 24) + (b << 16) + (c << 8) + d;
}
d2128 1
a2128 1
if (type == 3) { /* short int */
d2163 3
a2165 4
case 0x828d: /* Unknown */
case 0x828e: /* Unknown */
case 0x9217: /* Unknown */
break;
d2211 1
a2211 1
nef_curve_offset = base+val + 2112;
d2213 1
a2213 1
nef_curve_offset = base+val + 2;
a2270 1
nef_curve_offset = 0;
d2281 1
a2281 1
if (type == 3) { /* short int */
d2310 4
d2688 1
a2688 1
data_offset = tiff_data_compression = 0;
d3068 1
a3068 1
rgb_max = 0x3e00;
a3211 1
black = 400;
d3215 3
a3217 2
pre_mul[0] = 1.327;
pre_mul[2] = 2.093;
d3221 2
a3222 2
pre_mul[0] = 1.43;
pre_mul[2] = 2.16;
d3226 2
a3227 2
pre_mul[0] = 1.28;
pre_mul[2] = 2.00;
d3229 3
a3231 3
black = 0;
pre_mul[0] = 0.973;
pre_mul[2] = 0.987;
d3233 3
a3235 3
black = 0;
pre_mul[0] = 0.996;
pre_mul[2] = 1.279;
d3239 2
a3240 2
pre_mul[0] = 1.21;
pre_mul[2] = 1.63;
d3244 2
a3245 2
pre_mul[0] = 1.46;
pre_mul[2] = 1.84;
d3252 3
a3254 2
pre_mul[0] = 1.00;
pre_mul[2] = 1.20;
d3256 3
a3258 2
pre_mul[0] = 0.985;
pre_mul[2] = 1.15;
d3260 3
a3262 2
pre_mul[0] = 1.00;
pre_mul[2] = 1.20;
d3264 3
a3266 2
pre_mul[0] = 1.12;
pre_mul[2] = 1.07;
d3269 3
a3271 2
pre_mul[0] = 1.05;
pre_mul[2] = 1.17;
d3273 1
a3313 1
rgb_max = 0x3fc0;
a3320 1
black = 0;
d3685 1
a3685 1
"\nRaw Photo Decoder \"dcraw\" v5.82"
@
1.191
log
@Added camera white balance for all Olympus models.
@
text
@d3486 1
a3486 1
float rgb[4];
d3510 17
a3526 6
for (r=0; r < 3; r++)
rgb[r] = img[r];
for (rgb[3]=r=0; r < 3; r++) { /* Compute the magnitude */
if (rgb[r] < 0) rgb[r] = 0;
if (rgb[r] > rgb_max) rgb[r] = rgb_max;
rgb[3] += rgb[r]*rgb[r];
a3527 6
rgb[3] = sqrt(rgb[3])/2;
if (rgb[3] > 0xffff)
rgb[3] = 0xffff;
for (r=0; r < 4; r++)
img[r] = rgb[r];
histogram[img[3] >> 3]++; /* bin width is 8 */
d3665 1
a3665 1
"\nRaw Photo Decoder \"dcraw\" v5.81"
@
1.190
log
@Figured out how to get linear data from the Kodak DCS Pros.
Improved support for the Fuji S2 and F700.
Closed a histogram gap in the Canon S50 and G5.
@
text
@d2175 3
a2177 1
} else
d2185 4
a2188 1
val = fget4(ifp);
d2220 4
d2240 2
a2241 1
if (tag == 0x927c && !strncmp(make,"NIKON",5)) {
d3167 2
d3660 1
a3660 1
"\nRaw Photo Decoder \"dcraw\" v5.80"
@
1.189
log
@Fixed Kodak YUV code for widths not divisible by 8.
Discovered that Kodak DCS Pro files are 10-bpp.
@
text
@d465 1
a465 1
int lowbits, shift, i, row, r, col, save;
d482 5
a486 2
for (r=0; r < 8; r+=2, prow++)
*prow = (*prow << 2) + ((c >> r) & 3);
d794 1
a794 1
if (val == 0x3fff) /* If the primary is maxed, */
d796 2
d1236 19
d1258 1
a1258 1
ushort raw[6];
d1261 4
a1264 1
int diff, shift;
a1265 6
/*
Kodak claims that their "DCS Pro" cameras are all 12-bit,
but their raw data values never exceed 1023. Thus I treat
them as 10-bit cameras.
*/
shift = strncmp(model,"DCS Pro",7) ? 2 : 4;
d1317 1
a1317 1
BAYER(row,col) = diff << shift;
d1326 5
a1330 2
int i, li=0, si, diff, shift, six[6], y[4], cb=0, cr=0, rgb[3];
ushort *ip;
a1331 1
shift = strncmp(model,"DCS Pro",7) ? 2 : 4;
d1361 1
a1361 1
six[si] = diff << shift;
d1371 3
a1373 3
rgb[0] = y[i] + 1.40200/2 * cr;
rgb[1] = y[i] - 0.34414/2 * cb - 0.71414/2 * cr;
rgb[2] = y[i] + 1.77200/2 * cb;
d1375 1
a1375 1
if (rgb[c] > 0) ip[c] = rgb[c];
d3016 1
d3042 1
a3042 1
rgb_max = 0xffff;
d3265 2
a3266 2
pre_mul[1] = 1.0191;
pre_mul[2] = 1.1567;
d3268 2
a3269 2
pre_mul[0] = 1.25;
pre_mul[2] = 1.225;
d3271 2
a3272 2
pre_mul[0] = 1.24;
pre_mul[2] = 1.16;
d3274 2
a3275 2
pre_mul[0] = 1.273;
pre_mul[2] = 1.235;
a3295 4
if (pre_mul[1] == 1) {
pre_mul[0] *= 1.05;
pre_mul[2] *= 1.10;
}
d3648 1
a3648 1
"\nRaw Photo Decoder \"dcraw\" v5.79"
@
1.188
log
@Don't use canon_rgb_coeff() by default, other minor fixes.
@
text
@d1237 1
a1237 1
int diff;
d1239 6
d1296 1
a1296 1
BAYER(row,col) = diff << 2;
d1305 1
a1305 1
int i, li=0, si, diff, six[6], y[4], cb=0, cr=0, rgb[3];
d1308 1
d1320 5
d1338 1
a1338 1
six[si] = diff << 2;
d3593 2
d3628 1
a3628 1
"\nRaw Photo Decoder \"dcraw\" v5.78"
@
1.187
log
@Added the Panasonic DMC-LC1.
@
text
@d2829 1
d2832 1
d3257 2
d3474 2
a3475 1
if (rgb[3] > 0xffff) rgb[3] = 0xffff;
d3561 2
a3562 1
if (val > 0xffff) val=0xffff;
d3580 3
d3584 1
a3584 1
width-trim*2, height-trim*2, rgb_max);
d3594 2
a3595 1
if (val > 0xffff) val=0xffff;
d3614 1
a3614 1
"\nRaw Photo Decoder \"dcraw\" v5.77"
@
1.186
log
@Minor optimizations in vng_interpolate()
@
text
@d3092 1
a3092 1
} else if (!strcmp(model,"DIGILUX 2")) {
@
1.185
log
@Added the Kodak DCS Pro 14nx and SLR/c.
@
text
@d1945 1
d1998 2
a1999 3
gmin = INT_MAX; /* Choose a threshold */
gmax = 0;
for (g=0; g < 8; g++) {
d2017 7
a2023 2
t = pix[color] + (sum[c] - sum[color])/num;
brow[2][col][c] = t > 0 ? (t < 0xffff ? t : 0xffff) : 0;
@
1.184
log
@Added default white balance for the Canon EOS Kiss Digital.
@
text
@d3224 6
d3231 2
a3232 2
pre_mul[0] = 1.168;
pre_mul[2] = 1.230;
d3251 4
d3599 1
a3599 1
"\nRaw Photo Decoder \"dcraw\" v5.76"
@
1.183
log
@In 16-bit PPM output, replace 65535 with rgb_max.
@
text
@d2848 4
@
1.182
log
@Added the Casio Exlim Pro 600, Creo Leaf Valeo 22,
and Leica Digilux 2. Changed TIFF tags to hex.
@
text
@d3555 2
a3556 2
fprintf (ofp, "P6\n%d %d\n65535\n",
width-trim*2, height-trim*2);
d3585 1
a3585 1
"\nRaw Photo Decoder \"dcraw\" v5.75"
@
1.181
log
@Allow "-w" flag to work with "-h" and "-f".
Added camera white balance for all Minolta raw files.
Fixed white balance for the Canon EOS 300D DIGITAL.
Read all SubIFDs for non-Kodak cameras.
@
text
@d863 2
a864 1
void pentax_optio_load_raw()
d872 2
a873 2
for (col=0; col < 17; col++)
getbits(16);
a876 10
void packed_12_load_raw()
{
int row, col;
getbits(-1);
for (row=0; row < height; row++)
for (col=0; col < width; col++)
BAYER(row,col) = getbits(12) << 2;
}
d2219 4
a2222 1
val = fget4(ifp);
d2226 7
a2232 1
case 256: /* ImageWidth */
d2235 1
a2235 1
case 257: /* ImageHeight */
d2238 1
a2238 1
case 271: /* Make tag */
d2241 1
a2241 1
case 272: /* Model tag */
d2244 1
a2244 1
case 273: /* StripOffset */
d2248 1
a2248 1
case 33405: /* Model2 tag */
d2251 1
a2251 1
case 305: /* Software tag */
d2256 10
a2265 1
case 330: /* SubIFD tag */
d2294 1
a2294 1
if (make[0] == 0 && wide == 0x2a80000 && high == 0x2a80000) {
d2611 1
d3012 2
a3013 1
load_raw = pentax_optio_load_raw;
d3019 2
a3020 1
load_raw = pentax_optio_load_raw;
d3078 12
d3365 7
d3585 1
a3585 1
"\nRaw Photo Decoder \"dcraw\" v5.73"
@
1.180
log
@Added the Kodak DCS Pro SLR/n.
@
text
@d1842 1
a1842 1
else if (camera_red && camera_blue && colors == 3) {
a1843 1
pre_mul[1] = 1.0;
d1845 1
d2257 2
a2258 1
if (len > 2) len=2;
d2347 2
a2348 1
if (!strcmp(model,"Canon EOS DIGITAL REBEL") && wbi == 6)
d2642 7
d2990 2
a2991 2
pre_mul[0] = 1.57;
pre_mul[2] = 1.42;
d3554 1
a3554 1
"\nRaw Photo Decoder \"dcraw\" v5.71"
@
1.179
log
@Added the Kodaks DC20, DC25, DC40, DC50, and DC120.
Added the Nikon Coolpix 8700.
@
text
@d3187 3
d3545 1
a3545 1
"\nRaw Photo Decoder \"dcraw\" v5.70"
@
1.179.1.1
log
@Version 5.72 changes abandoned in this side branch.
@
text
@d1842 1
a1842 1
else if (camera_red && camera_blue) {
d1844 1
a1845 1
pre_mul[1] = pre_mul[3] = 1.0;
d2189 1
a2189 1
void mrw_parse_makernote(int base)
d2200 3
a2202 27
if (tag == 3) {
fseek (ifp, base+val + 112, SEEK_SET);
camera_red = fget4(ifp);
camera_red /= (camera_blue = fget4(ifp));
camera_blue = fget4(ifp) / camera_blue;
}
fseek (ifp, save, SEEK_SET);
}
}
void nef_parse_exif(int base)
{
int entries, tag, type, len, val, save;
entries = fget2(ifp);
while (entries--) {
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
val = fget4(ifp);
save = ftell(ifp);
if (tag == 0x927c) {
fseek (ifp, val+base, SEEK_SET);
if (!strncmp(make,"NIKON",5))
nef_parse_makernote();
else if (strstr(make,"Minolta"))
mrw_parse_makernote(base);
d2269 1
a2269 1
nef_parse_exif(base);
d2346 1
a2346 2
if (((!strcmp(model,"Canon EOS DIGITAL REBEL") ||
!strcmp(model,"Canon EOS 300D DIGITAL"))) && wbi == 6)
d3542 1
a3542 1
"\nRaw Photo Decoder \"dcraw\" v5.72"
@
1.178
log
@Added option for half-size output.
@
text
@d29 7
d991 223
d1235 2
d2588 2
d2691 2
d2942 4
d3196 1
d3212 53
d3338 6
d3542 1
a3542 1
"\nRaw Photo Decoder v5.62"
@
1.177
log
@Added the Canon PowerShot Pro1 and EOS-1D Mark II.
Never exit() -- always return from main().
@
text
@d62 1
d92 4
d195 1
a195 1
image[orow*width+col][FC(orow,col)] = pixel[col] << 4;
d224 1
a224 1
image[row*width+col][FC(row,col)] = (pixel[col] & 0x3ff) << 4;
d486 1
a486 2
image[irow*width+icol][FC(irow,icol)] =
pixel[r*raw_width+col] << shift;
d516 1
a516 1
len = fget2(ifp);
d518 1
a518 1
fread (data, 1, len-2, ifp);
d556 1
a556 1
image[irow*width+icol][FC(irow,icol)] = diff << 2;
d608 1
a608 1
image[row*width+col-left_margin][FC(row,col)] = curve[diff] << 2;
d631 1
a631 1
image[row*width+col-left_margin][FC(row,col)] = i << 2;
d701 1
a701 1
image[row*width+col][FC(row,col)] = (pixel[col] & 0x3ff) << 4;
d713 1
a713 1
image[row*width+col][FC(row,col)] = getbits(10) << 4;
d733 1
a733 1
image[r*width+c][FC(r,c)] = ntohs(pixel[col]) << 2;
d750 1
a750 1
image[r*width+c][FC(r,c)] = pixel[col] << 2;
d788 1
a788 1
image[r*width+c][FC(r,c)] = val;
d813 1
a813 1
image[row*width+col][FC(row,col)] = (todo[i+1] & 0x3ff) << 4;
d837 1
a837 1
image[row*width+col][FC(row,col)] = pixel[col+left_margin];
d852 1
a852 1
image[row*width+col][FC(row,col)] = pixel[width-1-col];
d863 1
a863 1
image[row*width+col][FC(row,col)] = getbits(12) << 2;
d876 1
a876 1
image[row*width+col][FC(row,col)] = getbits(12) << 2;
d891 1
a891 1
image[row*width+col][FC(row,col)] = pixel[col] << 8 >> (8+rsh);
d927 1
a927 1
image[row*width+col][FC(row,col)] = getbits(12) << 2;
d941 1
a941 1
image[row*width+col][FC(row,col)] = pixel[col] << 6;
d961 1
a961 1
image[row*width+col][FC(row,col)] = (pixel[col] & 0x3ff) << 4;
d979 1
a979 1
image[row*width+col][FC(row,col)] = (dp[0] << 2) + (dp[1] << 10);
d998 1
a998 1
image[row*width+icol][FC(row,icol)] = (ushort) pixel[col] << 6;
d1067 1
a1067 1
image[row*width+col][FC(row,col)] = diff << 2;
d1161 1
a1161 1
image[row*width+icol][FC(row,icol)] = ntohs(pixel[col]);
d1515 1
d1546 1
a1546 1
tot += image[r*width+c][FC(r,c)];
d1549 1
a1549 1
image[row*width+col][FC(row,col)] = tot/n;
d3234 1
a3234 1
int arg, status=0, identify_only=0, write_to_stdout=0;
d3242 1
a3242 1
"\nRaw Photo Decoder v5.60"
d3252 1
d3283 1
d3341 4
a3344 1
image = calloc (height * width, sizeof *image);
d3351 3
a3358 1
bad_pixels();
d3361 1
@
1.176
log
@Added the Pentax Optio S.
@
text
@d25 1
d75 1
d166 1
a166 1
exit(1);
d286 1
a286 1
void make_decoder (const uchar *source, int level)
d296 1
a296 1
exit(1);
d300 10
a309 7
if (level < next && i > leaf) {
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++];
d456 1
d484 1
a484 1
black += pixel[r*raw_width+col];
d489 2
a490 1
black = ((INT64) black << shift) / ((raw_width - width) * height);
d493 3
d502 2
a503 2
uchar head[64];
int jwide, trick, row, col, len, diff;
d505 24
a528 1
struct decode *dindex;
a529 4
fread (head, 1, 64, ifp);
init_decoder();
make_decoder (head+7, 0);
jwide = (head[43] << 8) + head[44];
d533 2
a534 2
for (row=0; row < height; row++)
for (col=0; col < width; col++)
d536 1
a536 1
for (dindex=first_decode; dindex->branch[0]; )
d549 6
a554 1
image[row*width+col][FC(row,col)] = diff << 2;
d556 2
a559 3
ushort fget2 (FILE *);
int fget4 (FILE *);
d999 1
a999 1
if (width < raw_width)
d1186 1
a1186 1
exit(1);
d1978 1
a1978 1
int wide=0, high=0, offset=0;
d2008 1
d2044 3
d2589 7
d2609 10
d3229 1
a3229 1
int arg, id, identify_only=0, write_to_stdout=0;
d3232 1
a3232 1
FILE *ofp;
d3237 1
a3237 1
"\nRaw Photo Decoder v5.58"
d3257 1
a3257 1
exit(1);
d3265 1
a3265 1
exit(1);
d3289 1
a3289 1
exit(1);
d3294 1
a3294 1
exit(1);
d3299 1
a3299 1
exit(1);
d3304 1
a3304 1
exit(1);
d3311 9
d3321 8
a3328 2
ifp = fopen (ifname, "rb");
if (!ifp) perror(ifname);
d3330 1
a3330 8
if (!(id = !ifp || identify()))
fprintf (stderr, "%s is a %s %s image.\n", ifname, make, model);
if (ifp) fclose(ifp);
if (arg+1 < argc) continue;
exit(id);
}
if (!ifp) continue;
if (identify()) {
d3362 1
a3362 1
if (write_to_stdout) {
d3364 1
a3364 2
ofp = stdout;
} else {
d3370 1
d3384 1
a3384 1
return 0;
@
1.175
log
@Added the Kodak NC2000F.
@
text
@d819 1
a819 1
void pentax_optio_s4_load_raw()
d2324 1
d2691 6
d2700 1
a2700 1
load_raw = pentax_optio_s4_load_raw;
d3183 1
a3183 1
"\nRaw Photo Decoder v5.57"
@
1.174
log
@Check array bounds when building a Huffman tree.
Fixed the Canon EOS 10D camera white balance.
@
text
@d950 1
a950 1
int row, col, margin;
d952 1
a952 1
if ((margin = (raw_width - width)/2))
d958 7
a964 4
for (col=0; col < width; col++)
image[row*width+col][FC(row,col)] = (ushort) pixel[col+margin] << 6;
if (margin == 2)
black += pixel[0] + pixel[1] + pixel[raw_width-2] + pixel[raw_width-1];
d966 2
a967 2
if (margin)
black = ((INT64) black << 6) / (4 * height);
d2799 17
a2815 1
if (!strcmp(model,"DCS315C")) {
d2818 1
a2819 1
} else if (!strcmp(model,"DCS330C")) {
a2821 1
black = 0;
d2823 2
d2827 1
d2829 1
a2829 1
} else if (!strcmp(model,"DCS460")) {
d2832 1
d2834 1
a2834 1
} else if (!strcmp(model,"DCS460A")) {
a2836 9
width -= 4;
} else if (!strcmp(model,"EOSDCS3B")) {
pre_mul[0] = 1.43;
pre_mul[2] = 2.16;
width -= 4;
} else if (!strcmp(model,"EOSDCS1")) {
pre_mul[0] = 1.28;
pre_mul[2] = 2.00;
width -= 4;
d2886 2
a2887 1
load_raw = kodak_easy_load_raw; break;
d2889 2
a2890 1
load_raw = lossless_jpeg_load_raw; break;
d3176 1
a3176 1
"\nRaw Photo Decoder v5.56"
@
1.173
log
@Fixed Custom WB for the Canon EOS DIGITAL REBEL.
@
text
@d62 1
d78 1
a78 1
} first_decode[32], second_decode[512];
d163 1
a163 1
fprintf (stderr, "Out of memory in %s\n", where);
d226 8
a233 1
A rough description of Canon's compression algorithm:
d235 16
a250 12
+ Each pixel outputs a 10-bit sample, from 0 to 1023.
+ Split the data into blocks of 64 samples each.
+ Subtract from each sample the value of the sample two positions
to the left, which has the same color filter. From the two
leftmost samples in each row, subtract 512.
+ For each nonzero sample, make a token consisting of two four-bit
numbers. The low nibble is the number of bits required to
represent the sample, and the high nibble is the number of
zero samples preceding this sample.
+ Output this token as a variable-length bitstring using
one of three tablesets. Follow it with a fixed-length
bitstring containing the sample.
d252 5
a256 3
The "first_decode" table is used for the first sample in each
block, and the "second_decode" table is used for the others.
*/
d284 1
a284 1
void make_decoder(struct decode *dest, const uchar *source, int level)
d286 2
a287 2
static struct decode *free; /* Next unused node */
static int leaf; /* number of leaves already added */
d290 5
a294 3
if (level==0) {
free = dest;
leaf = 0;
a295 4
free++;
/*
At what level should the next leaf appear?
*/
a297 1
d299 4
a302 4
dest->branch[0] = free;
make_decoder (free, source, level+1);
dest->branch[1] = free;
make_decoder (free, source, level+1);
d304 1
a304 1
dest->leaf = source[16 + leaf++];
d307 1
a307 1
void init_tables(unsigned table)
d371 4
a374 31
memset ( first_decode, 0, sizeof first_decode);
memset (second_decode, 0, sizeof second_decode);
make_decoder ( first_decode, first_tree[table], 0);
make_decoder (second_decode, second_tree[table], 0);
}
/*
getbits(-1) initializes the buffer
getbits(n) where 0 <= n <= 25 returns an n-bit integer
*/
unsigned getbits(int nbits)
{
static unsigned long bitbuf=0;
static int vbits=0;
unsigned c, ret;
if (nbits == 0) return 0;
if (nbits == -1)
ret = bitbuf = vbits = 0;
else {
ret = bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - nbits);
vbits -= nbits;
}
while (vbits < LONG_BIT - 7) {
c = fgetc(ifp);
bitbuf = (bitbuf << 8) + c;
if (c == 0xff && is_canon) /* Canon puts an extra 0 after 0xff */
fgetc(ifp);
vbits += 8;
}
return ret;
a378 4
Note that the width passed to this function is slightly
larger than the global width, because it includes some
blank pixels that (*load_raw) will strip off.
d380 1
a380 1
void decompress(ushort *outbuf, int count)
d386 1
d456 1
a456 1
decompress(0, 540 + lowbits*raw_height*raw_width/4);
d458 1
a458 1
decompress(pixel, raw_width/8); /* Get eight rows */
d498 2
a499 2
memset (first_decode, 0, sizeof first_decode);
make_decoder (first_decode, head+7, 0);
d502 1
a502 1
is_canon = 1;
d537 2
a538 2
memset (first_decode, 0, sizeof first_decode);
make_decoder (first_decode, nikon_tree, 0);
d1142 1
a1142 1
void foveon_decoder(struct decode *dest, unsigned huff[1024], unsigned code)
d1144 1
a1144 1
static struct decode *free;
d1147 5
a1151 1
free++;
d1155 1
a1155 1
dest->leaf = i;
d1158 1
a1158 3
} else
free = dest + 1;
d1162 4
a1165 4
dest->branch[0] = free;
foveon_decoder (free, huff, code);
dest->branch[1] = free;
foveon_decoder (free, huff, code+1);
d1170 1
a1170 1
struct decode decode[2048], *dindex;
d1181 2
a1182 2
memset (decode, 0, sizeof decode);
foveon_decoder (decode, huff, 0);
d1189 1
a1189 1
for (dindex=decode; dindex->branch[0]; ) {
d2046 3
a2048 2
int tboff, nrecs, i, type, len, roff, aoff, save;
int wbi=-1, remap[] = { 1,2,3,4,5,1 };
d2105 2
d2128 1
a2128 1
init_tables (fget4(ifp));
d2331 1
d3161 1
a3161 1
"\nRaw Photo Decoder v5.54"
@
1.172
log
@Simplified the CRW decompression logic.
@
text
@d2085 2
@
1.171
log
@Fixed the Nikon D1H default white balance.
@
text
@d403 1
a403 1
int i, leaf, len, sign, diff, diffbuf[64];
d427 3
a429 6
sign=(getbits(1)); /* 1 is positive, 0 is negative */
diff=getbits(len-1);
if (sign)
diff += 1 << (len-1);
else
diff += (-1 << len) + 1;
d3172 1
a3172 1
"\nRaw Photo Decoder v5.53"
@
1.170
log
@Save time by precomputing all possible "scale" values.
@
text
@d2584 2
a2585 2
pre_mul[0] = 1.347;
pre_mul[2] = 3.279;
@
1.169
log
@Added the Minolta DiMAGE A2 and Olympus C8080WZ.
@
text
@d3054 1
a3054 1
float max, mul, scale;
d3072 3
a3078 2
/* In some math libraries, pow(0,expo) doesn't return zero */
scale = rgb[3] ? mul * pow (rgb[3]*2/max, gamma_val-1) : 0;
d3080 1
a3080 1
val = rgb[c] * scale;
d3175 1
a3175 1
"\nRaw Photo Decoder v5.52"
@
1.168
log
@dcraw.c no longer calls external code to read lossless JPEG.
@
text
@d908 1
a908 1
fseek (ifp, 15360 - row*(-width*height*3/4 & -2048), SEEK_SET);
d1962 1
a1962 1
int wide=0, high=0;
d1980 1
a1980 1
wide = val >> 16;
d1983 1
a1983 1
high = val >> 16;
d1991 3
d2021 7
a2027 1
if (make[0] == 0 && wide == 680 && high == 680) {
d2421 2
a2422 2
if (!strncmp(make,"OLYMPUS",7) || !strncmp(make,"Minolta",7))
make[7] = 0;
d2690 1
a2690 1
if (!strcmp(model,"DiMAGE A1"))
a2762 2
height = 1966;
width = 2624;
a2763 1
data_offset = 0x54000;
a2767 3
height = 1684;
width = 2256;
data_offset = 0x4000;
a2771 3
height = 1924;
width = 2576;
data_offset = 0x4000;
a2775 2
height = 1926;
width = 2576;
a2780 2
height = 1950;
width = 2608;
d2782 5
d3174 1
a3174 1
"\nRaw Photo Decoder v5.50"
@
1.167
log
@Added the Nikon D70.
@
text
@a15 5
The Canon EOS-1D and some Kodak cameras compress their raw data
with lossless JPEG. To read such images, you must also download:
http://www.cybercom.net/~dcoffin/dcraw/ljpeg_decode.tar.gz
d41 2
a42 3
#include "jpeg.h"
#include "mcu.h"
#include "proto.h"
d287 1
a287 1
if (level < next) { /* Are we there yet? */
a507 1
#ifdef LJPEG_DECODE
d509 2
a510 1
Lossless JPEG code calls this function to get data.
d512 1
a512 1
int ReadJpegData (char *buffer, int numBytes)
d514 4
a517 2
return fread(buffer, 1, numBytes, ifp);
}
d519 24
a542 19
/*
Called from DecodeImage() in huffd.c to write one row.
Notice that one row of the JPEG data is two rows for us.
Canon did this so that the predictors could work against
like colors. Quite clever!
Kodak didn't think of that. 8-/
*/
void PmPutRow(ushort **buf, int numComp, int numCol, int row)
{
int r, col, trick=1;
trick = numComp * numCol / width;
row *= trick;
for (r = row; r < row+trick; r++)
for (col=0; col < width; col+=2) {
image[r*width+col+0][FC(r,col+0)] = buf[0][0] << 2;
image[r*width+col+1][FC(r,col+1)] = buf[0][1] << 2;
buf++;
d546 2
a547 19
void lossless_jpeg_load_raw()
{
DecompressInfo dcInfo;
MEMSET(&dcInfo, 0, sizeof(dcInfo));
ReadFileHeader (&dcInfo);
ReadScanHeader (&dcInfo);
DecoderStructInit (&dcInfo);
HuffDecoderInit (&dcInfo);
DecodeImage (&dcInfo);
FreeArray2D (mcuROW1);
FreeArray2D (mcuROW2);
}
#else
void lossless_jpeg_load_raw() { }
#endif /* LJPEG_DECODE */
ushort fget2 (FILE *f);
int fget4 (FILE *f);
d586 1
a586 1
hpred[col & 1] = vpred[i];
a2975 7
#ifndef LJPEG_DECODE
if (load_raw == lossless_jpeg_load_raw) {
fprintf (stderr, "%s: %s %s requires lossless JPEG decoder.\n",
ifname, make, model);
return 1;
}
#endif
d3173 1
a3173 4
"\nRaw Photo Decoder v5.47"
#ifdef LJPEG_DECODE
" with Lossless JPEG support"
#endif
@
1.166
log
@Changed "bit" to "bpp" for clarity.
@
text
@d1939 6
d2612 4
d3196 1
a3196 1
"\nRaw Photo Decoder v5.46"
@
1.165
log
@Fixed the Pentax Optio S4 white balance.
@
text
@d3061 1
a3061 1
Write the image to a 24-bit PPM file.
d3103 1
a3103 1
Write the image to a 48-bit Photoshop file.
d3149 1
a3149 1
Write the image to a 48-bit PPM file.
d3199 1
a3199 1
"\n-g Set gamma (0.6 by default, only for 24-bit output)"
d3205 3
a3207 3
"\n-2 Write 24-bit PPM (default)"
"\n-3 Write 48-bit PSD (Adobe Photoshop)"
"\n-4 Write 48-bit PPM"
@
1.164
log
@When finding the white point, consider that
half of a Fuji output image is black space.
@
text
@d2702 2
a2703 2
pre_mul[0] = 2.09;
pre_mul[1] = 1.06;
@
1.163
log
@Reduced vng_interpolate() execution time by one-third.
(thanks to Ahti Heinla for this fix)
@
text
@d3073 1
d3075 1
a3075 1
if ((total+=histogram[val]) > (int)(width*height*0.01)) break;
d3186 1
a3186 1
"\nRaw Photo Decoder v5.45"
@
1.162
log
@Added the Pentax Optio S4.
@
text
@d1759 6
a1764 3
while ((g = *ip++) != INT_MAX) { /* Calculate gradients */
diff = abs(pix[g] - pix[*ip++]);
diff <<= *ip++;
d1768 1
d3185 1
a3185 1
"\nRaw Photo Decoder v5.44"
@
1.161
log
@Added camera white balance for Nikon D100 and D2H. (Thanks, Eric!)
@
text
@d857 13
d2333 1
d2694 6
d3181 1
a3181 1
"\nRaw Photo Decoder v5.43"
@
1.160
log
@Added the Sony DSC-F828.
@
text
@d1899 1
a1900 1
save = ftell(ifp);
a1905 1
fseek (ifp, save, SEEK_SET);
d1911 14
d3161 1
a3161 1
"\nRaw Photo Decoder v5.42"
@
1.159
log
@Don't include values.h.
@
text
@d3 1
a3 1
Copyright 1997-2003 by Dave Coffin, dcoffin a cybercom o net
d1107 60
d2763 12
d3148 1
a3148 1
"\nRaw Photo Decoder v5.40"
@
1.158
log
@Added "-a" option for automatic white balance.
Vastly improved camera white balance for CRW files.
Changed default gamma to 0.6.
Added the Creative PC-CAM 600.
@
text
@d27 2
a32 1
#include
@
1.157
log
@Set black=0 for all Phase One cameras, added the Phase One H25.
@
text
@d24 3
d31 1
a31 4
#include
#include
#include
#include
d50 4
d61 3
a63 5
char make[64], model[64], model2[64];
int timestamp;
int tiff_data_offset, tiff_data_compression;
int kodak_data_compression;
int nef_curve_offset;
d68 1
a68 1
ushort (*image)[4];
d70 3
a72 3
float gamma_val=0.8, bright=1.0, red_scale=1.0, blue_scale=1.0;
int verbose=0, four_color_rgb=0, use_camera_wb=0;
int document_mode=0, quick_interpolate=0;
d152 12
a176 5
/*
Immediately after the 26-byte header come the data rows. First
the even rows 0..612, then the odd rows 1..611. Each row is 896
pixels, ten bits per pixel, packed into 1120 bytes (8960 bits).
*/
a190 5
/*
Copy 854 pixels into the image[] array. The other 42 pixels
are black. Left-shift by 4 for extra precision in upcoming
calculations.
*/
d195 2
a196 3
if ((orow+=2) > height) /* Once we've read all the even rows, */
orow = 1; /* read the odd rows. */
d377 1
a377 1
static unsigned bitbuf=0, ret=0;
d379 1
a379 1
unsigned char c;
d385 1
a385 1
ret = bitbuf << (8*sizeof(int) - vbits) >> (8*sizeof(int) - nbits);
d388 1
a388 1
while (vbits < 25) {
d491 2
a492 2
for (r=0; r < 8; r+=2)
*prow++ = (*prow << 2) + ((c >> r) & 3);
a547 2
fseek (ifp, tiff_data_offset, SEEK_SET);
d586 1
a586 1
fseek (ifp, tiff_data_offset, SEEK_SET);
a616 1
fseek (ifp, tiff_data_offset, SEEK_SET);
d652 1
a652 1
fseek (ifp, tiff_data_offset, SEEK_SET);
a682 1
fseek (ifp, 0, SEEK_SET);
a708 1
fseek (ifp, 0, SEEK_SET);
d727 1
a727 1
fseek (ifp, tiff_data_offset + (2944*24+32)*2, SEEK_SET);
a742 1
fseek (ifp, tiff_data_offset, SEEK_SET);
d757 1
a757 1
tiff_data_offset += (1472*4+24)*2;
a775 1
fseek (ifp, tiff_data_offset, SEEK_SET);
a798 1
fseek (ifp, tiff_data_offset, SEEK_SET);
d823 1
a823 1
fseek (ifp, tiff_data_offset + 8, SEEK_SET);
d827 1
a827 1
fseek (ifp, tiff_data_offset + 12 + top_margin*raw_width*2, SEEK_SET);
a859 1
fseek (ifp, tiff_data_offset, SEEK_SET);
a872 1
fseek (ifp, tiff_data_offset, SEEK_SET);
d918 1
a918 1
void casio_easy_load_raw()
d924 1
a924 2
merror (pixel, "casio_easy_load_raw()");
fseek (ifp, tiff_data_offset, SEEK_SET);
a938 1
fseek (ifp, 0, SEEK_SET);
a958 1
fseek (ifp, tiff_data_offset, SEEK_SET);
a979 1
fseek (ifp, tiff_data_offset, SEEK_SET);
a999 2
fseek (ifp, tiff_data_offset, SEEK_SET);
a1062 2
fseek (ifp, tiff_data_offset, SEEK_SET);
d1481 1
a1481 4
/*
Automatic color balance, currently used only in Document Mode.
*/
void auto_scale()
d1485 1
a1485 1
double sum[4], maxd=0;
d1487 34
a1520 14
for (c=0; c < 4; c++) {
min[c] = INT_MAX;
sum[c] = max[c] = count[c] = 0;
}
for (row=0; row < height; row++)
for (col=0; col < width; col++)
for (c=0; c < colors; c++) {
val = image[row*width+col][c];
if (!val) continue;
val -= black;
if (val < 0) val = 0;
if (min[c] > val) min[c] = val;
if (max[c] < val) max[c] = val;
sum[c] += val;
d1523 24
a1546 4
for (c=0; c < colors; c++) { /* Smallest pre_mul[] value */
pre_mul[c] = sum[c]/count[c]; /* should be 1.0 */
if (maxd < pre_mul[c])
maxd = pre_mul[c];
a1547 9
for (c=0; c < colors; c++)
pre_mul[c] = maxd / pre_mul[c];
}
void scale_colors()
{
int row, col, c, val;
rgb_max -= black;
d1789 1
a1789 1
tiff_data_offset = val;
d1793 1
a1793 1
tiff_data_offset = fget4(ifp);
d1944 27
d1977 1
a1977 1
int wbi=0;
d2000 30
a2029 14
fseek (ifp, aoff+100, SEEK_SET); /* could use 100, 108 or 116 */
camera_red = fget2(ifp);
camera_red = fget2(ifp) / camera_red;
camera_blue = fget2(ifp);
camera_blue /= fget2(ifp);
}
if (type == 0x0032 && !strcmp(model,"Canon EOS D30")) {
fseek (ifp, aoff+72, SEEK_SET); /* Get white balance (D30) */
camera_red = fget2(ifp);
camera_red = fget2(ifp) / camera_red;
camera_blue = fget2(ifp);
camera_blue /= fget2(ifp);
if (wbi==0) /* AWB doesn't work here */
camera_red = camera_blue = 0;
d2038 4
d2059 2
d2076 1
a2076 1
tiff_data_offset = atoi(val);
d2086 1
a2086 1
tiff_data_offset += tx * ty * 2;
d2228 1
a2228 1
int identify(char *fname)
d2241 1
d2252 1
d2254 1
a2254 1
tiff_data_offset = tiff_data_compression = 0;
d2264 2
a2265 2
tiff_data_offset = c - head;
fseek (ifp, tiff_data_offset + 8, SEEK_SET);
d2272 1
a2273 1
fseek (ifp, hlen, SEEK_SET);
d2279 1
a2279 1
tiff_data_offset = fget4(ifp) + 8;
d2284 1
a2284 1
tiff_data_offset = 0x1000;
d2297 1
a2297 1
tiff_data_offset += fget4(ifp);
d2303 1
a2303 1
tiff_data_offset -= 0x1000;
d2313 1
a2313 1
tiff_data_offset = fget4(ifp);
d2345 1
a2345 1
fprintf (stderr, "%s: unsupported file format.\n", fname);
d2474 1
a2474 1
tiff_data_offset = 288912;
d2480 1
a2480 1
tiff_data_offset = 289168;
d2602 1
a2602 1
tiff_data_offset = 0x10000;
d2658 1
a2658 1
tiff_data_offset = 68;
d2665 1
a2665 1
tiff_data_offset = 0x54000;
d2672 1
a2672 1
tiff_data_offset = 0x4000;
d2679 1
a2679 1
tiff_data_offset = 0x4000;
d2698 1
a2698 1
tiff_data_offset = 0x1a00;
d2796 1
a2796 1
fname, make, model, tiff_data_compression);
d2838 7
d2848 2
a2849 2
tiff_data_offset = width * 2;
load_raw = casio_easy_load_raw;
d2854 1
a2854 1
load_raw = casio_easy_load_raw;
d2869 1
a2869 1
fname, make, model);
d2875 1
a2875 1
fname, make, model);
a2880 7
if (use_camera_wb) {
if (camera_red && camera_blue && colors == 3) {
pre_mul[0] = camera_red;
pre_mul[2] = camera_blue;
} else
fprintf (stderr, "%s: Cannot use camera white balance.\n",fname);
}
a2887 4
else {
pre_mul[0] *= red_scale;
pre_mul[2] *= blue_scale;
}
d2900 1
d3075 1
a3075 1
"\nRaw Photo Decoder v5.27"
d3088 1
a3088 1
"\n-g Set gamma (0.8 by default, only for 24-bit output)"
d3090 2
a3091 1
"\n-w Use camera white balance settings if possible"
d3121 1
d3152 3
a3154 2
ifp = fopen(argv[arg],"rb");
if (!ifp) perror(argv[arg]);
d3156 2
a3157 2
if (!(id = !ifp || identify(argv[arg])))
fprintf (stderr, "%s is a %s %s image.\n", argv[arg], make, model);
d3163 1
a3163 1
if (identify(argv[arg])) {
d3171 1
a3171 1
"Loading %s %s image from %s...\n", make, model, argv[arg]);
a3179 4
if (verbose)
fprintf (stderr, "Scaling raw data (black=%d)...\n", black);
if (document_mode)
auto_scale();
d3193 1
a3193 1
ofname = malloc (strlen(argv[arg]) + 16);
d3199 1
a3199 1
strcpy (ofname, argv[arg]);
@
1.156
log
@Don't print informational messages unless "-v" flag is set.
Fixed a bug in kodak_yuv_load_raw().
@
text
@d23 1
a38 1
#define __USE_XOPEN
a826 1
INT64 bblack=0;
d828 2
a829 2
fseek (ifp, 8, SEEK_SET);
fseek (ifp, fget4(ifp) + 308, SEEK_SET);
d832 1
a832 1
fseek (ifp, 12 + top_margin*raw_width*2, SEEK_SET);
a842 2
for (col=left_margin+width; col < raw_width-1; col++)
bblack += pixel[col];
a843 2
black = bblack / (height * (raw_width-1-width-left_margin));
if (raw_width == 3120) black = 0;
d2198 1
a2198 1
if (!memcmp (head,"MMMMRawT",8)) {
d2200 3
a2202 2
fseek (ifp, 8, SEEK_SET);
fseek (ifp, fget4(ifp) + 148, SEEK_SET);
d2543 2
a2544 2
switch (raw_width) {
case 3120:
d2553 1
a2553 1
case 4056:
d2560 1
a2560 1
case 4134:
d2568 9
d3014 1
a3014 1
"\nRaw Photo Decoder v5.26"
@
1.155
log
@DJGPP does not #define WIN32
@
text
@d69 2
a70 1
int four_color_rgb=0, use_camera_wb=0, document_mode=0, quick_interpolate=0;
d1086 1
a1086 1
len = (width - col) * 3;
d1491 5
a1495 3
if (!fixed++)
fprintf (stderr, "Fixed bad pixels at:");
fprintf (stderr, " %d,%d", col, row);
d3009 1
a3009 1
"\nRaw Photo Decoder v5.25"
d3018 1
d3050 1
d3100 3
a3102 2
fprintf (stderr, "Loading %s %s image from %s...\n",
make, model, argv[arg]);
d3106 2
a3107 1
fprintf (stderr, "Foveon interpolation...\n");
d3111 2
a3112 1
fprintf (stderr, "Scaling raw data (black=%d)...\n", black);
d3120 3
a3122 2
fprintf (stderr, "%s interpolation...\n",
quick_interpolate ? "Bilinear":"VNG");
d3125 2
a3126 1
fprintf (stderr, "Converting to RGB colorspace...\n");
d3143 2
a3144 1
fprintf (stderr, "Writing data to %s...\n", ofname);
@
1.154
log
@Added the Phase One LightPhase and a Sinar camera.
Try to decode unknown Canon, Nikon, and Phase One models.
Created new global variables top_margin and left_margin.
Refactored extensively.
@
text
@d3069 1
a3069 1
#ifdef WIN32
@
1.153
log
@Added the Sigma SD10.
@
text
@a57 1
int raw_height, raw_width; /* Including black borders */
d62 1
d156 1
a156 1
void ps600_load_raw()
d197 1
a197 71
void a5_load_raw()
{
uchar data[1240], *dp;
ushort pixel[992], *pix;
int row, col;
/*
Each data row is 992 ten-bit pixels, packed into 1240 bytes.
*/
for (row=0; row < height; row++) {
fread (data, 1240, 1, ifp);
for (dp=data, pix=pixel; dp < data+1240; dp+=10, pix+=8)
{
pix[0] = (dp[1] << 2) + (dp[0] >> 6);
pix[1] = (dp[0] << 4) + (dp[3] >> 4);
pix[2] = (dp[3] << 6) + (dp[2] >> 2);
pix[3] = (dp[2] << 8) + (dp[5] );
pix[4] = (dp[4] << 2) + (dp[7] >> 6);
pix[5] = (dp[7] << 4) + (dp[6] >> 4);
pix[6] = (dp[6] << 6) + (dp[9] >> 2);
pix[7] = (dp[9] << 8) + (dp[8] );
}
/*
Copy 960 pixels into the image[] array. The other 32 pixels
are black. Left-shift by 4 for extra precision in upcoming
calculations.
*/
for (col=0; col < width; col++)
image[row*width+col][FC(row,col)] = (pixel[col] & 0x3ff) << 4;
for (col=width; col < 992; col++)
black += pixel[col] & 0x3ff;
}
black = ((INT64) black << 4) / ((992 - width) * height);
}
void a50_load_raw()
{
uchar data[1650], *dp;
ushort pixel[1320], *pix;
int row, col;
/*
Each row is 1320 ten-bit pixels, packed into 1650 bytes.
*/
for (row=0; row < height; row++) {
fread (data, 1650, 1, ifp);
for (dp=data, pix=pixel; dp < data+1650; dp+=10, pix+=8)
{
pix[0] = (dp[1] << 2) + (dp[0] >> 6);
pix[1] = (dp[0] << 4) + (dp[3] >> 4);
pix[2] = (dp[3] << 6) + (dp[2] >> 2);
pix[3] = (dp[2] << 8) + (dp[5] );
pix[4] = (dp[4] << 2) + (dp[7] >> 6);
pix[5] = (dp[7] << 4) + (dp[6] >> 4);
pix[6] = (dp[6] << 6) + (dp[9] >> 2);
pix[7] = (dp[9] << 8) + (dp[8] );
}
/*
Copy 1290 pixels into the image[] array. The other 30 pixels
are black. Left-shift by 4 for extra precision in upcoming
calculations.
*/
for (col=0; col < width; col++)
image[row*width+col][FC(row,col)] = (pixel[col] & 0x3ff) << 4;
for (col=width; col < 1320; col++)
black += pixel[col] & 0x3ff;
}
black = ((INT64) black << 4) / ((1320 - width) * height);
}
void pro70_load_raw()
a202 3
/*
Each row is 1552 ten-bit pixels, packed into 1940 bytes.
*/
d204 2
a205 2
fread (data, 1940, 1, ifp);
for (dp=data, pix=pixel; dp < data+1940; dp+=10, pix+=8)
a215 4
/*
Copy all pixels into the image[] array. Left-shift by 4 for
extra precision in upcoming calculations. No black pixels?
*/
d218 2
d221 2
d472 1
a472 1
unsigned top=0, left=0, irow, icol;
a474 8
/* Set the width of the black borders */
switch (raw_width) {
case 2144: top = 8; left = 4; break; /* G1 */
case 2224: top = 6; left = 48; break; /* EOS D30 */
case 2376: top = 6; left = 12; break; /* G2 or G3 */
case 2672: top = 6; left = 12; break; /* S50 */
case 3152: top =12; left = 64; break; /* EOS D60 */
}
d492 3
a494 1
for (r=0; r < 8; r++)
d496 1
a496 3
irow = row+r-top;
icol = col-left;
if (irow >= height) continue;
d503 1
a563 1
int left=0, right=0;
a571 7
if (!strcmp(model,"D1X"))
right = 4;
if (!strcmp(model,"D2H")) {
left = 6;
right = 8;
}
d588 1
a588 1
for (col=-left; col < width+right; col++)
d596 1
a596 1
if (col+left < 2) {
d602 1
a602 1
if ((unsigned) col >= width) continue;
d606 1
a606 1
image[row*width+col][FC(row,col)] = curve[diff] << 2;
a610 21
/*
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 nikon_is_compressed()
{
uchar test[256];
int i;
if (tiff_data_compression != 34713)
return 0;
if (strcmp(model,"D100"))
return 1;
fseek (ifp, tiff_data_offset, SEEK_SET);
fread (test, 1, 256, ifp);
for (i=15; i < 256; i+=16)
if (test[i]) return 1;
return 0;
}
a612 1
int left=0, right=0, skip16=0;
a614 18
if (!strcmp(model,"D100"))
width = 3034;
if (nikon_is_compressed()) {
nikon_compressed_load_raw();
return;
}
if (!strcmp(model,"D1X"))
right = 4;
if (!strcmp(model,"D100") && tiff_data_compression == 34713) {
right = 3;
skip16 = 1;
width = 3037;
}
if (!strcmp(model,"D2H")) {
left = 6;
right = 8;
}
d627 1
a627 1
for (col=-left; col < width+right; col++) {
d629 3
a631 3
if ((unsigned) col < width)
image[row*width+col][FC(row,col)] = i << 2;
if (skip16 && (col % 10) == 9)
d638 21
d799 1
a799 1
unsigned left=0, top=0, iten=0, isix, i, buffer=0, row, col, todo[16];
a800 4
switch (raw_width) {
case 1316: left = 6; top = 1; width = 1300; height = 1030; break;
case 2568: left = 8; top = 2; width = 2560; height = 1960; break;
}
d814 2
a815 2
row = todo[i] / raw_width - top;
col = todo[i] % raw_width - left;
d824 1
a824 1
int left=0, top=0, row, col, a, b;
a827 4
switch (raw_width) {
case 4056: left = 26; top = 5; break;
case 4134: left = 26; top = 20; break;
}
d832 1
a832 1
fseek (ifp, 12 + top*raw_width*2, SEEK_SET);
d842 2
a843 2
image[row*width+col][FC(row,col)] = pixel[col+left];
for (col=left+width; col < raw_width-1; col++)
d846 2
a847 1
black = bblack / (height * (raw_width-1-width-left));
d894 6
a899 1
void high_12_load_raw()
d904 1
a904 1
void low_12_load_raw()
d909 1
a909 1
void le_high_12_load_raw()
d1153 1
a1153 1
unsigned huff[1024], bitbuf=0, top=0, left=0;
a1155 9
/* Set the width of the black borders */
switch (raw_height) {
case 763: top = 2; break;
case 1531: top = 7; break;
}
switch (raw_width) {
case 1152: left = 8; break;
case 2304: left = 17; break;
}
d1178 2
a1179 2
if ((unsigned) row-top >= height ||
(unsigned) col-left >= width ) continue;
d1182 1
a1182 1
image[(row-top)*width+(col-left)][c] = pred[c];
a1871 2
tiff_data_offset = 0;
tiff_data_compression = 0;
d1905 1
a1905 1
model[0] = 0;
d1926 1
a1926 1
if (model[0] == 0 && wide == 680 && high == 680) {
d2172 21
a2193 10
pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = 1;
camera_red = camera_blue = black = timestamp = 0;
rgb_max = 0x4000;
colors = 3;
is_cmy = is_foveon = use_coeff = 0;
ymag = 1;
strcpy (make, "NIKON"); /* wild guess */
model[0] = model2[0] = 0;
tiff_data_offset = 0;
a2206 4
switch (raw_width) {
case 4056: strcpy (model, "H10"); break;
case 4134: strcpy (model, "H20"); break;
}
d2255 6
a2260 21
else if (fsize == 2465792) /* Nikon "DIAG RAW" formats */
strcpy (model,"E950");
else if (fsize == 2940928)
strcpy (model, nikon_e2100() ? "E2100":"E2500");
else if (fsize == 4771840)
strcpy (model,"E990/995");
else if (fsize == 5865472)
strcpy (model,"E4500");
else if (fsize == 5869568)
strcpy (model,"E4300");
else {
strcpy (make, "Casio"); /* Casio has similar formats */
if (fsize == 1976352)
strcpy (model, "QV-2000UX");
else if (fsize == 3217760)
strcpy (model, "QV-3*00EX");
else if (fsize == 7684000)
strcpy (model, "QV-4000");
else if (fsize == 6218368)
strcpy (model, "QV-5700");
}
d2280 2
a2281 1
if (model[0] == 0) {
d2285 27
a2311 1
is_canon = !strcmp(make,"Canon");
d2317 1
a2317 1
load_raw = ps600_load_raw;
d2323 1
d2326 1
a2326 1
load_raw = a5_load_raw;
d2333 1
d2336 1
a2336 1
load_raw = a50_load_raw;
d2345 1
a2345 1
load_raw = pro70_load_raw;
a2349 1
height = 1416;
a2352 1
load_raw = canon_compressed_load_raw;
d2356 1
a2356 1
} else if (!strcmp(model,"PowerShot G1")) {
d2359 19
a2377 13
colors = 4;
filters = 0xb4b4b4b4;
load_raw = canon_compressed_load_raw;
pre_mul[0] = 1.446;
pre_mul[1] = 1.405;
pre_mul[2] = 1.016;
} else if (!strcmp(model,"PowerShot S30")) {
height = 1550;
width = 2088;
filters = 0x94949494;
load_raw = canon_compressed_load_raw;
pre_mul[0] = 1.785;
pre_mul[2] = 1.266;
d2381 2
a2382 2
filters = 0x94949494;
load_raw = canon_compressed_load_raw;
d2396 2
a2397 2
filters = 0x94949494;
load_raw = canon_compressed_load_raw;
a2399 7
} else if (!strcmp(model,"EOS D30")) {
height = 1448;
width = 2176;
filters = 0x94949494;
load_raw = canon_compressed_load_raw;
pre_mul[0] = 1.592;
pre_mul[2] = 1.261;
d2403 2
a2404 2
filters = 0x94949494;
load_raw = canon_compressed_load_raw;
a2410 2
filters = 0x61616161;
load_raw = lossless_jpeg_load_raw;
a2416 2
filters = 0x61616161;
load_raw = lossless_jpeg_load_raw;
a2421 4
height = raw_height;
width = raw_width;
filters = 0x61616161;
load_raw = lossless_jpeg_load_raw;
a2424 2
height = 1324;
width = 2012;
a2425 1
load_raw = nikon_load_raw;
a2428 2
height = 1324;
width = 2012;
a2429 1
load_raw = nikon_load_raw;
a2432 1
height = 1324;
a2435 1
load_raw = nikon_load_raw;
d2439 2
a2440 2
height = 2024;
width = 3037;
a2441 1
load_raw = nikon_load_raw;
a2445 1
height = 1648;
d2447 1
a2448 1
load_raw = nikon_load_raw;
a2465 1
load_raw = nikon_load_raw;
d2471 12
a2482 11
height = 1206;
width = 1616;
filters = 0x94949494;
load_raw = nikon_e2100_load_raw;
pre_mul[0] = 1.945;
pre_mul[2] = 1.040;
} else if (!strcmp(model,"E2500")) {
height = 1204;
width = 1616;
filters = 0x4b4b4b4b;
goto coolpix;
a2486 1
load_raw = nikon_load_raw;
a2492 2
height = 1924;
width = 2576;
a2495 1
load_raw = nikon_load_raw;
d2531 1
a2531 4
height = raw_height;
width = raw_width;
filters = 0x94949494;
load_raw = low_12_load_raw;
a2538 1
filters = 0x94949494;
d2540 1
a2540 1
load_raw = low_12_load_raw;
d2543 28
a2570 4
} else if (!strcmp(model,"H10")) {
height = 2672;
width = 4012;
filters = 0x94949494;
a2572 8
} else if (!strcmp(model,"H20")) {
height = 4098;
width = 4098;
filters = 0x49494949;
load_raw = phase_one_load_raw;
pre_mul[0] = 1.963;
pre_mul[2] = 1.430;
rgb_max = 0xffff;
d2581 8
a2599 1
filters = 0x94949494;
d2601 1
a2601 1
load_raw = high_12_load_raw;
a2606 1
filters = 0x94949494;
d2608 1
a2608 1
load_raw = high_12_load_raw;
a2620 1
filters = 0x94949494;
a2630 2
height = raw_height;
width = raw_width;
d2728 13
a2740 2
height = raw_height;
width = raw_width;
d2746 7
a2752 7
switch (height = raw_height) {
case 763: height = 756; break;
case 1531: height = 1514; break;
}
switch (width = raw_width) {
case 1152: width = 1136; break;
case 2304: width = 2271; break;
d2768 1
a2768 2
raw_width = width = 1632;
filters = 0x94949494;
a2774 1
filters = 0x94949494;
d2779 1
a2779 2
filters = 0x94949494;
load_raw = high_12_load_raw;
a2782 1
filters = 0x94949494;
a2784 2
height = raw_height;
width = raw_width;
d2787 4
a2790 2
} else {
fprintf (stderr, "%s: %s %s is not yet supported.\n",fname, make, model);
d2800 2
d3006 1
a3006 1
"\nRaw Photo Decoder v5.20"
@
1.152
log
@Added the Olympus C5060WZ.
@
text
@d2190 1
a2190 1
}, mul[3] = { 1.179, 1.0, 0.713 };
d2195 1
a2195 1
coeff[i][j] = foveon[i][j] * mul[i];
d2843 1
a2843 1
} else if (!strcmp(model,"SD9")) {
d2856 6
d3106 1
a3106 1
"\nRaw Photo Decoder v5.19"
@
1.151
log
@"-c" now works in Windows, so "-o" is superfluous.
Fixed buffer overflow, segfaults, and memory leaks in main().
@
text
@d1023 1
a1023 1
void olympus_c5050z_load_raw()
d1030 1
a1030 1
fseek (ifp, 15360 + row*(width*height*3/4 + 184), SEEK_SET);
d2721 1
a2721 1
load_raw = olympus_c5050z_load_raw;
d2724 5
d3100 1
a3100 1
"\nRaw Photo Decoder v5.18"
@
1.150
log
@Do not write image data to a terminal.
In Windows, set stdout to binary mode.
@
text
@d29 1
d3087 2
a3088 2
char data[256], *cp;
int arg, id, identify_only=0, write_to_stdout=0, minuso=0;
d3095 1
a3095 1
"\nRaw Photo Decoder v5.17"
a3103 1
"\n-o file Write output to this file"
d3119 8
a3126 2
for (arg=1; argv[arg][0] == '-'; arg++)
switch (argv[arg][1])
d3128 16
a3143 34
case 'i':
identify_only = 1; break;
case 'c':
write_to_stdout = 1; break;
case 'o':
minuso = ++arg; break;
case 'f':
four_color_rgb = 1; break;
case 'd':
document_mode = 1; break;
case 'q':
quick_interpolate = 1; break;
case 'g':
gamma_val = atof(argv[++arg]); break;
case 'b':
bright = atof(argv[++arg]); break;
case 'w':
use_camera_wb = 1; break;
case 'r':
red_scale = atof(argv[++arg]); break;
case 'l':
blue_scale = atof(argv[++arg]); break;
case '2':
write_fun = write_ppm;
write_ext = ".ppm";
break;
case '3':
write_fun = write_psd;
write_ext = ".psd";
break;
case '4':
write_fun = write_ppm16;
write_ext = ".ppm";
break;
d3145 1
a3145 1
fprintf (stderr, "Unknown option \"%s\"\n", argv[arg]);
d3148 5
a3152 1
d3207 2
d3210 1
a3210 1
strcpy (data, "standard output");
d3213 4
a3216 6
strcpy (data, argv[arg]);
if ((cp = strrchr (data, '.'))) *cp = 0;
strcat (data, write_ext);
if (minuso)
strcpy (data, argv[minuso]);
ofp = fopen (data, "wb");
d3218 2
a3219 2
perror(data);
continue;
d3222 1
a3222 1
fprintf (stderr, "Writing data to %s...\n", data);
d3226 2
a3227 1
@
1.149
log
@Don't return without freeing fname.
@
text
@d29 1
d3087 1
a3087 1
int arg, id, identify_only=0, write_to_files=1, minuso=0;
d3094 1
a3094 1
"\nRaw Photo Decoder v5.16"
a3118 2
/* Parse out the options */
d3125 1
a3125 1
write_to_files = 0; break;
d3161 12
a3172 1
/* Process the named files */
d3215 4
a3218 3
ofp = stdout;
strcpy (data, "standard output");
if (write_to_files) {
d3232 1
a3232 1
if (write_to_files)
@
1.148
log
@Added the Olympus E-1.
@
text
@d1568 1
a1568 1
FILE *fp;
a1578 1
if (*fname != '/') return;
d1581 1
a1581 1
while (1) {
@
1.147
log
@Don't assume that an "int" is 32 bits!
@
text
@d988 1
a988 1
void unpacked_load_raw(int rsh)
d998 2
d1001 1
a1001 1
image[row*width+col][FC(row,col)] = ntohs(pixel[col]) << 8 >> (8+rsh);
d1008 1
a1008 1
unpacked_load_raw(2);
d1013 6
a1018 1
unpacked_load_raw(-2);
d2692 8
d3094 1
a3094 1
"\nRaw Photo Decoder v5.15"
@
1.146
log
@Created a new white balance for the PowerShot G3 and S45.
Made identify() logic more readable.
Removed redundant xxx_load_raw() code.
Added the Phase One H10 and H20, and the Imacon Ixpress.
@
text
@d442 1
a442 1
unsigned long getbits(int nbits)
d444 1
a444 1
static unsigned long bitbuf=0, ret=0;
d452 1
a452 1
ret = bitbuf << (32 - vbits) >> (32 - nbits);
@
1.145
log
@Made "juice" an argument to canon_rgb_coeff().
@
text
@d931 46
d988 1
a988 1
void unpacked_12_load_raw()
d994 1
a994 1
merror (pixel, "unpacked_12_load_raw()");
d999 1
a999 1
image[row*width+col][FC(row,col)] = ntohs(pixel[col]) << 2;
d1004 1
a1004 1
void olympus_load_raw()
d1006 2
a1007 2
ushort *pixel;
int row, col;
d1009 3
a1011 9
pixel = calloc (width, sizeof *pixel);
merror (pixel, "olympus_load_raw()");
fseek (ifp, tiff_data_offset, SEEK_SET);
for (row=0; row < height; row++) {
fread (pixel, 2, width, ifp);
for (col=0; col < width; col++)
image[row*width+col][FC(row,col)] = ntohs(pixel[col]) >> 2;
}
free (pixel);
d1014 1
a1014 1
void olympus2_load_raw()
a1028 11
void kyocera_load_raw()
{
int row, col;
fseek (ifp, tiff_data_offset, SEEK_SET);
getbits(-1);
for (row=0; row < height; row++)
for (col=0; col < width; col++)
image[row*width+col][FC(row,col)] = getbits(12) << 2;
}
d1980 1
d1999 6
d2038 4
d2120 1
d2282 2
a2283 2
char head[26], *c;
unsigned hlen, fsize, magic, i;
d2297 2
a2298 1
fread (head, 1, 26, ifp);
d2301 13
a2313 4
fseek (ifp, 0, SEEK_SET);
magic = fget4(ifp);
if (order == 0x4949 || order == 0x4d4d) {
if (!memcmp(head,"HEAPCCDR",8)) {
d2318 1
a2318 1
} else if (magic == 0x4d524d) { /* "\0MRM" (Minolta) */
d2325 1
a2325 1
} else if (magic >> 16 == 0x424d) { /* "BM" */
d2333 1
a2333 1
} else if (magic >> 16 == 0x4252) { /* "BR" */
d2347 1
a2347 1
} else if (!memcmp(head+19,"ARECOYK",7)) {
d2350 1
a2350 1
} else if (magic == 0x46554a49) { /* "FUJI" */
d2356 1
a2356 1
} else if (magic == 0x4453432d) /* "DSC-" */
d2358 1
a2358 1
else if (magic == 0x464f5662) /* "FOVb" */
d2472 8
a2479 2
pre_mul[0] = 1.965;
pre_mul[2] = 1.208;
d2650 1
a2650 1
load_raw = unpacked_12_load_raw;
d2660 1
a2660 1
load_raw = unpacked_12_load_raw;
d2663 22
d2690 1
a2690 1
load_raw = olympus_load_raw;
d2698 1
a2698 1
load_raw = olympus_load_raw;
d2705 1
a2705 1
load_raw = olympus2_load_raw;
d2713 1
a2713 1
load_raw = kyocera_load_raw;
d2853 1
a2853 1
load_raw = olympus_load_raw;
d3079 1
a3079 1
"\nRaw Photo Decoder v5.10"
@
1.144
log
@Added the Fuji S7000.
@
text
@d2154 1
a2154 1
void canon_rgb_coeff()
a2160 1
float juice = 0.1; /* weaken the above matrix */
d2420 1
a2420 1
canon_rgb_coeff();
@
1.143
log
@Added the Nikon Coolpix 2100.
@
text
@d844 1
a844 1
void fuji_s5000_load_raw()
d846 1
a846 1
ushort pixel[1472];
d849 3
a851 3
fseek (ifp, tiff_data_offset + (1472*4+24)*2, SEEK_SET);
for (row=0; row < 2152; row++) {
fread (pixel, 2, 1472, ifp);
d853 3
a855 3
swab (pixel, pixel, 1472*2);
for (col=0; col < 1424; col++) {
r = 1423 - col + (row >> 1);
d857 1
a857 1
image[r*width+c][FC(r,c)] = pixel[col];
d862 11
d2573 9
d3001 1
a3001 1
"\nRaw Photo Decoder v5.09"
@
1.142
log
@Recognize newer Canon models by CCD size instead of by name.
@
text
@d763 47
d2302 1
a2302 1
strcpy (model,"E2500");
d2516 7
d2981 1
a2981 1
"\nRaw Photo Decoder v5.08"
@
1.141
log
@Changed canon_has_lowbits() to get 16k instead of 8k.
@
text
@d2357 1
a2357 4
} else if (!strcmp(model,"PowerShot G2") ||
!strcmp(model,"PowerShot G3") ||
!strcmp(model,"PowerShot S40") ||
!strcmp(model,"PowerShot S45")) {
d2366 1
a2366 2
} else if (!strcmp(model,"PowerShot G5") ||
!strcmp(model,"PowerShot S50")) {
d2380 1
a2380 5
} else if (!strcmp(model,"EOS D60") ||
!strcmp(model,"EOS 10D") ||
!strcmp(model,"EOS 300D DIGITAL") ||
!strcmp(model,"EOS Kiss Digital") ||
!strcmp(model,"EOS DIGITAL REBEL")) {
d2927 1
a2927 1
"\nRaw Photo Decoder v5.07"
@
1.140
log
@Added "EOS Kiss Digital".
@
text
@d526 1
a526 1
uchar test[8192];
d530 2
a531 2
fread (test, 1, 8192, ifp);
for (i=540; i < 8191; i++)
d2935 1
a2935 1
"\nRaw Photo Decoder v5.06"
@
1.139
log
@Fixed kodak_compressed_load_raw() to handle uncompressed blocks.
@
text
@d2387 1
d2935 1
a2935 1
"\nRaw Photo Decoder v5.05"
@
1.138
log
@Added the PENTAX *ist D.
@
text
@d1023 2
a1024 1
unsigned row, col, len, i, bits=0, pred[2];
d1036 2
a1037 1
for (i=0; i < len; ) {
d1039 3
a1041 2
blen[i++] = c & 15;
blen[i++] = c >> 4;
d1049 31
a1080 13
len = blen[col & 255]; /* Number of bits for this pixel */
if (bits < len) { /* Got enough bits in the buffer? */
for (i=0; i < 32; i+=8)
bitbuf += (INT64) fgetc(ifp) << (bits+(i^8));
bits += 32;
}
diff = bitbuf & (0xffff >> (16-len)); /* Pull bits from buffer */
bitbuf >>= len;
bits -= len;
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
pred[col & 1] += diff;
diff = pred[col & 1];
d2934 1
a2934 1
"\nRaw Photo Decoder v5.04"
@
1.137
log
@Added the Minolta DiMAGE A1.
@
text
@d2256 2
d2262 3
a2264 3
if (!strncmp(model,"Canon",5) || !strncmp(model,"NIKON",5) ||
!strncmp(model,"SIGMA",5))
memmove (model, model+6, 64-6);
d2511 8
d2913 1
a2913 1
"\nRaw Photo Decoder v5.03"
@
1.136
log
@Allow rgb_max to be 0xffff for the Fuji F700 without causing
overflows in vng_interpolate() or convert_to_rgb().
Sometimes the Canon EOS D2000C doesn't split rows.
@
text
@d873 12
a884 1
void minolta_load_raw()
d890 1
a890 1
merror (pixel, "minolta_load_raw()");
d2504 5
a2508 3
load_raw = minolta_load_raw;
pre_mul[0] = 1;
pre_mul[2] = 1;
d2903 1
a2903 1
"\nRaw Photo Decoder v5.02"
@
1.135
log
@Updated my email address and URL
@
text
@d2 1
a2 1
Raw Photo Decoder (formerly "Canon PowerShot Converter")
d70 1
a70 1
int histogram[0x1000];
d608 1
a608 1
if (make[0] == 'C') trick=2; /* Canon */
d838 1
a838 1
image[r*width+c][FC(r,c)] = val >> 1;
d1692 1
a1692 1
brow[2][col][c] = t > 0 ? t:0;
d2488 1
a2488 1
rgb_max = 0x7fff;
d2757 1
a2757 1
rgb[3] = sqrt(rgb[3]);
d2761 1
a2761 1
histogram[img[3] >> 4]++; /* bin width is 16 */
d2778 1
a2778 1
for (val=0x1000, total=0; --val; )
d2793 1
a2793 1
scale = rgb[3] ? mul * pow (rgb[3]/max, gamma_val-1) : 0;
d2890 1
a2890 1
"\nRaw Photo Decoder v5.00"
@
1.134
log
@Added the Canon EOS DIGITAL REBEL
@
text
@d3 1
a3 1
Copyright 1997-2003 by Dave Coffin
d20 1
a20 1
http://www.shore.net/~dcoffin/powershot/ljpeg_decode.tar.gz
d2894 1
a2894 1
"\nby Dave Coffin (dcoffin@@shore.net)"
@
1.133
log
@Allow the coeff[][] matrix to be used with RGB cameras.
Added a matrix to improve the color on my PowerShot G2.
@
text
@d2352 2
a2353 1
!strcmp(model,"EOS 300D DIGITAL")) {
@
1.132
log
@Added the Canon EOS 300D.
@
text
@d71 2
d2060 19
d2082 1
a2082 1
float my_coeff[3][4] =
d2087 1
a2087 1
for (r=0; r < 3; r++) {
a2089 1
}
d2153 1
a2153 1
unsigned hlen, fsize, magic, g;
d2331 2
d2694 4
a2697 4
if (use_coeff)
for (g=0; g < colors; g++) {
coeff[0][g] *= red_scale;
coeff[2][g] *= blue_scale;
d2699 2
a2700 2
else if (colors == 3) {
pre_mul[0] *= red_scale; /* Apply user-selected color balance */
d2702 12
a2713 10
if (four_color_rgb) { /* Use two types of green */
magic = filters;
for (g=0; g < 32; g+=4) {
if ((filters >> g & 15) == 9)
filters |= 2 << g;
if ((filters >> g & 15) == 6)
filters |= 8 << g;
}
if (filters != magic) colors++;
}
a2882 1
void (*write_fun)(FILE *) = write_ppm;
d2889 1
a2889 1
"\nRaw Photo Decoder v4.94"
@
1.131
log
@Rewrote rollei_load_raw() to decode the entire image.
@
text
@d2329 2
a2330 1
!strcmp(model,"EOS 10D")) {
d2866 1
a2866 1
"\nRaw Photo Decoder v4.93"
@
1.130
log
@Removed "xmag" variable.
Added the Rollei d530flex and Nikon D2H cameras.
@
text
@d843 2
a844 2
ushort *pixel, val;
int row, col;
d846 5
a850 2
pixel = calloc (width, 2);
merror (pixel, "rollei_load_raw()");
d852 15
a866 6
for (row=0; row < height; row++) {
fread (pixel, 2, width, ifp);
for (col=0; col < width; col++) {
val = ntohs(pixel[col]);
val = val << 6 | val >> 10;
image[row*width+col][FC(row,col)] = val >> 2;
a868 1
free (pixel);
a2005 1
tiff_data_offset += raw_width * (raw_width == 1316 ? 2:4);
d2865 1
a2865 1
"\nRaw Photo Decoder v4.92"
@
1.129
log
@Added support for the Fuji S5000 and F700 models.
@
text
@d62 1
a62 1
int is_canon, is_cmy, is_foveon, use_coeff, trim, xmag, ymag;
d133 1
a133 1
These are Bayer grids, used by most RGB cameras:
d135 1
a135 1
0x94949494: 0x61616161: 0x16161616:
d137 5
a141 5
0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
0 R G R G R G 0 G R G R G R 0 B G B G B G
1 G B G B G B 1 B G B G B G 1 G R G R G R
2 R G R G R G 2 G R G R G R 2 B G B G B G
3 G B G B G B 3 B G B G B G 3 G R G R G R
d640 1
a640 1
int waste=0;
d650 5
a654 1
waste = 4;
d672 1
a672 1
for (col=0; col < width+waste; col++)
d680 2
a681 2
if (col < 2) {
i = 2*(row & 1) + col;
d683 1
a683 1
hpred[col] = vpred[i];
d686 1
a686 1
if (col >= width) continue;
d718 1
a718 1
int waste=0, skip16=0;
d728 1
a728 1
waste = 4;
d730 1
a730 1
waste = 3;
d734 4
d751 1
a751 1
for (col=0; col < width+waste; col++) {
d753 1
a753 1
if (col < width)
d841 19
d1972 28
d2130 1
a2130 1
xmag = ymag = 1;
d2186 3
a2188 1
} else if (magic == 0x464f5662) /* "FOVb" */
d2381 7
d2592 7
d2747 1
a2747 1
xmag*(width-trim*2), ymag*(height-trim*2));
d2749 1
a2749 1
ppm = calloc (width-trim*2, 3*xmag);
d2761 1
a2761 2
for (i=0; i < xmag; i++)
ppm[xmag*(col-trim)+i][c] = val;
d2765 1
a2765 1
fwrite (ppm, width-trim*2, 3*xmag, ofp);
d2855 1
a2855 1
"\nRaw Photo Decoder v4.90"
@
1.128
log
@Added "-q" option for simple bilinear interpolation.
@
text
@d36 1
d771 1
a771 1
void fuji_load_raw()
d776 1
a776 2
fseek (ifp, 100, SEEK_SET);
fseek (ifp, fget4(ifp) + (2944*24+32)*2, SEEK_SET);
d787 46
d2125 7
a2131 3
} else if (magic == 0x46554a49) /* "FUJI" */
parse_tiff(120);
else if (magic == 0x464f5662) /* "FOVb" */
d2373 1
a2373 1
load_raw = fuji_load_raw;
d2376 15
d2785 1
a2785 1
"\nRaw Photo Decoder v4.88"
@
1.127
log
@Nikon changed the format of uncompressed D100 images.
@
text
@d66 1
a66 1
int four_color_rgb=0, use_camera_wb=0, document_mode=0;
d1535 2
d2720 1
a2720 1
"\nRaw Photo Decoder v4.87"
d2732 1
d2760 2
d2826 2
a2827 1
fprintf (stderr, "VNG interpolation...\n");
@
1.126
log
@Use the correct method to find the Fuji S2's raw data.
@
text
@a649 2
if (!strcmp(model,"D100"))
width = 3034;
d691 3
a693 3
Try to figure out if the image is compressed, based on my limited
collection of NEF files. For the D100, every 16th byte of an
uncompressed image is zero.
d700 2
d703 1
a703 1
return tiff_data_compression == 34713;
d716 2
d724 1
a724 1
if (!strcmp(model,"D100")) {
d727 1
d2718 1
a2718 1
"\nRaw Photo Decoder v4.86"
@
1.125
log
@Added support for the Casio QV-2000UX.
@
text
@d770 1
a770 1
int gray=0, row, col, r, c;
d772 2
a773 5
fseek (ifp, 0, SEEK_SET);
while (gray < 2944)
if (fget2(ifp) == 2048) gray++;
else gray=0;
fseek (ifp, (2944*23+32) << 1, SEEK_CUR);
d2715 1
a2715 1
"\nRaw Photo Decoder v4.85"
@
1.124
log
@Moved unistd.h, added "-o" option.
@
text
@d845 1
a845 1
void casio_qv3000ex_load_raw()
d847 1
a847 1
uchar pixel[2080];
d850 3
a852 1
fseek (ifp, 0, SEEK_SET);
d854 1
a854 1
fread (pixel, 1, 2080, ifp);
d858 1
d2093 3
a2095 1
if (fsize == 3217760)
d2476 6
d2485 1
d2487 1
a2487 1
load_raw = casio_qv3000ex_load_raw;
a2491 1
tiff_data_offset = 0;
d2718 1
a2718 1
"\nRaw Photo Decoder v4.84"
@
1.123
log
@Added code to repair bad pixels.
@
text
@a28 1
#include
d36 1
d2699 1
a2699 1
int arg, id, identify_only=0, write_to_files=1;
d2707 1
a2707 1
"\nRaw Photo Decoder v4.83"
d2716 1
d2740 2
d2821 2
@
1.122
log
@Added support for the Canon PowerShot G5.
@
text
@d28 2
d56 1
d1348 53
d1880 4
d2020 1
a2020 1
camera_red = camera_blue = black = 0;
d2707 1
a2707 1
"\nRaw Photo Decoder v4.81"
d2798 1
@
1.121
log
@Added support for the CONTAX N DIGITAL camera.
@
text
@d2129 2
a2130 1
} else if (!strcmp(model,"PowerShot S50")) {
d2647 1
a2647 1
"\nRaw Photo Decoder v4.80"
@
1.120
log
@Don't mistake Microsoft BMP for Nucore BMQ (both start with "BM")
@
text
@d831 11
d1956 1
a1956 1
char head[8], *c;
d1971 1
a1971 1
fread (head, 1, 8, ifp);
d2011 3
d2288 8
d2646 1
a2646 1
"\nRaw Photo Decoder v4.79"
@
1.119
log
@Allow the "-i" option to work with multiple files.
@
text
@d1980 6
a1985 2
strcpy (model,"BMQ");
goto nucore;
d2624 1
a2624 1
"\nRaw Photo Decoder v4.78"
@
1.118
log
@Wrote a function to handle all memory errors.
@
text
@d2612 1
a2612 1
int arg, id_one_file=0, write_to_files=1;
d2620 1
a2620 1
"\nRaw Photo Decoder v4.77"
d2627 1
a2627 1
"\n-i Identify the first file and exit"
d2649 1
a2649 1
id_one_file = 1; break;
d2689 6
a2694 4
if (id_one_file) {
if (!ifp || identify(argv[arg])) exit(1);
fprintf (stderr, "%s is a %s %s image.\n", argv[arg], make, model);
exit(0);
@
1.117
log
@Added the five megapixel Nucore BMQ format.
@
text
@d141 7
d549 1
a549 4
if (!pixel) {
perror("canon_compressed_load_raw() calloc failed");
exit(1);
}
d658 1
a658 4
if (!curve) {
perror("curve calloc failed");
exit(1);
}
d790 1
a790 4
if (!pixel) {
perror("minolta_load_raw() calloc failed");
exit(1);
}
d806 1
a806 4
if (!pixel) {
perror("olympus_load_raw() calloc failed");
exit(1);
}
d870 1
a870 4
if (!data) {
perror("nucore_load_raw() calloc failed");
exit(1);
}
d892 1
a892 4
if (!pixel) {
perror("kodak_easy_load_raw() calloc failed");
exit(1);
}
d1160 1
a1160 4
if (!smrow[6]) {
perror("foveon_interpolate() calloc failed");
exit(1);
}
d1268 1
a1268 4
if (!shrink) {
perror("foveon_interpolate() calloc failed");
exit(1);
}
d1498 1
a1498 4
if (!brow[4]) {
perror("vng_interpolate() calloc failed");
exit(1);
}
d1840 1
a1840 4
if (!buf) {
perror("parse_foveon() malloc failed");
exit(1);
}
d2514 1
a2514 4
if (!ppm) {
perror("write_ppm() calloc failed");
exit(1);
}
d2563 1
a2563 4
if (!buffer) {
perror("write_psd() calloc failed");
exit(1);
}
d2593 1
a2593 4
if (!ppm) {
perror("write_ppm16() calloc failed");
exit(1);
}
d2620 1
a2620 1
"\nRaw Photo Decoder v4.76"
d2700 1
a2700 4
if (!image) {
perror("image calloc failed");
exit(1);
}
@
1.116
log
@Don't try to decode TIFF files written by Adobe Photoshop.
@
text
@d872 1
a872 1
int row, col;
d880 1
a880 1
for (row=0; row < height; row++) {
d882 4
d2015 4
d2652 1
a2652 1
"\nRaw Photo Decoder v4.75"
@
1.115
log
@Decode the Fuji S2 correctly by rotating 45 degrees.
@
text
@d1718 1
d1746 5
d2644 1
a2644 1
"\nRaw Photo Decoder v4.74"
@
1.114
log
@Added support for the Canon EOS D2000C.
@
text
@a138 9
The Fuji S2 does not use a Bayer grid. It has flat, wide
pixels in the following pattern, stored in the file with
a ninety-degree rotation (not shown here).
bbbb|rrrr|bbbb|rrrr|bbbb|rrrr
gggg|gggg|gggg|gggg|gggg|gggg
rrrr|bbbb|rrrr|bbbb|rrrr|bbbb
gggg|gggg|gggg|gggg|gggg|gggg
d761 1
a761 1
Rotate the image ninety degrees.
d766 1
a766 1
int gray=0, row, col;
d773 1
a773 1
for (col=width; col--; ) {
d775 5
a779 2
for (row=0; row < height; row++)
image[row*width+col][FC(row,col)] = ntohs(pixel[row]) << 2;
d2243 3
a2245 4
height = 2880;
width = 2144;
filters = 0x58525852;
xmag = 2;
d2638 1
a2638 1
"\nRaw Photo Decoder v4.72"
@
1.113
log
@Added Nucore BMQ and RAW file formats.
@
text
@d2166 7
d2645 1
a2645 1
"\nRaw Photo Decoder v4.71"
@
1.112
log
@Fix for CodeWarrior compiler (Thorsten Lemke)
@
text
@d875 19
d1997 14
d2409 5
d2638 1
a2638 1
"\nRaw Photo Decoder v4.70"
@
1.111
log
@Added support for four Casio cameras.
Added support for the Sigma SD9 in MED and LOW resolutions.
Added grayscale "Document Mode".
@
text
@d610 3
a612 3
for (col=0; col < width; ) {
image[r*width+col++][FC(r,col)] = buf[0][0] << 2;
image[r*width+col++][FC(r,col)] = buf[0][1] << 2;
@
1.110
log
@Changed some words in the usage message.
@
text
@d63 1
a63 1
int four_color_rgb=0, use_camera_wb=0;
d818 1
a818 1
fseek (ifp, 0x4000, SEEK_SET);
d842 33
d1029 4
d1034 2
a1035 1
case 2304: top = 7; left = 17; break; /* Sigma SD9 */
d1333 4
a1336 1
void scale_colors()
a1338 1
#ifdef STATS
d1340 1
a1340 1
double sum[4];
d1346 25
a1370 1
#endif
d1374 9
a1382 20
for (c=0; c < colors; c++)
if ((val = image[row*width+col][c])) {
val -= black;
#ifdef STATS
if ((unsigned) row-225 < 192 && (unsigned) col-288 < 256) {
if (min[c] > val) min[c] = val;
if (max[c] < val) max[c] = val;
sum[c] += val;
count[c]++;
}
#endif
val *= pre_mul[c];
if (val < 0) val = 0;
if (val > rgb_max) val = rgb_max;
image[row*width+col][c] = val;
}
#ifdef STATS
for (c=0; c < colors; c++)
fprintf (stderr, "%6d%6d %f\n", min[c], max[c], sum[c]/count[c]);
#endif
d1992 9
d2227 1
d2235 1
d2346 9
a2354 2
height = 1514;
width = 2271;
d2360 16
d2423 1
a2423 1
int row, col, r, g;
d2427 2
d2433 2
d2439 1
a2439 1
rgb[r] = img[0];
d2600 1
a2600 1
"\nRaw Photo Decoder v4.64"
d2610 1
d2634 2
d2693 2
d2698 1
a2698 1
if (filters) {
@
1.109
log
@Support the Kodak DCS Pro 14n in "low-res" 6MB mode.
@
text
@d2518 3
a2520 3
"\n-f Interpolate RGB as four colors"
"\n-g Set gamma value (%5.3f by default, only for 24-bit output)"
"\n-b Set brightness (%5.3f by default)"
d2522 2
a2523 2
"\n-r Set red scaling (daylight = 1.0)"
"\n-l Set blue scaling (daylight = 1.0)"
d2527 1
a2527 2
"\n\n",
argv[0], gamma_val, bright);
@
1.108
log
@Color-balanced the PowerShot A5
@
text
@d55 1
d58 1
a58 1
int is_canon, is_cmy, use_coeff, trim, xmag, ymag;
d911 53
d1556 3
d1899 1
a1899 1
is_cmy = use_coeff = 0;
d2247 6
d2254 5
a2258 8
pre_mul[0] = 1.06;
pre_mul[2] = 1.50;
} else if (!strncmp(model2,"PB645H",6)) {
pre_mul[0] = 1.20;
pre_mul[2] = 1.52;
} else if (!strcmp(model,"DCS Pro 14n")) {
pre_mul[0] = 0.9932;
pre_mul[2] = 1.1288;
d2269 7
a2275 1
load_raw = kodak_compressed_load_raw; break;
d2286 1
d2509 1
a2509 1
"\nRaw Photo Decoder v4.61"
d2595 1
a2595 1
if (colors == 3 && !filters) {
@
1.107
log
@Don't convert each pixel twice to RGB.
Convert once and save the result in image[] array.
@
text
@d1918 3
a1920 3
pre_mul[0] = 1.550;
pre_mul[1] = 1.354;
pre_mul[3] = 1.014;
d2442 1
a2442 1
"\nRaw Photo Decoder v4.60"
@
1.106
log
@Don't allow subzero RGB values for CMY cameras.
@
text
@d65 1
d2264 4
a2267 1
void get_rgb(float rgb[4], ushort image[4])
d2269 3
a2271 2
int r, g;
float cmy[4];
d2273 30
a2302 12
memset (rgb, 0, 4 * sizeof (float));
if (colors == 1) {
for (r=0; r < 3; r++) /* RGB from grayscale */
rgb[r] = image[0];
rgb[3] = 3 * rgb[0]*rgb[0];
} else if (!use_coeff)
for (r=0; r < 3; r++) { /* RGB from RGB */
if (r == 1 && colors == 4)
rgb[1] = (image[1] + image[3]) >> 1;
else
rgb[r] = image[r];
rgb[3] += rgb[r]*rgb[r]; /* Compute magnitude */
a2303 17
else
for (r=0; r < 3; r++) { /* RGB from GMCY or Foveon */
for (g=0; g < colors; g++)
rgb[r] += image[g] * coeff[r][g];
if (rgb[r] < 0) rgb[r] = 0;
if (rgb[r] > rgb_max) rgb[r] = rgb_max;
rgb[3] += rgb[r]*rgb[r];
}
if (is_cmy) {
memcpy (cmy, rgb, sizeof cmy);
rgb[0] = cmy[0] + cmy[1] - cmy[2];
rgb[1] = cmy[1] + cmy[2] - cmy[0];
rgb[2] = cmy[2] + cmy[0] - cmy[1];
for (r=0; r < 3; r++)
if (rgb[r] < 0) rgb[r] = 0;
rgb[3] = rgb[0]*rgb[0] + rgb[1]*rgb[1] + rgb[2]*rgb[2];
}
d2311 3
a2313 2
int y, x, i;
unsigned c, val;
a2314 2
float rgb[4], max, max2, expo, mul, scale;
int total, histogram[0x1000];
d2317 1
a2317 12
Build a histogram of magnitudes using 4096 bins of 64 values each.
*/
memset (histogram, 0, sizeof histogram);
for (y=trim; y < height-trim; y++)
for (x=trim; x < width-trim; x++) {
get_rgb (rgb, image[y*width+x]);
val = (int) sqrt(rgb[3]) >> 6;
if (val > 0xfff) val=0xfff;
histogram[val]++;
}
/*
Set the white point to the 99.66th percentile
d2321 1
a2321 2
max = val << 6;
max2 = max * max;
a2330 1
expo = (gamma_val-1)/2; /* Pull these out of the loop */
d2333 3
a2335 5
for (y=trim; y < height-trim; y++)
{
for (x=trim; x < width-trim; x++)
{
get_rgb (rgb, image[y*width+x]);
d2337 3
a2339 6
scale = 0;
if (rgb[3]) scale = mul * pow(rgb[3]/max2,expo);
for (c=0; c < 3; c++)
{
val=rgb[c]*scale;
d2342 1
a2342 1
ppm[xmag*(x-trim)+i][c] = val;
d2369 2
a2370 3
int hw[2], psize, y, x, c, val;
float rgb[4];
ushort *buffer, *pred;
d2385 3
a2387 3
for (y=trim; y < height-trim; y++) {
for (x=trim; x < width-trim; x++) {
get_rgb (rgb, image[y*width+x]);
d2405 2
a2406 3
ushort (*ppm)[3];
int y, x, c, val;
float rgb[4];
d2417 3
a2419 3
for (y=trim; y < height-trim; y++) {
for (x=trim; x < width-trim; x++) {
get_rgb (rgb, image[y*width+x]);
d2423 1
a2423 1
ppm[x-trim][c] = htons(val);
d2442 1
a2442 1
"\nRaw Photo Decoder v4.54"
d2541 2
@
1.105
log
@Added definitions for WIN32
@
text
@d1838 1
a1838 1
camera_red = camera_blue = 0;
d2294 2
a2445 13
/*
Creates a new filename with a different extension
*/
void exten(char *new_name, const char *old, const char *ext)
{
char *cp;
strcpy(new_name,old);
cp=strrchr(new_name,'.');
if (!cp) cp=new_name+strlen(new_name);
strcpy(cp,ext);
}
d2448 1
a2448 1
char data[256];
d2457 1
a2457 1
"\nRaw Photo Decoder v4.53"
a2521 1
black = 0;
d2559 4
a2562 2
exten(data, argv[arg], write_ext);
ofp = fopen(data,"wb");
@
1.104
log
@Changed "read_crw" to "load_raw" everywhere.
@
text
@d31 2
@
1.103
log
@Added the Canon EOS 10D
@
text
@d58 1
a58 1
void (*read_crw)();
d146 1
a146 1
void ps600_read_crw()
d187 1
a187 1
void a5_read_crw()
d222 1
a222 1
void a50_read_crw()
d257 1
a257 1
void pro70_read_crw()
d462 1
a462 1
blank pixels that (*read_crw) will strip off.
d531 1
a531 1
void canon_compressed_read_crw()
d548 1
a548 1
perror("canon_compressed_read_crw() calloc failed");
d613 1
a613 1
void lossless_jpeg_read_crw()
d629 1
a629 1
void lossless_jpeg_read_crw() { }
d635 1
a635 1
void nikon_compressed_read_crw()
d712 1
a712 1
void nikon_read_crw()
d718 1
a718 1
nikon_compressed_read_crw();
d750 1
a750 1
void nikon_e950_read_crw()
d768 1
a768 1
void fuji_read_crw()
d785 1
a785 1
void minolta_read_crw()
d792 1
a792 1
perror("minolta_read_crw() calloc failed");
d804 1
a804 1
void olympus_read_crw()
d811 1
a811 1
perror("olympus_read_crw() calloc failed");
d823 1
a823 1
void olympus2_read_crw()
d838 1
a838 1
void kodak_easy_read_crw()
d847 1
a847 1
perror("kodak_easy_read_crw() calloc failed");
d863 1
a863 1
void kodak_compressed_read_crw()
d931 1
a931 1
void foveon_read_crw()
d1906 1
a1906 1
read_crw = ps600_read_crw;
d1914 1
a1914 1
read_crw = a5_read_crw;
d1923 1
a1923 1
read_crw = a50_read_crw;
d1932 1
a1932 1
read_crw = pro70_read_crw;
d1941 1
a1941 1
read_crw = canon_compressed_read_crw;
d1950 1
a1950 1
read_crw = canon_compressed_read_crw;
d1958 1
a1958 1
read_crw = canon_compressed_read_crw;
d1968 1
a1968 1
read_crw = canon_compressed_read_crw;
d1975 1
a1975 1
read_crw = canon_compressed_read_crw;
d1982 1
a1982 1
read_crw = canon_compressed_read_crw;
d1990 1
a1990 1
read_crw = canon_compressed_read_crw;
d1998 1
a1998 1
read_crw = lossless_jpeg_read_crw;
d2006 1
a2006 1
read_crw = lossless_jpeg_read_crw;
d2015 1
a2015 1
read_crw = nikon_read_crw;
d2022 1
a2022 1
read_crw = nikon_read_crw;
d2030 1
a2030 1
read_crw = nikon_read_crw;
d2037 1
a2037 1
read_crw = nikon_read_crw;
d2046 1
a2046 1
read_crw = nikon_e950_read_crw;
d2056 1
a2056 1
read_crw = nikon_read_crw;
d2070 1
a2070 1
read_crw = nikon_read_crw;
d2082 1
a2082 1
read_crw = nikon_read_crw;
d2091 1
a2091 1
read_crw = fuji_read_crw;
d2098 1
a2098 1
read_crw = minolta_read_crw;
d2105 1
a2105 1
read_crw = olympus_read_crw;
d2112 1
a2112 1
read_crw = olympus_read_crw;
d2119 1
a2119 1
read_crw = olympus2_read_crw;
d2201 1
a2201 1
read_crw = kodak_easy_read_crw; break;
d2203 1
a2203 1
read_crw = lossless_jpeg_read_crw; break;
d2206 1
a2206 1
read_crw = kodak_compressed_read_crw; break;
d2216 1
a2216 1
read_crw = foveon_read_crw;
d2224 1
a2224 1
if (read_crw == lossless_jpeg_read_crw) {
d2466 1
a2466 1
"\nRaw Photo Decoder v4.52"
d2551 1
a2551 1
(*read_crw)();
@
1.102
log
@Added "-i" option for quickly identifying raw photos.
@
text
@d1985 2
a1986 1
} else if (!strcmp(model,"EOS D60")) {
d2466 1
a2466 1
"\nRaw Photo Decoder v4.51"
@
1.101
log
@Added support for the PowerShot S50.
@
text
@d2457 1
a2457 1
int arg, write_to_files=1;
d2465 1
a2465 1
"\nRaw Photo Decoder v4.50"
d2470 1
a2470 1
"\n\nUsage: %s [options] file1.crw file2.crw ...\n"
d2472 1
d2493 2
d2532 5
a2536 3
if (!ifp) {
perror(argv[arg]);
continue;
d2538 1
@
1.100
log
@Re-adjusted the Nikon E950 based on _sunlit_ photos.
@
text
@d543 1
d1971 7
d2465 1
a2465 1
"\nRaw Photo Decoder v4.49"
@
1.99
log
@Use the new Nikon E950 matrix for the 990 also.
@
text
@d1760 4
a1763 2
float sum, my_coeff[3][4] =
{ { -1.4, 1.4, -1.2, 2.2 }, { 4, -2, -2, 3 }, { -1, 1.5, 3.3, -2 } };
a1765 2
for (sum=g=0; g < 4; g++)
sum += my_coeff[r][g];
d1767 1
a1767 1
coeff[r][g] = my_coeff[r][g] / sum;
d2039 3
a2041 3
pre_mul[0] = 1.09392;
pre_mul[1] = 1.04542;
pre_mul[2] = 1.2396;
d2457 1
a2457 1
"\nRaw Photo Decoder v4.48"
@
1.98
log
@Added support for the Nikon E950 and E990.
Created a special coeff[] matrix for the E950.
@
text
@d2048 1
d2457 1
a2457 1
"\nRaw Photo Decoder v4.47"
@
1.97
log
@Forgot bit-shift for the Olympus C5050Z (no big deal)
@
text
@d749 15
d1757 15
d1868 3
a1870 1
else if (fsize == 2940928) /* Nikon "DIAG RAW" formats */
d1873 1
a1873 1
strcpy (model,"E995");
d2032 2
a2033 2
} else if (!strcmp(model,"E2500")) {
height = 1204;
d2036 7
a2042 2
goto coolpix;
} else if (!strcmp(model,"E995")) {
d2046 9
d2227 1
a2227 1
if (colors == 4)
d2456 1
a2456 1
"\nRaw Photo Decoder v4.45"
@
1.96
log
@Added more transformation and smoothing steps to foveon_interpolate().
@
text
@d818 1
a818 1
image[row*width+col][FC(row,col)] = getbits(12);
@
1.95
log
@Added support for the Nikon E4300 (no white balance)
@
text
@d957 12
d971 2
d982 3
a984 5
{ -631, -2025, 822 } } };
float mul[3] =
{ 1.0321, 1.0, 1.1124 };
static const int curve[72] =
{ 0,1,2,2,3,4,5,6,6,7,8,9,9,10,11,11,12,13,13,14,14,
d988 23
a1010 2
curve2[20] = { 0,1,1,2,3,3,4,4,5,5,6,6,6,7,7,7,7,7,7,7 };
ushort *pix, prev[3];
d1012 1
a1012 1
int (*smrow[7])[4], smlast, smred, smred_p=0, hood[7], min, max;
d1126 1
a1126 5
i = (total[c] * j >> 16) - pix[c];
if (i < -71) i = -27;
else if (i < 0) i = -curve[-i];
else if (i < 72) i = curve[ i];
else i = 27;
d1128 1
a1128 5
if (i > 19) i -= 8;
else if (i >= 0) i -= curve2[ i];
else if (i > -20) i += curve2[-i];
else i += 8;
ipix[c] = i;
d1132 1
a1132 6
i = ipix[c] - sum;
if (i < -19) i = -8;
else if (i < 0) i = -curve2[-i];
else if (i < 20) i = curve2[ i];
else i = 8;
i = ipix[c] - i;
d1139 80
d1730 4
a1733 4
{ 1.5, -0.5, 0 },
{ -2.3, 5.3, -2 },
{ 0.68, -3.18, 3.5 }
}, mul[3] = { 1.0, 1.0, 0.7448 };
d2162 1
d2410 1
a2410 1
"\nRaw Photo Decoder v4.42"
@
1.94
log
@Added support for the Kodak DCS Pro 14n.
@
text
@d1744 2
d1910 5
d2309 1
a2309 1
"\nRaw Photo Decoder v4.41"
@
1.93
log
@Rebalanced my PS600 from an old photo -- filter colors have shifted.
Explicitly declared "signed char" in vng_interpolate().
Added support for some Nikon "DIAG RAW" formats.
Added a Foveon-specific interpolation routine.
@
text
@d868 5
d2030 3
d2302 1
a2302 1
"\nRaw Photo Decoder v4.40"
@
1.92
log
@Removed PNG support, and replaced it with 48-bit PPM.
@
text
@d731 1
a731 1
if (model[0] == 'E')
d733 6
d952 165
d1166 1
a1166 1
static const char *cp, terms[] = {
d1625 4
a1628 4
{ 1.25, 0, -0.25 },
{ -2.5, 6, -2.5 },
{ -0.5, 0, 1.5 }
};
d1633 1
a1633 1
coeff[i][j] = foveon[i][j];
d1697 1
a1697 1
unsigned magic, hlen, g;
d1706 3
a1708 1
make[0] = model[0] = model2[0] = 0;
d1710 6
a1716 2
hlen = fget4(ifp);
fread (head, 1, 8, ifp);
d1718 1
a1718 2
fseek (ifp, 0, SEEK_END);
parse_ciff(hlen, ftell(ifp) - hlen);
d1722 18
a1739 15
} else {
fseek (ifp, 0, SEEK_SET);
magic = fget4(ifp);
if (magic == 0x46554a49) /* "FUJI" */
parse_tiff(120);
else if (magic == 0x4d524d) { /* "\0MRM" */
parse_tiff(48);
fseek (ifp, 4, SEEK_SET);
tiff_data_offset = fget4(ifp) + 8;
fseek (ifp, 24, SEEK_SET);
raw_height = fget2(ifp);
raw_width = fget2(ifp);
} else if (magic == 0x464f5662) /* "FOVb" */
parse_foveon();
}
d1767 2
a1768 3
pre_mul[0] = 1.388;
pre_mul[1] = 1.489;
pre_mul[2] = 1.051;
d1893 15
d1911 2
a1913 1
filters = 0xb4b4b4b4;
a2046 2
pre_mul[0] = 1.159;
pre_mul[1] = 1.006;
d2193 1
a2193 1
unsigned char head[] = {
d2294 1
a2294 1
"\nRaw Photo Decoder v4.35"
d2375 7
a2381 2
fprintf (stderr, "Scaling raw data (black=%d)...\n", black);
scale_colors();
@
1.91
log
@Created a transform matrix for Foveon data, similar to GMCY.
@
text
@d6 3
a8 3
any digital camera into PPM or PNG format. TIFF and CIFF parsing
are based upon public specifications, but no such documentation
is available for the raw sensor data, so writing this program has
a36 4
#ifndef NO_PNG
#include
#endif
d600 1
a600 2
register int r, col;
int trick=1;
d641 1
a641 1
int vpred[4], hpred[2], csize, row, col, i, len;
a643 1
register int diff;
d846 1
a846 1
register int diff;
d907 1
a907 1
short table[1024], pred[3];
d917 1
a917 1
table[i] = fget2(ifp);
d935 1
a935 2
i = dindex->leaf;
pred[c] += table[i];
d1155 1
a1155 1
register uchar a, b;
d1170 1
a1170 1
register uchar a, b, c, d;
d1938 1
a1938 1
register unsigned c, val;
d1977 1
a1977 1
get_rgb(rgb,image[y*width+x]);
d2031 3
a2033 5
for (y=trim; y < height-trim; y++)
{
for (x=trim; x < width-trim; x++)
{
get_rgb(rgb, image[y * width + x]);
a2045 1
#ifndef NO_PNG
d2047 1
a2047 1
Write the image to a 48-bit PNG file.
d2049 1
a2049 1
void write_png(FILE *ofp)
d2051 1
a2051 3
png_structp png_ptr;
png_infop info_ptr;
ushort (*png)[3];
d2055 6
a2060 28
png_ptr = png_create_write_struct
(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) return;
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return;
}
if (setjmp(png_ptr->jmpbuf)) {
png_destroy_write_struct(&png_ptr, &info_ptr);
return;
}
png_init_io (png_ptr, ofp);
png_set_IHDR (png_ptr, info_ptr, width-trim*2, height-trim*2,
16, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
/* Comment out this line if you want compression */
png_set_compression_level(png_ptr, 0);
png_write_info(png_ptr, info_ptr);
if (htons(0xaa55) != 0xaa55)
png_set_swap(png_ptr);
png = calloc(width-trim*2,6);
if (!png) {
perror("write_png() calloc failed");
d2066 1
a2066 1
get_rgb(rgb, image[y*width+x]);
d2070 1
a2070 1
png[x-trim][c] = val;
d2073 1
a2073 1
png_write_row(png_ptr, (png_bytep) png);
d2075 1
a2075 3
free (png);
png_write_end(png_ptr, NULL);
png_destroy_write_struct(&png_ptr, &info_ptr);
a2076 1
#endif
d2102 1
a2102 1
"\nRaw Photo Decoder v4.34"
d2118 1
a2118 3
#ifndef NO_PNG
"\n-4 Write 48-bit PNG"
#endif
a2150 1
#ifndef NO_PNG
d2152 2
a2153 2
write_fun = write_png;
write_ext = ".png";
a2154 1
#endif
@
1.90
log
@Color-balanced the Sigma SD9 based on the outdoor photo.
Added support for the Olympus C5050Z.
@
text
@d59 1
a59 1
int is_canon, is_cmy, is_rgb, trim, xmag, ymag;
d1458 67
a1524 1
void make_coeff();
d1539 1
a1539 1
is_cmy = 0;
d1859 1
d1880 8
a1887 1
if ((is_rgb = colors == 3)) {
a1899 6
} else if (colors == 4) {
make_coeff();
for (g=0; g < 4; g++) {
coeff[0][g] *= red_scale;
coeff[2][g] *= blue_scale;
}
a1903 52
/*
Given a matrix that converts RGB to GMCY, create a matrix to do
the opposite. Only square matrices can be inverted, so I create
four 3x3 matrices by omitting a different GMCY color in each one.
The final coeff[][] matrix is the sum of these four.
*/
void make_coeff()
{
static const float gmcy[4][3] = {
/* red green blue */
{ 0.11, 0.86, 0.08 }, /* green */
{ 0.50, 0.29, 0.51 }, /* magenta */
{ 0.11, 0.92, 0.75 }, /* cyan */
{ 0.81, 0.98, 0.08 } /* yellow */
};
double invert[3][6], num;
int ignore, i, j, k, r, g;
memset (coeff, 0, sizeof coeff);
for (ignore=0; ignore < 4; ignore++) {
for (j=0; j < 3; j++) {
g = (j < ignore) ? j : j+1;
for (r=0; r < 3; r++) {
invert[j][r] = gmcy[g][r]; /* 3x3 matrix to invert */
invert[j][r+3] = (r == j); /* Identity matrix */
}
}
for (j=0; j < 3; j++) {
num = invert[j][j]; /* Normalize this row */
for (i=0; i < 6; i++)
invert[j][i] /= num;
for (k=0; k < 3; k++) { /* Subtract it from the other rows */
if (k==j) continue;
num = invert[k][j];
for (i=0; i < 6; i++)
invert[k][i] -= invert[j][i] * num;
}
}
for (j=0; j < 3; j++) { /* Add the result to coeff[][] */
g = (j < ignore) ? j : j+1;
for (r=0; r < 3; r++)
coeff[r][g] += invert[r][j+3];
}
}
for (r=0; r < 3; r++) { /* Normalize such that: */
for (num=g=0; g < 4; g++) /* (1,1,1,1) x coeff = (1,1,1) */
num += coeff[r][g];
for (g=0; g < 4; g++)
coeff[r][g] /= num;
}
}
d1914 1
a1914 1
} else if (is_rgb)
d1923 2
a1924 2
for (r=0; r < 3; r++) { /* RGB from GMCY */
for (g=0; g < 4; g++)
d2139 1
a2139 1
"\nRaw Photo Decoder v4.32"
@
1.89
log
@Added preliminary support for the Sigma SD9.
Rebalanced the color on the PowerShot 600.
@
text
@d3 1
a3 1
Copyright 1997-2002 by Dave Coffin
d807 15
d1694 7
d1793 2
a1794 2
pre_mul[0] = 1.006;
pre_mul[2] = 1.147;
d2123 1
a2123 1
"\nRaw Photo Decoder v4.30"
@
1.88
log
@Gave up trying to uncap red and blue when green is not saturated.
@
text
@d871 67
d952 4
a955 3
for (col=0; col < width; col++) {
c = FC(row,col);
val = image[row*width+col][c] - black;
d957 6
a962 6
if ((unsigned) row-186 < 10 && (unsigned) col-465 < 104) {
if (min[c] > val) min[c] = val;
if (max[c] < val) max[c] = val;
sum[c] += val;
count[c]++;
}
d964 5
a968 5
val *= pre_mul[c];
if (val < 0) val = 0;
if (val > rgb_max) val = rgb_max;
image[row*width+col][c] = val;
}
d1407 36
d1484 2
a1485 1
}
d1494 2
a1495 1
if (!strncmp(model,"Canon",5) || !strncmp(model,"NIKON",5))
d1514 3
a1516 3
pre_mul[0] = 1.377;
pre_mul[1] = 1.428;
pre_mul[2] = 1.010;
d1766 7
d2101 1
a2101 1
"\nRaw Photo Decoder v4.26"
@
1.87
log
@Provided option to interpolate RGB as _four_ colors,
to correct the "screen door effect".
@
text
@d898 1
a898 3
if (val > rgb_max && (!is_rgb || (c & 1) ||
image[row*width+col+(col ? -1:1)][FC(row,col+1)]+256 > rgb_max))
val = rgb_max;
d1988 1
a1988 1
"\nRaw Photo Decoder v4.25"
@
1.86
log
@I deleted "rgb_max -= black;" by mistake. Oops!
@
text
@d54 1
a54 2
int height, width, trim, colors, is_cmy, is_canon, black, rgb_max;
int xmag, ymag;
d58 2
a59 1
int use_camera_wb=0;
a60 1
char make[64], model[64], model2[64];
d64 3
a66 2
float rgb_mul[3], camera_red, camera_blue;
float gmcy_mul[4], coeff[3][4];
d78 1
a78 1
Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2 = R/G/B
a873 1
float *scale;
a883 1
scale = (colors == 3) ? rgb_mul:gmcy_mul;
d896 1
a896 1
val *= scale[c];
d898 2
a899 2
if (val > rgb_max && (colors != 3 || c == 1 ||
image[row*width+col+(col ? -1:1)][1]+256 > rgb_max))
d1350 1
a1350 1
unsigned magic, hlen;
d1352 1
a1352 2
rgb_mul[0] = rgb_mul[1] = rgb_mul[2] = 1;
gmcy_mul[0] = gmcy_mul[1] = gmcy_mul[2] = gmcy_mul[3] = 1;
d1410 3
a1412 3
gmcy_mul[0] = 1.377;
gmcy_mul[1] = 1.428;
gmcy_mul[2] = 1.010;
d1419 3
a1421 3
gmcy_mul[0] = 1.550;
gmcy_mul[1] = 1.354;
gmcy_mul[3] = 1.014;
d1428 3
a1430 3
gmcy_mul[0] = 1.750;
gmcy_mul[1] = 1.381;
gmcy_mul[3] = 1.182;
d1437 3
a1439 3
gmcy_mul[0] = 1.389;
gmcy_mul[1] = 1.343;
gmcy_mul[3] = 1.034;
d1446 3
a1448 3
gmcy_mul[0] = 1.496;
gmcy_mul[1] = 1.509;
gmcy_mul[3] = 1.009;
d1455 3
a1457 3
gmcy_mul[0] = 1.446;
gmcy_mul[1] = 1.405;
gmcy_mul[2] = 1.016;
d1463 2
a1464 2
rgb_mul[0] = 1.785;
rgb_mul[2] = 1.266;
d1473 2
a1474 2
rgb_mul[0] = 1.965;
rgb_mul[2] = 1.208;
d1480 2
a1481 2
rgb_mul[0] = 1.592;
rgb_mul[2] = 1.261;
d1487 2
a1488 2
rgb_mul[0] = 2.242;
rgb_mul[2] = 1.245;
d1496 2
a1497 2
rgb_mul[0] = 1.976;
rgb_mul[2] = 1.282;
d1504 2
a1505 2
rgb_mul[0] = 1.66;
rgb_mul[2] = 1.13;
d1512 2
a1513 2
rgb_mul[0] = 0.838;
rgb_mul[2] = 1.095;
d1519 2
a1520 2
rgb_mul[0] = 1.347;
rgb_mul[2] = 3.279;
d1527 2
a1528 2
rgb_mul[0] = 1.910;
rgb_mul[2] = 1.220;
d1534 2
a1535 2
rgb_mul[0] = 2.374;
rgb_mul[2] = 1.677;
d1543 3
a1545 3
gmcy_mul[0] = 1.300;
gmcy_mul[1] = 1.300;
gmcy_mul[3] = 1.148;
d1552 2
a1553 2
rgb_mul[0] = 1.424;
rgb_mul[2] = 1.718;
d1559 2
a1560 2
rgb_mul[0] = 1;
rgb_mul[2] = 1;
d1566 2
a1567 2
rgb_mul[0] = 1.43;
rgb_mul[2] = 1.77;
d1573 2
a1574 2
rgb_mul[0] = 1.43;
rgb_mul[2] = 1.77;
d1581 2
a1582 2
rgb_mul[0] = 0.973;
rgb_mul[2] = 0.987;
d1585 2
a1586 2
rgb_mul[0] = 0.996;
rgb_mul[2] = 1.279;
d1589 2
a1590 2
rgb_mul[0] = 1.21;
rgb_mul[2] = 1.63;
d1593 2
a1594 2
rgb_mul[0] = 1.46;
rgb_mul[2] = 1.84;
d1601 2
a1602 2
rgb_mul[0] = 1.43;
rgb_mul[2] = 2.16;
d1605 2
a1606 2
rgb_mul[0] = 1.28;
rgb_mul[2] = 2.00;
d1609 2
a1610 2
rgb_mul[0] = 1.00;
rgb_mul[2] = 1.20;
d1612 2
a1613 2
rgb_mul[0] = 0.985;
rgb_mul[2] = 1.15;
d1615 2
a1616 2
rgb_mul[0] = 1.00;
rgb_mul[2] = 1.20;
d1618 2
a1619 2
rgb_mul[0] = 1.12;
rgb_mul[2] = 1.07;
d1622 2
a1623 2
rgb_mul[0] = 1.05;
rgb_mul[2] = 1.17;
d1628 2
a1629 2
rgb_mul[0] = 1.35;
rgb_mul[2] = 1.18;
d1632 2
a1633 2
rgb_mul[0] = 1.06;
rgb_mul[2] = 1.72;
d1638 2
a1639 2
rgb_mul[0] = 1.06;
rgb_mul[2] = 1.385;
d1641 2
a1642 2
rgb_mul[0] = 1.06;
rgb_mul[2] = 1.50;
d1644 2
a1645 2
rgb_mul[0] = 1.20;
rgb_mul[2] = 1.52;
d1650 1
d1675 2
a1676 2
rgb_mul[0] = camera_red;
rgb_mul[2] = camera_blue;
d1680 20
a1699 3
rgb_mul[0] *= red_scale; /* Apply user-selected color balance */
rgb_mul[2] *= blue_scale;
if (colors == 4) make_coeff();
d1748 1
a1748 1
for (num=g=0; g < 4; g++) /* (1,1,1,1) x coeff = rgb_mul[] */
d1751 1
a1751 1
coeff[r][g] *= rgb_mul[r]/num;
d1765 1
a1765 1
} else if (colors == 3)
d1767 4
a1770 1
rgb[r] = image[r];
d1990 1
a1990 1
"\nRaw Photo Decoder v4.21"
d1998 1
d2021 2
@
1.85
log
@Do scaling in GMCY space before vng_interpolate()
For this I had to rebalance all GMCY cameras.
@
text
@d884 1
d1972 1
a1972 1
"\nRaw Photo Decoder v4.20"
@
1.84
log
@Do RGB scaling _before_ vng_interpolate()
Use correct formula for diagonal gradients
@
text
@d66 1
a66 1
float coeff[3][4];
a870 15
void subtract_black()
{
ushort *img;
int size;
img = image[0];
size = width * height * 4;
while (size--)
if (*img > black)
*img++ -= black;
else
*img++ = 0;
rgb_max -= black;
}
d874 11
a884 2
if (colors != 3) return;
d888 7
a894 6
if (c != 1) {
val = image[row*width+col][c] * rgb_mul[c];
if (val > rgb_max &&
image[row*width+col+(col ? -1:1)][1]+256 > rgb_max)
val = rgb_max;
image[row*width+col][c] = val;
d896 12
a907 1
}
d1345 2
a1346 2
Open a CRW file, identify which camera created it, and set
global variables accordingly. Returns nonzero if an error occurs.
d1353 2
a1354 3
rgb_mul[0] = 1.592;
rgb_mul[1] = 1.0;
rgb_mul[2] = 1.261;
d1357 1
a1357 1
colors = 4;
d1409 1
d1412 3
a1414 2
rgb_mul[0] = 1.667;
rgb_mul[2] = 1.667;
d1418 1
d1421 3
a1423 2
rgb_mul[0] = 1.111;
rgb_mul[2] = 0.978;
d1427 1
d1430 3
a1432 2
rgb_mul[0] = 1.316;
rgb_mul[2] = 0.776;
d1436 1
d1439 3
d1445 1
d1448 3
d1454 1
d1457 3
a1459 2
rgb_mul[0] = 1.469;
rgb_mul[2] = 1.327;
a1462 1
colors = 3;
a1472 1
colors = 3;
d1475 1
a1475 1
rgb_mul[0] = 1.966;
a1479 1
colors = 3;
d1482 2
a1486 1
colors = 3;
a1494 1
colors = 3;
a1502 1
colors = 3;
a1511 1
colors = 3;
a1518 1
colors = 3;
a1525 1
colors = 3;
a1533 1
colors = 3;
d1542 1
d1545 3
a1547 2
rgb_mul[0] = 2.126;
rgb_mul[2] = 1.197;
a1550 1
colors = 3;
a1558 1
colors = 3;
a1565 1
colors = 3;
a1572 1
colors = 3;
a1579 1
colors = 3;
a1580 2
rgb_mul[0] = 1;
rgb_mul[2] = 1;
d1731 3
a1733 1
for (r=0; r < 3; r++) /* Multiply coeff[][] by rgb_mul[] */
d1735 2
a1736 1
coeff[r][g] *= rgb_mul[r];
d1759 1
d1971 1
a1971 1
"\nRaw Photo Decoder v4.10"
d2053 1
a2053 4
if (black) {
fprintf (stderr, "Subtracting thermal noise (%d)...\n", black);
subtract_black();
}
@
1.83
log
@Set camera white balance for EOS D30 if it's not "Auto".
@
text
@d886 18
d941 1
a941 1
int code[8][576], *ip, ihood[8], gval[8], gmin, gmax, sum[4];
d1003 11
a1013 1
*ip++ = INT_MAX;
a1015 5
for (cp=chood, g=0; g < 8; g++) {
ihood[g] = *cp++ * width;
ihood[g] += *cp++;
ihood[g] *= 4;
}
d1043 2
a1044 1
for (num=g=0; g < 8; g++) { /* Average the neighbors */
d1047 4
a1050 1
sum[c] += pix[ihood[g] + c];
d1054 1
a1054 2
color = FC(row,col); /* Save to buffer */
for (c=0; c < colors; c++) {
d1525 1
d1740 1
a1740 3
rgb[r] = image[r] * rgb_mul[r];
if (rgb[r] > rgb_max && image[1]+256 > rgb_max)
rgb[r] = rgb_max;
d1959 1
a1959 1
"\nRaw Photo Decoder v4.03"
d2045 1
@
1.82
log
@Moved the fopen() call into main()
@
text
@d1279 8
a1286 4
if (type == 0x1031) { /* Get the raw width and height */
fseek (ifp, aoff+2, SEEK_SET);
raw_width = fget2(ifp);
raw_height = fget2(ifp);
d1295 5
d1934 1
a1934 1
"\nRaw Photo Decoder v4.02"
@
1.81
log
@Don't apply rgb_max until the green channel is saturated
@
text
@d27 1
d1307 1
a1307 1
int open_and_id(char *fname)
a1320 5
ifp = fopen(fname,"rb");
if (!ifp) {
perror(fname);
return 1;
}
d1925 1
a1925 1
"\nRaw Photo Decoder v4.01"
d1989 7
a1995 2
if (open_and_id(argv[arg])) {
if (ifp) fclose(ifp);
@
1.80
log
@Use Variable Number Gradient interpolation for all cameras.
@
text
@d1709 1
a1709 1
if (rgb[r] > rgb_max)
d1929 1
a1929 1
"\nRaw Photo Decoder v4.00"
@
1.79
log
@Fixed ProBack645 kludge with "model2" string.
New "-w" flag uses camera white balance settings.
@
text
@d54 1
a72 29
I assume that the influence of one pixel upon another is proportionate
to the inverse square of the distance between them. So I've designed
three neighborhoods for aspect ratios of 1:1, 1:2, and 2:1.
Triplet format is y-offset,x-offset,weight. 0,0,0 marks the end.
*/
const char square_hood[] = {
-1,-1,1, -1,0,2, -1,1,1,
0,-1,2, 0,1,2,
1,-1,1, 1,0,2, 1,1,1,
0,0,0 };
const char wide_hood[] = {
-1,-1,1, -1,0,1, -1,1,1,
0,-2,1, 0,-1,4, 0,1,4, 0,2,1,
1,-1,1, 1,0,1, 1,1,1,
0,0,0 };
const char tall_hood[] = {
-2,0,1,
-1,-1,1, -1,0,4, -1,1,1,
0,-1,1, 0,1,1,
1,-1,1, 1,0,4, 1,1,1,
2,0,1,
0,0,0 };
const char *hood;
/*
d886 3
a888 56
RGB interpolation algorithm designed by Matt Dillon.
GMCY cameras still use my algorithm.
His explanation follows:
* When this function is called, we only have one color for
* each pixel. This code searches the 5x5 neighborhood and
* synthesizes the other colors based on interpolation. The
* algorithm works as follows. Take one portion of the
* CCD filter pattern:
*
* 0 1 2 3 4
* 0 G R G R G
* 1 B G B G B
* 2 G RR G
* 3 B G B G B
* 4 G R G R G
*
* Lets say we are on pixel (x,y) = (2,2), the bracketed green above, and
* we are trying to synthesize the Blue and Red guns for that pixel based
* on the surrounding pixels.
*
* We could average the surrounding blue pixels to synthesize a blue for
* (2,2) but that will blur the image somewhat if we are on the boundary
* of an edge. Instead what we do is calculate a temporary green for each
* blue pixel and then generate the blue for (2,2) by scaling it against
* the differential between the temporary green and the green in (2,2).
*
* For example, the green for the blue pixel at (2,1) is calculated by
* averaging the green at (2,0) and (2,2). A scaling factor is generated
* using this green and the green at (2,2), we multiply in the Blue pixel
* at (2,1), and that is the Blue we store for (2,2). It's actually somewhat
* more complicated since there are other blue's around (2,2). What we do
* is execute this calculate for each blue and do a weighted average of the
* result, and that final number is the Blue we store at (2,2).
*
* The scaling factor tends to blow up in low-light situations due to
* the calculation of the scaling factor becoming skewed (think about the
* difference between two pixel brightnesses of 10 and 15, and 4000 and 4005).
* To compensate we introduce a constant in the scaling process, llfactor.
* The higher the constant the closer the scaling factor gets to 1:1 (a
* straight average of the surrounding blue's regardless of the scale
* generated using the green's). This results in somewhat more blurring
* but hides low-light dropouts.
*/
#define lowlight_val 0
void dillon_interpolate()
{
int row, col, cc, c;
int vb, vr, val;
int dx, dy;
int avg[4], sum[4];
int base = 4096 + 64;
int llfactor = 8 + lowlight_val * 16;
int weight;
int size;
ushort (*oimage)[4];
d890 1
a890 7
size = height * width * 8;
oimage = malloc(size);
if (!oimage) {
perror("dillon_interpolate() calloc failed");
exit(1);
}
memcpy (oimage, image, size);
d892 52
a943 21
for (row=2; row < height-2; row++) {
for (col=2; col < width-2; col++) {
cc = FC(row,col);
vb = oimage[row*width+col][cc];
avg[0] = avg[1] = avg[2] = avg[3] = 0;
sum[0] = sum[1] = sum[2] = sum[3] = 0;
for (dy = -1; dy <= 1; ++dy) {
for (dx = -1; dx <= 1; ++dx) {
c = FC(row+dy, col+dx);
vr = oimage[(row+dy*2)*width + (col+dx*2)][cc];
vr = (vb + vr) / 2;
/*
* RGB CCDs almost universally repeat the same
* color filter 2 pixels in any direction.
*/
val = oimage[(row+dy)*width + (col+dx)][c];
weight = base - abs(vr - vb);
val = (llfactor + vb) * val / (llfactor + vr);
weight = 100;
avg[c] += val * weight;
sum[c] += weight;
d945 12
d958 3
a960 3
for (c=0; c < colors; c++) {
if (sum[c])
image[row*width+col][c] = (avg[c] + (sum[c]/2)) / sum[c];
d962 1
d965 18
a982 26
free (oimage);
}
/*
When this function is called, we only have one color for
each pixel. Search the 3x3 neighborhood for pixels of
other colors, and average them. Diagonal neighbors get
counted once, orthogonal neighbors twice.
*/
void bilinear_interpolate()
{
unsigned row, col, cc, y, x, w, c, avg[8];
const char *h;
for (row=1; row < height-1; row++)
for (col=1; col < width-1; col++) {
cc = FC(row,col);
memset (avg, 0, sizeof avg);
for (h = hood; ; ) {
y = row + *h++;
x = col + *h++;
if ((w = *h++) == 0) break;
if (y >= height || x >= width) continue;
if ((c = FC(y,x)) == cc) continue;
avg[c] += w * image[y*width+x][c];
avg[c+4] += w;
d984 1
a984 3
for (c=0; c < colors; c++)
if (c != cc)
image[row*width+col][c] = avg[c] / avg[c+4];
d986 9
a994 23
}
/*
We now have all color values for each pixel. Sharpen the
spatial detail by assuming that neighboring pixels have
similar color ratios.
To avoid amplifying noise, wherever any color value falls
below a certain threshold, that pixel and all neighboring
pixels will be left unchanged.
*/
void smooth_hues()
{
ushort (*last)[4];
ushort (*curr)[4];
void *tmp;
unsigned row, col, cc, y, x, w, c, val, avg[8];
const char *h;
last = calloc (width, sizeof *curr);
curr = calloc (width, sizeof *curr);
if (!last || !curr) {
perror("smooth_hues() calloc failed");
d997 4
a1000 1
for (row=2; row < height-2; row++) {
d1002 14
a1015 7
memset (avg, 0, sizeof avg);
for (h = hood; ; ) { /* Any noisy neighbors in the 'hood? */
y = row + *h++;
x = col + *h++;
if ((w = *h++) == 0) break;
for (c=0; c < colors; c++)
if (image[y*width+x][c] < 75) goto noise;
d1017 13
a1029 10
cc = FC(row,col); /* Neighbors are OK to use */
for (h = hood; ; ) {
y = row + *h++;
x = col + *h++;
if ((w = *h++) == 0) break;
if ((c = FC(y,x)) == cc) continue;
val = ((unsigned long) image[y*width+x][c] << 16) /
image[y*width+x][cc] * image[row*width+col][cc] >> 16;
avg[c] += w * val;
avg[c+4] += w;
d1031 1
a1031 3
noise:
for (c=0; c < colors; c++)
curr[col][c] = avg[c+4] ? avg[c]/avg[c+4] : image[row*width+col][c];
d1033 8
a1040 9
if (row > 2)
memcpy (image[(row-1)*width+2], last+2, (width-4)*sizeof *last);
tmp = last;
last = curr;
curr = tmp;
}
memcpy (image[(row-1)*width+2], last+2, (width-4)*sizeof *last);
free (last);
free (curr);
d1180 1
a1180 1
if (tag == 0x927c) { /* MakerNote */
d1213 1
a1213 3
fread (make, 64, 1, ifp);
if (len > 63) len=63;
make[len]=0;
d1216 1
a1216 3
fread (model, 64, 1, ifp);
if (len > 63) len=63;
model[len]=0;
d1219 1
a1219 3
fread (model2, 64, 1, ifp);
if (len > 63) len=63;
model2[len]=0;
d1318 1
a1318 1
hood = square_hood;
d1356 1
a1356 1
model[16] = 0;
d1482 1
a1482 1
hood = wide_hood;
d1506 1
a1506 1
hood = tall_hood;
d1734 1
a1734 1
int y, x, i, ymag=1, xmag=1;
a1758 2
if (hood == tall_hood) xmag = 2;
if (hood == wide_hood) ymag = 2;
d1921 1
a1921 1
int i, arg, write_to_files=1, dillon=0, dillon_ok, smooth=1;
d1929 1
a1929 1
"\nRaw Photo Decoder v3.65"
a1936 2
"\n-d Use Dillon interpolation if possible"
"\n-s Number of times to smooth hues (1 by default)"
a1958 4
case 'd':
dillon = 1; break;
case 's':
smooth = atoi(argv[++arg]); break;
d2011 1
a2011 18
if (filters == 0) goto nointerp;
dillon_ok = dillon;
for (i=8; i < 32; i+=8)
if ((filters >> i & 0xff) != (filters & 0xff))
dillon_ok = 0;
if (dillon_ok) {
fprintf (stderr, "Dillon interpolation...\n");
dillon_interpolate();
trim = 2;
} else {
if (dillon)
fprintf (stderr, "Filter pattern is not Dillon-compatible.\n");
fprintf (stderr, "Bilinear interpolation...\n");
bilinear_interpolate();
for (i=0; i < smooth; i++) {
fprintf (stderr, "Smoothing hues...\n");
smooth_hues();
}
d2013 2
a2015 1
nointerp:
@
1.78
log
@Added support for Kodak DCR compression
@
text
@d57 1
a57 1
int kodak_645m;
d59 1
a59 1
char make[64], model[64];
d63 1
a63 1
float rgb_mul[3];
a1177 6
case 0x920e:
kodak_645m = 0;
break;
case 0xa20e:
kodak_645m = 1;
break;
d1184 1
a1184 1
int base=0, offset=0, entries, tag, type, len, val;
d1209 9
d1279 5
d1312 1
d1330 11
d1346 7
d1377 1
d1388 1
a1388 1
model[0] = 0;
d1665 6
a1670 8
} else if (!strcmp(model,"ProBack645")) {
if (kodak_645m) {
rgb_mul[0] = 1.06; /* 645M sample image */
rgb_mul[2] = 1.50;
} else {
rgb_mul[0] = 1.20; /* 645H sample image */
rgb_mul[2] = 1.52;
}
d1697 7
d1829 1
a1829 1
perror("ppm calloc failed");
d1888 1
a1888 1
perror("psd calloc failed");
d1949 1
a1949 1
perror("png calloc failed");
d1994 1
a1994 1
"\nRaw Photo Decoder v3.60"
d2006 1
d2034 2
@
1.77
log
@Added support for the Canon EOS-1DS.
@
text
@d57 1
d859 39
d1017 1
a1017 1
void first_interpolate()
d1050 1
a1050 1
void second_interpolate()
d1061 1
a1061 1
perror("second_interpolate() calloc failed");
d1178 6
d1277 1
d1624 21
d1652 3
d1961 1
a1961 1
"\nRaw Photo Decoder v3.54"
d1970 1
a1970 1
"\n-s Number of times to smooth colors (1 by default)"
d2058 2
a2059 2
fprintf (stderr, "First interpolation...\n");
first_interpolate();
d2061 2
a2062 2
fprintf (stderr, "Second interpolation...\n");
second_interpolate();
@
1.76
log
@Fixed segfault caused by "crw -d -4"
@
text
@d165 3
a167 3
The Fuji S2 does not use a Bayer grid. Instead, it flattens
out the pixels as shown below, and then stores these pixels
in the file with a ninety-degree rotation.
d647 1
a647 4
if (!strcmp(model,"EOS-1D"))
fseek (ifp, 288912, SEEK_SET);
else
fseek (ifp, tiff_data_offset, SEEK_SET);
d1436 1
d1439 10
d1890 1
a1890 1
"\nRaw Photo Decoder v3.53"
d1975 1
a1975 1
if (colors == 1) goto nointerp;
@
1.75
log
@Correct a 2:1 or 1:2 aspect ratio in write_ppm, not in the
documentation. PSD and PNG output are unchanged.
@
text
@d1847 1
a1847 1
png[x-1][c] = val;
d1882 1
a1882 1
"\nRaw Photo Decoder v3.52"
@
1.74
log
@Added support for the Fuji FinePixS2Pro and Minolta DiMAGE 7.
Improved interpolation to better handle non-square pixels.
@
text
@d1685 1
a1685 1
int y, x;
d1710 4
a1713 1
fprintf (ofp, "P6\n%d %d\n255\n", width-trim*2, height-trim*2);
d1715 1
a1715 1
ppm = calloc(width-trim*2,3);
d1736 2
a1737 1
ppm[x-trim][c]=val;
d1740 2
a1741 1
fwrite (ppm, width-trim*2, 3, ofp);
d1882 1
a1882 1
"\nRaw Photo Decoder v3.50"
@
1.73
log
@Major overhaul in version 3.40:
Camera make and model are two separate strings.
Added support for 15 new camera models (mostly Kodak).
Thanks to Kodak, I now support greyscale and CMY cameras.
All Canon-compressed formats get decoded in one subroutine.
Get the correct value for nef_curve_offset, we hope.
Changed name from "Canon PowerShot Converter" to "Raw Photo
Decoder", as Canon cameras are a minority now.
@
text
@d53 1
a53 1
int height, width, trim, colors, is_cmy, black, canon, rgb_max;
d71 29
d155 1
a155 9
Some RGB cameras use 0x94949494:
0 1 2 3 4 5
0 R G R G R G
1 G B G B G B
2 R G R G R G
3 G B G B G B
Some use 0x61616161:
d157 1
a157 5
0 1 2 3 4 5
0 G R G R G R
1 B G B G B G
2 G R G R G R
3 B G B G B G
d159 14
a172 1
Some use 0x16161616:
a173 5
0 1 2 3 4 5
0 B G B G B G
1 G R G R G R
2 B G B G B G
3 G R G R G R
d480 2
a481 1
if (c == 0xff && canon) fgetc(ifp); /* Canon puts an extra 0 after 0xff */
d778 39
d982 2
a983 2
int row, col, cc, x, y, c, val;
int avg[8];
d989 9
a997 11
for (y = row-1; y < row+2; y++)
for (x = col-1; x < col+2; x++)
if ((c = FC(y,x)) != cc) {
val = image[y*width+x][c];
avg[c] += val;
avg[c+4]++;
if (y==row || x==col) { /* Orthogonal neighbor */
avg[c] += val;
avg[c+4]++;
}
}
d1018 2
a1019 2
int row, col, cc, x, y, c, val;
int avg[8];
d1030 14
a1043 9
for (y = row-1; y < row+2; y++) /* Any noisy neighbors? */
for (x = col-1; x < col+2; x++)
for (c=0; c < colors; c++)
if (image[y*width+x][c] < 75) goto noise;
cc = FC(row,col);
for (y = row-1; y < row+2; y++) /* Neighbors are OK to use */
for (x = col-1; x < col+2; x++)
if ((c = FC(y,x)) != cc) {
val = ((unsigned long) image[y*width+x][c] << 16) /
d1045 3
a1047 7
avg[c] += val;
avg[c+4]++;
if (y==row || x==col) { /* Count orthogonal neighbor twice */
avg[c] += val;
avg[c+4]++;
}
}
d1073 3
a1075 1
if (order == 0x4d4d) /* "MM" means big-endian */
a1076 2
else /* "II" means little-endian */
return a + (b << 8);
d1090 3
a1092 1
if (order == 0x4d4d)
a1093 2
else
return a + (b << 8) + (c << 16) + (d << 24);
d1096 1
a1096 1
void tiff_parse_subifd()
d1126 1
a1126 1
fseek (ifp, val, SEEK_SET);
d1202 1
a1202 1
void parse_tiff()
d1209 2
a1210 1
fseek (ifp, 2, SEEK_SET); /* open_and_id() already got byte order */
d1213 1
a1213 1
fseek (ifp, doff, SEEK_SET);
d1221 1
a1221 1
fseek (ifp, val, SEEK_SET);
d1236 3
a1238 3
fseek (ifp, val, SEEK_SET);
fseek (ifp, fget4(ifp), SEEK_SET);
tiff_parse_subifd();
d1242 1
a1242 1
tiff_parse_subifd();
d1301 1
a1301 1
int hlen;
d1309 1
a1309 1
canon = 1;
d1326 14
a1339 1
parse_tiff();
d1344 1
a1344 1
if (!strncmp(make,"OLYMPUS",7))
d1360 1
a1444 1
canon = 0;
a1452 1
canon = 0;
a1460 1
canon = 0;
d1462 1
a1469 1
canon = 0;
a1476 1
canon = 0;
d1481 17
d1877 1
a1877 1
"\nRaw Photo Decoder v3.40"
@
1.72
log
@Trying not to amplify noise in second_interpolate().
@
text
@d2 1
a2 1
Canon PowerShot Converter
d5 5
a9 6
A portable ANSI C program to convert raw CRW files from Canon
digital cameras into PPM or PNG format.
This is an entirely original work; no other copyrights apply.
Any similarity to Canon's code is only to the extent necessary
to decode image formats of Canon's design.
d12 1
a12 1
otherwise. Comments and questions are welcome.
d17 2
a18 2
The Canon EOS-1D digital camera compresses its data with
lossless JPEG. To read EOS-1D images, you must also download:
d53 1
a53 1
int height, width, trim, colors, black, canon, rgb_max;
d55 2
a56 1
int nef_curve_offset, nef_data_compression, nef_data_offset, nef_rows_per_strip;
d58 1
a58 1
char name[64];
d134 1
a134 1
The EOS-1D uses 0x61616161:
d142 1
a142 1
The Nikon cameras use 0x16161616:
a513 6
void pro90_read_crw()
{
ushort pixel[1944*8];
int row, r, col;
decompress(0,540);
d515 2
a516 20
Read eight rows at a time.
Each row has 1896 image pixels and 48 black pixels.
*/
for (row=0; row < height; row += 8) {
decompress(pixel,243);
for (r=0; r < 8; r++) {
for (col=0; col < width; col++)
image[(row+r)*width+col][FC(row+r,col)] =
(pixel[(r*1944)+col] & 0x3ff) << 4;
for (col=width; col < 1944; col++)
black += pixel[(r*1944)+col] & 0x3ff;
}
}
black = ((INT64) black << 4) / ((1944 - width) * height);
}
void g1_read_crw()
{
ushort pixel[2144*2];
int row, r, col;
d518 1
a518 5
decompress(0,540);
/*
Read two rows at a time.
The image has a black border, eight pixels wide on top,
two on the bottom, four on the left, and 52 on the right.
d520 1
a520 14
for (row = -8; row < height+2; row += 2) {
decompress(pixel,67);
for (r=0; r < 2; r++)
for (col = -4; col < width+52; col++)
if ((unsigned) (row+r) < height && (unsigned) col < width)
image[(row+r)*width+col][FC(row+r,col)] =
(pixel[(r*2144)+col+4] & 0x3ff) << 4;
else
black += pixel[(r*2144)+col+4] & 0x3ff;
}
black = ((INT64) black << 4) / (10 * 2144 + 56 * height);
}
void g2_read_crw()
d522 11
a532 20
ushort pixel[2376*8];
int row, r, col;
decompress(0,540);
/*
Read eight rows at a time.
The image has a black border, six pixels wide on top,
two on the bottom, 12 on the left, and 52 on the right.
*/
for (row = -6; row < height+2; row += 8) {
decompress(pixel,297);
for (r=0; r < 8; r++)
for (col = -12; col < width+52; col++)
if ((unsigned) (row+r) < height && (unsigned) col < width)
image[(row+r)*width+col][FC(row+r,col)] =
(pixel[(r*2376)+col+12] & 0x3ff) << 4;
else
black += pixel[(r*2376)+col+12] & 0x3ff;
}
black = ((INT64) black << 4) / (8 * 2376 + 64 * height);
d535 1
a535 7
/*
The "PowerShot" cameras provide 10 bits per pixel in one compressed
chunk. The "EOS" cameras provide 12 bits per pixel: first the two
low bits of every pixel, not compressed, followed by the top ten bits
compressed as in the PowerShot cameras.
*/
void d30_read_crw()
d538 1
a538 1
int i, row, r, col, save;
d544 1
d546 1
d549 1
a549 1
pixel = calloc (raw_width*4, sizeof *pixel);
d551 1
a551 1
perror("d30_read_crw() calloc failed");
d554 14
a567 9
decompress(0, 540 + raw_height*raw_width/4);
for (row=0; row < raw_height; row+=4) {
decompress(pixel, raw_width/16); /* Get four rows */
save = ftell(ifp); /* Don't lose our place */
fseek (ifp, 26 + row*raw_width/4, SEEK_SET);/* Add the low bits */
for (prow=pixel, i=0; i < raw_width; i++) {
c = fgetc(ifp);
for (r=0; r < 8; r+=2)
*prow++ = (*prow << 2) + ((c >> r) & 3);
d569 1
a569 2
fseek (ifp, save, SEEK_SET);
for (r=0; r < 4; r++)
d576 1
a576 1
(pixel[r*raw_width+col] & 0xfff) << 2;
d578 1
a578 1
black += pixel[r*raw_width+col] & 0xfff;
d582 1
a582 1
black = ((INT64) black << 2) / (left * height);
d599 2
d605 1
d607 3
a609 2
row *= 2;
for (r = row; r < row + 2; r++)
d617 1
a617 1
void eos1d_read_crw()
d621 4
a624 1
fseek (ifp, 288912, SEEK_SET);
d635 2
d654 1
a654 1
if (!strcmp(name,"NIKON D1X"))
d656 1
a656 1
if (!strcmp(name,"NIKON D100"))
a661 2
if (nef_curve_offset == 0)
nef_curve_offset = strcmp(name,"NIKON D100") ? 3488:5974;
d674 1
a674 2
fseek (ifp, nef_data_offset, SEEK_SET);
fseek (ifp, fget4(ifp), SEEK_SET);
d711 3
a713 4
if (strcmp(name,"NIKON D100"))
return nef_data_compression == 0x8799;
fseek (ifp, nef_data_offset, SEEK_SET);
fseek (ifp, fget4(ifp), SEEK_SET);
d729 1
a729 1
if (!strcmp(name,"NIKON D1X"))
d731 1
a731 1
if (!strcmp(name,"NIKON D100")) {
d736 2
a737 1
if (nef_rows_per_strip == 0) return;
d740 1
a740 1
if (name[0] == 'E')
a741 5
if (irow % nef_rows_per_strip == 0) {
fseek (ifp, nef_data_offset + irow/nef_rows_per_strip*4, SEEK_SET);
fseek (ifp, fget4(ifp), SEEK_SET);
getbits(-1);
}
d771 25
d1032 1
a1032 1
void nef_parse_subifd()
d1034 1
a1034 1
int entries, tag, type, len, val;
d1055 1
a1055 1
nef_data_compression = val;
d1059 7
a1065 3
nef_data_offset = ftell(ifp)-4;
else
nef_data_offset = val;
a1069 1
nef_rows_per_strip = val;
d1083 1
a1083 1
int base=0, offset=0, entries, tag, type, len, val, save;
d1108 2
a1109 1
save = ftell(ifp);
d1136 1
a1136 1
Parse a TIFF file looking for camera name and decompress offsets.
d1142 2
a1144 3
nef_data_compression = 0;
nef_data_offset = 0;
nef_rows_per_strip = 0;
d1158 5
d1164 3
a1166 1
fread (name, 64, 1, ifp);
d1169 9
a1177 5
if (len == 2) { /* Get the _second_ sub-image */
fget4(ifp);
fseek (ifp, fget4(ifp), SEEK_SET);
}
nef_parse_subifd();
d1190 1
a1190 1
The camera name, and the decode table number.
d1206 1
a1206 1
if (type == 0x080a) { /* Get the camera name */
d1208 3
a1210 2
while (fgetc(ifp));
fread (name, 64, 1, ifp);
d1243 1
d1251 1
a1251 1
name[0] = 0;
d1263 14
a1276 1
c = name + strlen(name); /* Remove trailing spaces */
d1278 2
a1279 2
if (name[0] == 0) {
fprintf(stderr,"%s has an unknown format.\n",fname);
d1282 1
a1282 1
if (!strcmp(name,"Canon PowerShot 600")) {
d1289 1
a1289 1
} else if (!strcmp(name,"Canon PowerShot A5")) {
d1296 1
a1296 1
} else if (!strcmp(name,"Canon PowerShot A50")) {
d1303 1
a1303 1
} else if (!strcmp(name,"Canon PowerShot Pro70")) {
d1308 1
a1308 1
} else if (!strcmp(name,"Canon PowerShot Pro90 IS")) {
d1312 2
a1313 2
read_crw = pro90_read_crw;
} else if (!strcmp(name,"Canon PowerShot G1")) {
d1317 1
a1317 1
read_crw = g1_read_crw;
d1320 1
a1320 1
} else if (!strcmp(name,"Canon PowerShot S30")) {
d1325 1
a1325 1
read_crw = g1_read_crw;
d1328 4
a1331 2
} else if (!strcmp(name,"Canon PowerShot G2") ||
!strcmp(name,"Canon PowerShot S40")) {
d1336 1
a1336 1
read_crw = g2_read_crw;
d1339 1
a1339 1
} else if (!strcmp(name,"Canon EOS D30")) {
d1344 2
a1345 2
read_crw = d30_read_crw;
} else if (!strcmp(name,"Canon EOS D60")) {
d1350 1
a1350 1
read_crw = d30_read_crw;
d1354 1
a1354 2
} else if (!strcmp(name,"Canon EOS-1D")) {
#ifdef LJPEG_DECODE
d1359 1
a1359 1
read_crw = eos1d_read_crw;
d1362 1
a1362 5
#else
fprintf(stderr,"crw.c was compiled without EOS-1D support.\n");
return 1;
#endif
} else if (!strcmp(name,"NIKON D1")) {
d1371 1
a1371 1
} else if (!strcmp(name,"NIKON D1H")) {
d1380 1
a1380 1
} else if (!strcmp(name,"NIKON D1X")) {
d1389 1
a1389 1
} else if (!strcmp(name,"NIKON D100")) {
d1398 1
a1398 1
} else if (!strcmp(name,"E5000") || !strcmp(name,"E5700")) {
d1406 1
a1406 1
} else if (!strcmp(name,"E-10")) {
d1414 1
a1414 1
} else if (!strncmp(name,"E-20",4)) {
d1422 67
d1490 7
a1496 1
fprintf(stderr,"Sorry, the %s is not yet supported.\n",name);
d1499 1
d1558 1
d1561 5
a1565 1
if (colors == 3)
d1579 7
d1618 1
a1618 1
fprintf(ofp,"P6\n%d %d\n255\n",width-trim*2,height-trim*2);
d1784 2
a1785 2
fprintf(stderr,
"\nCanon PowerShot Converter v3.18"
d1787 1
a1787 1
" with EOS-1D support"
d1843 1
a1843 1
fprintf(stderr,"Unknown option \"%s\"\n",argv[arg]);
d1851 1
d1861 2
a1862 2
black = 0;
fprintf (stderr, "Loading %s image from %s...\n",name,argv[arg]);
d1866 1
a1866 1
fprintf (stderr, "Subtracting thermal noise (%d)...\n",black);
d1869 2
d1890 1
d1901 1
a1901 1
fprintf (stderr, "Writing data to %s...\n",data);
@
1.71
log
@Bought a Kodak Grey Card and rebalanced my PowerShot G2.
(using the white side, direct sunlight, no clouds)
@
text
@d966 7
a972 3
We now have all color values for each pixel. Smooth the
color balance to avoid artifacts. This function may be
called more than once.
d990 5
d996 1
a996 2
memset (avg, 0, sizeof avg);
for (y = row-1; y < row+2; y++)
d998 1
a998 1
if ((c = FC(y,x)) != cc && image[y*width+x][cc]) {
d1003 1
a1003 1
if (y==row || x==col) { /* Orthogonal neighbor */
d1008 1
a1008 1
curr[col][cc] = image[row*width+col][cc];
d1010 1
a1010 2
if (c != cc)
curr[col][c] = avg[c+4] ? avg[c] / avg[c+4] : 0;
d1697 1
a1697 1
"\nCanon PowerShot Converter v3.15"
@
1.70
log
@Reorganized NEF decoding, improved compatibility with Windows and C++.
@
text
@d1323 2
a1324 2
rgb_mul[0] = 1.828;
rgb_mul[2] = 1.326;
d1690 1
a1690 1
"\nCanon PowerShot Converter v3.14"
@
1.69
log
@Correctly decode the Nikon E5000 and E5700
@
text
@d28 5
d34 2
d56 1
a56 1
int nikon_curve_offset, nikon_data_compression, nikon_data_offset;
d189 1
a189 1
black = ((long long) black << 4) / ((896 - width) * height);
d224 1
a224 1
black = ((long long) black << 4) / ((992 - width) * height);
d259 1
a259 1
black = ((long long) black << 4) / ((1320 - width) * height);
d534 1
a534 1
black = ((long long) black << 4) / ((1944 - width) * height);
d558 1
a558 1
black = ((long long) black << 4) / (10 * 2144 + 56 * height);
d582 1
a582 1
black = ((long long) black << 4) / (8 * 2376 + 64 * height);
d632 1
a632 1
black = ((long long) black << 2) / (left * height);
d683 1
a683 1
void nikon_d1x_read_crw()
a690 1
uchar test[256], skip16=0;
d697 1
a697 7
/*
Try to figure out if the image is compressed, based on
my limited collection of NEF files. For the D100, every
16th byte of an uncompressed image is zero.
*/
fseek (ifp, nikon_data_offset, SEEK_SET);
if (!strcmp(name,"NIKON D100")) {
a698 22
fread (test, 1, 256, ifp);
for (i=0; i < 16; i++)
if (test[i*16+15]) goto compressed;
fseek (ifp, -256, SEEK_CUR);
width = 3037;
waste = 3;
skip16 = 1;
} else if (nikon_data_compression == 0x8799)
goto compressed;
/* Read an uncompressed image */
getbits(-1);
for (row=0; row < height; row++) {
for (col=0; col < width+waste; col++) {
i = getbits(12);
if (col < width)
image[row*width+col][FC(row,col)] = i << 2;
if (skip16 && (col % 10) == 9)
getbits(8);
}
}
return;
a699 2
/* Read an compressed image */
compressed:
d703 3
a705 3
if (nikon_curve_offset == 0)
nikon_curve_offset = strcmp(name,"NIKON D100") ? 3488:5974;
fseek (ifp, nikon_curve_offset, SEEK_SET);
d711 1
a711 1
perror("nikon_d1x_read_crw() calloc failed");
d717 2
a718 1
fseek (ifp, nikon_data_offset, SEEK_SET);
d722 2
a723 2
for (col=0; col < width+waste; col++) {
d745 21
a765 1
void nikon_e5000_read_crw()
d767 2
a768 3
uchar data[3864], *dp;
ushort pixel[2576], *pix;
int irow, row, col;
d770 27
a796 8
fseek (ifp, 589225, SEEK_SET);
for (irow=row=0; irow < height; irow++)
{
fread (data, 3864, 1, ifp);
for (dp=data, pix=pixel; dp < data+3864; dp+=3, pix+=2)
{
pix[0] = (dp[0] << 4) + (dp[1] >> 4);
pix[1] = (dp[1] << 8) + dp[2];
a797 5
for (col=0; col < width; col++)
image[row*width+col][FC(row,col)] = (pixel[col] & 0xfff) << 2;
if ((row+=2) >= height) /* Once we've read all the even rows, */
row = 1; /* read the odd rows. */
d973 1
a973 1
ushort (*this)[4];
d978 3
a980 3
last = calloc (width, sizeof *this);
this = calloc (width, sizeof *this);
if (!last || !this) {
d1000 1
a1000 1
this[col][cc] = image[row*width+col][cc];
d1003 1
a1003 1
this[col][c] = avg[c+4] ? avg[c] / avg[c+4] : 0;
d1008 2
a1009 2
last = this;
this = tmp;
d1013 1
a1013 1
free (this);
d1049 1
a1049 1
void nikon_parse_subifd()
d1051 1
a1051 1
int entries, tag, type, len, val, save;
a1061 1
save = ftell(ifp);
d1072 1
a1072 1
nikon_data_compression = val;
d1076 3
a1078 5
nikon_data_offset = val;
else {
fseek (ifp, val, SEEK_SET);
nikon_data_offset = fget4(ifp);
}
d1081 1
d1083 2
d1086 1
a1091 1
fseek (ifp, save, SEEK_SET);
d1095 1
a1095 1
void nikon_parse_makernote()
d1124 1
a1124 1
nikon_curve_offset = base+val + 2;
d1129 1
a1129 1
void nikon_parse_exif()
d1142 1
a1142 1
nikon_parse_makernote();
d1155 4
a1158 3
nikon_curve_offset = 0;
nikon_data_compression = 0;
nikon_data_offset = 0;
d1176 5
a1180 1
nikon_parse_subifd();
d1183 1
a1183 1
nikon_parse_exif();
d1359 1
a1359 1
read_crw = nikon_d1x_read_crw;
d1368 1
a1368 1
read_crw = nikon_d1x_read_crw;
d1377 1
a1377 1
read_crw = nikon_d1x_read_crw;
d1386 1
a1386 1
read_crw = nikon_d1x_read_crw;
d1392 1
d1394 1
a1394 1
read_crw = nikon_e5000_read_crw;
d1669 1
a1669 1
void exten(char *new, const char *old, const char *ext)
d1673 3
a1675 3
strcpy(new,old);
cp=strrchr(new,'.');
if (!cp) cp=new+strlen(new);
d1690 1
a1690 1
"\nCanon PowerShot Converter v3.11"
@
1.68
log
@Greatly improved NEF parsing, thanks to Chris Breeze.
@
text
@d768 1
a768 1
void nikon_e5700_read_crw()
d774 1
a774 1
fseek (ifp, 589226, SEEK_SET);
d780 2
a781 2
pix[0] = (dp[0] << 8) + (dp[1] & 0xf0) + (dp[1] >> 4);
pix[1] = (dp[2] << 4) + (dp[1] & 0x0f);
d1374 1
a1374 1
} else if (!strcmp(name,"E5700")) {
d1377 2
a1378 2
filters = 0xe1e1e1e1;
read_crw = nikon_e5700_read_crw;
d1674 1
a1674 1
"\nCanon PowerShot Converter v3.10"
@
1.67
log
@Don't assume that the compiler evaluates left-to-right!
@
text
@d49 1
a49 1
int nef_data_offset;
d678 1
a678 1
int waste=0, comp;
d696 1
a696 4
fseek (ifp, nef_data_offset+58, SEEK_SET);
comp = fget2(ifp);
fseek (ifp, nef_data_offset+142, SEEK_SET);
fseek (ifp, fget4(ifp)+8, SEEK_SET);
d706 1
a706 1
} else if (comp == 0x8799)
d727 3
a729 4
if (!strcmp(name,"NIKON D100"))
fseek (ifp, 5974, SEEK_SET);
else
fseek (ifp, 3488, SEEK_SET);
d741 1
a741 2
fseek (ifp, nef_data_offset+82, SEEK_SET);
fseek (ifp, fget4(ifp), SEEK_SET);
d1039 99
d1145 3
d1159 1
a1161 1
fseek (ifp, val, SEEK_SET);
d1165 5
a1169 1
nef_data_offset = val;
d1180 1
a1180 1
void parse (int offset, int length)
d1209 1
a1209 1
parse (aoff, len);
d1244 1
a1244 1
parse (hlen, ftell(ifp) - hlen);
d1674 1
a1674 1
"\nCanon PowerShot Converter v3.06"
@
1.66
log
@Color-balanced the PowerShot G2 based on my new camera.
@
text
@d1013 1
d1017 4
d1022 3
a1024 3
return (fgetc(f) << 8) + fgetc(f);
else
return fgetc(f) + (fgetc(f) << 8);
d1032 6
d1039 1
a1039 1
return (fgetc(f) << 24) + (fgetc(f) << 16) + (fgetc(f) << 8) + fgetc(f);
d1041 1
a1041 1
return fgetc(f) + (fgetc(f) << 8) + (fgetc(f) << 16) + (fgetc(f) << 24);
d1573 1
a1573 1
"\nCanon PowerShot Converter v3.05"
@
1.65
log
@Allow Dillon interpolation for some GMCY cameras.
@
text
@d1196 2
a1197 2
rgb_mul[0] = 2.156;
rgb_mul[2] = 1.043;
d1562 1
a1562 1
"\nCanon PowerShot Converter v3.04"
@
1.64
log
@Added support for the Nikon E5700
@
text
@d1554 1
a1554 1
int i, arg, write_to_files=1, dillon=0, smooth=1;
d1562 1
a1562 1
"\nCanon PowerShot Converter v3.03"
d1570 1
a1570 1
"\n-d Use Dillon interpolation for RGB cameras"
d1645 5
a1649 1
if (dillon && colors == 3) {
d1654 2
@
1.63
log
@Added support for the Olympus E-20
@
text
@d773 23
d1262 7
d1562 1
a1562 1
"\nCanon PowerShot Converter v3.02"
@
1.62
log
@Don't do arithmetic with byte-swapped numbers!
@
text
@d775 1
a775 1
ushort pixel[2256];
d778 5
d785 1
a785 1
fread (pixel, 2, 2256, ifp);
d789 1
d1247 8
d1532 1
a1532 1
"\nCanon PowerShot Converter v3.01"
@
1.61
log
@Added support for uncompressed Nikon D100 images.
Added support for the Olympus E-10 (uncompressed)
Added Matt Dillon's RGB interpolation algorithm.
Releasing all this as version 3.00.
@
text
@d1409 1
a1409 1
psize = hw[0] * hw[1];
d1518 1
a1518 1
"\nCanon PowerShot Converter v3.00"
@
1.60
log
@Added support for the Nikon D100
@
text
@d47 1
a47 1
int height, width, colors, black, canon, rgb_max;
d678 1
a678 1
int waste=0;
d684 1
a688 1
/* Read an uncompressed image */
d691 5
d697 14
a710 4
if (fget2(ifp) != 0x8799) {
fseek (ifp, nef_data_offset+142, SEEK_SET);
fseek (ifp, fget4(ifp)+8, SEEK_SET);
getbits(-1);
d712 9
a720 5
for (row=0; row < height; row++) {
for (col=0; col < width; col++)
image[row*width+col][FC(row,col)] = getbits(12) << 2;
for (col=0; col < waste; col++)
getbits(12);
a721 1
return;
d723 1
d726 1
d730 1
a730 1
if (!strcmp(name,"NIKON D100 "))
d773 13
d802 98
d1012 1
a1012 1
if (fget2(ifp) != 42) return;
d1081 1
a1081 1
char head[8];
d1108 2
d1197 1
a1197 1
} else if (!strcmp(name,"NIKON D1 ")) {
d1224 1
a1224 1
} else if (!strcmp(name,"NIKON D100 ")) {
d1226 1
a1226 1
width = 3034;
d1233 8
d1336 2
a1337 2
for (y=1; y < height-1; y++)
for (x=1; x < width-1; x++) {
d1351 1
a1351 1
fprintf(ofp,"P6\n%d %d\n255\n",width-2,height-2);
d1353 1
a1353 1
ppm = calloc(width-2,3);
d1361 1
a1361 1
for (y=1; y < height-1; y++)
d1363 1
a1363 1
for (x=1; x < width-1; x++)
d1374 1
a1374 1
ppm[x-1][c]=val;
d1377 1
a1377 1
fwrite (ppm, width-2, 3, ofp);
d1404 2
a1405 2
hw[0] = htonl(height-2); /* write the header */
hw[1] = htonl(width-2);
d1409 1
a1409 1
psize = (height-2) * (width-2);
d1417 1
a1417 1
for (y=1; y < height-1; y++)
d1419 1
a1419 1
for (x=1; x < width-1; x++)
d1459 1
a1459 1
png_set_IHDR (png_ptr, info_ptr, width-2, height-2,
d1471 1
a1471 1
png = calloc(width-2,6);
d1477 2
a1478 2
for (y=1; y < height-1; y++) {
for (x=1; x < width-1; x++) {
d1510 1
a1510 1
int i, arg, smooth=1, write_to_files=1;
d1518 1
a1518 1
"\nCanon PowerShot Converter v2.96"
d1526 1
d1549 2
d1601 12
a1612 5
fprintf (stderr, "First interpolation...\n");
first_interpolate();
for (i=0; i < smooth; i++) {
fprintf (stderr, "Second interpolation...\n");
second_interpolate();
@
1.59
log
@Fixed compiler warnings generated by "gcc -O2 -Wall".
@
text
@d710 4
a713 1
fseek (ifp, 3488, SEEK_SET);
d1091 9
d1377 1
a1377 1
"\nCanon PowerShot Converter v2.95"
@
1.58
log
@Added command-line arguments for color balance.
@
text
@d588 1
a588 1
unsigned top, left, irow, icol;
d674 1
d879 1
a879 1
while (doff = fget4(ifp)) {
d1058 1
a1058 1
fprintf(stderr,"crw.c was compiled without EOS-1D support.\n",fname);
d1173 1
a1173 1
int y, x, i;
a1177 1
char p6head[32];
@
1.57
log
@Added support for the Nikon D1H
@
text
@d54 1
a54 1
float gamma_val=0.8, bright=1.0;
d1091 2
d1365 1
a1365 1
"\nCanon PowerShot Converter v2.94"
d1376 2
d1401 4
@
1.56
log
@Calculate the GMCY -> RGB matrix here, instead of using invert.c.
@
text
@d1069 9
d1363 1
a1363 1
"\nCanon PowerShot Converter v2.93"
@
1.55
log
@Don't multiply rgb_max by bright -- that was a mistake.
@
text
@d938 2
d947 1
a947 6
static const float def_coeff[3][4] = {
{ -2.400719, 3.539540, -2.515721, 3.421035 }, /* red from GMCY */
{ 4.013642, -1.710916, 0.690795, 0.417247 }, /* green from GMCY */
{ -2.345669, 3.385090, 3.521597, -2.249256 } /* blue from GMCY */
};
int hlen, i, r, g;
d1082 1
a1082 4
for (r=0; r < 3; r++) {
for (g=0; g < 4; g++)
coeff[r][g] = def_coeff[r][g] * rgb_mul[r];
}
d1087 16
a1102 1
Convert a GMCY quadruplet to an RGB triplet.
d1104 30
a1133 2
The following table shows how the four CCD pixel types respond
to the three primary colors, on a scale of 0-100.
a1134 9
RGB---> red green blue
GMCY-v
green 11 86 8
magenta 50 29 51
cyan 11 92 75
yellow 81 98 8
get_rgb() is based on an inversion of this table.
*/
d1140 2
a1141 2
for (r=0; r < 3; r++) {
if (colors == 3) {
d1145 4
a1148 1
} else {
d1151 2
a1152 1
if (rgb[r] < 0) rgb[r]=0;
a1153 2
rgb[3] += rgb[r]*rgb[r]; /* Compute magnitude */
}
d1354 1
a1354 1
"\nCanon PowerShot Converter v2.91"
@
1.54
log
@Fixed the "pink sky" problem for RGB cameras, and adjusted the
brightness algorithm.
@
text
@d955 1
a955 1
rgb_max = 0x4000 * bright;
d1049 1
a1049 1
rgb_max = 16000 * bright;
d1324 1
a1324 1
"\nCanon PowerShot Converter v2.90"
@
1.53
log
@Added option to call second_interpolate() multiple times,
or not at all. Color-balanced the Canon EOS D60.
@
text
@d47 1
a47 1
int height, width, colors, black, canon;
d761 1
d955 1
d1049 1
d1113 1
a1113 1
if (colors == 3)
d1115 3
a1117 1
else {
d1150 1
a1150 1
Set the maximum magnitude to the 98th percentile
d1153 1
a1153 1
if ((total+=histogram[val]) > (int)(width*height*0.06)) break;
d1165 1
a1165 1
mul = bright * 362 / max;
d1173 2
a1174 1
scale = rgb[3] ? mul * pow(rgb[3]/max2,expo) : 0;
d1206 1
a1206 1
int hw[2], psize, y, x, c, val, max=0xffff;
a1222 5
if (colors == 3)
max = 0x4000 * bright;
if (max > 0xffff)
max = 0xffff;
d1230 1
a1230 1
if (val > max) val = max;
d1249 1
a1249 1
int y, x, c, val, max=0xffff;
a1282 5
if (colors == 3)
max = 0x4000 * bright;
if (max > 0xffff)
max = 0xffff;
d1288 1
a1288 1
if (val > max) val = max;
d1324 1
a1324 1
"\nCanon PowerShot Converter v2.88"
@
1.52
log
@The top 12 rows of the D60 image contain strange values.
Don't use them to calculate the black point.
@
text
@d1045 2
d1320 1
a1320 1
int i, arg, write_to_files=1;
d1328 1
a1328 1
"\nCanon PowerShot Converter v2.86"
d1336 1
d1356 2
d1404 4
a1407 3
fprintf (stderr, "Second interpolation...\n");
second_interpolate();
@
1.51
log
@Added support for the Canon EOS D60 camera.
@
text
@d616 2
a617 1
if (irow < height && icol < width)
d625 1
a625 8
/*
"i" is the number of full rows to include in the average.
On the EOS D60, the top seven rows are zero, not black,
hence I do not include them in the denominator.
*/
i = raw_height - height;
if (raw_width == 3152) i -= 7;
black = ((long long) black << 2) / (i * raw_width + left * height);
d1326 1
a1326 1
"\nCanon PowerShot Converter v2.85"
@
1.50
log
@Never call pow(base,exp) with a base of zero
@
text
@d48 1
d461 1
a461 1
void decompress(ushort *outbuf, int width, int count)
d467 1
a467 1
if (!width) { /* Initialize */
d499 1
a499 1
if (pixel++ % width == 0)
d512 1
a512 1
decompress(0,0,540);
d518 1
a518 1
decompress(pixel,1944,243);
d535 1
a535 1
decompress(0,0,540);
d542 1
a542 1
decompress(pixel,2144,67);
d559 1
a559 1
decompress(0,0,540);
d566 1
a566 1
decompress(pixel,2376,297);
d579 4
a582 3
All other cameras give 10 bits per sample; the EOS D30 gives 12.
The other two bits are in a different part of the file, so I save
my place, and seek over there to pick them up.
d586 1
a586 1
ushort pixel[2224*4], *prow;
d588 1
d591 16
a606 11
decompress(0,0,810076);
/*
Read four rows at a time.
The image has a black border, six pixels wide on top,
two on the bottom, 48 on the left, and none on the right.
*/
for (row = -6; row < height+2; row += 4) {
decompress(pixel,2224,139);
save = ftell(ifp);
fseek (ifp, (row+6)*(2224/4) + 26, SEEK_SET); /* Get low bits */
for (prow=pixel, i=0; i < 2224; i++) {
d613 6
a618 4
for (col = -48; col < width; col++)
if ((unsigned) (row+r) < height && col >= 0)
image[(row+r)*width+col][FC(row+r,col)] =
(pixel[(r*2224)+col+48] & 0xfff) << 2;
d620 2
a621 1
black += pixel[(r*2224)+col+48] & 0xfff;
d623 9
a631 1
black = ((long long) black << 2) / (8 * 2224 + 48 * height);
d928 5
d1045 6
d1332 1
a1332 1
"\nCanon PowerShot Converter v2.81"
@
1.49
log
@Added support for the Nikon D1 model
@
text
@d1141 2
a1142 1
scale = mul * pow(rgb[3]/max2,expo);
d1302 1
a1302 1
"\nCanon PowerShot Converter v2.80"
@
1.48
log
@Removed unnecessary return
@
text
@d25 5
a32 4
#include
#include
#include
#include
d134 1
a134 1
The Nikon D1X uses 0x16161616:
d664 1
d675 3
a677 1
fseek (ifp, nef_data_offset+76, SEEK_SET);
d679 1
a679 1
fseek (ifp, nef_data_offset+160, SEEK_SET);
d683 6
a688 6
for (row=0; row < 1324; row++)
for (col=0; col < 4028; col++) {
diff = getbits(12);
if (col < width)
image[row*width+col][FC(row,col)] = diff << 2;
}
d708 1
a708 1
fseek (ifp, nef_data_offset+100, SEEK_SET);
d712 2
a713 2
for (row=0; row < 1324; row++)
for (col=0; col < 4028; col++) {
d874 1
a874 1
case 0x110:
d878 1
a878 1
case 0x8825:
d1034 9
d1301 1
a1301 1
"\nCanon PowerShot Converter v2.75"
@
1.47
log
@Added support for uncompressed Nikon D1X files.
@
text
@a1038 1
return 0;
@
1.46
log
@Added Nikon NEF support that actually works!
@
text
@d672 17
d704 2
a705 1
fseek (ifp, nef_data_offset+244, SEEK_SET);
d723 1
a723 1
if (col >= 4024) continue;
a1025 1
return 0;
d1289 1
a1289 1
"\nCanon PowerShot Converter v2.70"
@
1.45
log
@Added support for the Nikon D1X compressed NEF format.
@
text
@d47 1
d132 8
d659 1
a659 1
short fget2 (FILE *f);
d687 1
a687 1
fseek (ifp, 83662, SEEK_SET);
d709 1
a709 1
image[row*width+col][FC(row,col)] = curve[diff];
d814 1
a814 1
short fget2 (FILE *f)
d834 31
d922 1
d924 12
a935 35
hlen = fget4(ifp);
fread (head, 1, 8, ifp);
if (memcmp(head,"HEAPCCDR",8) || (order != 0x4949 && order != 0x4d4d)) {
fseek(ifp, 250, SEEK_SET);
fread(name, 64, 1, ifp);
if (!strcmp(name,"Canon EOS-1D")) {
#ifdef LJPEG_DECODE
height = 1662;
width = 2496;
colors = 3;
filters = 0x61616161;
read_crw = eos1d_read_crw;
rgb_mul[0] = 1.976;
rgb_mul[2] = 1.282;
return 0;
#else
fprintf(stderr,"crw.c was compiled without EOS-1D support.\n",fname);
return 1;
#endif
}
fseek(ifp, 382, SEEK_SET);
fread(name, 64, 1, ifp);
if (!strcmp(name,"NIKON D1X")) {
height = 1324;
width = 4024;
colors = 3;
canon = 0;
filters = 0x94949494;
read_crw = nikon_d1x_read_crw;
rgb_mul[0] = 1.3;
rgb_mul[2] = 1.24;
return 0;
}
fprintf(stderr,"%s is not a Canon RAW file.\n",fname);
a937 6
name[0] = 0;
fseek (ifp, 0, SEEK_END);
parse (hlen, ftell(ifp) - hlen);
fseek (ifp, hlen, SEEK_SET);
d999 24
d1272 1
a1272 1
"\nCanon PowerShot Converter v2.60"
d1336 1
a1336 1
fprintf (stderr, "Loading data from %s...\n",argv[arg]);
d1339 4
a1342 2
fprintf (stderr, "Subtracting thermal noise (%d)...\n",black);
subtract_black();
@
1.44
log
@Merged in EOS-1D code after it passed beta test.
@
text
@d46 1
a46 1
int height, width, colors, black;
d437 1
a437 1
if (c == 0xff) fgetc(ifp); /* always extra 00 after ff */
d650 55
d875 1
a902 3
} else {
fprintf(stderr,"%s is not a Canon RAW file.\n",fname);
return 1;
d904 15
d1236 1
a1236 1
"\nCanon PowerShot Converter v2.55"
@
1.43
log
@Adjusted the S30 color balance
@
text
@d17 6
a22 1
*/
d33 6
d116 1
a116 1
All RGB cameras use 0x94949494:
d123 8
d605 45
d831 20
a850 2
fprintf(stderr,"%s is not a Canon CRW file.\n",fname);
return 1;
d1168 4
a1171 1
"\nCanon PowerShot Converter v2.54"
d1234 1
a1240 1
fclose(ifp);
@
1.42
log
@Avoid bus errors on CPUs that enforce word alignment.
@
text
@d820 2
a821 2
rgb_mul[0] = 1.97;
rgb_mul[2] = 1.123;
d1086 1
a1086 1
"\nCanon PowerShot Converter v2.53"
@
1.41
log
@Changes by Markus Mayer to prevent compiler warnings
@
text
@d958 1
a958 2
int *hw = (int *)(head+14);
int psize, y, x, c, val, max=0xffff;
d964 1
d1086 1
a1086 1
"\nCanon PowerShot Converter v2.52"
@
1.40
log
@Color-balanced the PowerShot G1
@
text
@d3 1
a3 1
Copyright 1997-2001 by Dave Coffin
d302 1
a302 1
int make_decoder(struct decode *dest, const uchar *source, int level)
d305 1
a305 1
static leaf; /* number of leaves already added */
d328 1
a328 1
init_tables(unsigned table)
d431 1
a431 1
decompress(ushort *outbuf, int width, int count)
d586 1
a586 1
subtract_black()
d606 1
a606 1
first_interpolate()
d637 1
a637 1
second_interpolate()
d709 1
a709 1
parse (int offset, int length)
d742 1
a742 1
open_and_id(char *fname)
d863 1
a863 1
get_rgb(float rgb[4], ushort image[4])
d1065 1
a1065 1
exten(char *new, const char *old, const char *ext)
d1075 1
a1075 1
main(int argc, char **argv)
d1174 1
@
1.39
log
@Added NO_PNG compile flag, since most people don't need 48-bit output.
@
text
@d812 2
d1086 1
a1086 1
"\nCanon PowerShot Converter v2.51"
@
1.38
log
@Fixed color balance for S40 and G2 cameras.
@
text
@d20 1
d22 1
d995 1
d1058 1
d1093 4
a1096 1
"\n-4 Write 48-bit PNG\n\n",
d1120 1
d1125 1
@
1.37
log
@Removed old "ymul" hack.
Use black pixels to subtract thermal noise from image.
@
text
@d3 1
a3 1
Copyright (c)1997-2001 by Dave Coffin
d825 2
d1080 1
a1080 1
"\nCanon PowerShot Converter v2.50"
@
1.36
log
@Added support for the PowerShot S30 camera
@
text
@d33 1
a33 1
int height, width, colors;
a38 1
float ymul[4];
d51 2
a55 1
d57 1
a57 1
Filter pattern of the PowerShot 600:
d60 3
a62 3
0 G M G M G M Return values
1 C Y C Y C Y 0 1 2 3
2 M G M G M G G M C Y
d64 46
d111 1
d139 1
a139 1
are blank. Left-shift by 4 for extra precision in upcoming
d144 2
d150 1
a152 9
/*
Filter pattern of the PowerShot A5:
0 1 2 3 4 5
0 C Y C Y C Y Return values
1 G M G M G M 0 1 2 3
2 C Y C Y C Y G M C Y
3 M G M G M G
*/
d164 1
a164 1
for (dp=data, pix=pixel; dp < data+1200; dp+=10, pix+=8)
d177 1
a177 1
are blank. Left-shift by 4 for extra precision in upcoming
d182 2
d185 1
a187 13
/*
Filter pattern of the PowerShot A50:
0 1 2 3 4 5
0 C Y C Y C Y Return values
1 M G M G M G 0 1 2 3
2 Y C Y C Y C G M C Y
3 G M G M G M
4 C Y C Y C Y
5 G M G M G M
6 Y C Y C Y C
7 M G M G M G
*/
d212 1
a212 1
are blank. Left-shift by 4 for extra precision in upcoming
d217 2
d220 1
a222 13
/*
Filter pattern of the PowerShot Pro70:
0 1 2 3 4 5
0 Y C Y C Y C Return values
1 M G M G M G 0 1 2 3
2 C Y C Y C Y G M C Y
3 G M G M G M
4 Y C Y C Y C
5 G M G M G M
6 C Y C Y C Y
7 M G M G M G
*/
d247 1
a247 1
extra precision in upcoming calculations.
a474 7
/*
Filter pattern of the PowerShot Pro90 and G1:
0 1 2 3 4 5 Return values
0 G M G M G M 0 1 2 3
1 Y C Y C Y C G M C Y
*/
d481 4
a484 1
d487 1
a487 1
for (r=0; r < 8; r++)
d491 3
d495 1
d504 6
a509 4
/* Read two rows at a time, discarding the first eight */
for (row = -8; row < height; row += 2) {
a510 1
if (row < 0) continue;
d512 3
a514 2
for (col=0; col < width; col++)
image[(row+r)*width+col][FC(row+r,col)] =
d516 2
d519 1
a521 9
/*
Filter pattern of the PowerShot G2 and EOS D30:
0 1 2 3 4 5 Return values
0 R G R G R G 0 1 2
1 G B G B G B R G B
2 R G R G R G
3 G B G B G B
*/
d524 2
a525 2
ushort pixel[2376*8], *prow, (*imrow)[4];
int row, r, orow, col;
d528 6
a533 4
/* Read eight rows at a time, discarding the first six */
for (row = -6; row < height; row += 8) {
d535 7
a541 9
for (r=0; r < 8; r++) {
orow = row + r;
if (orow < 0) continue;
if (orow >= height) break;
imrow = image + orow*width;
prow = pixel + r*2376 + 12;
for (col=0; col < width; col++)
imrow[col][FC(orow,col)] = (prow[col] & 0x3ff) << 4;
}
d543 1
d553 2
a554 2
ushort pixel[2224*4], *prow, (*imrow)[4];
int i, row, r, orow, col, save;
d558 6
a563 4
/* Read four rows at a time, discarding the first six rows */
for (row = -6; row < height; row += 4) {
d573 23
a595 10
for (r=0; r < 4; r++) {
orow = row + r;
if (orow < 0) continue;
if (orow >= height) break;
imrow = image + orow*width;
prow = pixel + r*2224 + 48;
for (col=0; col < width; col++)
imrow[col][FC(orow,col)] = (prow[col] & 0xfff) << 2;
}
}
a749 1
for (i=0; i < 4; i++) ymul[i]=1.0;
a780 2
ymul[0] = 0.9866;
ymul[2] = 1.0125;
a787 4
ymul[0] = 1.0005;
ymul[1] = 1.0056;
ymul[2] = 0.9980;
ymul[3] = 0.9959;
d882 1
a882 2
float rgb[4], max, max2, expo, scale;
float gymul[4];
d913 1
a913 2
for (y=0; y < 4; y++)
gymul[y] = bright * 362 / max * pow(ymul[y],gamma_val);
d920 1
a920 1
scale = gymul[y&3] * pow(rgb[3]/max2,expo);
d1078 1
a1078 1
"\nCanon PowerShot Converter v2.37"
d1133 1
d1136 2
@
1.35
log
@Added support for 48-bit Adobe Photoshop format
@
text
@d784 8
d1054 1
a1054 1
"\nCanon PowerShot Converter v2.35"
@
1.34
log
@Synchronized code between C programs, fail more intelligently
on non-CRW files, have heap.c write JPEG thumbnails, and have
decompress.c correctly parse the heap.
@
text
@d843 1
a843 1
write_ppm(FILE *ofp)
d902 56
d962 1
a962 1
write_png(FILE *ofp)
d967 2
a968 2
float rgb[4], val;
int y, x, c, max=0xffff;
d1038 3
a1040 1
int i, arg, write_to_files=1, format_png=0, row;
d1046 1
a1046 1
"\nCanon PowerShot Converter v2.32"
d1051 1
a1051 1
"\n-g Set gamma value (%5.3f by default)"
d1054 2
a1055 1
"\n-4 Write 48-bit PNG (-g ignored)\n\n",
d1072 7
a1078 1
format_png=0; break;
d1080 3
a1082 1
format_png=1; break;
d1110 1
d1112 1
a1112 1
exten(data, argv[arg], format_png ? ".png":".ppm");
d1119 2
a1120 7
if (format_png) {
fprintf (stderr, "Writing PNG output...\n");
write_png(ofp);
} else {
fprintf (stderr, "Writing PPM output...\n");
write_ppm(ofp);
}
d1123 1
@
1.33
log
@Many changes for v2.30:
Inlined the filter functions for better performance.
Histogram the magnitudes instead of their squares.
Set rgb_mul[1] = 1.0 and adjust red and blue accordingly.
Allow manual brightness adjustment of PNG output.
@
text
@d122 1
a122 1
fread(data, 1240, 1, ifp);
d167 1
a167 1
fread(data, 1650, 1, ifp);
d212 1
a212 1
fread(data, 1940, 1, ifp);
d653 3
a655 1
if (order == 0x4949) /* "II" means little-endian */
a656 6
else if (order == 0x4d4d) /* "MM" means big-endian */
return (fgetc(f) << 8) + fgetc(f);
else {
fprintf(stderr,"Unknown byte order!");
exit(1);
}
d664 3
a666 1
if (order == 0x4949)
a667 6
else if (order == 0x4d4d)
return (fgetc(f) << 24) + (fgetc(f) << 16) + (fgetc(f) << 8) + fgetc(f);
else {
fprintf(stderr,"Unknown byte order!");
exit(1);
}
d676 1
a676 1
int save, toff, nrecs, i, type, len, off;
d679 2
a680 2
toff = fget4(ifp) + offset;
fseek (ifp, toff, SEEK_SET);
d685 2
a686 1
off = fget4(ifp);
d689 1
a689 1
fseek (ifp, offset+off, SEEK_SET);
d694 1
a694 1
fseek (ifp, offset+off, SEEK_SET);
d698 1
a698 1
parse (offset+off, len);
d728 2
a729 2
fread (&order, 2, 1, ifp);
hlen = fget4(ifp);
d732 1
a732 1
if (memcmp(head,"HEAPCCDR",8)) {
d988 1
a988 1
"\nCanon PowerShot Converter v2.30"
@
1.32
log
@Sometimes the CYGM-to-RGB matrix produces a negative value.
Do not allow this!
@
text
@d6 1
a6 1
digital cameras into PPM format.
d34 1
a36 1
int (*filter)(int,int);
d49 8
a64 5
ps600_filter(int row, int col)
{
return (0xe1e4 >> ((((row) << 1 & 6) + ((col) & 1)) << 1) & 3);
}
d96 1
a96 1
image[orow*width+col][(*filter)(orow,col)] = pixel[col] << 4;
a111 5
a5_filter(int row, int col)
{
return (0x1e4e >> ((((row) << 1 & 6) + ((col) & 1)) << 1) & 3);
}
d140 1
a140 1
image[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4;
a156 5
a50_filter(int row, int col)
{
return (0x1b4e4b1e >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3);
}
d185 1
a185 1
image[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4;
a201 5
pro70_filter(int row, int col)
{
return (0x1e4b4e1b >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3);
}
d229 1
a229 1
image[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4;
a460 5
pro90_filter(int row, int col)
{
return (0xb4 >> ((((row) << 1 & 2) + ((col) & 1)) << 1) & 3);
}
d472 1
a472 1
image[(row+r)*width+col][(*filter)(row+r,col)] =
d491 1
a491 1
image[(row+r)*width+col][(*filter)(row+r,col)] =
a504 5
rgb_filter(row,col)
{
return (((row) & 1) + ((col) & 1));
}
d523 1
a523 1
imrow[col][(*filter)(orow,col)] = (prow[col] & 0x3ff) << 4;
d560 1
a560 1
imrow[col][(*filter)(orow,col)] = (prow[col] & 0xfff) << 2;
d578 1
a578 1
cc = (*filter)(row,col);
d582 1
a582 1
if ((c = (*filter)(y,x)) != cc) {
d618 1
a618 1
cc = (*filter)(row,col);
d622 1
a622 1
if ((c = (*filter)(y,x)) != cc && image[y*width+x][cc]) {
d725 3
a727 1
for (i=0; i < 3; i++) rgb_mul[i]=1.0;
d752 4
a755 2
rgb_mul[1] = 0.6;
rgb_mul[2] = 1.0;
a757 2
filter = ps600_filter;
read_crw = ps600_read_crw;
d761 4
a764 2
rgb_mul[1] = 0.90;
rgb_mul[2] = 0.88;
a768 2
filter = a5_filter;
read_crw = a5_read_crw;
d772 1
a772 3
rgb_mul[1] = 0.76;
rgb_mul[2] = 0.59;
filter = a50_filter;
d774 2
d779 1
a779 3
rgb_mul[1] = 0.628;
rgb_mul[2] = 0.792;
filter = pro70_filter;
d784 1
a784 3
rgb_mul[1] = 0.628;
rgb_mul[2] = 0.792;
filter = pro90_filter;
d789 1
a789 3
rgb_mul[1] = 0.628;
rgb_mul[2] = 0.792;
filter = pro90_filter;
d796 1
a796 3
rgb_mul[1] = 0.628;
rgb_mul[2] = 0.792;
filter = rgb_filter;
d802 1
a802 3
rgb_mul[1] = 0.628;
rgb_mul[2] = 0.792;
filter = rgb_filter;
d857 1
a857 1
int total, histogram[0x4000];
d861 1
a861 1
Build a histogram of magnitudes
d867 2
a868 2
val = rgb[3]/0x100000;
if (val > 0x3fff) val=0x3fff;
d874 1
a874 1
for (val=0x4000, total=0; --val; )
d876 2
a877 2
max2 = val << 20;
max = sqrt(max2);
d952 4
a955 6
if (colors == 3) { /* Preserve the green bits */
rgb_mul[0] /= rgb_mul[1];
rgb_mul[2] /= rgb_mul[1];
rgb_mul[1] = 1.0;
max = 0x4000;
}
d961 1
a961 1
val = rgb[c];
d995 1
a995 1
"\nCanon PowerShot Converter v2.21"
d1003 1
a1003 1
"\n-4 Write 48-bit PNG (-g and -b ignored)\n\n",
@
1.31
log
@When saving an RGB image to PNG, preserve the green bits.
@
text
@d868 1
a868 1
else
d871 2
a929 1
if (val < 0) val=0;
d1027 1
a1027 1
"\nCanon PowerShot Converter v2.20"
@
1.30
log
@Added PNG support for all camera models.
@
text
@d876 1
a876 1
Convert the GMCY grid to RGB and write it to a PPM file.
d940 1
a940 1
Write the rgb[] array to a PNG file
d981 6
a986 2
if (colors == 3)
max = rgb_mul[1] * 0x4000;
@
1.29
log
@Properly parse through the CIFF data instead of searching
for the camera name.
@
text
@d20 2
d938 62
d1016 1
a1016 1
int i, arg, write_to_files=1, row;
d1022 1
a1022 1
"\nCanon PowerShot Converter v2.10"
d1026 1
a1026 1
"\n-c Write PPM to standard output"
d1028 3
a1030 1
"\n-b Set brightness (%5.3f by default)\n\n",
d1046 4
d1076 1
a1076 1
fprintf (stderr, "Writing RGB output...\n");
d1078 1
a1078 1
exten(data, argv[arg],".ppm");
d1084 6
d1091 2
a1093 2
} else
write_ppm(stdout);
@
1.28
log
@Don't choke on corrupt data -- make best effort to decode
Treat "PowerShot S40" as synonym for "PowerShot G2"
@
text
@d30 1
d32 1
d669 1
a669 2
Search for string str in block data of length len.
Return pointer to matching string, or zero if not found.
d671 1
a671 1
char *search(char *data, int len, char *str)
d673 9
a681 2
char *d;
int slen, i;
d683 44
a726 4
slen=strlen(str);
for (d=data; d < data+len-slen; d++) {
for (i=0; d[i]==str[i] && i++ < slen; );
if (i >= slen) return d;
a727 1
return 0;
a729 1
#define tlen 0x8000
d736 1
a736 1
char head[26], tail[tlen], *name, *p;
d742 1
a742 1
int i, r, g;
d753 5
a757 2
fread (head,1,26,ifp);
if (memcmp(head+6,"HEAPCCDR",8)) {
d761 5
a765 6
/*
Read the last tlen bytes of the file
*/
fseek (ifp, -tlen, SEEK_END);
fread (tail, 1, tlen, ifp);
fseek (ifp, 26, SEEK_SET);
d767 1
a767 6
name = search(tail, tlen, "Canon PowerShot ");
if (!name) name = search(tail, tlen, "Canon EOS ");
if (!name) {
fprintf(stderr,"%s: camera is not a Canon PowerShot.\n",fname);
return 1;
} else if (!strcmp(name,"Canon PowerShot 600")) {
d801 1
a801 1
} else if (!strncmp(name,"Canon PowerShot Pro90",21)) {
a807 1
init_tables (name[4762]);
a814 1
init_tables (name[4762]);
a823 1
init_tables (name[4774]);
a831 1
init_tables (name[3594]);
a841 1
#undef tlen
d958 1
a958 1
"\nCanon PowerShot Converter v2.00"
@
1.27
log
@Added support for PowerShot G2 and EOS D30
Eliminated pipelining -- all steps are now performed separately
Totally rewrote interpolation to work with RGB or CYGM
@
text
@d313 1
a313 1
init_tables(int table)
d640 1
a640 1
if ((c = (*filter)(y,x)) != cc) {
d653 1
a653 1
this[col][c] = avg[c] / avg[c+4];
d774 2
a775 1
} else if (!strcmp(name,"Canon PowerShot G2")) {
@
1.26
log
@Added G2 support, then discovered that the filters are RGB.
It's time to rewrite this program!
@
text
@d6 1
a6 1
PowerShot digital cameras into PPM format.
d30 2
a31 2
int height, width;
ushort (*gmcy)[4];
d33 1
a33 2
void (*read_crw)(int);
int histogram[1024];
d36 1
d58 1
a58 5
/*
Load CCD pixel values into the gmcy[] array. Unknown colors
(such as cyan under a magenta filter) must be set to zero.
*/
void ps600_read_crw(int row)
a67 3
Since the rows are not stored in top-to-bottom order like the
other cameras, we must load all rows before processing can begin.
a68 2
if (row) return;
a82 2
memset(gmcy + row*width, 0, width*sizeof *gmcy);
d84 1
a84 1
Copy 854 pixels into the gmcy[] array. The other 42 pixels
d89 1
a89 1
gmcy[orow*width+col][(*filter)(orow,col)] = pixel[col] << 4;
d110 1
a110 5
/*
Load CCD pixel values into the gmcy[] array. Unknown colors
(such as cyan under a magenta filter) must be set to zero.
*/
void a5_read_crw(int row)
d114 1
a114 1
int col;
d119 13
a131 14
fread(data, 1240, 1, ifp);
for (dp=data, pix=pixel; dp < data+1200; dp+=10, pix+=8)
{
pix[0] = (dp[1] << 2) + (dp[0] >> 6);
pix[1] = (dp[0] << 4) + (dp[3] >> 4);
pix[2] = (dp[3] << 6) + (dp[2] >> 2);
pix[3] = (dp[2] << 8) + (dp[5] );
pix[4] = (dp[4] << 2) + (dp[7] >> 6);
pix[5] = (dp[7] << 4) + (dp[6] >> 4);
pix[6] = (dp[6] << 6) + (dp[9] >> 2);
pix[7] = (dp[9] << 8) + (dp[8] );
}
memset(gmcy + row*width, 0, width*sizeof *gmcy);
d133 1
a133 1
Copy 960 pixels into the gmcy[] array. The other 32 pixels
d137 3
a139 2
for (col=0; col < width; col++)
gmcy[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4;
d160 1
a160 5
/*
Load CCD pixel values into the gmcy[] array. Unknown colors
(such as cyan under a magenta filter) must be set to zero.
*/
void a50_read_crw(int row)
d164 1
a164 1
int col;
d169 13
a181 14
fread(data, 1650, 1, ifp);
for (dp=data, pix=pixel; dp < data+1650; dp+=10, pix+=8)
{
pix[0] = (dp[1] << 2) + (dp[0] >> 6);
pix[1] = (dp[0] << 4) + (dp[3] >> 4);
pix[2] = (dp[3] << 6) + (dp[2] >> 2);
pix[3] = (dp[2] << 8) + (dp[5] );
pix[4] = (dp[4] << 2) + (dp[7] >> 6);
pix[5] = (dp[7] << 4) + (dp[6] >> 4);
pix[6] = (dp[6] << 6) + (dp[9] >> 2);
pix[7] = (dp[9] << 8) + (dp[8] );
}
memset(gmcy + row*width, 0, width*sizeof *gmcy);
d183 1
a183 1
Copy 1290 pixels into the gmcy[] array. The other 30 pixels
d187 3
a189 2
for (col=0; col < width; col++)
gmcy[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4;
d210 1
a210 1
void pro70_read_crw(int row)
d214 1
a214 1
int col;
d219 13
a231 14
fread(data, 1940, 1, ifp);
for (dp=data, pix=pixel; dp < data+1940; dp+=10, pix+=8)
{
pix[0] = (dp[1] << 2) + (dp[0] >> 6); /* Same as PS A5 */
pix[1] = (dp[0] << 4) + (dp[3] >> 4);
pix[2] = (dp[3] << 6) + (dp[2] >> 2);
pix[3] = (dp[2] << 8) + (dp[5] );
pix[4] = (dp[4] << 2) + (dp[7] >> 6);
pix[5] = (dp[7] << 4) + (dp[6] >> 4);
pix[6] = (dp[6] << 6) + (dp[9] >> 2);
pix[7] = (dp[9] << 8) + (dp[8] );
}
memset(gmcy + row*width, 0, width*sizeof *gmcy);
d233 1
a233 1
Copy all pixels into the gmcy[] array. Left-shift by 4 for
d236 3
a238 2
for (col=0; col < width; col++)
gmcy[row*width+col][(*filter)(row,col)] = (pixel[col] & 0x3ff) << 4;
d376 1
d422 1
a422 1
if (!count) { /* Initialize */
d424 1
a424 1
fseek (ifp, 540, SEEK_SET);
d474 1
a474 1
void pro90_read_crw(int row)
d477 1
a477 1
int r, col;
d479 1
a479 3
/* Read rows eight at a time */
if (row & 7) return;
decompress(pixel,1944,243);
d481 5
a485 4
memset(gmcy + row*width, 0, 8*width*sizeof *gmcy);
for (r=0; r < 8; r++)
for (col=0; col < width; col++)
gmcy[(row+r)*width+col][(*filter)(row+r,col)] =
d487 1
d490 1
a490 1
void g1_read_crw(int row)
d493 1
a493 4
int r, col;
/* Read rows two at a time */
if (row & 1) return;
d495 1
a495 4
/* The first eight rows are blank. Discard them. */
if (row == 0)
for (r=4; r--; )
decompress(pixel,2144,67);
d497 1
a497 1
decompress(pixel,2144,67);
d499 6
a504 4
memset(gmcy + row*width, 0, 2*width*sizeof *gmcy);
for (r=0; r < 2; r++)
for (col=0; col < width; col++)
gmcy[(row+r)*width+col][(*filter)(row+r,col)] =
d506 1
d510 1
a510 1
Filter pattern of the PowerShot G2:
d513 4
a516 2
0 G M G M G M 0 1 2 3
1 Y C Y C Y C G M C Y
d518 1
a518 1
g2_filter(int row, int col)
d520 1
a520 1
return (0x4e >> ((((row) << 1 & 2) + ((col) & 1)) << 1) & 3);
d523 1
a523 1
void g2_read_crw(int row)
d525 4
a528 2
ushort pixel[2376*8], *prow, (*grow)[4];
int start=0, end, r, orow, col;
d530 1
a530 1
/* Read rows eight at a time, discarding the first six rows */
d532 50
a581 4
if (row == 0)
start = 6;
else if ((row & 7) != 2)
return;
d583 31
a613 1
decompress(pixel,2376,297);
d615 18
a632 9
end = height - row;
if (end > 8) end = 8;
memset(gmcy + row*width, 0, end*width*sizeof *gmcy);
for (r=start; r < end; r++) {
orow = row-start + r;
grow = gmcy + orow*width;
prow = pixel + r*2376 + 12;
for (col=0; col < width; col++)
grow[col][(*filter)(orow,col)] = (prow[col] & 0x3ff) << 4;
d634 30
a695 1
float rgb_mul[3] = { 1.0, 1.0, 1.0 };
d699 2
d720 1
d729 2
a730 2
ymul[1] = 1.0125;
ymul[3] = 0.9866;
d738 4
a741 4
ymul[0] = 1.0056;
ymul[1] = 0.9980;
ymul[2] = 0.9959;
ymul[3] = 1.0005;
d765 1
a765 2
init_tables(name[4762]);
decompress(0,0,0);
d773 1
a773 2
init_tables(name[4762]);
decompress(0,0,0);
a775 1
height = 100;
d777 1
d780 1
a780 1
filter = g2_filter;
d782 10
a791 2
init_tables(name[4774]);
decompress(0,0,0);
a804 27
When this function is called, we only have one GMCY value for
each pixel. Do linear interpolation to get the other three.
read_crw(row+1) must happen before first_interpolate(row).
first_interpolate() is non-destructive, so this row can be
referenced while interpolating the next row.
*/
first_interpolate(int y)
{
int x, sy, sx, c;
static const uchar shift[]={ 2,1,2, 1,16,1, 2,1,2 }, *sp;
for (x=1; x < width-1; x++)
{
sp=shift;
for (sy=y-1; sy < y+2; sy++)
{
for (sx=x-1; sx < x+2; sx++)
{
c=(*filter)(sy,sx);
gmcy[y*width+x][c] += gmcy[sy*width+sx][c] >> *sp++;
}
}
}
}
/*
d819 1
a819 1
get_rgb(float rgb[4], ushort gmcy[4])
d823 7
a829 4
memset(rgb,0,4 * sizeof (float));
for (r=0; r < 3; r++) { /* RGB colors */
for (g=0; g < 4; g++) /* GMCY colors */
rgb[r] += coeff[r][g] * gmcy[g];
a834 54
Now that we have four GMCY values for each pixel (one known, three
interpolated), adjust each interpolated value so that its ratio to
the known value approximates that of neighboring pixels.
second_interpolate(row) must be called after first_interpolate(row+1)
A copy of the original row is needed to interpolating the next row.
Therefore, second_interpolate() writes the modified row one pixel
above and to the left of the original.
Edge pixels are discarded. Pixels one in from the edge are memcpy'd
to their new locations.
Convert each GMCY value to RGB, and compile a histogram of their
magnitudes. Discard the RGB values.
*/
second_interpolate(int y)
{
int x, c, sy, sx, sc;
ushort this[4];
static const uchar shift[]={ 2,1,2, 1, 1, 2,1,2 }, *sp;
float rgb[4];
unsigned val;
if (y==1 || y==height-2) /* y is never outside this range */
{
memcpy(gmcy+(y-1)*width,gmcy+y*width+1,(width-2)*sizeof this);
return;
}
if (y==2) memset(histogram,0,sizeof histogram);
memcpy(gmcy+(y-1)*width,gmcy+y*width+1,sizeof this);
for (x=2; x < width-2; x++)
{
c=(*filter)(y,x);
sp=shift;
memset(this,0,sizeof this);
this[c]=gmcy[y*width+x][c];
for (sy=y-1; sy < y+2; sy++) /* 28% of run-time is this loop */
for (sx=x-1; sx < x+2; sx = sx+1+(sy==y))
{
sc=(*filter)(sy,sx);
this[sc] +=
( (unsigned long) gmcy[sy*width+sx][sc] << 16) /
gmcy[sy*width+sx][c] * gmcy[y*width+x][c] >> (16 + *sp++);
}
memcpy(gmcy+(y-1)*width+x-1,this,sizeof this);
get_rgb(rgb,this);
val = rgb[3]/0x1000000; /* Collect statistics */
if (val > 1023) val=1023;
histogram[val]++;
}
memcpy(gmcy+(y-1)*width+x-1,gmcy+y*width+x,sizeof this);
}
/*
d844 1
a844 1
int total;
d848 11
d861 1
a861 1
for (val=1024, total=0; --val; )
d863 1
a863 1
max2 = val << 24;
d877 1
a877 1
for (y=0; y < height-2; y++)
d879 1
a879 1
for (x=0; x < width-2; x++)
d881 1
a881 1
get_rgb(rgb,gmcy[y*width+x]);
d889 1
a889 1
ppm[x][c]=val;
d919 1
a919 1
"\nCanon PowerShot Converter v1.92"
d954 3
a956 3
gmcy = calloc(height*width,sizeof *gmcy);
if (!gmcy) {
perror("gmcy calloc failed");
d959 6
a964 12
for (row=0; row < 3; row++)
(*read_crw)(row);
first_interpolate(1);
/* This loop is a good place to put a progress bar */
for (row=3; row < height; row++) {
(*read_crw)(row);
first_interpolate(row-1);
second_interpolate(row-2);
}
second_interpolate(height-2);
d967 1
d979 1
a979 1
free (gmcy);
@
1.25
log
@Use a search algorithm to find the camera name at run-time.
Size arrays dynamically depending on which camera was detected.
Added support for compressed data format used by the Pro90 and G1.
@
text
@d2 1
a2 1
Canon PowerShot Converter v2.00
d6 1
a6 1
digital cameras into PPM format.
d487 1
a487 1
pro90_g1_filter(int row, int col)
d494 1
a494 1
ushort pixel[1944*8], *pix;
d510 1
a510 1
ushort pixel[2144*2], *pix;
d531 38
a620 1
if (!name) name = search(tail, tlen, "Canon EOS ");
d622 1
a622 1
fprintf(stderr,"%s: cannot identify camera model.\n",fname);
d663 1
a663 1
filter = pro90_g1_filter;
d672 1
a672 1
filter = pro90_g1_filter;
d676 10
d880 1
a880 1
"\nCanon PowerShot Converter v1.90"
@
1.24
log
@Added typedef for "ushort".
@
text
@d2 2
a3 1
Canon PowerShot Converter v1.00
d5 2
a6 1
by Dave Coffin (dcoffin@@shore.net)
d8 6
a13 3
No rights reserved. Do what you want with this code,
but I accept no responsibility for any consequences
of its (mis)use.
a18 1
#include
a23 62
#ifdef PS_600
#define H 613
#define W 854
#define RED_MUL 1.0
#define GRN_MUL 0.6
#define BLU_MUL 1.0
/* Use this to remove annoying horizontal patterns */
const float ymul[4] = { 1.0, 1.0125, 1.0, 0.9866 };
#elif defined(PS_A5)
#define H 776
#define W 960
#define RED_MUL 1.0
#define GRN_MUL 0.90
#define BLU_MUL 0.88
const float ymul[4] = { 1.0056, 0.9980, 0.9959, 1.0005 };
#elif defined(PS_A50)
#define H 968
#define W 1290
#define RED_MUL 1.0
#define GRN_MUL 0.76
#define BLU_MUL 0.59
const float ymul[4] = { 1.0, 1.0, 1.0, 1.0 };
#elif defined(PS_PRO70)
#define H 1024
#define W 1552
#define RED_MUL 1.0
#define GRN_MUL 0.628
#define BLU_MUL 0.792
const float ymul[4] = { 1.0, 1.0, 1.0, 1.0 };
#else
#error You must compile with exactly one of the following:
#error -DPS_600 -DPS_A5 -DPS_A50 -DPS_PRO70
#endif
/* Default values, which may be modified on the command line */
float gamma_val=0.8, bright=1.0;
/* DOS likes to trash binary files!! */
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define WFLAGS O_WRONLY | O_CREAT | O_TRUNC | O_BINARY
d27 1
a27 1
/* This array holds the GMCY values for each pixel */
d29 5
a33 1
ushort gmcy[H][W][4];
d35 8
a43 1
#ifdef PS_600
d45 1
a45 2
Returns the filter color of a given pixel.
The pattern is:
d52 5
a56 3
*/
#define filter(row,col) \
(0xe1e4 >> ((((row) << 1 & 6) + ((col) & 1)) << 1) & 3)
d61 2
a62 2
*/
void read_crw(int row, int fd)
d75 1
a75 1
*/
d78 1
a78 1
for (irow=orow=0; irow < H; irow++)
d80 1
a80 1
read (fd, data, 1120);
d93 1
a93 1
memset(gmcy[orow], 0, W*4*sizeof (ushort)); /* Set row to zero */
d98 3
a100 3
*/
for (col=0; col < W; col++)
gmcy[orow][col][filter(orow,col)] = pixel[col] << 4;
d102 1
a102 1
if ((orow+=2) > H) /* Once we've read all the even rows, */
a106 2
#elif defined(PS_A5)
d108 1
a108 2
Returns the filter color of a given pixel.
The pattern is:
d115 5
a119 3
*/
#define filter(row,col) \
(0x1e4e >> ((((row) << 1 & 6) + ((col) & 1)) << 1) & 3)
d124 2
a125 2
*/
void read_crw(int row, int fd)
d133 2
a134 2
*/
read(fd,data,1240);
d147 1
a147 1
memset(gmcy[row], 0, W*4*sizeof (ushort)); /* Set row to zero */
d152 3
a154 3
*/
for (col=0; col < W; col++)
gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4;
a156 2
#elif defined(PS_A50)
d158 1
a158 2
Returns the filter color of a given pixel.
The pattern is:
d169 5
a173 3
*/
#define filter(row,col) \
(0x1b4e4b1e >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
d178 2
a179 2
*/
void read_crw(int row, int fd)
d187 2
a188 2
*/
read(fd,data,1650);
d201 1
a201 1
memset(gmcy[row], 0, W*4*sizeof (ushort)); /* Set row to zero */
d206 3
a208 3
*/
for (col=0; col < W; col++)
gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4;
a210 2
#elif defined(PS_PRO70)
d212 1
a212 2
Returns the filter color of a given pixel.
The pattern is:
d223 5
a227 3
*/
#define filter(row,col) \
(0x1e4b4e1b >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
d229 1
a229 5
/*
Load CCD pixel values into the gmcy[] array. Unknown colors
(such as cyan under a magenta filter) must be set to zero.
*/
void read_crw(int row, int fd)
d237 2
a238 2
*/
read(fd,data,1940);
d241 1
a241 1
pix[0] = (dp[1] << 2) + (dp[0] >> 6); /* Same as PS_A5 */
d251 1
a251 1
memset(gmcy[row], 0, W*4*sizeof (ushort)); /* Set row to zero */
d255 290
a544 3
*/
for (col=0; col < W; col++)
gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4;
d547 103
a649 1
#endif /* End of model-specific code */
d658 1
a658 1
*/
d664 1
a664 1
for (x=1; x < W-1; x++)
d671 2
a672 2
c=filter(sy,sx);
gmcy[y][x][c] += gmcy[sy][sx][c] >> *sp++;
d691 2
a692 3
get_rgb() is based on this table.
*/
a695 9
static const float coeff[3][4] =
{
{ -2.400719 * RED_MUL, 3.539540 * RED_MUL, /* red from GMCY */
-2.515721 * RED_MUL, 3.421035 * RED_MUL },
{ 4.013642 * GRN_MUL, -1.710916 * GRN_MUL, /* green from GMCY */
0.690795 * GRN_MUL, 0.417247 * GRN_MUL },
{ -2.345669 * BLU_MUL, 3.385090 * BLU_MUL, /* blue from GMCY */
3.521597 * BLU_MUL, -2.249256 * BLU_MUL }
};
d698 1
a698 2
for (r=0; r < 3; r++) /* RGB colors */
{
d720 1
a720 1
*/
d729 1
a729 1
if (y==1 || y==H-2) /* y is never outside this range */
d731 1
a731 1
memcpy(&gmcy[y-1][0],&gmcy[y][1],(W-2)*sizeof this);
d735 2
a736 2
memcpy(&gmcy[y-1][0],&gmcy[y][1],sizeof this);
for (x=2; x < W-2; x++)
d738 1
a738 1
c=filter(y,x);
d741 1
a741 1
this[c]=gmcy[y][x][c];
d745 1
a745 1
sc=filter(sy,sx);
d747 2
a748 2
( (unsigned long) gmcy[sy][sx][sc] << 16) /
gmcy[sy][sx][c] * gmcy[y][x][c] >> (16 + *sp++);
d750 1
a750 1
memcpy(&gmcy[y-1][x-1],this,sizeof this);
d756 1
a756 1
memcpy(&gmcy[y-1][x-1],&gmcy[y][x],sizeof this);
d761 2
a762 2
*/
write_ppm(int fd)
d766 1
a766 1
uchar ppm[W-2][3];
d774 1
a774 1
*/
d776 1
a776 1
if ((total+=histogram[val]) > (int)(W*H*0.06)) break;
d780 1
a780 1
write(fd,p6head,sprintf(p6head,"P6\n%d %d\n255\n",W-2,H-2));
d782 5
d791 1
a791 1
for (y=0; y < H-2; y++)
d793 1
a793 1
for (x=0; x < W-2; x++)
d795 1
a795 1
get_rgb(rgb,gmcy[y][x]);
d806 1
a806 1
write (fd, ppm, sizeof ppm);
d808 1
d811 3
a813 1
/* Creates a new filename with a different extension */
d827 2
a828 1
int i, arg, fd, write_to_files=1, row;
d833 1
a833 11
"\nCanon PowerShot "
#ifdef PS_600
"600"
#elif defined(PS_A5)
"A5"
#elif defined(PS_A50)
"A50"
#elif defined(PS_PRO70)
"Pro70"
#endif
" Converter v1.00"
d860 1
a860 1
/* Process the named files */
d864 2
a865 11
fd = open(argv[arg],O_RDONLY | O_BINARY);
if (fd < 0)
{ perror(argv[arg]);
continue; }
/* Check the header to confirm this is a CRW file */
read (fd, data, 26);
if (memcmp(data+6,"HEAPCCDR",8))
{
fprintf(stderr,"%s is not a Canon PowerShot CRW file.\n",argv[arg]);
d868 5
d874 1
a874 1
read_crw(row,fd);
d876 5
a880 3
for (row=3; row < H; row++)
{
read_crw(row,fd);
d884 4
a887 4
second_interpolate(H-2);
close(fd);
if (write_to_files)
{
d889 7
a895 6
fd = open(data,WFLAGS,0644);
if (fd < 0)
{ perror(data);
return; }
write_ppm(fd);
close(fd);
d897 2
a898 1
write_ppm(1);
@
1.23
log
@Removed the word "untested"
@
text
@d83 1
@
1.22
log
@Adjusted color balance from Snorre Selmer's pictures.
@
text
@d67 1
a67 1
#error -DPS_600 -DPS_A5 -DPS_A50 -DPS_PRO70 (untested)
@
1.21
log
@Rotated ymul[] to match image, fixed declaration.
@
text
@d60 2
a61 2
#define GRN_MUL 0.76
#define BLU_MUL 0.59
@
1.20
log
@Added support for the PowerShot Pro70, based on Ed Hamrick's code.
@
text
@d30 1
a30 1
const float ymul[4] = { 0.9866, 1.0, 1.0125, 1.0 };
d41 1
a41 1
const float ymul[4] = { 1.0005, 1.0056, 0.9980, 0.9959 };
d175 1
a175 1
int row, col;
@
1.19
log
@Attempted an optimization in second_interpolate()
gmcy[row] really does need to be cleared before loading!
@
text
@d54 11
d67 1
a67 1
#error -DPS_600 -DPS_A5 -DPS_A50 -DPS_PRO70
d258 54
d389 1
a389 1
Edge pixels are discarded. Pixels one in from the edge get memcpy'd
d505 2
@
1.18
log
@Candidate for 1.00 release. Fixed edges in second_interpolate()
Discovered that "gcc -O" doubles execution speed. Wow!
@
text
@d127 1
d181 2
d236 2
d260 1
a260 1
uchar shift[]={ 2,1,2, 1,16,1, 2,1,2 }, *sp;
d334 1
a334 1
static const uchar shift[]={ 2,1,2, 1,0,1, 2,1,2 }, *sp;
a346 1
memset(this,0,sizeof this);
d349 2
d352 1
a352 1
for (sx=x-1; sx < x+2; sx++)
@
1.17
log
@Quick first draft of a pipelined CRW converter. Doesn't
handle edges properly yet. Quite a disappointment; I was
hoping to get a big speed increase from the L2 cache...
@
text
@d2 1
a2 1
Canon PowerShot Converter v0.96
a19 2
#define DEBUG
d55 2
a56 1
#error You must compile with -DPS_600, -DPS_A5, or -DPS_A50
a88 1
a109 1
a131 1
memset(gmcy[orow], 0, W*8); /* Set row to zero */
a151 1
a184 1
memset(gmcy[row], 0, W*8); /* Set row to zero */
a237 1
memset(gmcy[row], 0, W*8); /* Set row to zero */
d248 3
a250 1
first_interpolate(row) must be called after read_crw(row+1)!
d300 1
a300 1
memset(rgb,0,16);
d310 11
a320 5
We now have all four GMCY values for each pixel. Smooth the color
balance to avoid artifacts. As a side effect, this moves the whole
image one pixel up and to the left. Convert each GMCY value to RGB,
and compile a histogram of their magnitudes. RGB values are discarded
and re-calculated in write_ppm().
d322 2
a323 1
second_interpolate(row) must be called after first_interpolate(row+1)!
a324 1
d333 5
d339 1
d345 1
a345 1
for (sy=y-1; sy < y+2; sy++)
d359 1
d369 1
a369 1
uchar ppm[W][3];
a382 4
#ifdef DEBUG
fprintf(stderr,"Writing PPM file...\n");
#endif
a384 4
/*
Second pass: Scale RGB and write to PPM file
*/
d389 1
a389 1
for (y=1; y < H-1; y++)
d391 1
a391 1
for (x=1; x < W-1; x++)
d404 1
a404 1
write (fd, ppm+1, (W-2)*3);
a405 4
#ifdef DEBUG
fprintf(stderr,"Done!\n");
#endif
a422 1
ushort dummy;
d435 1
a435 1
" Converter v0.96"
d479 4
a482 1
for (row=0; row < H; row++)
a483 2
for (i=0; i < W; i+=4)
dummy=gmcy[row][i][0];
d485 2
a486 2
if (row > 1) first_interpolate(row-1);
if (row > 3) second_interpolate(row-2);
d488 1
@
1.16
log
@If "ymul" is global, we can't modify it with each image
Adjust the color balance for whiter whites
@
text
@a62 1
int write_to_files=1;
d74 1
a74 1
/* This 4MB array holds the GMCY values for each pixel */
d77 1
a77 11
/* Creates a new filename with a different extension */
exten(char *new, const char *old, const char *ext)
{
char *cp;
strcpy(new,old);
cp=strrchr(new,'.');
if (!cp) cp=new+strlen(new);
strcpy(cp,ext);
}
d98 1
a98 1
read_crw(const char *fname)
d102 1
a102 19
int fd, irow, orow, col;
fd = open(fname,O_RDONLY | O_BINARY);
if (fd < 0)
{ perror(fname);
return 0; }
/* Check the header to confirm this is a CRW file */
read (fd, data, 26);
if (memcmp(data,"MM",2) || memcmp(data+6,"HEAPCCDR",8))
{
fprintf(stderr,"%s is not a Canon PowerShot 600 file.\n",fname);
return 0;
}
#ifdef DEBUG
fprintf(stderr,"Unpacking %s...\n",fname);
#endif
d108 3
d113 2
a141 2
close(fd);
return 1; /* Success */
d164 1
a164 1
read_crw(const char *fname)
d168 1
a168 19
int fd, row, col;
fd = open(fname,O_RDONLY | O_BINARY);
if (fd < 0)
{ perror(fname);
return 0; }
/* Check the header to confirm this is a CRW file */
read (fd, data, 26);
if (memcmp(data,"II",2) || memcmp(data+6,"HEAPCCDR",8))
{
fprintf(stderr,"%s is not a Canon PowerShot A5 file.\n",fname);
return 0;
}
#ifdef DEBUG
fprintf(stderr,"Unpacking %s...\n",fname);
#endif
d171 1
a171 2
Immediately after the 26-byte header come the data rows.
Each row is 992 pixels, ten bits each, packed into 1240 bytes.
d173 2
a174 1
for (row=0; row < H; row++)
d176 9
a184 12
read(fd,data,1240);
for (dp=data, pix=pixel; dp < data+1200; dp+=10, pix+=8)
{
pix[0] = (dp[1] << 2) + (dp[0] >> 6);
pix[1] = (dp[0] << 4) + (dp[3] >> 4);
pix[2] = (dp[3] << 6) + (dp[2] >> 2);
pix[3] = (dp[2] << 8) + (dp[5] );
pix[4] = (dp[4] << 2) + (dp[7] >> 6);
pix[5] = (dp[7] << 4) + (dp[6] >> 4);
pix[6] = (dp[6] << 6) + (dp[9] >> 2);
pix[7] = (dp[9] << 8) + (dp[8] );
}
d190 3
a192 6
memset(gmcy[row], 0, W*8); /* Set row to zero */
for (col=0; col < W; col++)
gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4;
}
close(fd);
return 1; /* Success */
d218 1
a218 1
read_crw(const char *fname)
d222 1
a222 19
int fd, row, col;
fd = open(fname,O_RDONLY | O_BINARY);
if (fd < 0)
{ perror(fname);
return 0; }
/* Check the header to confirm this is a CRW file */
read (fd, data, 26);
if (memcmp(data,"II",2) || memcmp(data+6,"HEAPCCDR",8))
{
fprintf(stderr,"%s is not a Canon PowerShot A50 file.\n",fname);
return 0;
}
#ifdef DEBUG
fprintf(stderr,"Unpacking %s...\n",fname);
#endif
d225 1
a225 2
Immediately after the 26-byte header come the data rows.
Each row is 1320 pixels, ten bits each, packed into 1650 bytes.
d227 2
a228 1
for (row=0; row < H; row++)
d230 9
a238 12
read(fd,data,1650);
for (dp=data, pix=pixel; dp < data+1650; dp+=10, pix+=8)
{
pix[0] = (dp[1] << 2) + (dp[0] >> 6);
pix[1] = (dp[0] << 4) + (dp[3] >> 4);
pix[2] = (dp[3] << 6) + (dp[2] >> 2);
pix[3] = (dp[2] << 8) + (dp[5] );
pix[4] = (dp[4] << 2) + (dp[7] >> 6);
pix[5] = (dp[7] << 4) + (dp[6] >> 4);
pix[6] = (dp[6] << 6) + (dp[9] >> 2);
pix[7] = (dp[9] << 8) + (dp[8] );
}
d244 3
a246 6
memset(gmcy[row], 0, W*8); /* Set row to zero */
for (col=0; col < W; col++)
gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4;
}
close(fd);
return 1; /* Success */
d252 4
a255 3
When this function is called, we only have one GMCY
value for each pixel. Do linear interpolation to get
the other three.
d257 1
a257 2
first_interpolate()
d259 1
a259 1
int y, x, sy, sx, c;
d262 1
a262 5
#ifdef DEBUG
fprintf(stderr,"First interpolation...\n");
#endif
for (y=1; y < H-1; y++)
d264 2
a265 1
for (x=1; x < W-1; x++)
d267 5
a271 7
sp=shift;
for (sy=y-1; sy < y+2; sy++)
for (sx=x-1; sx < x+2; sx++)
{
c=filter(sy,sx);
gmcy[y][x][c] += gmcy[sy][sx][c] >> *sp++;
}
a276 43
We now have all four GMCY values for each pixel. Smooth
the color balance to avoid artifacts. This function may
be called more than once.
*/
second_interpolate()
{
ushort data[2][W][4];
ushort (*last_row)[4]=data[0];
ushort (*this_row)[4]=data[1];
void *tmp;
int y, x, c, sy, sx, sc;
uchar shift[]={ 2,1,2, 1,0,1, 2,1,2 }, *sp;
#ifdef DEBUG
fprintf(stderr,"Second interpolation...\n");
#endif
for (y=2; y < H-2; y++)
{
memset(this_row, 0, W*8);
for (x=2; x < W-2; x++)
{
sp=shift;
c=filter(y,x);
for (sy=y-1; sy < y+2; sy++)
for (sx=x-1; sx < x+2; sx++)
{
sc=filter(sy,sx);
this_row[x][sc] +=
( (unsigned long) gmcy[sy][sx][sc] << 16) /
gmcy[sy][sx][c] * gmcy[y][x][c] >> (16 + *sp++);
}
}
if (y > 2) memcpy(gmcy[y-1]+2,last_row+2,(W-4)*8);
tmp = last_row;
last_row = this_row;
this_row = tmp;
}
}
/*
d315 40
d357 1
a357 2
write_ppm(char *fname)
d359 1
a359 1
int fd=1, y, x, i;
d364 1
a364 1
int histo[1024], total;
a366 18
#ifdef DEBUG
fprintf(stderr,"First pass RGB...\n");
#endif
/*
First pass: Gather stats on the RGB image
*/
memset(histo,0,sizeof histo);
for (y=2; y < H-2; y++)
{
for (x=2; x < W-2; x++)
{
get_rgb(rgb,gmcy[y][x]);
val = rgb[3]/0x1000000;
if (val > 1023) val=1023;
histo[val]++;
}
}
d371 1
a371 1
if ((total+=histo[val]) > (int)(W*H*0.06)) break;
d376 1
a376 1
fprintf(stderr,"Second pass RGB...\n");
a378 7
if (write_to_files)
{
fd = open(fname,WFLAGS,0644);
if (fd < 0)
{ perror(fname);
return; }
}
a405 1
if (write_to_files) close(fd);
d412 11
d425 3
a427 2
char fname[256];
int arg;
d471 9
a479 1
if (read_crw(argv[arg]))
d481 2
a482 4
first_interpolate();
second_interpolate();
exten(fname, argv[arg],".ppm");
write_ppm(fname);
d484 20
@
1.15
log
@Version 0.95
Added support for the PowerShot A50
@
text
@d2 1
a2 1
Canon PowerShot Converter v0.95
a13 1
#include
d51 2
a52 2
#define GRN_MUL 0.90
#define BLU_MUL 0.88
d414 1
a414 1
get_rgb(float rgb[4], ushort gmcy[4]) /* 3.70 seconds */
d446 1
d495 1
a495 1
ymul[y] = bright * 362 / max * pow(ymul[y],gamma_val);
d502 1
a502 1
scale = ymul[y&3] * pow(rgb[3]/max2,expo);
d537 1
a537 1
" Converter v0.95"
@
1.14
log
@Saw major problems with the "tea can" image and made corrections:
- Magnitudes, not color values, are used to find the maximum.
- Color balance and row multipliers (ymul[]) have been adjusted.
@
text
@d2 1
a2 1
Canon PowerShot Converter v0.94
d32 3
d44 13
d58 1
a58 1
#error You must compile with -DPS_600 or -DPS_A5
d245 46
d294 33
a449 7
/* Use this to remove annoying horizontal patterns */
#ifdef PS_600
float ymul[4] = { 0.9866, 1.0, 1.0125, 1.0 };
#elif defined(PS_A5)
float ymul[4] = { 1.0005, 1.0056, 0.9980, 0.9959 };
#endif
d534 2
d537 1
a537 1
" Converter v0.94"
@
1.13
log
@Merged PowerShot A5 code back into the trunk.
@
text
@d2 1
a2 1
Canon PowerShot Converter v0.90
d38 2
a39 2
#define GRN_MUL 1.0
#define BLU_MUL 1.0
d349 1
a349 1
register c, val;
d351 2
a352 2
float rgb[4], max, max2, expo, mult, scale;
int histo[512], total;
d359 1
a359 1
float ymul[4] = { 1.0, 1.0, 1.0, 1.0 };
d375 3
a377 4
for (c=0; c < 3; c++)
{
histo [(int)rgb[c] >> 10]++;
}
d381 1
a381 1
Set the maximum to the 96th percentile
d383 4
a386 4
for (val=512, total=0; --val; )
if ((total+=histo[val]) > (int)(W*H*0.11)) break;
max = val << 10;
max2 = max*max;
a405 1
mult = bright * 362 / max;
d407 1
a407 1
ymul[y] = pow(ymul[y],gamma_val);
d414 1
a414 1
scale = mult * ymul[y&3] * pow(rgb[3]/max2,expo);
d447 1
a447 1
" Converter v0.90"
@
1.12
log
@Replaced "60000" with a macro.
@
text
@d2 1
a2 1
Canon PowerShot 600 Converter v0.86
d4 1
a4 1
by Dave Coffin (dcoffin at shore dot net)
d23 4
a26 1
/* Use these to adjust the final color balance */
d32 13
a61 2
#define H 613
#define W 854
d75 1
d155 76
d355 6
a360 2
/* Use this to remove an annoying horizontal pattern */
float ymul[4]={ 0.9866, 1.0, 1.0125, 1.0 };
d443 7
a449 1
"\nCanon PowerShot 600 Converter v0.86"
@
1.11
log
@Cosmetic changes to match the new PowerShot A5 version
@
text
@d290 1
a290 1
if ((total+=histo[val]) > 60000) break;
@
1.11.1.1
log
@Converter for the Canon PowerShot A5
@
text
@d2 1
a2 1
Canon PowerShot A5 Converter v0.86
d26 1
a26 1
#define GRN_MUL 1.0
d46 2
a47 2
#define H 776
#define W 960
d66 4
a69 4
0 C Y C Y C Y Return values
1 G M G M G M 0 1 2 3
2 C Y C Y C Y G M C Y
3 M G M G M G
d73 1
a73 1
(0x1e4e >> ((((row) << 1 & 6) + ((col) & 1)) << 1) & 3)
d81 3
a83 3
uchar data[1240], *dp;
ushort pixel[992], *pix;
int fd, row, col;
d93 1
a93 1
if (memcmp(data,"II",2) || memcmp(data+6,"HEAPCCDR",8))
d95 1
a95 1
fprintf(stderr,"%s is not a Canon PowerShot A5 file.\n",fname);
d104 3
a106 2
Immediately after the 26-byte header come the data rows.
Each row is 992 pixels, ten bits each, packed into 1240 bytes.
d108 2
a109 1
for (row=0; row < H; row++)
d111 2
a112 2
read(fd,data,1240);
for (dp=data, pix=pixel; dp < data+1200; dp+=10, pix+=8)
d114 8
a121 8
pix[0] = (dp[1] << 2) + (dp[0] >> 6);
pix[1] = (dp[0] << 4) + (dp[3] >> 4);
pix[2] = (dp[3] << 6) + (dp[2] >> 2);
pix[3] = (dp[2] << 8) + (dp[5] );
pix[4] = (dp[4] << 2) + (dp[7] >> 6);
pix[5] = (dp[7] << 4) + (dp[6] >> 4);
pix[6] = (dp[6] << 6) + (dp[9] >> 2);
pix[7] = (dp[9] << 8) + (dp[8] );
d123 1
d125 1
a125 1
Copy 960 pixels into the gmcy[] array. The other 32 pixels
d129 1
a129 1
memset(gmcy[row], 0, W*8); /* Set row to zero */
d131 4
a134 1
gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3f0) << 4;
d264 2
a265 2
/* Use this to remove annoying horizontal patterns */
float ymul[4]={ 1.0, 1.0, 1.0, 1.0 };
d348 1
a348 1
"\nCanon PowerShot A5 Converter v0.86"
@
1.11.1.2
log
@Fixed two bugs that Vlad pointed out. What a difference!!
@
text
@d2 1
a2 1
Canon PowerShot A5 Converter v0.87
d128 1
a128 1
gmcy[row][col][filter(row,col)] = (pixel[col] & 0x3ff) << 4;
d284 1
a284 1
if ((total+=histo[val]) > 90000) break;
d342 1
a342 1
"\nCanon PowerShot A5 Converter v0.87"
@
1.11.1.3
log
@Replaced "90000" with a macro.
@
text
@d284 1
a284 1
if ((total+=histo[val]) > (int)(W*H*0.11)) break;
@
1.10
log
@Changed the width and height to macros for more flexibility.
@
text
@d2 1
a2 1
CRW to PPM converter Version 0.85
d4 1
a4 1
by Dave Coffin (dcoffin at shore dot net) 8/30/97
d32 1
d42 1
a42 3
int write_to_files=1;
typedef unsigned char uchar;
d51 1
a51 1
exten(char *new, char *old, char *ext)
d77 1
a77 1
(such as cyan under a magenta filter) must be set to zero.
d79 1
a79 2
read_crw(char *fname)
d95 1
a95 1
fprintf(stderr,"%s is not a CRW file.\n",fname);
d104 3
a106 3
Immediately after the 26-byte header come the data rows. First
the even rows 0..612, then the odd rows 1..611. Each row is 896
pixels, ten bits per pixel, packed into 1120 bytes (8960 bits).
a110 1
/* Read one packed row */
a111 2
/* Unpack the pixels */
d126 2
a127 2
are blank. Left-shift by 4 for extra precision in upcoming
calculations.
d129 1
a129 1
memset(gmcy[orow], 0, W * 8); /* Set row to zero */
d133 2
a134 2
if ((orow+=2) > H) /* Once we've read all the even rows, */
orow = 1; /* read the odd rows. */
d137 1
a137 1
return 1; /* Success */
d142 2
a143 2
value for each pixel. Do linear interpolation to get
the other three.
d161 1
a161 1
for (sx=x-1; sx < x+2; sx++)
d163 2
a164 2
c=filter(sy,sx);
gmcy[y][x][c] += gmcy[sy][sx][c] >> *sp++;
d172 2
a173 2
the color balance to avoid artifacts. This function may be
called more than once.
d198 1
a198 1
for (sx=x-1; sx < x+2; sx++)
d200 4
a203 4
sc=filter(sy,sx);
this_row[x][sc] +=
( (unsigned long) gmcy[sy][sx][sc] << 16)
/ gmcy[sy][sx][c] * gmcy[y][x][c] >> (16 + *sp++);
d217 1
a217 1
to the three primary colors, on a scale of 0-100.
d248 1
a248 1
}
d282 1
a282 1
histo [(int)rgb[c] >> 10]++;
d311 1
a311 1
expo = (gamma_val-1)/2; /* Pull these out of the loop */
d331 1
a331 1
write (fd, ppm+1, (W-2) * 3);
d348 3
a350 3
"\nCRW to PPM converter by Dave Coffin (dcoffin@@shore.net)"
"\nVersion 0.85, last modified 8/30/97\n"
"\nUsage: %s [options] file1.crw file2.crw ...\n"
d352 1
a352 1
"\n-c Write to standard output"
@
1.9
log
@Changed "gamma" to "gamma_val" to avoid name conflict.
@
text
@d9 3
d47 3
a49 1
ushort gmcy[613][854][4];
d111 1
a111 1
for (irow=orow=0; irow < 613; irow++)
d134 2
a135 2
memset(gmcy[orow], 0, 854 * 8); /* Set row to zero */
for (col=0; col < 854; col++)
d138 1
a138 1
if ((orow+=2) > 612) /* Once we've read all the even rows, */
d160 1
a160 1
for (y=1; y < 612; y++)
d162 1
a162 1
for (x=1; x < 853; x++)
d183 1
a183 1
ushort data[2][854][4];
d195 1
a195 1
for (y=2; y < 611; y++)
d197 2
a198 2
memset(this_row, 0, 854*8);
for (x=2; x < 852; x++)
d211 1
a211 1
if (y > 2) memcpy(gmcy[y-1]+2,last_row+2,850*8);
d264 1
a264 1
uchar ppm[854][3];
d267 1
d280 1
a280 1
for (y=2; y < 611; y++)
d282 1
a282 1
for (x=2; x < 852; x++)
d310 1
a310 1
write(fd,"P6\n852 611\n255\n",15);
d321 1
a321 1
for (y=1; y < 612; y++)
d323 1
a323 1
for (x=1; x < 853; x++)
d336 1
a336 1
write (fd, ppm+1, 852 * 3);
@
1.8
log
@Version 0.85
Added user-adjustable brightness and gamma correction.
@
text
@d28 1
a28 1
float gamma=0.8, bright=1.0;
d310 1
a310 1
expo = (gamma-1)/2; /* Pull these out of the loop */
d313 1
a313 1
ymul[y] = pow(ymul[y],gamma);
d354 1
a354 1
argv[0], gamma, bright);
d366 1
a366 1
gamma=atof(argv[++arg]); break;
@
1.7
log
@Version 0.8
Devised a totally new interpolation algorithm, using a 3x3 block.
Run time is much longer, but image quality has vastly improved.
@
text
@d2 1
a2 1
CRW to PPM converter Version 0.8
d4 1
a4 1
by Dave Coffin (dcoffin at shore dot net) 8/23/97
d15 1
d23 2
a24 2
#define GRN_MUL 0.535
#define BLU_MUL 0.709
d26 3
a28 1
#define GAMMA 0.75
d38 2
d229 1
a229 1
get_rgb(float rgb[3], ushort gmcy[4]) /* 3.70 seconds */
d242 4
a245 3
memset(rgb,0,12);
for (r=0; r < 3; r++) /* RGB colors */
for (g=0; g < 4; g++) /* GMCY colors */
d247 2
d257 1
a257 1
int fd, y, x, i;
d260 5
a264 2
float rgb[3], max, gamma, gamtab[257];
int histo[256], total, bot, mid, top;
d271 1
a271 2
First pass: Needed to find the maximum color value.
Construct a histogram with binning of 1024.
d281 1
a281 1
histo [(int)rgb[c] >> 10] ++;
d286 1
a286 1
Set the maximum to the 95th percentile
d288 2
a289 2
for (val=256, total=0; --val; )
if ((total+=histo[val]) > 80000) break;
d291 1
a291 4
gamma = GAMMA;
for (i=0; i < 257; i++)
gamtab[i] = pow(i/256.0,1/gamma) * max;
d297 7
a303 4
fd = open(fname,WFLAGS,0644);
if (fd < 0)
{ perror(fname);
return; }
d309 7
a315 1
for (y=1; y < 612; y++) /* 4.93 seconds */
d320 2
d324 4
a327 9
for (bot=0,top=256; top-bot > 1; ) /* 3.00 seconds */
{
mid = bot+top >> 1; /* Do a binary search */
if (rgb[c] > gamtab[mid])
bot=mid;
else
top=mid;
}
ppm[x][c]=bot;
d332 1
a332 1
close(fd);
d344 1
a344 1
if (argc < 2)
d346 9
a354 3
puts("\nCRW to PPM converter by Dave Coffin (dcoffin@@shore.net)");
puts("Version 0.8, last modified 8/23/97\n");
printf("Usage: %s file1.crw file2.crw ...\n\n",argv[0]);
d358 19
a376 1
for (arg=1; arg < argc; arg++)
@
1.6
log
@Version 0.4, just for testing
A breakthrough! I finally figured out what the "mystery pixels" are.
@
text
@d2 1
a2 1
CRW to PPM converter Version 0.4
d4 1
a4 1
by Dave Coffin (dcoffin at shore dot net) 8/24/97
a16 2
/* Create extra files with debugging info */
d22 4
a25 2
#define GRN_MUL 0.5
#define BLU_MUL 1.0
d52 10
a61 5
#ifdef DEBUG
debug (char *arg, char *ext)
{
char fname[64];
int fd;
d63 2
a64 9
exten(fname,arg,ext);
fd = open(fname,WFLAGS,0644);
if (fd < 0)
{ perror(fname);
fd = open("/dev/null",O_WRONLY);
}
return fd;
}
#endif
d67 2
a68 6
Returns the color of a given pixel. The pattern goes:
(0,0)-> G M G M G M row 0
C Y C Y C Y row 1
M G M G M G row 2
C Y C Y C Y row 3
a69 9
color (unsigned x, unsigned y)
{
int color;
color = ((y & 1) << 1) + (x & 1);
if ((y & 3) == 2) /* 0=green, 1=magenta, 2=cyan, 3=yellow */
color ^= 1; /* Swap green and magenta on row 2 */
return color;
}
d71 1
a71 2
/* Read a CRW file into the pgm[] array */
read_crw(char *arg)
d73 3
a75 9
uchar data[1120], *dp, *gp;
int fd, irow, icol, orow, ocol;
#ifdef DEBUG
int gfd, gcol, mfd, mcol;
uchar grid[896], myst[224];
gfd = debug(arg,".grid");
mfd = debug(arg,".myst");
d77 1
a77 5
write(gfd,"P5\n896 613\n255\n",15);
write(mfd,"P4\n1792 613\n",12);
#endif
fd = open(arg,O_RDONLY | O_BINARY);
d79 1
a79 1
{ perror(arg);
d82 3
a84 1
read (fd, data, 26); /* Check the header */
d87 1
a87 1
fprintf(stderr,"%s is not a CRW file.\n",arg);
d91 10
d103 2
a104 1
read (fd, data, 1120); /* Read one row */
d106 2
a107 2
#ifdef DEBUG
for (dp=data, gp=grid; dp < data+1120; dp+=10, gp+=8)
d109 8
a116 21
/* wrong */
gp[0]=(dp[0] << 2) + (dp[1] >> 4 & 3);
gp[1]=(dp[2] << 2) + (dp[1] >> 2 & 3);
gp[2]=(dp[3] << 2) + (dp[1] >> 0 & 3);
gp[3]=(dp[4] << 2) + (dp[1] >> 6 & 3);
gp[4]=(dp[5] << 2) + (dp[9] >> 0 & 3);
gp[5]=(dp[6] << 2) + (dp[9] >> 2 & 3);
gp[6]=(dp[7] << 2) + (dp[9] >> 4 & 3);
gp[7]=(dp[8] << 2) + (dp[9] >> 6 & 3);
#if 0
/* right */
gp[0]=(dp[0] << 2) + (dp[1] >> 6 & 3);
gp[1]=(dp[2] << 2) + (dp[1] >> 4 & 3);
gp[2]=(dp[3] << 2) + (dp[1] >> 2 & 3);
gp[3]=(dp[4] << 2) + (dp[1] >> 0 & 3);
gp[4]=(dp[5] << 2) + (dp[9] >> 0 & 3);
gp[5]=(dp[6] << 2) + (dp[9] >> 2 & 3);
gp[6]=(dp[7] << 2) + (dp[9] >> 4 & 3);
gp[7]=(dp[8] << 2) + (dp[9] >> 6 & 3);
#endif
a117 5
lseek (gfd, orow*896+15, 0);
write (gfd, grid, 896);
lseek (mfd, orow*224+12, 0);
write (mfd, myst, 224);
#endif
d119 29
a147 12
#if 0
for (icol=gcol=mcol=0; icol < 1120; icol++)
{
if ( icol % 10 != 1 && icol % 10 != 9 )
grid[gcol++] = data[icol]; /* Data pixels go here */
else
myst[mcol++] = data[icol]; /* Mystery pixels go here */
}
lseek (gfd, orow*896+15, 0);
write (gfd, grid, 896);
lseek (mfd, orow*224+12, 0);
write (mfd, myst, 224);
d150 3
a152 1
for (icol=ocol=0; icol < 1067; icol++)
d154 7
a160 5
if ( icol % 10 != 1 && icol % 10 != 9 )
{
gmcy[orow][ocol][color(orow,ocol)] = (ushort) data[icol] << 6;
ocol++;
}
a161 2
if ((orow+=2) > 612) /* Once we've read all the even rows, */
orow = 1; /* read the odd rows. */
d163 17
a179 1
close(fd);
d182 1
a182 2
close(gfd);
close(mfd);
d185 21
a205 1
return 1; /* Success */
d209 1
a209 1
Converts a GMCY quadruplet into an RGB triplet.
d223 2
a224 1
get_rgb(float rgb[3], uchar gmcy[4])
d243 11
d255 3
a257 1
#if 0
d260 2
a261 4
For all values of (x,y), the pixels (x,y), (x+1,y), (x,y+1),
and (x+1,y+1) form a GMCY vector (i.e. no two have the same color).
Convert these vectors to RGB, then try to remove the artifacts that
appear when there's an edge between x and x+1.
d263 26
a288 5
write_ppm(char *fname)
{
int out, y, x, sy, sx, c, val, prev;
uchar gmcy[4], ppm[853][3];
float rgb[3];
d290 2
a291 2
out = open(fname,WFLAGS,0644);
if (out < 0)
d294 1
a294 1
write(out,"P6\n853 612\n255\n",15);
d296 4
a299 1
for (y=0; y < 612; y++)
d301 1
a301 1
for (x=0; x < 853; x++)
d303 1
a303 4
for (sy=y; sy < y+2; sy++)
for (sx=x; sx < x+2; sx++)
gmcy[color(sx,sy)] = pgm[sy][sx];
get_rgb(rgb,gmcy);
d306 9
a314 4
val = floor(rgb[c]);
if (val < 0) val=0;
if (val > 255) val=255;
ppm[x][c] = val;
d317 1
a317 1
write (out, ppm, sizeof ppm);
d319 5
a323 1
close(out);
a324 1
#endif
d329 1
a329 2
int arg, fd, x, y;
short magic;
d334 1
a334 1
puts("Version 0.4, last modified 8/24/97\n");
d343 3
a345 2
exten(fname, argv[arg],".ppm"); /* Open a PPM file for RGB output */
#if 0
a346 1
#endif
@
1.5
log
@Version 0.3
More comments, better error checking.
Switched back to 2x2 blocks, and tried Moire smoothing.
@
text
@d2 1
a2 1
CRW to PPM converter Version 0.3
d4 1
a4 1
by Dave Coffin (dcoffin at shore dot net) 3/24/97
d17 1
a17 1
typedef unsigned char uchar;
d19 1
a19 2
/* This array holds the raw pixel values */
uchar pgm[613][854];
d21 5
a25 5
/*
Write the raw pixel values to a PGM file before
RGB conversion. Useful for debugging.
*/
#define WANT_PGM_FILE
d28 1
d35 51
d87 1
a87 1
read_crw(int in)
d89 13
a101 2
uchar data[1120];
int bin, irow, icol, orow, ocol;
d103 11
a113 3
read (in, data, 24); /* Chop the header */
if (memcmp(data+4,"HEAPCCDR",8)) /* Make sure it's CRW */
return 1;
d117 47
a163 1
read (in, data, 1120); /* Read one row */
d166 5
a170 2
if ( icol % 10 != 1 && icol % 10 != 9 ) /* Delete the "mystery pixels" */
pgm[orow][ocol++] = data[icol];
d175 1
a175 3
close(in);
return 0; /* Success */
}
d177 4
a180 28
/* Used for parsing PGM headers */
int get_num(FILE *fp)
{
int num=0;
char c;
for (;;)
{
if (isspace(c=getc(fp))) /* Ignore whitespace */
continue;
if ( c=='#' ) /* Ignore comments */
while (getc(fp) != '\n');
else if (isdigit(c)) /* Grab digits */
{ do {
num = num*10 + (c - '0'); /* Make a number */
c=getc(fp);
} while (isdigit(c));
return num; /* Return it */
} else
fprintf(stderr,"Illegal byte in header\n");
}
}
/* Read a PGM file, skipping the CRW -> PGM conversion */
read_pgm(int in)
{
int width, height, maxval;
FILE *fp;
d182 1
a182 17
#if O_BINARY != 0
fp=fdopen(in,"rb");
#else
fp=fdopen(in,"r");
#endif
width=get_num(fp);
height=get_num(fp);
maxval=get_num(fp);
if (width != 854 || height != 613 || maxval != 255)
{ fprintf(stderr, "PGM file must be 854x613, 256 colors!\n");
fclose(fp);
return 1;
}
fread(pgm,854,613,fp);
fclose(fp);
return 0;
d205 6
a210 6
{ -2.400719, 3.539540, -2.515721, 3.421035 }, /* red */
#if 0
{ 4.013642, -1.710916, 0.690795, 0.417247 }, /* green */
#endif
{ 2.006821, -0.855458, 0.345397, 0.208623 }, /* green/2 (why??) */
{ -2.345669, 3.385090, 3.521597, -2.249256 } /* blue */
a218 11
/*
Returns the color of a given pixel. The pattern goes:
(0,0)-> G M G M G M
C Y C Y C Y
M G M G M G
C Y C Y C Y
*/
color (unsigned x, unsigned y)
{
int color;
d220 1
a220 5
color = ((y & 1) << 1) + (x & 1);
if ((y & 3) == 2) /* 0=green, 1=magenta, 2=cyan, 3=yellow */
color ^= 1; /* Swap green and magenta */
return color;
}
a255 16
/* This moire smoothing doesn't work very well. */
#ifdef MOIRE_SMOOTH
for (c=0; c < 3; c++)
{
prev = ppm[0][c];
for (x=1; x < 852; x++)
{
val = prev + ppm[x][c]*2 + ppm[x+1][c] + 1 >> 2;
prev = ppm[x][c];
ppm[x][c] = val;
}
}
#endif
d260 1
a260 11
/* Creates a new filename with a different extension */
exten(char *new, char *old, char *ext)
{
char *cp;
strcpy(new,old);
cp=strrchr(new,'.');
if (!cp) cp=new+strlen(new);
strcpy(cp,ext);
}
d271 1
a271 1
puts("Version 0.3, last modified 3/24/97\n");
d278 1
a278 6
fd = open(argv[arg],O_RDONLY | O_BINARY);
if (fd < 0)
{ perror(argv[arg]);
continue; }
read(fd,&magic,2);
if (magic == 0x4d4d) /* "MM" */
d280 3
a282 14
if (read_crw(fd))
{ fprintf(stderr,"%s is not a CRW file.\n",argv[arg]);
continue;
}
#ifdef WANT_PGM_FILE
exten(fname, argv[arg],".pgm"); /* Write the pixel data to */
fd = open(fname,WFLAGS,0644); /* a PGM file */
if (fd < 0)
{ perror(fname);
continue; }
write(fd,"P5\n854 613\n255\n",15);
write(fd, pgm, 613*854);
close(fd);
a284 7
else if (ntohs(magic)==0x5035) /* "P5" */
{
if (read_pgm(fd)) continue;
}
exten(fname, argv[arg],".ppm"); /* Open a PPM file for RGB output */
write_ppm(fname);
@
1.4
log
@Changes for version 0.2:
Removed BLACK correction; it didn't help.
Pre-solved color equations for a big speed increase.
@
text
@d2 1
a2 1
CRW to PPM converter Version 0.2
d4 1
a4 1
by Dave Coffin (dcoffin at shore dot net) 2/24/97
d42 2
d50 1
a50 1
if ( icol % 10 != 1 && icol % 10 != 9 ) /* Cut out noise columns */
d110 12
a121 1
Ask Canon how this works; I have no clue.
d123 1
a123 1
get_rgb(float rgb[3], int gmcy[4])
d128 6
a133 3
{ -5.175675, 3.853136, -1.681311, 5.270232 },
{ 1.281218, -1.147541, 1.935073, 0.487001 },
{ -3.167515, 2.900609, 4.132598, -1.720971 }
d161 4
a164 2
Interpolate GMCY values for each non-edge pixel (using
all eight neighbors), then convert the result to RGB.
d168 2
a169 2
int out, y, x, sy, sx, c, val, gmcy[4];
uchar ppm[852][3];
a170 1
uchar shift[]={ 0,1,0, 1,2,1, 0,1,0 }, *sp;
d176 1
a176 1
write(out,"P6\n852 611\n255\n",15);
d178 1
a178 1
for (y=0; y < 611; y++)
d180 1
a180 1
for (x=0; x < 852; x++)
d182 4
a185 7
memset(gmcy,0,sizeof gmcy);
sp=shift;
for (sy=y; sy < y+3; sy++) /* Average a 3x3 block */
for (sx=x; sx < x+3; sx++)
gmcy[color(sx,sy)] += pgm[sy][sx] << *sp++;
get_rgb(rgb,gmcy); /* Convert GMCY averages to RGB */
d188 3
a190 3
val = floor(rgb[c]/4); /* Save the RGB values */
if (val < 0) val=0;
if (val > 255) val=255;
d194 16
d235 1
a235 1
puts("Version 0.2, last modified 2/24/97\n");
d249 4
a252 1
read_crw(fd);
d265 1
a265 1
else if (magic==0x3550 || magic==0x5035) /* "P5" or "5P" */
@
1.3
log
@Final 0.1 version. Changed 2x2 blocks to weighted 3x3 neighborhood.
@
text
@d2 1
a2 1
CRW to PPM converter Version 0.1
d4 1
a4 1
by Dave Coffin (dcoffin@@shore.net) 2/22/97
a34 23
/* Subtract this number from all input pixels */
#define BLACK 6
/*
This table describes the color response of the four
pixel types, according to experiment. It is used by
get_rgb() to convert GMCY colorspace to RGB.
Notice that blue light generates a negative response
in green and yellow pixels. Strange.
*/
const float coeff[4][3] =
{
/* red * + green * + blue * = pixel color */
{ 0.052296, 0.255409,-0.047466 }, /* green */
{ 0.156993, 0.046792, 0.046537 }, /* magenta */
{-0.004344, 0.280239, 0.045865 }, /* cyan */
{ 0.145482, 0.309211,-0.089371 }, /* yellow */
};
/* Matrix used for solving equations */
double mat[3][4];
a106 39
These three functions solve a 4x3 matrix (three equations,
three unknowns), leaving the answers in the last column. To
improve performance, they should be combined, inlined, and
written in assembly.
*/
norm(row)
{
float div;
int i;
div=mat[row][row];
for (i=row+1; i < 4; i++)
mat[row][i] /= div;
}
sub(arow,brow)
{
float mul;
int i;
mul=mat[arow][brow];
for (i=brow+1; i < 4; i++)
mat[arow][i] -= mat[brow][i] * mul;
}
solve()
{
norm(0);
sub(1,0);
sub(2,0);
norm(1);
sub(0,1);
sub(2,1);
norm(2);
sub(0,2);
sub(1,2);
}
/*
d108 1
a108 5
We have four equations with three unknowns. My
answer is to solve the system four times, omitting
one equation each time, then average the results.
Canon must know a better way--this method is SLOW!!!
d112 7
a118 1
int omit, color, equ, i;
d121 3
a123 13
for (omit=0; omit < 4; omit++)
{
for (color=equ=0; color < 4; color++)
if (color != omit)
{
for (i=0; i < 3; i++)
mat[equ][i] = coeff[color][i];
mat[equ++][3] = gmcy[color];
}
solve();
for (i=0; i < 3; i++) /* Save this solution */
rgb[i] += mat[i][3];
}
d169 1
a169 1
gmcy[color(sx,sy)] += pgm[sy][sx] - BLACK << *sp++;
d174 1
a174 1
val = floor(rgb[c]/24); /* Scale and save the RGB values */
d205 1
a205 1
puts("Version 0.1, last modified 2/22/97\n");
@
1.2
log
@Use 2x2 squares instead of orthogonal neighbors.
@
text
@d23 2
a24 2
Write the raw pixel values to a PGM file before RGB conversion.
Useful for debugging.
a27 6
/* Subtract this number from all pixels after writing PGM file. */
#define BLACK 6
/* Matrix used for solving equations */
double mat[3][4];
d35 3
d40 5
a44 11
pixel types, according to experiment. I have no idea
why some terms are negative. Perhaps Canon would like
to fill in the correct values?
An intuitive, but incorrect, table would be:
red green blue
0 1 0 green
1 0 1 magenta
0 1 1 cyan
1 1 0 yellow
d48 5
a52 4
{ 0.052296, 0.255409,-0.047466 },
{ 0.156993, 0.046792, 0.046537 },
{-0.004344, 0.280239, 0.045865 },
{ 0.145482, 0.309211,-0.089371 },
d55 2
a56 9
#if 0
{
/* red * + green * + blue * = pixel color */
{ 0.051146, 0.319806, -0.067939 }, /* green */
{ 0.219660, 0.045533, 0.048611 }, /* magenta */
{-0.045775, 0.337888, 0.057842 }, /* cyan */
{ 0.184652, 0.391803, -0.127791 }, /* yellow */
};
#endif
d132 2
a133 2
improve performance, this should be inlined or written in
assembly.
d170 5
a174 4
The tough part is, we have four equations with three
unknowns. The best answer is to solve the system
four times, omitting one equation each time, then
average the results.
d176 1
a176 1
get_rgb(float rgb[3], uchar gmcy[4])
d197 1
a197 1
Returns the color of the given pixel. The pattern goes:
d214 4
d220 2
a221 2
int out, y, x, sy, sx, c, val;
uchar gmcy[4], ppm[853][3];
d223 1
d229 1
a229 1
write(out,"P6\n853 612\n255\n",15);
d231 1
a231 1
for (y=0; y < 612; y++)
d233 1
a233 1
for (x=0; x < 853; x++)
d235 8
a242 5
for (sy=y; sy < y+2; sy++)
for (sx=x; sx < x+2; sx++)
gmcy[color(sx,sy)] = pgm[sy][sx] - BLACK;
get_rgb(rgb,gmcy);
for (c=0; c < 3; c++) /* Scale and save the RGB values */
d244 1
a244 1
val = floor(rgb[c]/4);
@
1.1
log
@Initial revision
@
text
@d32 1
a32 1
float mat[3][4];
d55 8
a62 1
float coeff[4][3] =
a72 7
{
{ 0.052296, 0.255409,-0.047466 },
{ 0.156993, 0.046792, 0.046537 },
{-0.004344, 0.280239, 0.045865 },
{ 0.145482, 0.309211,-0.089371 },
};
d183 36
a218 2
/* Add one pixel to the equation */
add_pixel (int row, unsigned x, unsigned y)
d220 1
a220 1
int color, value, i;
a221 1
if (x >= 854 || y >= 613) return; /* Don't count this pixel */
d225 1
a225 7
value = pgm[y][x] - BLACK;
#if BLACK
if (value < 0) value=0;
#endif
for (i=0; i < 3; i++)
mat[row][i] += coeff[color][i];
mat[row][3] += value;
d230 3
a232 3
int out, y, x, c, val;
uchar ppm[854*3], *pptr, max[4];
float scale=1;
d238 1
a238 14
write(out,"P6\n854 613\n255\n",15);
#if 0
memset(max,0,4);
for (y=0; y < 613; y++)
for (x=0; x < 854; x++)
{
c = ((y & 1) << 1) + (x & 1);
if ((y & 3) == 2) /* 0=green, 1=magenta, 2=cyan, 3=yellow */
c ^= 1; /* Swap green and magenta */
if (max[c] < pgm[y][x])
max[c] = pgm[y][x];
}
#endif
d240 1
a240 1
for (y=0; y < 613; y++)
d242 1
a242 2
pptr=ppm;
for (x=0; x < 854; x++)
d244 5
a248 8
memset(mat,0,sizeof mat); /* Zero out the matrix */
add_pixel(0,x,y); /* Equation 0 uses this pixel */
add_pixel(1,x-1,y); /* Equation 1 uses pixels left and right */
add_pixel(1,x+1,y);
add_pixel(2,x,y-1); /* Equation 2 uses pixels above and below */
add_pixel(2,x,y+1);
solve(); /* Solve for red, green, and blue */
for (c=0; c < 3; c++) /* Scale and save these values */
d250 1
a250 1
val = floor(mat[c][3] * scale);
d253 1
a253 1
*pptr++ = val;
d256 1
a256 1
write (out, ppm, 854*3);
@